0

I need to analyze a string previous reader with fgets,

then I have a row from:

name age steps\n
mario 10 1 2 3 4\n
joe   15 3 5\n
max   20 9 3 2 4 5\n

there are a variable number of steps for each column, then I can read name and age with

 sscanf(mystring, "%s %d", name, &age);

after this I have a for cycle for read all steps

   int step[20];
   int index=0;
   while(sscanf(mystring,"%d", &step[index++])>0);

but this cycle never ends populating all array data with the age column.

Rahul Sinha
  • 1,969
  • 14
  • 17
danilonet
  • 1,757
  • 16
  • 33
  • I guess the `while` loop will end because it will rrad the name and fail to interpret it as number. Please post [mcve]. – MikeCAT Jun 08 '16 at 10:51
  • 1
    You read the same string over and over.... what did you expect – M.M Jun 08 '16 at 10:52
  • 1
    You are always scanning the same string, you would need to advance the string handed to `sscanf`; just use `strtok` as shown in the answer from terence hill. – Karsten Koop Jun 08 '16 at 10:54
  • "i need to analyze a string" --> This often leads to the question: Should code detect unexpected strings like `"dan 1 2 3 x`` or "joe bob 1 2 3"? Or do you simply want an answers that assume the data in the strings well formed? – chux - Reinstate Monica Jun 08 '16 at 16:10
  • @RahulSinha: if you are going to edit 10 or more posts per hour, better make sure your edits are significant, rather than trivial. – Jongware Jun 08 '16 at 17:31

2 Answers2

2

A working solution is given in the answer from sokkyoku.

Another possibility to read variable length lines is to use strtok like in the following code snippet:

int getlines (FILE *fin)
{
    int  nlines = 0;
    int  count  = 0;
    char line[BUFFSIZE]={0};
    char *p;

    if(NULL == fgets(buff, BUFFSIZE, fin))
        return -1;

    while(fgets(line, BUFFSIZE, fin) != NULL) {
        //Remove the '\n' or '\r' character
        line[strcspn(line, "\r\n")] = 0;
        count = 0;
        printf("line[%d] = %s\n", nlines, line);
        for(p = line; (p = strtok(p, " \t")) != NULL; p = NULL) {
            printf("%s ", p);
            ++count;
        }
        printf("\n\n");
        ++nlines;
    }

    return nlines;
}

Explanation of the above function getlines:

Each line in the file fin is read using fgets and stored in the variable line. Then each substring in line (separated by a white space or \t character) is extracted and the pointer to that substring stored in p, by means of the function strtok in the for loop (see for example this post for further example on strtok).

The function then just print p but you can do everything with the substring here. I also count (++count) the number of items found in each line. At the end, the function getline count and returns the number of lines read.

Community
  • 1
  • 1
terence hill
  • 3,354
  • 18
  • 31
  • Minor bits: 1) Why `'\n'` in `strtok(p, " \t\n")`? `line[strcspn(line, "\r\n")] = 0;` insures there is no longer a `'\n'`. 2) "separated by a white space or \t \n character" is really "separated by a space or \t \n character". – chux - Reinstate Monica Jun 08 '16 at 15:12
  • @chux thanks, I added the `line[strcspn(line, "\r\n")] = 0` later and didn't modify the strtok – terence hill Jun 08 '16 at 15:23
2

The reason this never ends is because you are constantly providing the same string to scan.

sscanf provides the %n switch which stores the amount of characters read before it is reached inside a, which allows you to move forward in your input string by that amount of characters before rescanning.

This'll work:

int step[20];
int index=0;
int readLen;
while(sscanf(mystring,"%d%n", &step[index++], &readLen)>0) {
  mystring += readLen;
}
sokkyoku
  • 2,161
  • 1
  • 20
  • 22