我有一个小的示例程序来说明下面的问题:我有一份简单的文本文件,其中有三个单词(每个单词在一行中),fscanf读取这些单词,将其分配给一个临时变量,然后传输到一个字符串数组。然而,这些值似乎并没有转移到数组中此外,当我在while循环中从第二个printf中删除注释//时,我会得到一个seg错误
我对C还很陌生,所以直到现在才学习这些函数的用法!提前感谢您的帮助!
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[])
{
char* words[15];
char tmp[45];
int i = 0;
FILE* fp = fopen("small", "r");
while (fscanf(fp, "%s", tmp) == 1)
{
printf("%sn", tmp);
words[i] = tmp;
i++;
//printf("%s ", words[i]);
}
printf("n");
printf("Words 0 = %sn", words[0]);
printf("Words 2 = %sn", words[1]);
printf("Words 3 = %sn", words[2]);
fclose(fp);
}
输出
pears
apples
zipper
Words 0 = zipper
Words 2 = zipper
Words 3 = zipper
在您的代码中,words[i] = tmp;
不是将每个输入存储到words
数组的方法。它只将tmp
数组的基地址存储到每个words[i]
和更高版本中,在打印时,它实际上在每次迭代中打印tmp
的最新内容。
如果要将tmp
数组的内容获取到每个words[i]
中,则需要使用
- 为每个
words[i]
分配内存并使用strcpy()
- 使用
strdup()
并将其分配给words[i]
在任何一种情况下,您都必须在退出前free()
分配的内存。
我过去也遇到过同样的问题。
问题是,当您从文件中读取时,单词会保存在缓冲区中,然后将其存储到变量temp中
问题是,当你读下一个单词时,缓冲区的内容会发生变化。这也影响了之前的通话!
所以你读"梨",你打印"梨"和单词[0]="梨"
然后你读"苹果",你打印苹果和单词[1]="苹果"。还有单词[0]="苹果"现在!!
等等…
您需要做的是在读取文件之前,使用malloc为每个单词[i]分配内存,并使其等于"。
例如words[0] = ""
等
然后,当您开始读取文件时,应该使用strcpy()函数来处理temp和word[i]。这将解决你的问题。
我试着尽可能简单地回答这个问题,因为在过去,这个问题困扰着我,让我很困惑。
代码的第一个重要问题是这行
char* words[15];
它为您提供了一个由15个字符指针组成的数组(char*
)。这是而不是与15个字符串的数组相同。没有用于存储字符串的内存。
要获得存储字符串的内存,可以执行以下操作:
char words[15][45];
// ^ ^^
// no * memory for each of the 15 strings
现在您有15个字符串的内存。每个字符串最多可以有44个字符。
通过此更改,您不需要tmp
变量,只需直接读取words
即可。类似于:
#include <stdio.h>
#include <string.h>
int main (int argc, char* argv[])
{
char words[15][45];
int i = 0;
FILE* fp = fopen("small", "r");
if (!fp)
{
printf("no such filen");
return 0;
}
while ((i < 15) && (fscanf(fp, "%44s", words[i]) == 1))
{ // ^^^^^^^^ is the same as &words[i][0]
i++;
}
printf("n");
int t;
for (t = 0; t < i; ++t)
{
printf("Words %d = %sn", t, words[t]);
}
fclose(fp);
return 0;
}
添加了其他一些重要更改:
1) fopen
之后,必须检查空
2) 对于%s的扫描,总是给出最大大小(即%44s),因此不会出现缓冲区溢出
3) 确保在读取15个字符串时停止while
(以防止缓冲区溢出)
4) 只打印在中读取的字符串数量
最后,我在main
的末尾添加了return 0