0

I had a CSV file. I have managed to convert all the commas to spaces, and have put the entire thing in one massive string. When I print out the string I get data like this:

DATA1 STUFF1 10 0.1 550 120 140 0.121
DATA2 STUFF2 20 0.1 250 250 200 0.022
DATA3 STUFF3 30 0.1 120 330 10 0.064
DATA4 STUFF4 40 0.1 920 380 10 0.193

etc

I'm currently having a problem in that when I scan the data into my stuct array that is meant to hold this data, it just produces the first line over and over again, ignoring the rest. So when I print it out, I just get
DATA1 STUFF1 10 0.1 550 120 140 0.121
DATA1 STUFF1 10 0.1 550 120 140 0.121
DATA1 STUFF1 10 0.1 550 120 140 0.121
DATA1 STUFF1 10 0.1 550 120 140 0.121

i=0;
while(i<MAX)
{
    sscanf(str, "%s %s %d %f %d %d %d %f", &datas[i].c1, &datas[i].c2, 
    &datas[i].n1, &datas[i].n2, &datas[i].n3, &datas[i].n4, 
    &datas[i].n5, &datas[i].n6);        
    i++;
}

MAX is the number of records in the CSV file, datas is my array of structures, str is the string that i have stored all the data without spaces and i is just an integer.

The actual structure:

struct data{
    char c1[10], c2[10];
    int n1, n3, n4, n5;
    float n2, n6;
};
struct data datas[MAX];

Anyone got a solution? New to C so please explain like I'm 5.

  • Please look at the usage of `sscanf()`. The code inside loop seems doubtful. – Gaurav Pathak Mar 31 '17 at 11:57
  • How do you mean doubtful? That does not help in any way. – user7604801 Mar 31 '17 at 12:01
  • Please take a look at the answer given by @Jay. And please read [this](https://www.tutorialspoint.com/c_standard_library/c_function_sscanf.htm) – Gaurav Pathak Mar 31 '17 at 12:02
  • Duplicate of "Using sscanf() in loops". Also an argument for not putting it all into one big string. – Jonathan Leffler Mar 31 '17 at 12:07
  • Try `int offset = 0; while(i < MAX) { sscanf(str + offset, "%s %s %d %f %d %d %d %f%n", &datas[i].c1, &datas[i].c2, &datas[i].n1, &datas[i].n2, &datas[i].n3, &datas[i].n4, &datas[i].n5, &datas[i].n6, &offset); i++; }` – Spikatrix Mar 31 '17 at 12:15
  • @CoolGuy that is very close It gets the first two data sets but not the rest – user7604801 Mar 31 '17 at 12:39
  • @user7604801 Try `int offset = 0; while(i < MAX) { sscanf(str + (offset * i), "%s %s %d %f %d %d %d %f%n", &datas[i].c1, &datas[i].c2, &datas[i].n1, &datas[i].n2, &datas[i].n3, &datas[i].n4, &datas[i].n5, &datas[i].n6, &offset); i++; }` then – Spikatrix Mar 31 '17 at 13:52
  • @CoolGuy Nope, still the same Although I don't see why it shouldn't work – user7604801 Mar 31 '17 at 14:46
  • @user7604801 Err, maybe `int offset = 0; char* p = str; while(i < MAX) { sscanf(p += offset, "%s %s %d %f %d %d %d %f%n", &datas[i].c1, &datas[i].c2, &datas[i].n1, &datas[i].n2, &datas[i].n3, &datas[i].n4, &datas[i].n5, &datas[i].n6, &offset); i++; }`? I'm on mobile, so its hard to test... – Spikatrix Mar 31 '17 at 14:51
  • @CoolGuy Nope still the same – user7604801 Mar 31 '17 at 15:59
  • @user7604801 If you could post a [mcve], I might be able to spot the error. – Spikatrix Mar 31 '17 at 16:09
  • @CoolGuy Nevermind - copy and paste error so actually the last one works. Thank you very much, you're a life saver – user7604801 Mar 31 '17 at 16:25

2 Answers2

4

Through the multiple iterations of the loop, you are passing the same string (i.e. the string points to the same location - beginning of the string) which results in same values getting parsed.

You need advance the string to point to the correct location within the string for the subsequent scanf operations.

You can probably have some delimiter in the string at the end of "one set" of data and use strtok or similar such functions to move within the string.

Jay
  • 24,173
  • 25
  • 93
  • 141
  • So use \n as the delimiter but then how do I actually use that to get each set out seperately? Do I put it in the while loop before scanf? – user7604801 Mar 31 '17 at 12:02
  • Yes. You can use strtok to parse for "\n". You can add that code after the scanf in the while loop so that the first parsing works fine. – Jay Mar 31 '17 at 12:18
  • Refer https://linux.die.net/man/3/strtok – Jay Mar 31 '17 at 12:21
1
sscanf(str, "%s %s %d %f %d %d %d %f", &datas[i].c1, &datas[i].c2, 
    &datas[i].n1, &datas[i].n2, &datas[i].n3, &datas[i].n4, 
    &datas[i].n5, &datas[i].n6);

As you said that str is a big string this is why the content of your structure members remains same. Please modify your code if possible to use str as array of pointers and then use

sscanf(str[i], "%s %s %d %f %d %d %d %f", &datas[i].c1, &datas[i].c2, 
    &datas[i].n1, &datas[i].n2, &datas[i].n3, &datas[i].n4, 
    &datas[i].n5, &datas[i].n6);

Please check how to declare and use array of pointers.

Gaurav Pathak
  • 1,065
  • 11
  • 28
  • Please read this [link](https://www.tutorialspoint.com/cprogramming/c_array_of_pointers.htm) for an understanding of array of pointers. – Gaurav Pathak Mar 31 '17 at 12:11
  • Ok I did that, but now every record looks like this:| DATA1 STUFF1 10 0.1 550 120 140 0.121 | ATA1 ST... 0.121 | TA1 ST... 0.121 | A1 ST....0.121 | it's just taking off the front character each time – user7604801 Mar 31 '17 at 12:27