C - 3rd scanf修改第二个scanf的变量

时间:2013-09-16 15:25:05

标签: c printf scanf

我想我已经尝试了任何东西(刷新stdin,scanf来消费换行等),但没有任何效果,正如我所希望的那样。出于某种原因,第3次扫描会在以下代码中修改第2次扫描的变量:

#include <stdio.h>

int main()
{
  char first_name[16], last_name[21];
  char filename[11];
  FILE *opening;

  printf("The program saves your first and last name into a file.\n");

  printf("Enter your first name:");
  scanf("%s", first_name);
  getchar();

  printf("Enter your last name:");
  scanf(" %s", last_name);
  getchar();

  printf("File where you want to save your name:");
  scanf(" %s", filename);

  opening = fopen(filename, "wb");

  fprintf(opening, "%s %s", first_name, last_name);
  printf("\nSuccessfully saved the data!");

  fclose(opening);

  return 0;
}

输出:

The program saves your first and last name into a file.
Enter your first name: John
Enter your last name: Doe
File where you want to save your name: filename.txt

Successfully saved the data!

除了filename.txt的内容是这样的所有细节和花花公子:

  

John t

我猜测't'字符来自某个'txt',但我刚开始学习C而且我不知道如何解决这段代码。请问大师能帮帮我吗?

3 个答案:

答案 0 :(得分:1)

您的filename缓冲区太小。

你写了filename.txt,这是12个字符,加上零来完成它,得到13.你只分配11.试试这样:

char filename[20];

它应该有效。

使用scanf时要小心,它会导致非常讨厌的问题,就像你现在遇到的那样。它非常适合实验和学习C,因为它向您展示了正确的内存处理是多么重要。对于任何实际项目,您应该考虑使用不同的功能或框架。

答案 1 :(得分:0)

如果您输入filename.txt作为文件名,那么您将超出filename的缓冲区。那是未定义的行为,是造成奇怪结果的原因。

要修复,请使char filename[11];更大,记住为NULL终止符允许1个额外字符。在您的特定情况下,char filename[14];允许在%s来电中scanf之前存在错误空格。

否则,一切看起来都很好。

答案 2 :(得分:0)

在字符串上使用scanf()是危险的,因为它可以在缓冲区提供内存的更多数据中读取

如果在字符串中扫描,则应通过将此数字添加到传递给scanf()的格式,告诉scanf()要读取多少字符:

char file_name[11];

...

scanf("%10s", file_name); /* As file_name provides memor for 11 characters, read a
                             maximum of 10 characters into file_name leaving 1 
                             character room for the necessary `0-`terminator indicating 
                             the end of the "string". */

此外,您的代码错过了fopen系统调用的错误检查。

最好做这样的事情:

opening = fopen(filename, "wb");
if (NULL == opening)
{
  perror("fopen() failed");
  exit(EXIT_FAILURE);
}