[英]How to use fscanf() for two strings (of ANY length) and dynamically allocate/de-allocate the memory properly
我需要读取一个 input.txt 文件并从文件中的每一行打印出两个单独的字符串。 我使用了一个 while 循环和一个 fscanf function 来获取每个字符串并忽略它们之间的空格。 如果输入文件的一行中的字符串太长,则会出现分段错误。 但是,当我运行我的可执行文件时,我也会收到一个munmap_chunk(): invalid pointer错误。
如果我没有为 string1 和 string2 分配 memory,fscanf 不能正常工作。 我相信 fscanf 正在更改指向 string1 和 string2 的指针,这导致了 munmap_chunk() 错误。 但是,我需要取消分配我给 string1 和 string2 的 memory 所以我没有 memory 泄漏。
如何扫描此文件中的字符串(任意长度)并正确取消分配 memory?
int main(int argc, char *argv[])
{
char *string1;
char *string2;
string1 = (char *)malloc(sizeof(string1)); //these strings need memory allocated for the fscanf to function properly
string2 = (char *)malloc(sizeof(string2));
FILE* file = fopen(argv[1], "r");
while (fscanf(file, "%s %s", string1, string2) != EOF)
{
printf("%s %s\n", string1, string2);
}
fclose(file);
//Deallocating memory
free(string1);
free(string2);
return 0;
}
'fscanf' 不会更改指针,但如果您没有为输入分配足够的空间,它可能会损坏 memory。
而且您没有正确分配 memory: string1
和string2
是指针,因此您分配的只是指针的大小(取决于您的系统,4 或 8 个字节)。
如果您需要从文件中读取一行并且事先不知道该行的最大长度,则不能使用fscanf
。
您需要分配一个起始缓冲区,例如:
string1 = malloc(512 * sizeof(char));
512 是一个任意但相当大的线长度。 然后,您使用fread
在循环中一次读取一个字节,并检查行尾(通常是 '\n')。
您还必须计算您阅读了多少,如果该行超过 512 字节,请使用realloc
来增加缓冲区的大小,如下所示:
if (bytesRead == (string1Size - 1) && curByte != '\n') {
string1Size += 512;
string1 = realloc(string1, string1Size);
}
这里, bytesRead
是一个int
变量,用于计算到目前为止您成功读取了多少字节,而string1Size
也是用于跟踪string1
缓冲区大小的int
变量。
string1 = (char *)malloc(sizeof(string1));
只为 4 或 8 个字符分配 memory 因为 string1 是一个char *
,这就是指针的大小。
要为 memory 分配 100 个字符,您需要执行char *string1 = malloc(sizeof(char) * 100)
。
如何扫描此文件中的字符串(任意长度)并正确取消分配 memory?
您不能使用fscanf
,因为它将读取输入与解析输入混合在一起。 在解析之前,您不知道将要读取什么。
相反,将该行读入一个可以检查的大缓冲区。 一旦你知道碎片有多大,你就可以分配适量的 memory 并复制到它。
因为我们正在重用行缓冲区,并在完成后将其丢弃,所以我们可以将其设置为我们认为需要的大小。 1024 或 4096 通常是不错的选择。 我喜欢BUFSIZ 。
char line[BUFSIZ];
while( fgets(line, sizeof(line), file) ) {
// now parse line
}
解析可以通过多种方式完成。 一个简单的就是strtok
(STRing TOKenize)。 这将线标记到位。 使用strdup
将它们复制到适量的 memory 中。
char line[BUFSIZ];
while( fgets(line, sizeof(line), file) ) {
char words[2];
int i = 0;
for(
char *word = strtok(line, " ");
word;
word = strtok(NULL, " ")
) {
words[i] = strdup(word);
i++;
}
printf("%s %s", words[0], words[1]);
free(words[0]);
free(words[1]);
}
line
和words
在堆栈上分配,它们将被自动释放。 但是strdup分配的memory在堆上,需要释放。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.