为什么我不断得到0我的C代码无法输入开关

时间:2018-10-18 12:57:05

标签: c scanf

编写一个C程序,计算4个整数的最大值,最小值,总和和平均值。

这 程序以十进制,十六进制或八进制格式读取4个整数,并指定一个字符 从命令提示符处进行数学运算(x表示最大值,m表示最小值,s表示总和,a表示平均值) (在Ubuntu上为xterminal)并输出操作结果。

输入/输出格式详细信息为 在下面提供。

对于x,m和s操作,结果应打印为整数;但作为浮点数 平均(a)操作。

整数输出将以十六进制格式打印,而浮动 点值将以科学格式打印。 输入:

<number 1>[space] <number 2>[space] <number 3>[space] <number 4>[space] <operation>

样本输入1:0xFF 99077 0 s,预期输出1:0x1a1

样本输入2:0x10 10 10 010 a,预期输出2:1.100000e + 01

样品输入3:0770 0xFF 270 0xAB m,预期输出3:0xab

样本输入4:010 0x10 10 0x3 x,预期输出4:0x10

这是我编写的代码

#include <stdio.h>

int main() {
  int num1, num2, num3, num4;
  char op;

  scanf("%d%d%d%d%c", &num1, &num2, &num3, &num4, &op);

  switch (op)
  {
  case'x':
    if (num1 > num2&&num1 > num3&&num1 > num4)
      printf("%d", num1);
    else if (num2 > num1&&num2 > num3&&num2 > num4)
      printf("%d", num2);
    else if (num3 > num1&&num3 > num1&&num3 > num4)
      printf("%d", num3);
    else
      printf("%d", num4);
    break;
  case'm':
    if (num1 < num2&&num1 < num3&&num1 < num4)
      printf("%d", num1);
    else if (num2 < num1&&num2 < num3&&num2 < num4)
      printf("%d", num2);
    else if (num3 < num1&&num3 < num1&&num3 < num4)
      printf("%d", num3);
    else
      printf("%d", num4);
    break;
  case's':
    printf("%d", num1 + num2 + num3 + num4);
    break;
  case'a':
    printf(" %f", (num1 + num2 + num3 + num4) / 4);
    break;
  }

  return 0;
}

3 个答案:

答案 0 :(得分:3)

您需要在%d之间添加空格。此处很好地说明了为什么需要space的原因。这样代码就会变成

scanf("%d %d %d %d %c",&num1,&num2,&num3,&num4,&op);

要以十六进制格式打印,您需要使用“%x”表示。

printf("%x",num1);

要以科学格式打印,请使用“%.10e”

printf("%.10e",num1);

另一件事,为了得到一个除法浮点数,并且每个数字都是整数,您需要至少使分子或分母成为浮点。 就您而言,

printf("%.10e"(num1+num2+num3+num4)/4.0);

答案 1 :(得分:0)

printf("0x%2x", op);之后添加scanf()会导致0x20被打印出来。

0x20是空格字符的十六进制值,因此证实了我们的怀疑,即正在读取空格字符而不是所需的运算符。

scanf()替换%d%d%d%d%c%d%d%d%d %c)中的格式字符串会导致该方法正常工作,因为空格字符现在在运算符之前已被忽略。

输入:1 2 3 4 x

输出:4

答案 2 :(得分:0)

正如Tau和Toby所指出的那样,您在%c调用中的scanf()转换说明符将读取最后一个数字和运算符之间的第一个空白字符。

%c是转换运算符中的一种特殊情况:大多数其他转换默认情况下会跳过空格,直到它们遇到非空格字符为止。对于具有换行符的用户输入或具有不同列间空白量的列表文本数据,这是有意义的:您想读取下一个数字或单词,而对空格不感兴趣。

相比之下,

%c仅读取下一个字符,包括空格等;这对自己动手分析很有用。

有两种简单的方法可以解决此问题。

  • 侵入性较小的一种是在%cscanf("%d%d%d%d %c", &num1, &num2, &num3, &num4, &op);之前添加一些空间。单个空格是格式字符串中的“指令”,指示scanf跳过全部空格,直到找到非空格字符为止。 (有关规范的带注释的引用,请参见下文。)程序中的其他所有内容都无需更改。

  • 您还可以使用%s读取字符串并检查其第一个字符。 %s用于读取下一个单词,因此会自动跳过空格。但是,您需要注意太长的用户输入:它既不会溢出您正在使用的缓冲区,也不能留在输入中并混淆以后的scanf。我们将字符串长度限制为1,但要提供2个字符的空格,因为scanf将以空字符终止字符串。我们将忽略由于程序终止而无法读取的输入。示例:

    // ...
    char op[2] = {'\0', '\0'}; // space for the `'\0'`
    // Read a string of length 1 (just a single char, in effect)
    int numScanned = scanf("%d%d%d%d%1s", &num1, &num2, &num3, &num4, op);
    switch (op[0]) // switch on first char in the array
    {
      case'x':
      // ...
    }
    


一些评论:

num3 > num1&&num3 > num1&&num3 > num4)和另一个逻辑表达式具有两个冗余项(num3 > num1)。

在具有较低优先级的操作数和运算符之间插入空格也将提高可读性,例如:

num3 > num1 && num3 > num4)

有些人即使在多余的子表达式上都加上了括号,但我不是那个朋友。

最后一个printf中最后一个浮点格式转换是错误的,因为参数表达式的类型为int;也许您想将一个整数转换为浮点数?这将导致所有int被提升为浮点并产生浮点结果:

printf(" %f", ((float)num1 + num2 + num3 + num4) / 4);

请注意,转换完整结果还不够:您仍将执行整数除法,将其舍入为较低的整数,然后将该整数转换为无意义的浮点数。


来自the latest ISO C standard draft, 7.21.6.2的关于scanf的引号(在方括号中带有一些格式和说明):

  

格式由零个或多个指令组成:

     
      
  • 一个或多个空格字符;
  •   
  • 一个普通的多字节字符(既不是%也不是空格字符)
  •   
  • 或转换说明(如%d)。
  •   

因此格式字符串中的空格字符(例如,我建议的%cscanf("%d%d%d%d %c", ...前面的空格)是伪指令,例如%d ...做什么?

  

由空格字符组成的指令通过读取输入直到第一个非空格字符(仍未读取)[...]来执行。

嗯,好的:它将跳过空格,并使下一个字符可用,这正是我们所需要的。 :-)。