如何将此“for”循环转换为在C中使用EOF?

时间:2014-02-13 02:42:55

标签: c string loops eof

char* readScores(int* actualCount) {

char* stringArray = (char*)malloc(100*sizeof(char));

for(int i = 0; i <= 13; i++) {
    *actualCount = *actualCount + 1;
    scanf("%s", &stringArray[i]);
    printf("stringArray = %s when i = %d\t actualCount = %d\n", &stringArray[i], i, *actualCount);
}
printf("Finished!");

return stringArray;
}

使用这段代码,我循环遍历一个带有一些单词的.txt文件。当我运行这段代码时,我发现我确实在数组中的正确位置得到了正确的单词,但是一旦循环到达文件的末尾,程序就会给我一个段错误。我猜这是因为循环正在达到EOF值并抛出错误,但我无法弄清楚如何修复它。以下是结果的屏幕截图:http://i.imgur.com/kduzBnp.png

感谢您的帮助!

修改

我将代码更改为:

while(scanf("%s", &stringArray) != EOF) {
    *actualCount = *actualCount + 1;
    printf("stringArray = %s when actualCount = %d\n", &stringArray, *actualCount);
}

但是,我仍然遇到具有相同输出值的段错误。所以我知道它正在正确读取文件,我只是不知道为什么它会在最后停止并抛出错误。

5 个答案:

答案 0 :(得分:2)

只要scanf成功从标准输入中读取单词,您就希望继续循环。

因此循环的终止条件应使用scanf返回的结果。

scanf返回成功读取的项目数。如果成功阅读了某个单词,则会返回1,否则会返回0EOF

但您的代码还存在其他一些问题。

char* stringArray = (char*)malloc(100*sizeof(char));

这不会为100个字符串分配空间,甚至不会为100个指向字符串的指针分配空间。它仅为100 char s的单个数组分配空间。最好写成:

char *stringArray = malloc(100);

投放malloc的结果是不必要的,可以掩盖错误,sizeof(char)按定义为1。

你的for循环将连续的单词读入内存,从分配数组中的位置0开始,然后是位置1,然后是位置2等,每个读取覆盖前一个的部分。

此外,具有scanf格式的"%s"本质上是不安全的,因为它将读取与用户类型(或来自stdin所连接的任何字符)一样多的字符,而不管目标数组的大小。

使用fgets()读取文本行更安全,然后可能sscanf来解析输入(尽管sscanf有一些问题)。

如果你想存储多个字符串,你需要为它们分配空间。我不确定你要提供什么来提供更具体的建议。

答案 1 :(得分:1)

scanf()通常是一个很糟糕的功能,但是,从评论中收集到的,如果你坚持使用它,下面的代码会做我想你想做的事情,在这里:

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

char ** create_string_array(const size_t num_strings, const size_t maxlen) {
    char ** new_array = malloc(num_strings * sizeof(*new_array));
    if ( new_array == NULL ) {
        perror("Couldn't allocate memory for string array.");
        exit(EXIT_FAILURE);
    }

    for ( size_t i = 0; i < num_strings; ++i ) {
        new_array[i] = malloc(maxlen);
        if ( new_array[i] == NULL ) {
            perror("Couldn't allocate memory for string.");
            exit(EXIT_FAILURE);
        }
    }

    return new_array;
}

void free_string_array(char ** array, const size_t num_strings) {
    for ( size_t i = 0; i < num_strings; ++i ) {
        free(array[i]);
    }
    free(array);
}

char ** readScores(int* actualCount) {

    char ** stringArray = create_string_array(14, 100);

    for (int i = 0; i < 14; ++i) {
        int status = scanf("%s", stringArray[i]);
        if ( status == 0 || status == EOF ) {
            break;
        }
        *actualCount = *actualCount + 1;
        printf("stringArray = %s when i = %d\t actualCount = %d\n",
            stringArray[i], i, *actualCount);
    }
    printf("Finished!\n");

    return stringArray;
}

int main(void) {
    int num_strings = 0;
    char ** stringArray = readScores(&num_strings);

    printf("There were %d strings read. They are:\n", num_strings);

    for ( int i = 0; i < num_strings; ++i ) {
        printf("%2d: %s\n", i + 1, stringArray[i]);
    }

    free_string_array(stringArray, num_strings);

    return EXIT_SUCCESS;
}

并使用合适的数据文件输出:

paul@local:~/src/c/scratch$ cat data_file
Twas
brillig
and
the
slithy
toves
did
gyre
and
gimble
in
the
wabe
paul@local:~/src/c/scratch$ cat data_file | ./strcount
stringArray = Twas when i = 0    actualCount = 1
stringArray = brillig when i = 1     actualCount = 2
stringArray = and when i = 2     actualCount = 3
stringArray = the when i = 3     actualCount = 4
stringArray = slithy when i = 4  actualCount = 5
stringArray = toves when i = 5   actualCount = 6
stringArray = did when i = 6     actualCount = 7
stringArray = gyre when i = 7    actualCount = 8
stringArray = and when i = 8     actualCount = 9
stringArray = gimble when i = 9  actualCount = 10
stringArray = in when i = 10     actualCount = 11
stringArray = the when i = 11    actualCount = 12
stringArray = wabe when i = 12   actualCount = 13
Finished!
There were 13 strings read. They are:
 1: Twas
 2: brillig
 3: and
 4: the
 5: slithy
 6: toves
 7: did
 8: gyre
 9: and
10: gimble
11: in
12: the
13: wabe
paul@local:~/src/c/scratch$ 

Keith已经指出了你所遇到的基本错误,即如果你需要一个动态的字符串数组,那么你需要malloc()内存来获得指向char *的指针数组,然后每个一个,malloc()内存用于字符串本身,原始代码不会执行此操作,您需要检查scanf()0EOF的回复。

答案 2 :(得分:0)

您可以使用while循环替换for循环。

while (fgets(buffer, buffer_size, fp)) {
    // do something with buffer
}
if (ferror(fp)) {
    // handle the error, usually exit or return
} else {
    // continue execution
}

答案 3 :(得分:0)

char* readScores(int* actualCount) {
    char* stringArray = (char*)malloc(100*sizeof(char));
    int i=0, len;
    while(scanf("%s%n%*c", &stringArray[i], &len)==1){
        printf("stringArray = %s when i = %d\t actualCount = %d\n", &stringArray[i], i, ++*actualCount);
        i += len + 1;
    }
    printf("Finished!");

    return stringArray;
}

答案 4 :(得分:-1)

您提供的代码没有问题。我自己和Windows上的MSVC都没有遇到任何麻烦。这是它的样子:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

int main( )
{
    FILE * asd;
    char* stringArray = calloc( 100, sizeof(char) );
    int actualCount = 0;

    freopen_s( &asd, "wsx.txt", "w+", stdin );

    fprintf_s( stdin, "this is a test this is only a test this also is a test" );
    rewind( stdin );

    for ( int i = 0; i <= 13; i++ ) {
        actualCount = actualCount + 1;
        scanf_s( "%s", &stringArray[i], 100 - i );
        printf_s( "stringArray = %s when i = %d\t actualCount = %d\n", &stringArray[i], i, actualCount );
    }
    printf( "Finished!" );

    Sleep( 5000 );
    return 0;
}

输出正如您所期望的那样,没有错误......所以我的答案是您遇到的问题是由于您编写的代码以外的其他原因。