I have following task:
Read comma separated data in below format:
string1, string2, integer_number
e.g:Hi, Hello, 123 John, Doe, 45
I wrote the below code to handle that case. The problem is that I have to distinguish the following cases:
asd, asd, asd
asd, asf
scanf
returns value 2
which is proper behavior because as I understand firstly there is no integer given, secondly there is no third value.
So, I need some help how to set the scanset to only pass as proper string data when it consists of some text and comma -> "text,".
Or maybe I should use different function than scanf()
.What makes this task harder is requirement to not use any additional arrays declared by [] or dynamically allocated. This has to be done only using those 3 variables. No other buffers allowed.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char string1[20];
char string2[20];
int number;
printf("Type data:\n");
int ret_val = scanf("%[a-zA-Z], %[a-zA-Z], %d", string1, string2, &number);
if (ret_val != 3) {
printf("ret_val %d", ret_val);
return 1;
}
printf("%s %s %d\n", string1, string2, number);
return 0;
}
The trick I usually rely on with *scanf()
is using %n
in order to detect that the input was read till this point; this is particularly useful when you expect some literals (they are not considered in the result of *scanf()
).
Note that according to man 3 sscanf
, %n
are not considered in the result of *scanf()
.
/**
gcc -std=c99 -o prog_c prog_c.c \
-pedantic -Wall -Wextra -Wconversion \
-Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
#include <stdio.h>
void
parse_line(const char *line)
{
printf("[%s] --> ", line);
char string1[20]="";
char string2[20]="";
int number=-1;
int n1=-1, n2=-1;
int r=sscanf(line, "%[a-zA-Z],%n %[a-zA-Z],%n %d",
string1, &n1, string2, &n2, &number);
switch(r)
{
case 3:
{
printf("3 fields extracted: %s %s %d\n", string1, string2, number);
break;
}
case 2:
{
if(n2!=-1) // this coma has been read
{
printf("incorrect third field, ");
}
printf("2 fields extracted: %s %s\n", string1, string2);
break;
}
case 1:
{
if(n1!=-1) // this coma has been read
{
printf("incorrect second field, ");
}
printf("1 field extracted: %s\n", string1);
break;
}
default:
{
printf("no field extracted\n");
}
}
}
int
main(void)
{
parse_line("Hi, Hello, 123");
parse_line("John, Doe, 45");
parse_line("asd, asd, asd");
parse_line("asd, asf");
parse_line("asd, ");
parse_line("asd");
parse_line("");
return 0;
}
/**
[Hi, Hello, 123] --> 3 fields extracted: Hi Hello 123
[John, Doe, 45] --> 3 fields extracted: John Doe 45
[asd, asd, asd] --> incorrect third field, 2 fields extracted: asd asd
[asd, asf] --> 2 fields extracted: asd asf
[asd, ] --> incorrect second field, 1 field extracted: asd
[asd] --> 1 field extracted: asd
[] --> no field extracted
**/