Reputation: 45
Let's say I have the following strings and a boolean:
bool numberGiven = false
"@give chocolate"
"@give white chocolate"
"@give dark chocolate"
"@give white chocolate 10"
"@give dark chocolate 2"
I want to save the words together in a char[] and the integer seperately as int using sscanf.
I want that the number is an optional input. Users do not have to type in a number but if they do, the boolean "numberGiven" will become "true".
I need an if statement to decide whether or not I have to make numberGiven "true". Note that the "item name" can be even more than just two words. Instead of dark chocolate it could be Kinder Schokolade Dark Chocolate for example (and of course the optional integer at the end)
Upvotes: 0
Views: 1263
Reputation: 40145
sscanf
can't be simply applied in consideration of the case where numbers are used for names.
So, do as follows.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
int main(void){
char line[96];
while(fgets(line, sizeof line, stdin)){
bool numberGiven = false;
char name[96];
int number;
if(strncmp(line, "@give ", 6) != 0){// check start with "@give "
printf("invalid format\n");
continue;
}
//end trim
size_t len = strlen(line);
char *p = &line[len-1];
while(isspace((unsigned char)*p)){
*p-- = 0;
}
p = strrchr(line, ' ');//last space (last part)
if(1 == sscanf(p, "%d", &number)){
numberGiven = true;
*p = 0;
}
strcpy(name, line + 6);// 6: "@give "
if(numberGiven)
printf("name:%s number:%d\n", name, number);
else
printf("name:%s\n", name, number);
}
return 0;
}
Upvotes: 0
Reputation: 753695
It looks like you need a scan-set in sscanf()
, assuming you don't have "@give 70% real chocolate 25
" as a possible string (that is, the name does not itself contain digits).
const char *buffer = "@give white chocolate 10";
int n_vals;
char name[300];
int number;
n_vals = sscanf(buffer, "@%299[^0-9] %d", name, &number);
if (n_vals == 1)
…process string with name only (and possible trailing blanks)…
else if (n_vals == 2)
…process string with name and number (and probably trailing blanks)…
else
…malformatted buffer…
If you want to match the @
in the data (input) string, remove it from the format string. If you don't want the @give
in the output string, use "@ give %299[^0-9] %d"
as the format string instead.
Note that the spaces in the format string map to optional spaces in the input data.
If you need to deal with 70%
problems, then it is probably time to think again. You might scan words one at a time (see Using sscanf()
in a loop for more information on that) and identify when you've reached the end of the string, and whether the last string was a pure number.
Upvotes: 0
Reputation: 140569
Never use (s)scanf
for anything. Instead, use a hand-written parser. Use isdigit
(from ctype.h
) to scan through the string until you reach the first digit, and then use strtoul
to convert the number. Something like this:
char *p = str, *q;
while (*p && !isdigit(*p)) p++;
if (!*p) {
numberGiven = false;
return;
}
numberGiven = true;
q = p-1;
while (q > str && isspace(*q) q--;
q[1] = '\0'; /* cut off the string before the number */
errno = 0;
number = strtoul(p, &q, 10);
if (q == p || *q != '\0' || errno)
parse_error();
Upvotes: 1