Как я могу прочитать символ, который ошибочно набран в конце ожидаемого числа с плавающей запятой? - PullRequest
0 голосов
/ 24 апреля 2018

У меня есть этот код, который предлагает пользователю ввести двумерный вектор, и я хочу встроить защиту от ошибок, поэтому, если вместо символа вводится символ, символ и т. Д., Он печатает ошибку и выдает запрос снова.Предполагая, что этот код работает отлично:

vect getVector(void)
{
    vect temp;
    bool flag = false; /* For repetition we use an 
                        * input flag initialized to false */

    while (flag == false)
    {
        printf("Enter a vector in the format x y: ");
        if((scanf("%f%f", &temp.x, &temp.y)) != 2)
            printf("  >Input Failure!\n");

        else
            flag = true; /* Input OK */

        clearBuffer(); /* A function I defined elsewhere */
    }

    return temp;
}

Ввод чего-то вроде «1.w 2.5» или «ac 3.2» прекрасно работает с защитой от ошибок.Однако, введя «1.2 3.c» или «1.6 2.54p» (все, что заканчивается символом), он просто игнорирует и отбрасывает этот символ.«1.2 3.c» читает «1.2 3.0», «1.6 2.54p» читает «1.6, 2.54» и т. Д.

Как мне встроить защиту, чтобы обнаружить этот завершающий символ и напечатать сообщение об ошибке?Надеюсь, я могу легко что-то встроить в то, что у меня уже есть.

Мне предложили сохранить ввод в символьной строке и проверить коды ASCII, и если они находятся в диапазоне чисел, а затем преобразовать их обратно в float, но я понятия не имею, как это можно сделать.Кроме того, я хотел бы знать, ПОЧЕМУ код игнорирует этот завершающий символ, может быть, тогда я сам смогу найти решение.Может быть, попытаться определить персонажа изначально?Извините, если это глупый вопрос, я просто не могу обернуться вокруг него.

Ответы [ 2 ]

0 голосов
/ 24 апреля 2018

Как я могу прочитать символ, который ошибочно набран в конце ожидаемого числа с плавающей запятой?
Я хочу встроить защиту от ошибок

Время прекратить использовать scanf() - везде. Да, можно использовать scanf() и иметь надежное обнаружение ошибок, но это не продуктивно.

Вместо этого рассмотрим fgets(), чтобы прочитать строку ввода пользователя @ Феликс Пальмен , а затем проанализировать строку.

Можно использовать sscanf() и " %n" для обнаружения дополнительного мусора, как показано ниже, или использовать вызовы strtof().

// return 1 on success
// return EOF on end-of-file or input error
int getVector(vect *v) {
  char buf[100];  // make this 2x expected max size
  vect temp;
  bool repeat = true;
  while (repeat) {
    printf("Enter a vector in the format x y: ");
    fflush(stdout);
    if (fgets(buf, sizeof buf, stdin) == NULL) {
      return EOF;
    }
    int n = 0;
    sscanf(buf, "%f%f %n", &temp.x, &temp.y, &n);
    // If scanning was incomplete or did not end at the end of the string, then fail
    if (n == 0 || buf[n]) {
      printf("  >Input Failure!\n");
    } else {
      repeat = false;
    }
  }
  *v = temp;
  return 1;
}
0 голосов
/ 24 апреля 2018

Вы можете, если хотите сделать немного больше ручной работы.

Семейство функций strtof() даст вам немного больше информации об ошибках, но они ожидают строку (char*) в качестве ввода.

Для этого вам нужно сначала прочитать в буфер (scanf("%s", buffer) будет работать для этого, но, как уже было отмечено, может быть подвержен ошибкам переполнения буфера, fgets() защитит от этого), затем прочитать ваши два числа с плавающей запятой из этого буфера с strtof() вот так:

printf("Enter a vector in the format x y: ");
scanf("%s %s", buffer1, buffer2);

char *cursor = buffer1;
temp.x = strtof(cursor, *cursor);
if(cursor < (buffer1 + strlen(buffer1)))
  printf("  >Input Failure!\n");

cursor = buffer1;
temp.y = strtof(cursor, *cursor);
if(cursor < (buffer2 + strlen(buffer2)))
  printf("  >Input Failure!\n");

Вызов scanf() здесь читает две строки, разделенные пробелами (пробел, табуляция, символ новой строки и т. Д.), В buffer1 и buffer2. Учитывая, что это scanf(), вам нужно убедиться, что достаточно места для чтения двух строк, чтобы компьютер не просто начал писать слишком далеко.

Два вызова strtof() здесь - каждое чтение начального пробела, за которым следует допустимое число с плавающей запятой, а затем cursor к первому символу, который больше не является частью этого числа с плавающей запятой. Поэтому, если он попадет в символ, который не является частью действительного числа с плавающей запятой, он не достигнет конца строки, что означает, что был получен неверный ввод.

...