bwilbz
bwilbz

Reputation: 1

scanf with more than one delimiter in C

I have a data file with strings, floats, and integers separated by a single comma and a random number of spaces. for example:

john    , smith ,  3.87 ,  2,  6

I would like to scan each value into a struct containing str,str,float,int,int & ignore the commas and spaces. I have figured out up to the float but cant seem to get the intgers. any help would be appreciated my code is as follows:

typedef struct applicant {  
char first[15]; 
char last[15];
float gpa;
int grev;
int greq;
} num1;

int main(int argc, char *argv[])
{
  FILE *in, *out;
  in = fopen(argv[1], "r");
  out = fopen(argv[2], "w");

  num1 class[10];

  int i;

  fscanf(in, "%[^,],%[^,],%f, %d, %d\n", class[i].first, class[i].last, &class[i].gpa, &class[i].grev, &class[i].greq);
  fprintf(out, "%s %s %f %d %d", class[i].first, class[i].last, class[i].gpa, class[i].grev, class[i].greq);

Upvotes: 0

Views: 504

Answers (2)

R Sahu
R Sahu

Reputation: 206667

I suggest the following approach.

  1. Read the contents of the file line by line.
  2. I am assuming the white spaces are not relevant. If that is indeed the case, replace the comma characters with spaces.
  3. Use a simpler format to read the data from the line of text to your struct.

Always check the return value of functions that read data from an input stream to make sure that you use the data only if the read operation was successful.


// Make it big enough for your needs.
#define LINE_SIZE 200

char line[LINE_SIZE];
if ( fgets(line, LINE_SIZE, in) != NULL )
{
   // Replace the commas by white space.
   char* cp = line;
   for ( ; *cp != '\0'; ++cp )
   {
      if ( *cp == ',' )
      {
         *cp = ' ';
      }
   }

   // Now use sscanf to read the data.
   // Always provide width with %s to prevent buffer overflow.
   int n = sscanf(line, "%14s%14s%f%d%d",
                  class[i].first,
                  class[i].last,
                  &class[i].gpa,
                  &class[i].grev,
                  &class[i].greq);

   // Use the data only if sscanf is successful.
   if ( n == 5 )
   {
      // Use the data
   }
}

Upvotes: 1

chanioxaris
chanioxaris

Reputation: 1006

As sturcotte06 mentioned you should use strtok() function alongside with atoi() and atof() to get the expected result.

char text[] = "john    , smith ,  3.87 ,  2,  6";

strcpy(class[i].first, strtok(text, ","));
strcpy(class[i].last, strtok(NULL, ",");
class[i].gpa = atof(strtok(NULL, ","));
class[i].grev = atoi(strtok(NULL, ","));
class[i].greq) = atoi(strtok(NULL, ","));

Upvotes: 2

Related Questions