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

void delspace(char *str);

int main() {
    int i, loops;
    char s1[101], s2[101];

    scanf("%d", &loops);

    while (loops--) {
        fgets(s1, 101, stdin);
        fgets(s2, 101, stdin);
        s1[strlen(s1)] = '\0';
        s2[strlen(s2)] = '\0';

        if (s1[0] == '\n' && s2[0] == '\n') {
            printf("YES\n");
            continue;
        }

        delspace(s1);
        delspace(s2);

        for (i = 0; s1[i] != '\0'; i++)
            s1[i] = tolower(s1[i]);

        for (i = 0; s2[i] != '\0'; i++)
            s2[i] = tolower(s2[i]);

        if (strcmp(s1, s2) == 0) {
            printf("YES\n");
        }
        else {
            printf("NO\n");
        }
    }

    return 0;
}

void delspace(char* str) {
    int i = 0;
    int j = 0;
    char sTmp[strlen(str)];

    while (str[i++] != '\0') {
        if (str[i] != ' ') {
            sTmp[j++] = str[i];
        }
    }
    sTmp[j] = '\0';
    strcpy(str, sTmp);
}

「loops」に入った後、「s1」には自動的に空白行が割り当てられました。それはどのように起こりますか?私のキーボードは正常に動作すると確信しています。

4

7 に答える 7

26

scanf()要求した内容を正確に読み取り\n、その行の終わりから次の情報fgets()を読み取るバッファに残します。改行を消費するために何かをするか、(私の好みの解決策)fgets()そしてsscanf()その文字列から。

于 2011-05-06T23:41:06.670 に答える
7

scanf改行文字を含め、入力バッファに空白を残します。fgetsを使用して次の行を読み取るには、現在の行の残りを手動で削除する必要があります。

int c;
do{
    c = getchar();
}while(c != EOF && c != '\n');
于 2011-05-07T00:08:55.880 に答える
6

これはよりシンプルなソリューションです

scanf("%d",&loops);
while ((getchar()) != '\n'); //This will consume the '\n' char
//now you're free to use fgets
fgets(string,sizeof(string),stdin);
于 2019-11-05T02:15:21.700 に答える
2

Geekosaurはあなたの質問にうまく答えました、私はあなたのコードに関する別の「問題」を指摘しているだけです。

実行前にすでに適切にヌル終了されている場合、その行s1[strlen(s1)] = '\0';ノーオペレーションです。s1

ただし、s1この行が実行される前に(そして、運が悪ければ)、がまだ適切にnullで終了していない場合は、次のようになります。

これは、基本的に既存のnullターミネータstrlenのインデックスを見つけて、それを返すためです。strlenの有効で最適化されていない実装は次のとおりです。

int strlen(char *string) {
    int i = 0;
    while(string[i] != '\0') {
        ++i;
    }
    return i;
}

したがって...文字列がnullで終了しないことを本当に心配している場合は、次のようにします。

  • string[sizeof(string)]='\0';ローカル自動文字列(コンパイラが文字列のサイズを「認識」している場合)。
  • またはstring[SIZE_OF_STRING]、他のすべての文字列の場合、SIZE_OF_STRINGは(最も一般的には)#define'd定数、または動的に割り当てられた文字列のcurrent-SIZE(長さではない)を格納するために特別に維持する変数です。

また、文字列がnullで終了しないことを本当に、本当に、本当に心配している場合(たとえば、TuxedoのATMIなどの「ダーティ」なライブラリメソッドを扱っている場合)「リターン文字列」を渡す前に「クリア」することもできます。疑わしいライブラリメソッドに:

  • 前:memset(string, NULL, SIZE_OF_STRING);
  • 呼び出す:DirtyFunction(/*out*/string);
  • 後:string[SIZE_OF_STRING]='\0'

