繁体   English   中英

如何测试 C 中的输入字符串是否具有正确的“格式”?

[英]How to test that an input string in C is of the correct 'format'?

我已经用 C 编写了一个简单的计算器应用程序,到目前为止它运行良好,但我遗漏了一件事:如何确保用户以正确的形式输入了一个输入,例如“6 + 7”。 有什么办法可以测试吗?

到目前为止,这是我的代码:

/*A simple calculator that can add, subtract and multiple. TODO: Division
and add error handling i.e. if not an expected input!*/

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

int main() {
  char input[10];
  int result;
  printf("Welcome to the calculator! The available operations are +, - and *.\n");
  while (1) {
    printf("What would you like to calculate?\n");
    fgets(input, 10, stdin); /*Getting user input in form e.g. 4 + 7*/

    /*Ideally test for input should go here*/

    /*Separating user input into the numbers and operators, using strtok and
    space as a delimiter*/
    char *firstNumber = strtok(input, " ");
    char *operator = strtok(NULL, " ");
    char *secondNumber = strtok(NULL, " ");

    /*Converting the separated numbers to integers*/
    int firstInt = atoi(firstNumber);
    int secondInt = atoi(secondNumber);

    if (strcmp(operator, "+") == 0) {
      result = firstInt + secondInt;
    } else if (strcmp(operator, "-") == 0) {
      result = firstInt - secondInt;
    } else if (strcmp(operator, "*") == 0) {
      result = firstInt * secondInt;
    } else {
      printf("That ain't a valid operator sonny jim. Try again:\n");
      continue;
    }

    printf("Your result is %d.\n", result);

    int flag = 0;

    while (flag == 0) {
      printf("Would you like to do another calculation? (yes or no)\n");
      fgets(input, 10, stdin);
      if (strcmp(input, "yes\n") == 0) {
        flag = 1;
      } else if (strcmp(input, "no\n") == 0) {
        flag = 2;
      } else {
        printf("That isn't a valid response. Please respond yes or no.\n");
      }
    }
    if (flag == 2) {
      break;
    }
  }

  return 0;

}

不一定是最好的方法,但我会这样使用sscanf

    int firstInt;
    int secondInt;
    char operator;
    if (3 != sscanf(input, "%d %c %d %1[^\n]", &firstInt, &operator, &secondInt, &temp)) {
      printf("Invalid input Billy!\n");
      continue;
    }

如果sscanf成功读取输入字符串中的值,则应返回 3。 如果它将返回 4,则意味着它读取了一些无效的尾随非空白字符。 这种方法的额外好处是您不需要使用atoi解析其他地方的操作数。

全码:

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

int main() {
  char input[10];
  char temp[2];
  int result;
  printf("Welcome to the calculator! The available operations are +, - and *.\n");
  while (1) {
    printf("What would you like to calculate?\n");
    fgets(input, 10, stdin); /*Getting user input in form e.g. 4 + 7*/

    /*Ideally test for input should go here*/
    int firstInt;
    int secondInt;
    char operator;
    if (3 != sscanf(input, "%d %c %d %1[^\n]", &firstInt, &operator, &secondInt, temp)) {
      printf("Invalid input Billy!\n");
      continue;
    }

    if ('+'== operator) {
      result = firstInt + secondInt;
    } else if ('-' == operator) {
      result = firstInt - secondInt;
    } else if ('*' == operator) {
      result = firstInt * secondInt;
    } else {
      printf("That ain't a valid operator sonny jim. Try again:\n");
      continue;
    }

    printf("Your result is %d.\n", result);

    int flag = 0;

    while (flag == 0) {
      printf("Would you like to do another calculation? (yes or no)\n");
      fgets(input, 10, stdin);
      if (strcmp(input, "yes\n") == 0) {
        flag = 1;
      } else if (strcmp(input, "no\n") == 0) {
        flag = 2;
      } else {
        printf("That isn't a valid response. Please respond yes or no.\n");
      }
    }
    if (flag == 2) {
      break;
    }
  }
  return 0;
}

您应该做的第一个测试是长度。 您只允许输入十个字符。 一个用于运算符,两个用于空格,一个用于\\n ,一个用于NUL终止符。 这样就只剩下 5 个字符要在两个操作数之间拆分了。 因此,如果用户输入543 * 65 ,则您已经截断了\\n 输入5432 * 65 ,您开始丢失重要数据。 我实现长度检查的方法是搜索\\n
if (input[0] && input[strlen(input) - 1] != '\\n') ,您知道输入已被截断。 接下来,您需要检查字符的有效性。 如果你保留你的strtok()方法,你可以在将字符串转换为整数时进行输入检查,如果你使用首选函数strtol() ††和更好的错误检查。 至于运营商,您已经对此进行了检查。 对于输入格式:检查 NULL 指针 如果strtok()找不到空格分隔符,它将返回一个 NULL 指针,然后您将尝试在程序中稍后读取该指针。

†:我个人会让我的输入字符限制更大:至少 25
††: man strtol了解更多信息

C 中的字符串是正确的“格式”吗?

一个更简单的方法是在末尾使用" %n"来记录扫描的偏移量——如果它已经做到了那么远。 类似于@Chris Dodd评论。

int firstNumber;
char operator[2];
int secondNumber;

int n = 0;
sscanf(input, "%d %1[+-] %d %n", &firstNumber, operator, &secondNumber, &n);
//  v---v--------------------  Scan complete?
if (n > 0 && input[n] == '\0') Success();
//           ^--------------^  No extra junk at the end?
else Fail();

检测空间是否存在很棘手。 这个答案和"%d %c %d"会通过“5-7”。 如果操作符需要空格,请使用

"%d%*[ ]%1[+-]*[ ]%d %n"

请注意, " %n" " "中的" %n"允许扫描容忍尾随'\\n' 根据需要使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM