【问题标题】:Logical issue with printf and scanfprintf 和 scanf 的逻辑问题
【发布时间】:2017-11-26 12:20:16
【问题描述】:

我正在修改我的基本 C 以准备即将到来的测验,当时我正在编写一个函数来简单地获取字符输入并将其存储到结构中并再次打印出来。编译没有任何问题,但我一直遇到逻辑问题。我该如何解决这个问题?

#include <stdio.h>

struct player
{
    char letter;
    int age;
    double avg;
};

int main()
{
    struct player P1;
    char name;
    int age;
    double avg;
    printf("Enter age: ");
    scanf("%d", &age);
    printf("Enter avg: ");
    scanf("%lf", &avg);
    printf("Enter name: ");
    scanf("%s", &name);

    P1.letter= name;
    P1.avg = avg;
    P1.age = age;
    printf("\n Age is: %d \n", P1.age); 
    printf("Avg is: %lf", P1.avg);
    printf(" \n Name is: %c \n", P1.letter);
    return 0;
}

如果我为 int 输入“1”,输出将是“年龄为:0”

【问题讨论】:

  • scanf("%s", &amp;name); => scanf("%c", &amp;name);
  • scanf("%s", &amp;name); - 你应该read the requirementsof the %s format specifier.。您没有提供足够的空间来读取名称字符串。
  • 好旧的缓冲区溢出!永远不要写入长度未知的 C 字符串。从不。
  • 请查看scanf的返回值
  • 使用 fgets 从键盘读取,使用 sscanf 从读取字符串中提取

标签: c struct printf scanf


【解决方案1】:

两个快速建议:

1) 除非您确定 name 缓冲区将仅由短名称填充(9 个或更少字符),否则请为缓冲区选择更合理的大小,例如:

char name[100]; 

这还需要延长结构中的成员letter

2) 当使用scanf() 读取变量时,被读取变量的地址 作为第二个参数传递。对于 int a;float b; 等变量,您必须使用 address of 运算符:&amp; 作为变量的前缀。但是因为C字符串的变量名指向数组中的第一个字符,它已经是那个变量的地址了。因此,在将 C 字符串读入 scanf() 函数时,您不需要显式的 &amp; 运算符。函数的返回值也应该用来判断调用是否成功。如图所示更改以下行:

scanf("%s", &name);
int count = scanf("%s",  name);//note: use return value of function
//  remove &            ^
if(count < 0)
{
    //handle error
}

【讨论】:

    【解决方案2】:

    您正在使用字符数据类型输入字符串“字符名称”,这会导致您出现未定义的行为。

    而不是声明一个像“char name[10]”这样的字符数组,然后读取名称。但是在分配时,您必须注意不能直接分配,您必须像这样使用 strcpy

    strcpy(p1.letter,name)(这里的字母也是字符数组)

    【讨论】:

      【解决方案3】:

      您正在尝试获取姓名、年龄和平均值。的播放器。所以要存储 name ,你应该声明一个数组而不是一个字符。并将名称分配给结构变量使用 strcpy()。(直接分配不起作用)。或者,如果你只取一个字符作为名字,那么像这样写 scanf:

      scanf("%c", &name);
      

      检查下面的代码,它会帮助你,

      #include <stdio.h>
      
      struct player
      {
          char letter[10];
          int age;
          double avg;
      };
      
      int main()
      {
          struct player P1;
          char name[10];
          int age;
          double avg;
          printf("Enter age: ");
          scanf("%d", &age);
          printf("Enter avg: ");
          scanf("%lf", &avg);
          printf("Enter name: ");
          scanf("%s", &name);
      
          strcpy(P1.letter,name);
          P1.avg = avg;
          P1.age = age;
          printf("\n Age is: %d \n", P1.age);
          printf("Avg is: %lf", P1.avg);
          printf(" \n Name is: %s \n", P1.letter);
          return 0;
      }
      

      【讨论】:

      • 请不要在答案中显示缓冲区溢出代码。 %s 需要一个字段宽度,在这种情况下为 %9s —— 为什么有这样一个 tiny 缓冲区?
      • 你有没有运行过这段代码..??它对我有用。检查说明,如果您想要播放器的商店名称,那么您需要字符数组而不是单个字符。
      • 输入 christopher-montgomery-joseph 作为名称,看看会发生什么。 scanf("%s", ...)总是是缓冲区溢出。永远不要这样写。
      • 哦,你的代码中的name 已经被评估为一个指针,所以&amp;name 是错误的。
      • 所以?将其增加到 1 MiB,然后输入更长的内容……没关系,这是损坏的代码
      猜你喜欢
      • 2015-01-30
      • 1970-01-01
      • 2019-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多