1

I used sscanf to segment one string taken from the input and store every token in a structure. The problem is that sscanf only reads the first word of the string and doesn't move ahead to the next word, printing the same token over and over. Here's the code.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define dim 30

typedef struct string { 
  char* token[dim];
}string;

int main() {
  string* New = (string *)malloc(dim*sizeof(string));
  char* s;
  char buffer[dim];
  int i = 0, r = 0, j = 0;
  s = (char*)malloc(sizeof(char*));
  printf("\nString to read:\n");
  fgets(s, dim, stdin);
  printf("\nThe string is: %s", s); 
  while(sscanf(s, " %s ", buffer) != EOF) {
    New->token[i] = malloc(dim*sizeof(char));
    strcpy(New->token[i], buffer);
    printf("\nAdded: %s", New->token[i]);
    ++i;
  }
}

For example, if i give "this is a string" as an input, sscanf will only get the word "this" multiple times without moving on to the next word.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
wako
  • 49
  • 3

1 Answers1

4

You need to increment the pointer of the source sscanf() reads from, so that it won't read from the same point, again and again.

Furthermore, the memory dynamically allocated for s by you didn't make any sense. It was too less in any case. By the call to fgets() later in the code I can see you meant to say s = malloc(dim * sizeof(char));, so I went ahead and fixed that.

Example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define dim 30

typedef struct string {
  char* token[dim];
} string;

int main() {
  string* New = malloc(dim*sizeof(string));
  char* s;
  char buffer[dim];
  int i = 0;
  s = malloc(dim * sizeof(char));
  fgets(s, dim, stdin);
  printf("The string is: %s\n", s); 
  char* ptr = s;
  int offset;
  while (sscanf(ptr, "%s%n", buffer, &offset) == 1) {
    ptr += offset;
    New->token[i] = malloc(strlen(buffer) + 1);
    strcpy(New->token[i], buffer);
    printf("Added: %s\n", New->token[i]);
    ++i;
  }

  // do work

  for(int j = 0; j < i; ++j)
    free(New->token[i]);
  free(New);
  free(s);

  return 0;
}

Output:

The string is: this is a string
Added: this
Added: is
Added: a
Added: string

PS: I am not sure about the schema of structures you have in mind, maybe you need to spend a moment or two, thinking about that twice; I mean whether your design approach is meaningful or not.

PPS: Unrelated to your problem: Do I cast the result of malloc? No!

Edit: As @chux said, " " in " %s%n" of sscanf() serves no purpose. I changed it to "%s%n".

Moreover, in order to reserve exactly as much memory as needed (which is the thing to do, when dealing with dynamic memory allocation), New->token[i] = malloc(dim*sizeof(char)); was changed to New->token[i] = malloc(strlen(buffer) + 1);.

gsamaras
  • 71,951
  • 46
  • 188
  • 305