为什么scanf会让我的switch语句变得怪异?

时间:2014-07-30 10:17:35

标签: c string scanf

如果我从scanf()声明中拨打case,我似乎无法弄清楚为什么我的程序无效。

在我致电scanf()之前,一切正常。它是一个非常小的基于控制台的菜单。它读取刚刚输入的字符串并相应地下移菜单。一切正常,直到我在一个它应该响应的整数中尝试scanf()

我首先想到返回一个值会破坏Switch语句......然后这不起作用所以我放了break个语句以防万一。但它仍然无法奏效。一旦scanf()未被评论,整个序列就会搞砸了。

void main(void) {
  char MenuS;
  MenuS = 's';
  while (MenuS != 'q') {
    MenuS = Menu();
  }
}

char Menu() {
  unsigned char Menu;
  unsigned char UserInput[9];
  unsigned int Offset;
  Offset = 0;
  printf("\nEnt:");
  gets(UserInput);
  trim(UserInput);

  if (UserInput[0] != 'q') {
    switch (UserInput[0]) {
    case 'r':
      scanf("%d", &Offset);
      printf("\nIn R");
      return ('r');
      break;
    case 'w':
      // printf("Is w");
      printf("\nIn W");
      return ('w');
      break;
    default:
      printf("\nSomething else");
      break;
    }
  } else {
    return 'q';
  }
}

3 个答案:

答案 0 :(得分:1)

我认为您遇到了问题,因为您声明了一个unsigned int变量,但是您在这里使用了错误的格式说明符:

scanf("%d", &Offset);

Offset是一个unsigned int变量。

您必须将%u用于无符号整数,而不是%d

试试这个,这可能会解决问题:

scanf("%u", &Offset);

答案 1 :(得分:1)

学习如何在编译器中启用所有警告和调试信息。使用gcc -Wall -g编译GCC

然后使用调试器(例如gdb)逐步运行您的程序。

最后,阅读您正在使用的函数的文档。记录scanf(3)以返回整数:

   These functions return the number of input items successfully matched
   and assigned, which can be fewer than provided for, or even zero in
   the event of an early matching failure.
   The value EOF is returned if the end of input is reached before
   either the first successful conversion or a matching failure occurs.
   EOF is also returned if a read error occurs, in which case the error
   indicator for the stream (see ferror(3)) is set, and errno is set
   indicate the error.

所以你应该编码

 if (scanf("%d", &Offset)<1) { perror("scanf failed"); exit (EXIT_FAILURE); };

顺便说一句,您的printf(3)格式字符串看起来很奇怪:它们结束(不是开始),换行符为\n,例如代码printf("In R\n");甚至更好

  printf("line %d of %s: In R\n", __LINE__, __FILE__);

或至少在他们之后明确调用fflush(NULL);,阅读 关于fflush(3),请记住stdio(3)buffered

最后, gets(3) 已弃用危险,使用fgets(3)或最好getline(3) 。所以至少用

替换gets(UserInput);
memset (UserInput, 0, sizeof(UserInput));
if (NULL == fgets(UserInput, sizeof(UserInput), stdin)) 
  { perror("fgets"); exit(EXIT_FAILURE); }

BTW,您的main函数声明不正确。最好是int main (int argc, char**argv);。它不应该返回void而是EXIT_SUCCESS,即成功时返回0,失败时返回其他内容。另请参阅EXIT_SUCCESSEXIT_FAILURE以及exit(3)

PS。您在程序开头缺少几个#include指令,至少:

#include <stdio.h>
#include <stdlib.h>

我认为你的代码有他们但你没有向我们展示。

注意:在C中使用大写字母在C中并不常见。一般来说,人 保留宏的大写字母。但这是一个惯例。

答案 2 :(得分:0)

  

当我从Switch内部调用ScanF时,它似乎忽略了Return和Break,而只是忽略了只打印&#34; Not Something&#34; ..

如果&#34;忽略了returnbreak&#34;然后你会落到case 'w'。但这并没有发生。因此,它不会忽略返回和中断(不是可能的)。

实际上程序流程就像你编写它一样工作。顺序是:

  • scanf("%d", &Offset);
  • 您输入一些数字并按Enter键
  • return ('r');
  • 返回主页:MenuS = Menu(); - MenuS现在是'r'
  • while (MenuS != 'q') { MenuS = Menu(); - 再次致电Menu
  • gets(UserInput); - 获取您之前输入的空白​​字符串
  • if (UserInput[0] != 'q') - 是的,因为UserInput[0]0,空白字符串的字符串结束标记
  • switch (UserInput[0]) {没有case 0,因此输入了default:
  • printf("\nSomething else");

要解决此问题:您需要放弃在输入数字后按下的Enter键。一种方法是在scanf

之后直接放置此代码
int c;
while ( (c = getchar()) != '\n' && c != EOF ) {}

注意,您的代码还有很多其他问题,但这是主要问题。