1

次のコードの間違いは何ですか?

    char* line=""; 

printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");

コンソールからの入力として行を取得しようとしていますが、「scanf」を使用している間は毎回プログラムがクラッシュします。私は性感染症を使いたくありません、私は完全にcinまたはcoutの使用を避けたいです。scanf()を使用して、入力として1行全体を取得する方法を学習しようとしています。

ありがとうございました。

4

9 に答える 9

6

入力文字列sscanf()自体にはスペースを割り当てることができないため、スペースを割り当てる必要があります。

char line[1024]; 

printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");

ただし、これはバッファをオーバーフローさせる可能性があるため危険であり、したがってセキュリティ上の懸念があります。std::string代わりに使用してください:

std::string line;

std::cout << "Write the line." << std::endl;
std::cin >> line;
std::cout << line << std::endl;

また:

std::getline (std::cin, line);
于 2012-04-19T11:46:56.697 に答える
3

scanf() は行と一致しません。%s は単一の単語に一致します。

#include <stdio.h>

int main() {
    char word[101];
    scanf("%100s", word);
    printf("word <%s>\n", word);
    return 0;
}

入力:

this is a test

出力:

word <this>

行の使用に一致させるに%100[^\n"]は、改行ではない100文字を意味します。

#include <stdio.h>

int main() {
    char word[101];
    scanf("%100[^\n]", word);
    printf("word <%s>\n", word);
    return 0;
}
于 2012-04-19T12:04:32.560 に答える
3

スペースが割り当てられてlineいません 次のようなことをする必要があります

char *line = malloc();

また

Char line[SOME_VALUE];

現在のところline、文字列リテラルを指すポインターは貧弱です。また、文字列リテラルを上書きすると、未定義の動作が発生する可能性があります。

于 2012-04-19T11:45:49.100 に答える
1

文字列リテラルを変更しようとしていますが、CではUndefined behaviorになり、C++ では const メモリに書き込もうとしています。

それを克服するには、 achar[]を割り当ててに割り当てるlineか、C++ の場合は使用std::stringして多くの苦痛を回避したい場合があります。

于 2012-04-19T11:45:49.643 に答える
1

以下に十分なメモリを割り当てる必要がありますline

char line[100];

例えば。

于 2012-04-19T11:46:12.927 に答える
1

呼び出しの%s変換指定子は、対応する引数が、入力を保持するのに十分な大きさのタイプの書き込み可能なバッファーscanfを指すことを期待しています。char [N]N

line文字列リテラルを指すように初期化しました""。これには 2 つの問題があります。1 つ目は、文字列リテラルの内容を変更しようとすると、未定義の動作が発生することです。言語定義では、文字列リテラルの格納方法は指定されていません。それらの有効期間と可視性のみを指定し、一部のプラットフォームはそれらを読み取り専用メモリ セグメントに貼り付けますが、他のプラットフォームは書き込み可能なデータ セグメントに配置します。したがって、あるプラットフォームで文字列リテラルの内容を変更しようとすると、アクセス違反が原因で完全にクラッシュする可能性がありますが、別のプラットフォームでは同じことが正常に機能する場合があります。言語定義は、何をすべきかを義務付けていません文字列リテラルを変更しようとすると発生します。実際、その動作を明示的にundefinedのままにするため、コンパイラは状況を自由に処理できます。一般に、文字列リテラルは書き込み不可であると常に想定することをお勧めします。

もう 1 つの問題は、文字列リテラルを含む配列のサイズが 0 ターミネータの 1 文字しか保持できないことです。C スタイルの文字列は の単純な配列として格納されchar、さらに文字を追加しても配列は自動的に拡張されないことに注意してください。

lineの配列として宣言するかchar、メモリを動的に割り当てる必要があります。

char line[MAX_INPUT_LEN];

また

char *line = malloc(INITIAL_INPUT_LEN);

メモリを動的に割り当てる利点は、必要に応じてバッファのサイズを変更できることです。

安全のために、読み取る最大文字数を指定する必要があります。バッファーのサイズが 21 文字を保持するサイズの場合、scanf呼び出しを次のように記述します。

scanf("%20s", line);

line保持できるよりも多くの文字が入力ストリームにある場合、scanfはそれらの余分な文字を に続くメモリに書き込みline、重要なものを破壊する可能性があります。バッファ オーバーフローは一般的なマルウェアのエクスプロイトであり、回避する必要があります。

また、%s完全な行は得られません。フィールド幅指定子があっても、次の空白文字まで読み取ります。のような別の変換指定子を使用する%[^\n]か、fgets()代わりに使用する必要があります。

于 2012-04-19T14:53:51.353 に答える
0

変化する:

char* line="";

char line[max_length_of_line_you_expect];
于 2012-04-19T11:47:03.630 に答える
0

line読み取られた文字列を保持する文字配列の先頭を指すはずのポインターは、実際には内容が変更できない文字列リテラル (空の文字列) を指しています。これは、あなたのケースではクラッシュとして現れる未定義の動作につながります。

これを修正するには、定義を次のように変更します。

char line[MAX];  // set suitable value for MAX

最大 MAX-1 文字数を に読み込みますline

于 2012-04-19T11:46:15.323 に答える
-1

scanfによって予約されているよりも多くの文字を書き込もうとしていますline。上記の回答で指摘されているように、期待する行よりも多くの文字を予約してみてください。

于 2012-04-19T11:49:38.247 に答える