【问题标题】:The practical difference of %c vs %s%c 与 %s 的实际区别
【发布时间】:2017-03-16 16:46:00
【问题描述】:

我需要做一份海鲜菜单作为我大学的作业。我将在这里提供相关代码:

 int main ()
{
int a,d;
float c ;
char b,s,S,m,M,l,L;

printf ("\n\t\t\t\tSeafood Menu\n");
printf ("----------------------------------------------------------------------------------\n");
printf ("\t\t\t\t\t\t      Dish Size\n");
printf ("Item Number\t Seafood Dish\t      Small\t       Medium      Large\t\n");
printf ("----------------------------------------------------------------------------------\n");
printf ("\t 1\t Fried   \t20.00 \t\t 40.00 \t\t 55.00\n");
    //Continue with a bunch of menu here

    printf ("   Enter item number            :");
    scanf ("%d",&a);
    printf ("   Enter dish size (S/M/L) :");
    scanf ("%s",&b);


        if ((a==1)&&((b=='s')||(b=='S')))
        {c=20.00;}
        //continue with a bunch of condition to choose the price per dish stated in the menu


    printf ("   Enter dish quantity     :");
    scanf ("%d",&d);
    printf ("   Price per dish size     :RM%.2f\n\n\n",c);


return 0;    
}

当我尝试将其中的格式标识符更改为 %c 时,它只是停止接受该特定 scanf 的输入。

printf ("Enter dish size (S/M/L):");
scanf ("%s",b);

我想附上图片,但似乎不允许我这样做,所以会留下两个链接:

Normal, using %s:abnormal, using %c

我很好奇为什么当我使用%c%s 有效时它不起作用?因为我输入的只是字符。请赐教。

【问题讨论】:

  • 两种变体都会调用未定义的行为。请阅读scanf 的文档以及关于字符和字符数组 的区别。一个 C 字符串。
  • %c%s 的行为应该在您方便的 C 参考手册中清楚地说明。如果您没有方便的 C 参考手册,我推荐 Harbison & Steele 的 C: A Reference Manual%c 从输入流中读取 single 字符并将其存储到单个 char 对象中。 %s 从输入流中读取 sequence 字符值,直到它看到空格或 EOF 并将它们作为 0 结尾的字符串存储到 chararray 中。

标签: c arrays char scanf format-specifiers


【解决方案1】:

我很好奇为什么当我使用 %c 而 %s 有效时它不起作用?

好吧,你猜怎么着,它没有用,即使它看起来是。

如手册页所述,对于scanf(),参数的类型为

  • %c 需要一个指向 char 的指针
  • %s 需要一个指向 char 数组的初始元素的指针。

引用C11,第 7.21.6.2 章,(强调我的

c 匹配字段指定数字的字符序列 width (如果指令中没有字段宽度,则为 1).

如果不存在l 长度修饰符,则相应的参数应为 指向足够大的字符数组的初始元素的指针,以接受 顺序。不添加空字符。

s 匹配一系列非空白字符。

如果不存在l 长度修饰符,则相应的参数应为 指向一个字符数组的初始元素的指针,它足够大,可以接受 序列和一个终止的空字符,它将自动添加。

在你的情况下,

  • 提供%s 是错误的,因为单个char 是一个太短的元素,无法扫描和保存一个数组,即以空值结尾。这会导致undefined behavior 发生内存溢出。

  • %c 应该有 "worked" ,如果输入流没有从之前的 ENTER 按键存储的newline。如果您清除所有待处理输入的输入流,您会发现它有效。使用类似的东西

    scanf(" %c", &b);   //the whitespace "eats up" all the previous whitespaces
    

    您可以查看我的this previous answer,以获取相同的详细信息。

【讨论】:

  • “指向char 数组的指针”具有误导性,因为%s 仍然需要指向char 的指针,而不是指向char 数组的指针。我系统上的手册页说,“指向字符数组的初始元素的指针”
  • @Dmitri 花时间添加相关的报价,希望这不再是误导。谢谢。 :)
  • @SouravGhosh 谢谢你的解释。这帮助我解决了我的问题。
猜你喜欢
  • 2020-02-13
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 2014-02-14
  • 2016-02-10
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
相关资源
最近更新 更多