Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

I've written a simple calculator app in C and it works pretty well so far but I'm missing one thing: how to ensure the user has entered an input in the correct form e.g. "6 + 7". Is there any way I can test for that?

Here is my code so far:

/*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;

}
like image 664
bavies Avatar asked Mar 29 '20 16:03

bavies


People also ask

What is an input string?

InputString returns what it reads as a string, without evaluation. The operation of InputString may vary from one computer system to another. When a Wolfram System front end is used, InputString typically works through a dialog box. When no front end is used, InputString reads from standard input.


2 Answers

Not necessarily the best way, but I would use sscanf this way:

    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 should return 3 if it successfully read in the values from the input string. If it would return 4 that would mean it read some trailing non whitespace characters which is invalid. The added benefit of this approach is that you don't need to parse the operands elsewhere with atoi.

Whole code:

#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;
}
like image 180
Eraklon Avatar answered Oct 24 '22 20:10

Eraklon


string in C is of the correct 'format'?

A simpler approach uses " %n" at the end to record the offset of the scan - if it made it that far. Akin to @Chris Dodd comment.

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();

Detecting if a space exists is tricky. This answer and "%d %c %d" would pass `"5-7". If spaces are required about the operator, use

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

Notice the " " in " %n" allows scanning to be tolerant of a trailing '\n'. Use as desired.

like image 44
chux - Reinstate Monica Avatar answered Oct 24 '22 20:10

chux - Reinstate Monica