1

1つの文で2つの類似した単語を見つける必要があり、これら2つの単語の間にどれだけの記号があるかを見つける必要があります. アルゴリズムがわかりません。

たとえば、文は次のようになります-

素敵なテーブルと素敵な椅子です。

似た言葉は――nice

それらの間の記号は11または8です(スペースが記号としてカウントされるかどうかはわかりません)

int main()    
char text[200];
printf("Enter one sentence \n ");
gets(text);

たぶんまず第一に

dist=strtok(text, " ,.!?");
while(dist!=0)
{
 printf("%s\n", dist);
 dist=strtok(NULL, " ,.!?");
 }

そして、各単語を出力し、2つの文字列がある場合は同様の単​​語を検索できるので、strstrを使用しますが、1つの文字列を処理する方法がわかりません。

4

4 に答える 4

2
  1. toupperorを使用tolowerして、文字列全体を大文字/小文字にします。これにより、その後の比較が容易になります。

  2. を使用して、文の各単語の先頭を指す値strtokの配列を作成します。char*必要に応じて、この段階で空の文字列と句読点を削除できます。

  3. 関数を使用して、ネストされたループを使用して、この配列内の単語の各ペアを比較しstrcmpます。

  4. strlen2 つの単語が一致すると、ポインタ演算と関数を使用して単語間の距離を計算できます。

于 2013-10-29T16:18:27.467 に答える
1

アルゴリズムは次のようになります。

  1. strtok (または必要に応じて手動で解析します。strtok はスレッドセーフではありません) を使用して、文内のすべての単語を取得します。
  2. 各ステップで、単語をマップ (ハッシュテーブル) に挿入します。ここで、キーは単語自体であり、値は文の開始位置であり、値は配列に格納されます。
  3. 入力の解析が完了すると、キーが単語として、値が元の文の開始位置の並べ替えられた配列としてのマップになります。
  4. ここで、文字数を取得するために必要なのは、単語に対応する配列内の任意の 2 つの連続する位置を減算することだけです。この配列には 2 つ以上の要素が含まれているため、単語は文に複数回出現します。例: "nice" が位置 10 と位置 20 に表示されると仮定すると、これら 2 つがマップ内の位置の配列に含まれることになります => 距離を計算できます
于 2013-10-29T16:21:08.740 に答える
0

結果を何に使用するかによって少し異なります。文字列の変更、統計情報の出力、単語のコピーなどに使用されますか? 定数文字列をサポートする必要があるかどうかなど、スレッド セーフである必要がありますか? 効率と単純さの中で最も重要なことは何ですか。

1 つのアプローチは、ポインター全体に依存することです。

  1. 最初の単語へのポインタptr1.
  2. 次の単語へのポインタptr2.
    1. ptr1単語と単語をチェックしますptr2
    2. ptr2次の単語に進みます。
    3. 一致が見つからない場合は、Goto 1.
  3. 一致が見つからない場合は、ptr2次の単語に進みます。
  4. 後藤2。

単語を比較するための骨組みは、次のようになります。

int compare_word(char *word1, char *word2)
{
        int i;

        for (i = 0;
                word1[i] && word2[i] &&
                word1[i] == word2[i] &&
                isalpha(word1[i]); ++i)
                ;

        return i && !isalpha(word1[i]) && !isalpha(word2[i]);
}

単語間の距離を計算するときに覚えておくべきことの 1 つは、utf-8 などのマルチバイト文字列形式に注意することです。1文字が数バイトになる場合があります。

a æøå a
 ^---^ 8 bytes, 5 characters.

を使用mbstowcsしてマルチバイト シーケンスの長さを取得できますが、ロケールにも注意する必要があります。典型的なシナリオ:

char *test = "æøå";

printf("%s: %u\n", test, mbstowcs(NULL, test, 0));
printf("%s: %u\n", test, strlen(test));

setlocale(LC_ALL, "");

puts("-----------------------------------------------");
printf("%s: %u\n", test, mbstowcs(NULL, test, 0));
printf("%s: %u\n", test, strlen(test));

結果:

æøå: 4294967295
æøå: 6
-----------------------------------------------
æøå: 3
æøå: 6

