2

I am able to extract fields in comma separate format using sscanf (see below) if all fields are populated. But if a field is blank then only up to the blank field is populated. Is there any way I can carry on, ignoring problem of blank fields so that subsequent fields do get populated?

#include <stdio.h>

int main(int argc, char* argv[]) {

   char* s = "Apple,Pear,Potato,11";

   char fruit1[10];
   char fruit2[10];
   char vegetable[10];
   int size;


   int num = sscanf(s, "%20[^,],%20[^,],%20[^,],%d", fruit1, fruit2, vegetable, &size);
   if (num == 4) {
      printf("This record contains 4 items\n");
      printf("first fruit: %s, second fruit: %s, vegetable: %s, size = %d\n", fruit1, fruit2, vegetable, size);
   }
   else {
      printf("This record does not contain 4 items\n");
   }


   // but here it fails - blank vegetable
   char* t = "Plum,Orange,,12";
   num = sscanf(t, "%20[^,],%20[^,],%20[^,],%d", fruit1, fruit2, vegetable, &size);

   if (num == 4) {
      printf("This record contains 4 items\n");
      printf("first fruit: %s, second fruit: %s, vegetable: %s, size = %d\n", fruit1, fruit2, vegetable, size);
   }
   else {
      printf("This record does not contain 4 items\n");
   }

   return 0;
}


/*
Prints:
This record contains 4 items
first fruit: Apple, second fruit: Pear, vegetable: Potato, size = 11
This record does not contain 4 items
*/
Angus Comber
  • 9,316
  • 14
  • 59
  • 107

2 Answers2

0

Avoid doing this manually, and use strtok :

char str[] = "Apple,Pear,Potato,11";
char* tokens = strtok (str,",");
// iterate over tokens ...
while (tokens != NULL)
{
  printf ("%s\n",tokens);
  tokens = strtok (NULL, ",");
}

Edit:

if you need to keep empty fields, consider the solution of this other discussion.

Community
  • 1
  • 1
quantdev
  • 23,517
  • 5
  • 55
  • 88
0

You can build your own scan function using strchr, note that scan replaces , with \0 in the original string, so if you want to tokenize a string literal (read only) you need an intermediate buffer:

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

char *scan(char **pp, char c)
{
    char *s = *pp, *p;

    p = strchr(*pp, c);
    if (p) *p++ = '\0';
    *pp = p;
    return s;
}

int main(void)
{
    char s1[] = "Apple,Pear,Potato,11";
    char s2[] = "Plum,Orange,,12";
    char fruit1[10];
    char fruit2[10];
    char vegetable[10];
    int size;
    char *p;

    p = s1;
    strcpy(fruit1, scan(&p, ','));
    strcpy(fruit2, scan(&p, ','));
    strcpy(vegetable, scan(&p, ','));
    size = strtol(scan(&p, ','), NULL, 10);
    printf("first fruit: %s, second fruit: %s, vegetable: %s, size = %d\n", fruit1, fruit2, vegetable, size);

    p = s2;
    strcpy(fruit1, scan(&p, ','));
    strcpy(fruit2, scan(&p, ','));
    strcpy(vegetable, scan(&p, ','));
    size = strtol(scan(&p, ','), NULL, 10);
    printf("first fruit: %s, second fruit: %s, vegetable: %s, size = %d\n", fruit1, fruit2, vegetable, size);

    return 0;
}

You can simplify your code using pointers:

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

char *scan(char **pp, char c)
{
    char *s = *pp, *p;

    p = strchr(*pp, c);
    if (p) *p++ = '\0';
    *pp = p;
    return s;
}

int main(void)
{
    char s1[] = "Apple,Pear,Potato,11";
    char s2[] = "Plum,Orange,,12";
    char *v[4], *p;
    int i;

    p = s1;
    for (i = 0; i < 4; i++) v[i] = scan(&p, ',');
    printf("first fruit: %s, second fruit: %s, vegetable: %s, size = %d\n", v[0], v[1], v[2], atoi(v[3]));

    p = s2;
    for (i = 0; i < 4; i++) v[i] = scan(&p, ',');
    printf("first fruit: %s, second fruit: %s, vegetable: %s, size = %d\n", v[0], v[1], v[2], atoi(v[3]));

    return 0;
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94