C读取由空格分隔的文本文件,字长无限制
C reading a text file separated by spaces with unbounded word size
我有一个文本文件,其中包含以空格分隔的单词(字符串)。字符串的大小没有限制,字数也没有限制。
我需要做的是将文件中的所有单词放入列表中。 (假设列表工作正常)。
我无法弄清楚如何克服无限字长问题。我试过这个:
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.
有人可以帮我吗?
你在哪个平台?
如果您使用的是 POSIX-ish 平台,请考虑使用 getline()
to read lines of unbounded size, then one of strcspn()
,
strpbrk()
,
strtok_r()
,或者(如果你真的下定决心让你的代码不可重用)
strtok()
得到单词的边界,最后使用
strdup()
创建副本的话。 strdup()
返回的指针将存储在通过 realloc()
.
管理的 char *
数组中
如果你的平台不够POSIX,那么你需要使用fgets()
来检查你是否真的阅读了整行——使用realloc()
分配更多 space 如果您的初始行不够长。一旦你有了一条线,你就可以像以前一样把它分开。
你可以乱用 POSIX getdelim()
除了它只需要一个分隔符而且你可能想要 spaces 和换行符来标记单词的结尾(也可能是制表符) ),它不会处理。
而且,如果您使用的是足够现代的 POSIX 系统,您可以考虑使用 m
修饰符来 scanf()
:
char *word = 0;
while (scanf("%ms", &word) == 1)
…store word in your list…
有了这个就更简单了。
采纳上述评论者的建议,只要内存不足或显然刚好足够,就会重新分配内存。
#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
我有一个文本文件,其中包含以空格分隔的单词(字符串)。字符串的大小没有限制,字数也没有限制。 我需要做的是将文件中的所有单词放入列表中。 (假设列表工作正常)。 我无法弄清楚如何克服无限字长问题。我试过这个:
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.
有人可以帮我吗?
你在哪个平台?
如果您使用的是 POSIX-ish 平台,请考虑使用 getline()
to read lines of unbounded size, then one of strcspn()
,
strpbrk()
,
strtok_r()
,或者(如果你真的下定决心让你的代码不可重用)
strtok()
得到单词的边界,最后使用
strdup()
创建副本的话。 strdup()
返回的指针将存储在通过 realloc()
.
char *
数组中
如果你的平台不够POSIX,那么你需要使用fgets()
来检查你是否真的阅读了整行——使用realloc()
分配更多 space 如果您的初始行不够长。一旦你有了一条线,你就可以像以前一样把它分开。
你可以乱用 POSIX getdelim()
除了它只需要一个分隔符而且你可能想要 spaces 和换行符来标记单词的结尾(也可能是制表符) ),它不会处理。
而且,如果您使用的是足够现代的 POSIX 系统,您可以考虑使用 m
修饰符来 scanf()
:
char *word = 0;
while (scanf("%ms", &word) == 1)
…store word in your list…
有了这个就更简单了。
采纳上述评论者的建议,只要内存不足或显然刚好足够,就会重新分配内存。
#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