SIG11は、(シグナルプロセッサで「フック」して別の言い方をしない限り、Unixがプログラムをハードターミネートするので、(事後に)何もログに記録できず、理解するのに役立つため、見つけるのに完全なバイアッチです。 where-in-the-hell-did-that-c​​ome-from ...特に、多くの場合、SIG11をスローするコード行が、文字列がnullターミネータを失う実際の原因に近いことを考えると。

それはあなたにとって意味がありますか?

PS:警告:strncpy常にnullで終了するとは限りません...おそらくstrlcpy代わりに意味します。私はこれを難しい方法で学びました...6000万ドルの請求実行がクラッシュしたとき。


編集:

参考:これは、私が呼び出す「安全な」(最適化されていない)バージョンのstrlenです(これはstring.hstrnlenにあるはずです。ため息をつきます)。

// retuns the length of the string (capped at size-1)
int strnlen(char *string, int size) {
    int i = 0;
    while( i<size && string[i]!='\0' ) {
        ++i;
    }
    return i;
}
于 2011-05-07T00:29:05.873 に答える
0

置くだけ scanf("%d\n",&loops);

それ以外の scanf("%d",&loops);

于 2016-09-09T00:27:17.330 に答える
-1

変数ラベルループで整数をスキャンした後、次の改行文字を無視する別の方法(Enterキーを押すため)は次のとおりです。

scanf ("%d%*c", &loops);

ここで、manページによると:

*割り当てを抑制します。次の変換は通常どおりに行われますが、ポインタは使用されません。変換の結果は単に破棄されます。

これは非常にまれですが、scanf中にエラーをチェックするための良い習慣です。

errno = 0
scanf ("%d%*c", &loops);
if (errno != 0) perror ("scanf");
// act accordingly to avoid un-necessary bug in the code

たとえば、コードでは、loopsは初期化されていないローカル変数であり、ガベージが含まれています。scanfが目的の値を満たせない場合、次のwhileループが任意に実行される可能性があります。

于 2019-12-31T01:53:29.647 に答える
-1

scanf()その行の終わりから次の\nを、fgets()それを読み取るバッファに残します。これを甘やかすには、改行を消費するために何かをしなければなりません。問題を見てみましょう。

問題

#include<stdio.h>
void main()
{
    char input[10];
    printf("Enter in fgets: ");
    scanf("%s", input);
    getchar();
    printf("Enter in scanf: ");
    fgets(input, 10, stdin);
}
出力:
Enter in scanf: Hello
Enter in fgets:

ご覧のとおり、fgetsの部分は表示されていません。解決策を見てみましょう。

scanfgetchar()fgets()

#include<stdio.h>
void main()
{
    char input[10];
    printf("Enter in fgets: ");
    scanf("%s", input);
    getchar();
    printf("Enter in scanf: ");
    fgets(input, 10, stdin);
}
出力:
Enter in scanf: Hello
Enter in fgets: Hello

scanf()後の使用が可能であればfgets()

#include<stdio.h>
void main()
{
    char input[10];
    printf("Enter in fgets: ");
    fgets(input, 10, stdin);
    getchar();
    printf("Enter in scanf: ");
    scanf("%s", input);
}
出力:
Enter in fgets: Hello
Enter in scanf: Hello

2回入れfget()ます(この方法はしばらくは機能しません)

#include<stdio.h>
void main()
{
    char input[10];
    printf("Enter in fgets: ");
    scanf("%s", input);
    getchar();
    printf("Enter in scanf: ");
    fgets(input, 10, stdin);
    fgets(input, 10, stdin)
}
出力:
Enter in scanf: Hello
Enter in fgets: Hello

はめ込みsscanf()を入れますscanf()

#include<stdio.h>
void main()
{
    char input[10];
    printf("Enter in fgets: ");
    sscanf(hello, "%s", input);
    getchar();
    printf("Enter in scanf: ");
    fgets(input, 10, stdin);
}
出力:
Enter in sscanf: Hello
Enter in fgets: Hello
于 2020-03-03T18:27:44.110 に答える