2

文字列を分割してトークンを出力しようとしています。

int main()
{
    char line[255] = "182930101223, KLA1513";
    char val1[16];
    char val2[7];

    strcpy(val1, strtok(line, ","));
    strcpy(val2, strtok(NULL, ","));

    printf("%s|%s\n", val1, val2);

    return 0;
}

印刷すると取得します

  3| KLA1513

それ以外の

182930101223| KLA1513

どうした?

4

2 に答える 2

7

OK、これは無関係な問題だと思っていましたが、あなたが見ている問題だと思います。

C 文字列は、含まれている文字よりも 1 文字余分に取ることに注意してください。これは終了 NUL 文字 ( \0) であり、テキストの終わりを示します。

実際KLA1513には 8 文字 ( KLA1513\0) も同様です。さらに、スペースをトリミングしていないため、9 文字です。_KLA1513\0(_はスペースです)。

これは、2 番目の でメモリをオーバーランしていることを意味し、未定義の動作strcpyにつながります。これは、最悪の悪夢であることに気付くでしょう。

印刷すると、プログラムがどのような状態にあるかは誰にもわかりません。上書きしたメモリがprint呼び出しの一部であったか、再度上書きされてvar2終了していない可能性があります。

もっとvar2大きくして (ここでは 9 文字で十分です)、将来的には安全な形式 (strncpyなど) を使用してください。このような間違いは、ハッカーがシステムを侵害する通常の方法です。

于 2013-08-24T15:30:34.597 に答える
2

これを試して:

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

int main()
{
    char line[] = "182930101223, KLA1513";
    char* val1;
    char* val2;

    val1 = strtok(line, ",");
    val2 = strtok(NULL, ",");

    printf("%s|%s\n", val1, val2);

    return 0;
}

strcpy()トークンは必要ありませんchar*。見つかった各トークンの最後にstrtok()クロージングを追加します。\0

また、トークンのサイズを事前に知る必要がないため、より安全です。トークンのサイズが問題でした。独自のメモリにトークンを保持する必要がある場合は、後で十分なサイズの文字列にコピーできます。

次のことはできないことに注意してください。

char* line = "182930101223, KLA1513";

strtok()文字列を変更し、リテラル C 文字列を変更することは許可されていないためです。

于 2013-08-24T15:33:16.167 に答える