とにかく。概念のサンプルとして、ここにいくつかのコード行があります。これはバイトセーフではないことに注意してください – (ASCII のみが適切な結果をもたらします)。点線の末尾の数字は、「距離: 単語 1 の先頭から単語 2 の先頭まで」「単語 1 の末尾から単語 2 の先頭までの距離」、および「単語幅」です。出力例:

$ ./wordword 
Enter one sentence:
Lizzie Borden took an axe And gave her mother forty whacks When she saw what she had done She gave her father forty-one.

Lizzie Borden took an axe And gave her mother forty whacks When she saw what she had done She gave her father forty-one.
                              ^---------------------------------------------------------------^ (64, 60, 4)
MATCH: 'gave' 60 bytes of separation.  (Press enter for next.)

Lizzie Borden took an axe And ____ her mother forty whacks When she saw what she had done She ____ her father forty-one.
                                   ^---------------------------------------------------------------^ (64, 61, 3)
MATCH: 'her' 61 bytes of separation.  (Press enter for next.)

Lizzie Borden took an axe And ____ ___ mother forty whacks When she saw what she had done She ____ ___ father forty-one.
                                              ^---------------------------------------------------------------^ (64, 59, 5)
MATCH: 'forty' 59 bytes of separation.  (Press enter for next.)

Lizzie Borden took an axe And ____ ___ mother _____ whacks When she saw what she had done She ____ ___ father _____-one.
                                                                ^------------^ (13, 10, 3)
MATCH: 'she' 10 bytes of separation.  (Press enter for next.)

サンプルコード。(わかりました、ここでは少しやり過ぎました。30 行から始めて、少し大きくなりました。しかし、それでもかなりの数の欠点があり、ポインターなどを使用した例としてのみ意図されています。):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define FMT_BBLACK     "\033[1;30m"                /* Bold color black */
#define FMT_BRED       "\033[1;31m"                /* Bold color red */
#define FMT_BGREEN     "\033[1;32m"                /* Bold color green */
#define FMT_BYELLOW    "\033[1;33m"                /* Bold color yellow */
#define FMT_BBLUE      "\033[1;34m"                /* Bold color blue */
#define FMT_BMAGENTA   "\033[1;35m"                /* Bold color magenta */
#define FMT_BCYAN      "\033[1;36m"                /* Bold color cyan */
#define FMT_BWHITE     "\033[1;37m"                /* Bold color white */
#define FMT_NONE       "\033[0m"                   /* Reset */
#define FMT_MATCH      FMT_BRED

#define DEL_NONE       0x00                        /* Keep words. (Causes re-match) */
#define DEL_WORD1      0x01                        /* Remove first word-match */
#define DEL_WORD2      0x02                        /* Remove second word-match */
#define DEL_BOTH       (DEL_WORD1 | DEL_WORD2)

/* Print graph */
int debug = 1;

/* ********************************************************************** *
 *        Helper functions
 * ********************************************************************** */
/* Return pointer to next alpha,
 * or null on end of string) */
char *skip_noword(char *p)
{
        while (*p && !isalpha(*p))
                ++p;
        return p;
}

/* Return pointer to byte after last alpha,
 * or null on end of C-string */
char *eof_word(char *p)
{
        while (*p && isalpha(*p))
                ++p;
        return p;
}

/* Return pointer to first letter of next word,
 * or null on end of C-string. */
char *next_word(char *p)
{
        p = eof_word(p);
        return skip_noword(p);
}

/* Compare whole word starting at p1 with word starting at p2.
 * Return 1 on match, else 0.
 * */
int compare_word(char *p1, char *p2)
{
        int i;

        for (i = 0;
                p1[i] && p2[i] &&
                isalpha(p1[i]) &&
                p1[i] == p2[i]; ++i)
                ;

        return i && !isalpha(p1[i]) && !isalpha(p2[i]);
}

/* ********************************************************************** *
 *        Search routine
 * ********************************************************************** */
/* Find next word with a matching entry.
 * Return pointer to first word.
 * Set match to matching entry.
 * */
