簡體   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