我不习惯用c编程,所以我想知道如何拥有一个数组,然后在一个文件中读取可变数量的变量,以及数组中的这些文件。
//how do I declare an array whose sizes varies
do {
char buffer[1000];
fscanf(file, %[^\n]\n", buffer);
//how do i add buffer to array
}while(!feof(file));
我不习惯用c编程,所以我想知道如何拥有一个数组,然后在一个文件中读取可变数量的变量,以及数组中的这些文件。
//how do I declare an array whose sizes varies
do {
char buffer[1000];
fscanf(file, %[^\n]\n", buffer);
//how do i add buffer to array
}while(!feof(file));
int nlines = 0
char **lines = NULL; /* Array of resulting lines */
int curline = 0;
char buffer[BUFSIZ]; /* Just alloocate this once, not each time through the loop */
do {
if (fgets(buffer, sizeof buffer, file)) { /* fgets() is the easy way to read a line */
if (curline >= nlines) { /* Have we filled up the result array? */
nlines += 1000; /* Increase size by 1,000 */
lines = realloc(lines, nlines*sizeof(*lines); /* And grow the array */
}
lines[curline] = strdup(buffer); /* Make a copy of the input line and add it to the array */
curline++;
}
}while(!feof(file));
数组在 C 中总是固定大小的。你不能改变它们的大小。您可以做的是预先估计您需要多少空间并动态分配该空间(使用malloc()
)。如果你碰巧用完了空间,你重新分配。请参阅相关文档realloc()
。基本上,你这样做:
buffer = realloc(size);
新大小可以比以前更大或更小(这意味着您可以“扩大”或“缩小”数组。)因此,如果一开始您想要 5000 个字符的空间,您可以:
char* buffer = malloc(5000);
如果稍后您用完了空间并想要额外的 2000 个字符(因此新大小将是 7000),您可以这样做:
buffer = realloc(7000);
已经存在的内容buffer
被保留。请注意,realloc()
可能无法真正增长内存块,因此它可能首先分配一个全新的块,然后将旧内存的内容复制到新块,然后释放旧内存。这意味着如果您将buffer
指针的副本存储在其他地方,它将指向不再存在的旧内存块。例如:
char* ptr = buffer;
buffer = realloc(7000);
那时,ptr
仅当 时有效ptr == buffer
,但不能保证是这种情况。
字符串数据位于数组条目中的数组通常不是最佳选择。如果完整的数据集可以舒适地放入内存并且条目数量有合理的上限,那么指针数组是一种选择。
但首先,避免没有明确长度的 scanf %s 和 %[] 格式。使用您的示例缓冲区大小 1000,您可以读取的最大字符串长度为 999,因此:
/* Some needed data */
int n;
struct ptrarray_t
{
char **strings;
int nalloc; /* number of string pointers allocated */
int nused; /* number of string pointers used */
} pa_hdr; /* presume this was initialized previously */
...
n = fscanf(file, "%999[\n]", buffer);
if (n!=1 || getc(file)!='\n')
{
there's a problem
}
/* Now add a string to the array */
if (pa_hdr.nused < pa_hdr.nalloc)
{
int len = strlen(buffer);
char *cp = malloc(len+1);
strcpy(cp, buffer);
pa_hdr.strings[pa_hdr.nused++] = cp;
}
此后对任何字符串的引用都只是 pa_hdr.strings[i],一个体面的设计将使用函数调用或宏来管理标头,而标头又将位于头文件中而不是内联。完成数组后,您将需要一个删除函数来释放所有这些 malloc()ed 指针。
如果有大量的小字符串, malloc() 在时间和空间开销上都可能很昂贵。您可以在较大的块中管理字符串池,这些块将很好地适应主机操作系统的内存分配和分页。使用一组函数有效地从这个字符串数组中创建一个对象将有助于您的开发。如上所述,您可以选择一个简单的策略,然后再优化实施。
您似乎正在尝试阅读,直到您阅读换行符。
最简单的方法是通过getline。
char *buffer = NULL;
int buffer_len;
int ret = getline(&buffer, &buffer_len, file);
...这将从文件中读取一行文本file
(除非ret
is -1
,其中有错误或者您位于文件末尾)。