-1

関数が新しい行に到達するたびに 0 を出力するようにしたいのですが、機能していませんが、ファイルから各単語を取得することは正常に機能します。迅速な対応をいただければ幸いです。

入力ファイルのデータは次のようになります。

blossom flower
bewilder confound confuse perplex
dwell live reside

コード:

int getWord(FILE * in, char str[]){
    int ch;
    int i = 0;
    while(!isalpha(ch = getc(in)) && ch != EOF);
        if(ch == EOF) return -1;
    str[i++] = tolower(ch);
    while(isalpha(ch = fgetc(in)) && ch != EOF){
            if(i < MAX_WORD)
                str[i++] = tolower(ch);
    }
    if(ch == '\n') return 0;
    str[i] = '\0';
    return 1;
}     
4

1 に答える 1

3

コメントの質問に対する直接の回答

私の質問はまだ答えられていませんreturn 0

なぜなら:

  1. Windows で実行している場合、
  2. ファイルはバイナリ ファイルとして開かれ、
  3. 行末で単語を終了する文字は、LF ではなく CR です。

次に関数を呼び出すと、最初のループで LF が読み取られ、アルファベット順ではないため無視されます。

主な回答

簡潔に言うと、コードは改行を認識します — 少なくとも Linux では。

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

enum { MAX_WORD = 50 };

static
int getWord(FILE *in, char str[])
{
    int ch;
    int i = 0;
    while (!isalpha(ch = getc(in)) && ch != EOF)
        ;
    if (ch == EOF)
        return -1;
    str[i++] = tolower(ch);
    while (isalpha(ch = fgetc(in)) && ch != EOF)
    {
        if (i < MAX_WORD)
            str[i++] = tolower(ch);
    }
    if (ch == '\n')
        return 0;
    str[i] = '\0';  // Bug; should be before the if
    return 1;
}

int main(void)
{
    char buffer[MAX_WORD];
    int rc;

    while ((rc = getWord(stdin, buffer)) >= 0)
        printf("Got: %d (%s)\n", rc, buffer);
    return 0;
}

入力ファイルが与えられた場合:

blossom flower
bewilder confound confuse perplex
dwell live reside

プログラムは次の出力を生成します。

Got: 1 (blossom)
Got: 0 (flowerm)
Got: 1 (bewilder)
Got: 1 (confound)
Got: 1 (confuse)
Got: 0 (perplex)
Got: 1 (dwell)
Got: 1 (live)
Got: 0 (residex)

改行を読み取ったとき (0 が返されたとき)、単語内に文字が残ってしまい、現在の単語が前の単語よりも短いことに注意してください。行の最後の単語が前の単語よりも長く、スタックが十分に乱雑である場合、不適切な動作が発生する可能性があります。条件の前に null 終了を移動することで、このバグを修正できますif。出力は次のとおりです。

Got: 1 (blossom)
Got: 0 (flower)
Got: 1 (bewilder)
Got: 1 (confound)
Got: 1 (confuse)
Got: 0 (perplex)
Got: 1 (dwell)
Got: 1 (live)
Got: 0 (reside)

Windows では、プログラムが a '\r'(CRLF 行末の CR 部分) を読み取った場合、単語を終了する文字が'\r'であり、次の関数呼び出しで最初のループが実行されたため、ゼロ リターンはスキップされることに注意してください。をスキップし'\n'ます。

プラットフォーム (Unix と Windows) を示すと、質問が明確になり、回答がより迅速に得られることに注意してください。

DOS (Windows) 形式のファイルを作成data.dosし、同じ (バグ修正済み) バイナリ (Ubuntu 14.04 派生物で実行) でそれを読み取ると、出力は次のようになります。

Got: 1 (blossom)
Got: 1 (flower)
Got: 1 (bewilder)
Got: 1 (confound)
Got: 1 (confuse)
Got: 1 (perplex)
Got: 1 (dwell)
Got: 1 (live)
Got: 1 (reside)

これは、「CR が単語を終了し、最初のループが改行をスキップする」シナリオに正確に対応します。戦略的な場所に印刷ステートメントを追加してデバッグすることもできます。

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

enum { MAX_WORD = 50 };

static
int getWord(FILE *in, char str[])
{
    int ch;
    int i = 0;
    while (!isalpha(ch = getc(in)) && ch != EOF)
    {
        if (ch == '\n') printf("Got-1 '\\n'\n");
        else if (ch == '\r') printf("Got-1 '\\r'\n");
        else printf("Got-1 '%c'\n", ch);
    }
    if (ch == EOF)
        return -1;
    str[i++] = tolower(ch);
    while (isalpha(ch = fgetc(in)) && ch != EOF)
    {
        if (i < MAX_WORD)
            str[i++] = tolower(ch);
    }
    if (ch == '\n') printf("Got-2 '\\n'\n");
    else if (ch == '\r') printf("Got-2 '\\r'\n");
    else printf("Got-2 '%c'\n", ch);
    str[i] = '\0';
    if (ch == '\n')
        return 0;
    return 1;
}

int main(void)
{
    char buffer[MAX_WORD];
    int rc;

    while ((rc = getWord(stdin, buffer)) >= 0)
        printf("Got: %d (%s)\n", rc, buffer);
    return 0;
}

Unix ファイルでは、出力は次のようになります。

Got-2 ' '
Got: 1 (blossom)
Got-2 '\n'
Got: 0 (flower)
Got-2 ' '
Got: 1 (bewilder)
Got-2 ' '
Got: 1 (confound)
Got-2 ' '
Got: 1 (confuse)
Got-2 '\n'
Got: 0 (perplex)
Got-2 ' '
Got: 1 (dwell)
Got-2 ' '
Got: 1 (live)
Got-2 '\n'
Got: 0 (reside)

そしてWindowsファイルで:

Got-2 ' '
Got: 1 (blossom)
Got-2 '\r'
Got: 1 (flower)
Got-1 '\n'
Got-2 ' '
Got: 1 (bewilder)
Got-2 ' '
Got: 1 (confound)
Got-2 ' '
Got: 1 (confuse)
Got-2 '\r'
Got: 1 (perplex)
Got-1 '\n'
Got-2 ' '
Got: 1 (dwell)
Got-2 ' '
Got: 1 (live)
Got-2 '\r'
Got: 1 (reside)
Got-1 '\n'

Unix/Linux は CRLF の組み合わせを特別に扱わないことに注意してください。これらは、入力ストリーム内の隣接する 2 つの文字にすぎません。

于 2014-10-02T23:14:02.843 に答える