1

このコードを使用していますが、正しく動作しません。

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

int main() {
    char line[120], *word;
    int o, row, col, letter, i;
    o = scanf("%s", line);
    row = 0;
    while(o != -1) {
        col = 0;
        while(isprint(line[col])) {
            word = (char *) malloc(sizeof(char)*20);
            for(i=0; i<20; i++) *(word + i) = 0;
            letter = 0;
            while(isalpha(line[col])) {
                *(word + letter) = line[col];
                col++;
                letter++;
            }
            col++;
            printf("%s\n", word);
            free(word);
        }
        row++;
        o = scanf("%s", line);
    }
return 0;
}

たとえば、次のように入力します。

can you take a string?

そして、私は出力として受け取ります:

can
you
take
a
ke
string

間違いを見つけることはできませんが、出力が私が望むものから遠くないという事実は、間違いが小さいことを意味します. 私を助けてください...:)

4

3 に答える 3

1

あなたのコードにもう少し良いアプローチを提案してもよろしいですか?

複雑にすることなく入力を取得する既知の安全な方法は、(既に指摘したように) fgetsを使用することです。

fgetsバッファの制限を超えないように、コンソールから取得する文字数を指定できます。

fgetsユーザー入力 (ポインターを使用)stdinまたはファイルからの読み取り (の代わりにファイル ハンドルを指定stdin) に使用できます。

ロジックを単純化する方法の例を次に示します。

#include <stdio.h>

int main()
{
    char input [100];

    /* the [0] bit checks if only a newline has been entered thereby ignoring empty lines */
    /* we also check if fgets returns NULL, which may lead to undefined behavior if ignored */
    while(fgets(input, 100, stdin) != NULL && input[0] != '\n') 
    {
        int i = 0;                       /* this counter keeps track of the current char in the input */
        int w = 0;                       /* keep track if we are in a word, fixes printing newline for each white line */
        while(input[i] != '\0')          /* while we're not at the end of the string */
        {
            switch(input[i])
            {
                case ' ':                /* if the character is any of the below then print newline */
                case '\t':
                case '\r':
                case '\f':
                case '\v':
                case '\n':
                if (w) { w = 0; printf("\n"); } 
                break;
                default:
                if (!w) { w = 1; }
                printf("%c", input[i]);  /* otheriwse print the character itself */
            }
            i++;
        }
    }

    return 0;
}
于 2013-06-14T17:08:23.593 に答える
0

あなたはそれo = scanf("%s", line);がライン全体をもたらすと考えているようです. これは正しくありません。最初の単語しか読み取れません。バッファ オーバーフローとスタイルの問題はさておき、プログラム全体は基本的に次のように要約できます。

#include <stdio.h>

int main() 
{
    char line[120];
    while(scanf("%s", line) != -1)
    {
        printf("%s\n", line);
    }
    return 0;
}

入力:

can you take a string?

出力:

can
you
take
a
string?

本当にアルファベット文字だけが必要な場合は、空白以外の他の文字も単語区切り文字と見なすか、無視するかを記述する必要があります。たとえば、2 回または?としてword1word印刷されます。wordwordword


編集:

非文字を完全に無視したい場合は、次のようにしてください。

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

void PrintOnlyLetters(char word[])
{
    int i;
    int count = 0;

    for(i = 0; word[i] != '\0'; i++)
    {
        if(isalpha(word[i]))
        {
            count++;
            printf("%c", word[i]);
        }
    }

    if(count > 0)
    {
        printf("\n");
    }
}

int main() 
{
    char word[120];

    while(scanf("%119s", word) > 0)
    {
        PrintOnlyLetters(word);
    }

    return 0;
}

入力:

can yo4u t@ke one (/1) or more string(s)?

出力:

can
you
tke
one
or
more
strings

これは単純で、初期化されていないメモリからの読み取りなしで必要なことを行いますが、それでも脆弱であることに注意してください。たとえば、119 文字を超える単語は分割されます (コードからバッファ オーバーフローを取り除くための変更)。

于 2013-06-14T17:14:45.247 に答える