C读取由具有无界字大小的空格分隔的文本文件

时间:2015-01-31 17:11:38

标签: c file text

我有一个文本文件,其中包含以空格分隔的单词(字符串)。字符串的大小不受限制,字数也不限。 我需要做的是将文件中的所有单词放在一个列表中。 (假设列表工作正常)。 我无法弄清楚如何克服无限大小的字大小问题。我试过这个:

FILE* f1;
f1 = fopen("file1.txt", "rt");
int a = 1;

char c = fgetc(f1);
while (c != ' '){
    c = fgetc(f1);
    a = a + 1;
}
char * word = " ";
fgets(word, a, f1);
printf("%s", word);
fclose(f1);
getchar();

我的文本文件如下所示:

 this is sparta

请注意,我能得到的只是第一个字,即使我做得不正确,因为我收到了错误:

Access violation writing location 0x00B36860.

有人可以帮帮我吗?

2 个答案:

答案 0 :(得分:3)

从上述评论者那里得到建议,只要没有足够的,或者显然足够的,就会重新分配记忆。

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

void fatal(char *msg) {
    printf("%s\n", msg);
    exit (1);
    }

int main() {
    FILE* f1 = NULL;
    char *word = NULL;
    size_t size = 2;
    long fpos = 0;
    char format [32];

    if ((f1 = fopen("file1.txt", "rt")) == NULL)        // open file
        fatal("Failed to open file");
    if ((word = malloc(size)) == NULL)                  // word memory
        fatal("Failed to allocate memory");
    sprintf (format, "%%%us", (unsigned)size-1);        // format for fscanf

    while(fscanf(f1, format, word) == 1) {
        while (strlen(word) >= size-1) {                // is buffer full?
            size *= 2;                                  // double buff size
            printf ("** doubling to %u **\n", (unsigned)size);
            if ((word = realloc(word, size)) == NULL)
                fatal("Failed to reallocate memory");
            sprintf (format, "%%%us", (unsigned)size-1);// new format spec
            fseek(f1, fpos, SEEK_SET);                  // re-read the line
            if (fscanf(f1, format, word) == 0)
                fatal("Failed to re-read file");
        }
        printf ("%s\n", word);
        fpos = ftell(f1);                               // mark file pos
    }

    free(word);
    fclose(f1);
    return(0);
}

节目输入

this   is  sparta
help 30000000000000000000000000000000000000000
me

节目输出:

** doubling to 4 **
** doubling to 8 **
this
is
sparta
help
** doubling to 16 **
** doubling to 32 **
** doubling to 64 **
30000000000000000000000000000000000000000
me

答案 1 :(得分:2)

你在哪个平台?

如果您使用的是POSIX-ish平台,请考虑使用getline()读取无限大小的行,然后使用strcspn()之一, strpbrk()strtok_r(),或(如果您真的决心让您的代码无法重复使用) strtok()获取单词的边界,最后使用 strdup()创建单词的副本。 strdup()返回的指针将存储在char *通过realloc()管理的数组中。

如果你没有足够的POSIX-ish平台,那么你需要使用fgets()检查是否确实读了整行 - 使用realloc()分配更多空间如果你的初始线不够长。一旦你有了一条线,你就可以像以前一样拆开它。

你可以搞乱POSIX getdelim(),除了它只需要一个分隔符,你可能想要空格和换行符来标记单词的结尾(也可能是标签),它将无法处理。

而且,如果您使用的是足够现代的POSIX系统,您可以考虑使用m修饰符scanf()

char *word = 0;

while (scanf("%ms", &word) == 1)
    …store word in your list…

当它可用时,这甚至更简单。