Reputation: 23
In the following code i need to extract doubles and string from a line formated like this "[double,double] string" with the string starting as a first non white character and any number of white characters after [
I do care about loading properly the numbers, but don't care about the string (could even be empty).
char *read;
size_t len=0;
double x,y;
int size;
getline(&read,&len,stdin);
char *name=(char*)malloc(strlen(read));
if(sscanf(read,"[ %lf, %lf ] %n",&x,&y,&size)!=2)
{
return 0;
}
sscanf(read,"%*.c%[^\n]s",size,name);
I already have implemented everything. I know that the second sscanf cannot work like this, only there to represent my thought. Is there any way how to get the size variable to be a parameter of how many characters not to load? I searched everything and the only thing i could find was to have number defined, which does not help here.
Also I am quite new to programming, so please be considerate about me not knowing maybe basic stuff.
Upvotes: 2
Views: 65
Reputation: 84561
If I understand your question and you want to separate, e.g. "[123.456, 789.34] Daffy Duck"
into the two doubles and the name using getline
and sscanf
allocating storage for name
, then a single call to POSIX getline()
and a single call to sscanf
reading name into a temporary array and then allocating and copying to name
will allow you to size name
exactly as required.
For example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 1024
int main (void) {
double x, y;
char *read = NULL, *name = NULL, tmp[MAXN];
size_t n = 0;
fputs ("input: ", stdout);
if (getline (&read, &n, stdin) == -1) {
fputs ("error: getline.\n", stderr);
return 1;
}
if (sscanf (read, " [%lf ,%lf ] %1023[^\n]", &x, &y, tmp) == 3) {
size_t len = strlen (tmp);
if (!(name = malloc (len + 1))) {
perror ("malloc-name");
return 1;
}
memcpy (name, tmp, len + 1);
printf ("x : %f\ny : %f\nname: %s\n", x, y, name);
free (name);
}
free (read);
}
There is no need to cast the return of malloc
, it is unnecessary. See: Do I cast the result of malloc?
Also note that when the parameter n = 0
as above, getline()
will allocate storage as needed to handle your input line. So following the call to getline()
, read
has allocated storage duration. You will need to free read
to avoid leaking memory and you cannot simply return a pointer to the beginning of name
within read
as you must preserve a pointer to the beginning of read
in order to be able to free
it.
Example Use/Output
Then by including appropriate whitespace in your sscanf
format-string you can flexibly read your input regardless of leading or intervening whitespace, e.g.
$ ./bin/readxyname
input: [123.456, 789.34] Daffy Duck
x : 123.456000
y : 789.340000
name: Daffy Duck
With no whitespace in input:
$ ./bin/readxyname
input: [123.456,789.34]Daffy Duck
x : 123.456000
y : 789.340000
name: Daffy Duck
With arbitrary whitespace in input:
$ input: [ 123.456 , 789.34 ] Daffy Duck
x : 123.456000
y : 789.340000
name: Daffy Duck
Look things over and let me know if you have further questions.
Upvotes: 3
Reputation: 8494
scanf
may ignore matches with the *
formatter. More on that on conversion specifications here. That way, you can match and store double and match and ignore the following string i.e. %*s
.
A bit easier way could be searching for ]
with i.e. strchr
and then passing sscanf
only the string portion you're actually interested in (now that you know where it begins and ends) through simple pointer arithmetics.
Upvotes: 0