【问题标题】:Getting an output with %s but %c is returning garbage value使用 %s 获取输出但 %c 返回垃圾值
【发布时间】:2018-04-28 15:47:44
【问题描述】:

我想接受学生的详细信息(姓名、卷号和分数)并打印与输出相同的内容。如果我接受姓名作为字符串,程序运行良好,但当我接受学生姓名时会遇到问题作为一个角色。 代码如下:

#include<stdio.h>
int main()
{
    struct student 
    {
        char name;
        int rn;
        float marks;
    };
    struct student s[2];
    int i;
    printf("Enter student's name,roll no. and marks:\n");
    for(i=1;i<=2;i++)
    {
        printf("%d ",i);
        scanf("%c %d %f",&s[i].name,&s[i].rn,&s[i].marks);
    }
    printf("Student's name,roll no. and marks are:\n");
    for(i=1;i<=2;i++)
    printf("\nname=%c\trn=%d\tmarks=%0.2f\n\n",s[i].name,s[i].rn,s[i].marks);
}

学生 1 的信息完全正确。但学生 2 的输出存在问题。我只想知道学生 2 的实际情况。

【问题讨论】:

  • 您已将字段描述符%c 与数据类型char 正确匹配,但char 似乎是数据类型的错误选择。它代表 one 字符,而对于名称,您可能需要一个足够长的 char 数组以容纳您的最大长度名称。切换到 char 数组后,您还需要使用字段描述符 %s
  • 索引从 0 而不是 1 开始。
  • @JohnBollinger 是的,我明白,但我想使用单个字符作为名称。那该怎么做?
  • @WebKing 正如其他人提到的,首先从0开始索引i并在%c之前给出空格。
  • 非常感谢@achal 和 user3121023。实际上 %c 正在考虑将下一行视为一个字符。当我在 scanf 中的 %c 之前给一个空格时,问题得到了解决。

标签: c arrays character structure


【解决方案1】:

改变这个:

for(i=1;i<=2;i++)

到这里:

for(i=0; i < 2; i++)

因为索引从 0 开始到数组的大小减去 1。

【讨论】:

    【解决方案2】:

    当我接受学生姓名作为字符时遇到问题? 那是因为 scanf() 是行缓冲的,即当您输入 一个字符 然后按 >ENTER 键,这也是一个有效的字符,因此您将提供两个字符作为输入。为避免此缓冲问题,请在 %c 之前添加空格。例如

    for(i = 0;i < 2;i++) { /* also you had s[2] means, you should start from  i = 0  */ 
            scanf(" %c%d%f",&s[i].name,&s[i].rn,&s[i].marks);
    }
    

    主要问题是for(i=1;i&lt;=2;i++),因为您从s[1] 开始并希望存储到s[2],但没有您声明的s[2] struct student s[2]; 表示s[0] & s[1],解决方案从i = 0开始。

    【讨论】:

      【解决方案3】:

      Struct 是一种值类型,它在堆栈上保存单个内存块。所以 1 个字符包含(取决于系统)1 个字符,如“M”。为了保留名称,您需要一个指针或字符数组。这样,您只存储 1 个字符,之后会发生一些随机内存垃圾,因为您引用的值越界,在本例中仅为 1 个字符。

      【讨论】:

      • 那么为什么在学生 1 的情况下不会出现这种内存垃圾?
      • 您正在应用 & 运算符,它是一个地址运算符。简而言之,它将创建一个指向内存位置的指针,并且您在写入学生姓名时正在引用该位置。这是在堆栈上 - 指向 char 起始地址的指针。那是完全不同的。在第一种情况下,您指的是内存位置而不是值本身。从 scanf 函数的角度来看,这会导致 char 被视为 char* 。希望对您有所帮助。