c - 扫描字符导致 devC 出现问题

标签 c string character

所以我的代码执行以下操作:

  1. 询问有什么选择
  2. 如果选项是1:扫描一些数字
  3. 如果选项为 2:打印这些数字
  4. 在每个选项之后,询问用户是否想继续选择(是/否)

这是我的主要代码

while(yesnocheck==1)
{
    printf("What's your option?: ");
    scanf("%d",&b);

    switch(b){
        case 1:
            printf("How many numbers?: ");
            scanf(" %d",&n);
            a=(struct sv*)malloc(n*sizeof(struct sv));

            for(int i=0;i<n;i++)
                scanf("%d",&((a+i)->num));
            break;
        case 2:
            for(int i=0;i<n;i++)
                printf("%d\n",(a+i)->num);
            break;
    }
    yesnocheck==yesnochecker();
}

这是 yesnochecker 函数:

int yesnochecker()
{
    char yesorno;
    printf("Do you want to continue? (Y/N)");

        while(scanf("%s",&yesorno))
    {
        if(yesorno=='Y')
            return 1;
        if(yesorno='N')
            return 0;   
        printf("*Wrong input. Please reenter (Y/N): ");
    }
}

所以在开发 C++ 上,我的代码将无法正确运行。完成选项 1 后,当我输入“Y”然后选择选项 2 时,案例 2 会显示一些奇怪的数字。然而,它在在线 C 编译器上运行良好。

然后,当我将 yesnochecker() 函数中的 char yesorno 更改为 char yesorno[2] 并将其视为字符串时,代码确实有效。

有人可以阐明一些吗?

最佳答案

scanf("%s", &c); 读取 char c 是个坏主意。 "%s" 需要一个缓冲区来存储字符串。唯一适合 char 的字符串是空字符串(仅由终止符 '\0' 组成——不是很有用)。每个包含 1 个字符的字符串都需要 2 个 char 的存储空间——1 个用于字符,1 个用于终止符 ('\0')。提供用于存储的 charUndefined Behavior .

因此,第一个提示是改用正确的格式化程序 - "%c"

这更好,因为它删除了未定义的行为。但是,它并没有解决另一个问题,如以下示例所示:

#include <stdio.h>

int cont()
{
  char c; do {
    printf("Continue (y/n): ");
    scanf("%c", &c);
    printf("Input %c\n", c);
  } while (c != 'y' && c != 'n');
  return c == 'y';
}

int main()
{
  int i = 0;
  do {
    printf("Loop iteration %d.\n", ++i);
  } while (cont());
  /* done */
  return 0;
}

输出:

Loop iteration 1.
Continue (y/n): <b>y↵</b>
Input 'y'
Loop iteration 2.
Continue (y/n): 
Input '
'
Continue (y/n): <b>n↵</b>
Input 'n'

Live Demo on ideone

什么?

scanf("%c") 从输入中消耗一个字符。另一个字符(为 ENTER 键插入)保留在输入缓冲区中,直到下一次调用任何输入函数。

太糟糕了,没有 ENTER 很难在控制台上确认输入。

一个可能的解决方案是读取字符,直到收到 ENTER 键(或由于任何原因输入失败)。 (顺便说一句,getc()fgetc() 也可用于读取单个字符。):

#include <stdio.h>

int cont()
{
  int c;
  do {
    int d;
    printf("Continue (y/n): ");
    if ((c = fgetc(stdin)) < 0) {
      fprintf(stderr, "Input failed!\n"); return 0;
    }
    printf("Input '%c'\n", c);
    for (d = c; d != '\n';) {
      if ((d = fgetc(stdin)) < 0) {
        fprintf(stderr, "Input failed!\n"); return 0;
      }
    }
  } while (c != 'y' && c != 'n');
  return c == 'y';
}

int main()
{
  int i = 0;
  do {
    printf("Loop iteration %d.\n", ++i);
  } while (cont());
  /* done */
  return 0;
}

输出:

Loop iteration 1.
Continue (y/n): <b>y↵</b>
Input 'y'
Loop iteration 2.
Continue (y/n): <b>Hello↵</b>
Input 'H'
Continue (y/n): <b>n↵</b>
Input 'n'

Live Demo on ideone

请注意,我将读取字符的类型更改为 int。这是因为 getc()/fgetc() 返回一个 int,它能够存储 256 个可能的 char 值以及在失败时返回的 -1

但是,将 int 与字符常量(例如 'y')进行比较没有任何问题。在 C 中,字符常量的类型只是 int ( SO: Type of character constant )。

关于c - 扫描字符导致 devC 出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52089868/

相关文章:

python - 将字符串转换为原始字节

c - 我从堆中分配内存来存储一个字符,但它保存的是一个字符串

c++ - 使用 libpcap 进行无线数据包注入(inject)

c++ - 如何将具有双高/双宽字符的字符串转换为普通字符串[VC++6]

c# - 截断字符串时意外拆分 unicode 字符

c - 在句子中查找特定字符并打印具有该字符的每个单词

c - 将 char 数组设置为全零值(在 C 中)

c - 如果必须终止控制台,如何查看 Visual Studio 的输出?

c - 地址值更改不会反射(reflect)在 while 循环中

c - libusb-1.0 热插拔事件在 fork() 之后停止在父级中工作,当子级调用 libusb_exit() 时