James Harrison
James Harrison

Reputation: 172

sscanf and strings

I'm parsing some CSV data in C for the purposes of a Ruby extension. In order to pull out the data from each row I'm using sscanf as follows:

  char* line = RSTRING_PTR(arg);
  double price;
  double volume_remaining;
  unsigned int type_id, range, order_id, volume_entered, minimum_volume, duration, station_id, region_id, solar_system_id, jumps;
  char* issued;
  char* bid;
  printf("I got %s\n",line);
  int res = sscanf(line, "%lf,%lf,%u,%u,%u,%u,%u,%s,%s,%u,%u,%u,%u,%u", &price, &volume_remaining, &type_id, &range, &order_id, &volume_entered, &minimum_volume, bid, issued, &duration, &station_id, &region_id, &solar_system_id, &jumps);
  printf("I matched %d values\n", res);
  printf("I have price %f, vol_rem %f, type_id %d, range %d, order_id %d, vol_ent %d, min_vol %d, issued %s, bid %s, duration %d, station_id %d, region_id %d, solar_system_id %d, jumps %d, source %s \n",price, volume_remaining, type_id, range, order_id, volume_entered, minimum_volume, issued, bid, duration, station_id, region_id, solar_system_id, jumps, source); // and hash build follows below

Running it produces this:

I got 728499.93,437.0,2032,32767,1132932560,588,1,False,2009-05-24 19:52:08.000,90,60003760,10000002,30000142,0
I matched 7 values
I have price 728499.930000, vol_rem 437.000000, type_id 2032, range 32767, order_id 1132932560, vol_ent 588, min_vol 1, issued (null), bid (null), duration -1210229476, station_id 3001, region_id 3001, solar_system_id 1, jumps -1210299816

Note the null strings. Basically, it seems like sscanf is tripping on these for some reason. I can't figure out why even having read the docs thoroughly. Any ideas?

Upvotes: 0

Views: 3861

Answers (4)

kitsionchen
kitsionchen

Reputation: 67

Allocating memory on the stack is the simple way. Example:

char issued[1024] = {0};
char bid[1024] = {0};

By the way, "Allocating memory on the stack" really just means taking the current position of the stack pointer, assigning it to the variable name and then incrementing the stack pointer by the size of the type of the variable. It's an extremely quick operation compared with allocating memory on the heap with malloc and friends. Unlike with malloc however you lose any stack allocated memory once you pop your current stack frame (i.e. execution reaches the end of the current function).

Upvotes: 2

waterlooalex
waterlooalex

Reputation: 13872

I agree with Thanatos. As a first start you need to allocate memory for issued and bid, you might do:

char issued[1024]; char bid[1024];

Upvotes: 0

Peter Kovacs
Peter Kovacs

Reputation: 2725

%s matches non-whitespace characters. What you probably want is %[^,]255 which will match every character other than , instead of %s. The 255, which is optional, specifies the field width that you're expecting for that field.

Upvotes: 1

Thanatos
Thanatos

Reputation: 44256

Your character pointers are unitialized, and point to a random segment of memory. You must allocate a buffer for sscanf() to write to, and it must be big enough. (You're lucky that didn't segfault.) That second part is the hard part -- scanf() might not be the right tool for the job here.

Upvotes: 2

Related Questions