char *word_word(char *buf, char **match)
{
        char *p;
        *match = NULL;

        buf = skip_noword(buf);

        /* Outer loop.
         * Advance one and one word. */
        while (*buf) {
                /* Inner loop.
                 * Compare current buf word with rest of words after it. */
                p = next_word(buf);
                while (*p) {
                        if (compare_word(buf, p)) {
                                *match = p;
                                return buf;
                        }
                        p = next_word(p);
                }
                buf = next_word(buf);
        }

        return (char*)NULL;
}

/* ********************************************************************** *
 *        Clear, Copy, Print etc.
 * ********************************************************************** */

/* Bytes between end of one word to beginning of next.
 * */
size_t words_dist(char *w1, char *w2)
{
        return w2 - eof_word(w1);
}

/* Replace all alpha characters with given char.
 * */
void clear_word(char *p, char r)
{
        while (*p && isalpha(*p))
                *p++ = r;
}

/* Return a copy of word pointed to by p.
 * */
void *word_cpy(char *p)
{
        void *buf;
        char *start = p;
        size_t n;

        n = eof_word(p) - start + 1;
        if (!(buf = malloc(n)))
                return (void*)NULL;
        memcpy(buf, start, n);
        ((char*)buf)[n - 1] = 0x00;

        return buf;
}

/* Print graph showing position of p2 and p3 in p1.
 * */
void explain(char *p1, char *p2, char *p3)
{
        size_t n1 = p3 - p2;
        size_t n2 = words_dist(p2, p3);

        puts(p1);
        while (p1++ != p2)
                putchar(' ');
        putchar('^');
        while (++p2 != p3)
                putchar('-');
        printf("^ (%d, %d, %d)\n", n1, n2, n1 - n2);
}

/* Print C-string using color.
 *
 * */
void print_word(FILE *out, char *word)
{
        fprintf(out, "%s%s%s", FMT_MATCH, word, FMT_NONE);
}

/* Print single word pointed to by p in (longer) C-string.
 * Use dynamic buffer.
 * */
void print_word_safe(FILE *out, char *p)
{
        char *word;

        if (!(word = word_cpy(p)))
                return;
        print_word(out, word);
        free(word);
}

/* Print single word pointed to by p in (longer) C-string.
 * Modify and reset source.
 * */
void print_word_mod(FILE *out, char *p)
{
        char *start = p;
        char csave;

        p = eof_word(p);
        csave = *p;
        *p = 0x00;
        print_word(out, start);
        *p = csave;
}

/* ********************************************************************** *
 *        Main
 * ********************************************************************** */
int main(int argc, char *argv[])
{
        char buf_scan[4096];    /* Buffer holding typed input. */
        char *buf_start;        /* Start of buffer. */
        char *buf_pos;          /* Current position in buffer. */
        char *match;            /* Position for matched word. */
        int delete;             /* Delete flag mask. */

        debug = 1;              /* 1=Print explanation. */
        delete = DEL_BOTH;      /* DEL_[NONE, WORD1, WORD2, BOTH] */

        if (argc > 1) {
                /* Use first argument instead of user input. */
                buf_start = argv[1];
        } else {
                /* Get user input. */
                buf_start = buf_scan;
                fputs("Enter one sentence:\n", stderr);
                if (!fgets(buf_scan, sizeof(buf_scan) - 1, stdin))
                        buf_scan[0] = 0x00;
                buf_scan[strlen(buf_scan) - 1] = 0x00;
                putc('\n', stderr);
        }

        buf_pos = buf_start;
        /* Get next matching pair. */
        while ((buf_pos = word_word(buf_pos, &match))) {
                if (debug)
                        explain(buf_start, buf_pos, match);
                /* Report findings */
                fputs("MATCH: ", stderr);
                print_word_mod(stderr, buf_pos);
                fprintf(stderr,
                        " %d bytes of separation.",
                        words_dist(buf_pos, match)
                );
                /* Clear out matched word pair. */
                if (delete & DEL_WORD1) {
                        clear_word(buf_pos, '_');
                }
                if (delete & DEL_WORD2) {
                        clear_word(match, '_');
                }
                /* Advance head to next word. */
                buf_pos = next_word(buf_pos);
                fputs("  (Press enter for next.)", stderr);
                getchar();
                putc('\n', stderr);
        }

        if (0 && debug)
                printf("FINE:\n%s\n\n", buf_start);

        return 0;
}
于 2013-10-29T23:35:37.447 に答える