Сканирование символа вызвало проблемы в devC - PullRequest
0 голосов
/ 30 августа 2018

Итак, мой код выполняет следующие действия:

  1. Спросите, что вариант
  2. Если опция 1: отсканировать несколько чисел
  3. Если опция 2: напечатать эти цифры
  4. После каждой опции спросите, хочет ли пользователь продолжить выбор (Y / N)

Это мой основной код

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): ");
    }
}

Так что на dev C ++ мой код не будет работать правильно. После того, как это сделано, вариант 1, когда я ввожу «Y», затем выбираю вариант 2, случай 2 покажет некоторые странные числа. Однако это хорошо работает на онлайн-компиляторах Си.

И затем, когда я изменяю функцию char yesorno в yesnochecker () на char yesorno[2] и воспринимаю ее как строку, код работает.

Может кто-нибудь пролить свет?

1 Ответ

0 голосов
/ 30 августа 2018

Плохо читать char c с scanf("%s", &c);. "%s" требуется буфер для хранения строки. Единственная строка, которая вписывается в char - это пустая строка (состоящая только из терминатора '\0' - не очень полезна). Каждая строка с 1 символом требует 2 char с хранения & ndash; 1 для символа, 1 для терминатора ('\0'). char для хранилища: Неопределенное поведение .

Итак, первая подсказка заключалась в том, чтобы вместо этого использовать правильный форматер & ndash; "%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&#x21b5;</b>
Input 'y'
Loop iteration 2.
Continue (y/n): 
Input '
'
Continue (y/n): <b>n&#x21b5;</b>
Input 'n'

Демонстрация в реальном времени на ideone

WTH?

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&#x21b5;</b>
Input 'y'
Loop iteration 2.
Continue (y/n): <b>Hello&#x21b5;</b>
Input 'H'
Continue (y/n): <b>n&#x21b5;</b>
Input 'n'

Демонстрация в реальном времени на ideone

Обратите внимание, что я изменил тип прочитанного символа на int. Это потому, что getc() / fgetc() возвращает int, который способен хранить любое из 256 возможных значений char, а также -1, который возвращается в случае сбоя.

Однако не составляет труда сравнить int с символьной константой (например, 'y'). В C тип символьных констант просто int ( SO: Тип символьной константы ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...