0

char *渡されたときにその文字列で特定のサブ文字列を検索し、空白の次の文字を次の空白まで出力する小さなテスト関数を作成しようとしています。

strstr()andを使用して基本的な実装を作成しましたstrncpy()が、このメソッドは一種の静的であり、一度に 1 つの検索語に対してのみ機能し、次の文字の出力は固定されています。

int ParseCommand(char *command)
{
    char *pSearch = strstr(command, CommandOne);
    char str[100];

    if (pSearch != NULL)
    {
        pSearch += strlen(CommandOne) + 1;
        strncpy(str, pSearch, 2);
        printf("%s\n\n", str);
    }

    printf("%s\n", command);
    return 0;
}

このコード サンプルが行うことは、 say を渡すとParseCommand("ten hats 10 are cool")関数が出力するものとCommandOne等しい場合です。これは機能しますが、操作を静的に実行しすぎて、 内でより多くのコマンドを検索するのが難しくなります。基本的に、渡された文字列内でコマンドが見つかるまでコマンドをループし、コマンドの後から次の空白まですべてをコピーするものが必要です。"hats""10"char *commandstrstr()

コマンドを検索する方法は知っています (すべての検索用語でポインター char 配列を作成し、strstr()null が返されなくなるまでそれらすべてをループします) が、検索用語の後に次の「単語」をコピーするにはどうすればよいでしょうか?

全体として、文内の検索用語を検索し、次の空白に到達するまでプレシードされたデータをコピーするには、いくつかの疑似コード ロジックが必要です。(文中の検索語の次の単語をコピーします。)

4

3 に答える 3

1

1 つの問題は、関数へのインターフェイスの設計です。特に最初の文字列を見つけた後に取得する必要がある場合は、インターフェイスが単純すぎます。そこで、より複雑なインターフェースを提案します。

int find_word_following(char *haystack, const char *needle, char **bgn, char **end);

haystack は、スキャンされる文字列です。針は見つける言葉です。および引数はポインタ (出力) であり、関数が針の後の単語の開始点と単語の終了点に 1 を加えた位置に設定しますbgnend戻り値は 0 (単語が見つからない) または 1 (単語が見つかった) です。戻って単語が見つかった場合*bgn == *end、その後に別の単語はありませんでした。と が干し草の山内の場所を指し、const-correctness が乱雑になるため、const char *干し草の山で指定しないことを選択しました。ただし、コードは干し草の山を変更しません。bgnend

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

int find_word_following(char *haystack, const char *needle, char **bgn, char **end);

int main(void)
{
    char *haystack = "ten hats 10 are cool";
    char *needle   = "hats";
    char *bgn;
    char *end;

    while (find_word_following(haystack, needle, &bgn, &end))
    {
        printf("Found <<%*.*s>>\n", (int)(end - bgn), (int)(end - bgn), bgn);
        needle = "are";  // Change search term
        haystack = end;  // Start where previous scan left off
    }
    return(0);
}

これだけの仕様があれば、関数を書くのはそれほど難しくありません。

int find_word_following(char *haystack, const char *needle, char **bgn, char **end)
{
    assert(haystack != 0 && needle != 0 && bgn != 0 && end != 0);
    char *word = strstr(haystack, needle);

    if (word == 0)
        return(0);
    word += strlen(needle);
    // Skip to end of word (in case we found 'hatstand')
    while (*word != '\0' && !isspace(*word))
        word++;
    while (isspace(*word))   // Skip spaces after word
        word++;
    *bgn = word;             // Start of following word
    while (*word != '\0' && !isspace(*word))
        word++;
    *end = word;
    return(1);
}

strspn()これらのループは、 andを適切に呼び出すことで置き換えることができますstrcspn()

プログラムの出力は次のとおりです。

Found <<10>>
Found <<cool>>

正確な単語を探すバリアントは次のとおりです。

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

int find_word_following(char *haystack, const char *needle, char **bgn, char **end);

int find_word_following(char *haystack, const char *needle, char **bgn, char **end)
{
    assert(haystack != 0 && needle != 0 && bgn != 0 && end != 0);
    size_t length = strlen(needle);
    char *word;
    while ((word = strstr(haystack, needle)) != 0)
    {
        if ((word == haystack || (word > haystack && isspace(*(word - 1)))) &&
            isspace(word[length]))
        {

            word += length;
            while (isspace(*word))   // Skip spaces after word
                word++;
            *bgn = word;             // Start of following word
            while (*word != '\0' && !isspace(*word))
                word++;
            *end = word;
            return(1);
        }
        haystack = word + length;
    }
    return(0);
}

int main(void)
{
    char *haystack = "ten hatstands with hats on are OK";
    char *needle   = "hats";
    char *bgn;
    char *end;

    while (find_word_following(haystack, needle, &bgn, &end))
    {
        printf("Found <<%*.*s>>\n", (int)(end - bgn), (int)(end - bgn), bgn);
        needle = "are";  // Change search term
        haystack = end;  // Start where previous scan left off
    }
    return(0);
}

出力 (入力文字列が異なることに注意してください) は次のとおりです。

Found <<on>>
Found <<OK>>
于 2012-10-18T04:30:27.060 に答える
1

簡単なプロトタイプを作成しましたが、うまくいくようです。

char *ParseCommand(char *command, char *find)
{
    char *p, *q, *t;

    p = strstr(command, find);

    if (p != NULL) {
        /* skip to the next word */
        for (q = p; *q != '\0' && *q != ' '; q++)
            ;
        if (*++q != '\0') {
            for (p = q; *q != '\0' && *q != ' '; q++)
                ;
            t = malloc(q - p);
            return strncpy(t, p, q - p);
        }
    }

    return NULL;
}

でテストすると、ParseCommand("ten hats 10 are cool", "hats")が返されます10

HTH。

于 2012-10-18T04:09:50.353 に答える
0

strtok() を使用して文字列をトークン化しないのはなぜですか? 次に、コマンドの文字列を解析します。

おそらく、この方法 (再帰降下で書きます) には文法が必要になるでしょう。

SPARKOT ADVICE EDIT(感謝): より高速な文字列検索アルゴリズムが必要な場合は、Boyer-Moore Algorithmを参照してください。

于 2012-10-18T04:09:09.953 に答える