Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fscanf() reading string with spaces in formatted lines

Tags:

c

scanf

Using this structure:

typedef struct sProduct{
  int code;
  char description[40];
  int price;
};

I want to read a txt file with this format:

1,Vino Malbec,12

where the format is: code,description,price. But I'm having problems to read the description when it has a space.

I tried this:

fscanf(file,"%d,%[^\n],%d\n",&p.code,&p.description,&p.price);

The code is being saved ok, but then in description is being saved Vino Malbec,12, when I only want to save Vino Malbec because 12 is the price.

Any help? Thanks!

like image 599
Mati Tucci Avatar asked Feb 11 '23 20:02

Mati Tucci


2 Answers

The main issue is "%[^\n],". The "%[^\n]" scans in all except the '\n', so description scans in the ','. Code needs to stop scanning into description when a comma is encountered.

With line orientated file data, 1st read 1 line at a time.

char buf[100];
if (fgets(buf, sizeof buf, file) == NULL) Handle_EOForIOError();

Then scan it. Use %39[^,] to not scan in ',' and limit width to 39 char.

int cnt = sscanf(buf,"%d , %39[^,],%d", &p.code, p.description, &p.price);
if (cnt != 3) Handle_IllFormattedData();

Another nifty trick is: use " %n" to record the end of parsing.

int n = 0;
sscanf(buf,"%d , %39[^,],%d %n", &p.code, p.description, &p.price, &n);
if (n == 0 || buf[n]) Handle_IllFormattedData_or_ExtraData();

[Edit]

Simplification: @user3386109

Correction: @cool-guy remove &

like image 106
chux - Reinstate Monica Avatar answered Feb 13 '23 08:02

chux - Reinstate Monica


@chux has already posted a good answer on this, but if you need to use fscanf, use

if(fscanf(file,"%d,%39[^,],%d",&p.code,p.description,&p.price)!=3)
    Handle_Bad_Data();

Here, the fscanf first scans a number(%d) and puts it in p.code. Then, it scans a comma(and discards it) and then scans a maximum of 39 characters or until a comma and puts everything in p.description. Then, it scans a comma(and discards it) and then, a number(%d) and puts it in p.price.

like image 35
Spikatrix Avatar answered Feb 13 '23 09:02

Spikatrix