How to test that an input string in C is of the correct 'format'?
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;
}
The first test you should do is for length. You only allow input of ten characters. That's one for the operator, two for spaces, one for the \n
, and one for the NUL
terminator. That leaves only 5 characters to be split amongst the two operands. So, if the user inputs 543 * 65
, you've already truncated the \n
. An input of 5432 * 65
, and you start losing important data. The way I would implement a length check is to search for the \n
:
if (input[0] && input[strlen(input) - 1] != '\n')
, you know the input has been truncated.† Next, you need to check for the validity of the characters. If you keep your strtok()
method, you can do input checking when you convert the string to an integer if you use the preferred function strtol()
†† with far better error checking. As for the operator, you already have checks on that. For formatting of input: check for NULL pointers. If strtok()
doesn't find a space delimiter, it will return a NULL pointer, which you would then try to read from later in your program.
†: I personally would make my input character limit larger: at least 25
††: man strtol
for more information
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.