【问题标题】:How can I read a character that is mistakenly typed at the end of an expecting floating point number?如何读取在预期浮点数末尾错误输入的字符?
【发布时间】:2018-10-04 22:59:48
【问题描述】:

我有这段代码,它提示用户输入一个二维向量,我想建立错误保护,所以如果输入一个字符、符号等而不是一个字符,它会打印一个错误并再次提示。假设这段代码完美运行:

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”或“a.c 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 码,如果它们在数字范围内,则将它们转换回浮点数,但我不知道这是怎么回事完毕。此外,我想知道为什么代码会忽略那个尾随字符,也许我可以自己想一个解决方案。也许最初尝试检测角色?对不起,如果这是一个愚蠢的问题,我就是无法理解它。

【问题讨论】:

  • scanf() 仅读取执行格式字符串中请求的转换所需的输入。我想有办法用scanf() 做你想做的事,但更好的是fgets()strtok()strtod() 的解决方案。请参阅我的beginners' guide away from scanf() 以获得一些见解(它只处理整数,但我想你可以转移到strtod())。
  • 如果你想做任何体面的错误处理,不要使用scanf

标签: c scanf trailing


【解决方案1】:

如果你想做更多的手工工作,你可以。

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() 调用将两个空格(空格、制表符、换行符等)分隔的字符串读入buffer1buffer2。鉴于这是scanf(),您需要确保有足够的空间来读取这两个字符串,这样计算机才不会开始写得太远。

这里对strtof() 的两次调用都读取前导空格,后跟一个有效的浮点数,然后将cursor 推进到不再是该浮点数一部分的第一个字符。因此,如果它碰到一个不属于有效浮点数的字符,它将不会到达字符串的末尾,这意味着收到了错误的输入。

【讨论】:

  • 请不要建议有缓冲区溢出的代码! fgets() 怎么了?
  • 顺便说一句,%s 甚至不起作用,OP 期望两个浮点数由空格分隔。
  • 老实说,我的知识非常有限——在我的课程中,我们也只学习了 scanf() 作为输入法,所以我试图写这个而不偏离我们应该知道的太多观点。这不是作业问题,只是我们正在使用的教科书中的一个问题 - 在这一点上我们应该能够回答它。
  • 另外,一位朋友建议使用char nextChar = getchar();,然后使用测试查看nextChar 是否为'\n' - 我不知道他的意思。有灯吗?
  • 您要做的错误检查越多,您需要的实际输入就越接近。使用getchar() 将允许您一次读取一个字符并随心所欲,但是您必须重新编写标准库中可用的几种方法中已经存在的所有数字解析,所以为什么要完美地重写好代码?
【解决方案2】:

如何读取在预期浮点数末尾错误键入的字符?
我想内置错误保护

是时候停止使用scanf() - 无处不在。是的,可能使用scanf() 并具有强大的错误检测功能,但效率不高。

请考虑fgets() 读取用户输入@Felix Palmen,然后解析字符串。

可以使用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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    相关资源
    最近更新 更多