0

I have a programming assignment that gives a data file “candidatesdata.txt” You are supposed to read information in and decipher what is the name, gender, height, and weight. The only problem is that there are quotations around the name and commas in between each data record. The file goes as follows:

Name,Gender,Height,Weight
"Tanner, Mark C.”,M,71.8,180.25
"Jinglehiemmerschmitt, John J.”,M,70.75,185.3
"Parker, Sarah J.",F,65.25,120.3

..cont.

How do I read the data records and ignore the quotations and the commas? This is what I have so far, it deletes some commas and quotations but also in the process it deletes the names.

#include <stdio.h>

struct candidateinfo
{
    char name[50];
    char gender;
    double height;
    double weight;
}candidate;


    int main()
{
    int count =0;
    FILE *candidate_data;


    // Open file
    candidate_data = fopen("/Users/moisestrevino/Documents/CS 1324/Assignment #5/Assignment #5/candidatedata.txt","r");

    fscanf(candidate_data, "%*[^\n]");
    fgetc(candidate_data);

    // Get rid of unecessary letters

      while (count<40)
      {
          count++;

         fscanf(candidate_data,"\"%[^\"],%c,%lf,%lf\n", candidate.name, &candidate.gender, &candidate.height, &candidate.weight);

          printf("%s %c %lf %lf\n",candidate.name, candidate.gender, candidate.height, candidate.weight);
      }

    fclose(candidate_data);
    return 0;

 }

Output:

     Tanner, Mark C.  0.000000 0.000000
,M,71.8,180.25
  0.000000 0.000000
Jinglehiemmerschmitt, John J.  0.000000 0.000000
,M,70.75,185.3
  0.000000 0.000000
Parker, Sarah J.  0.000000 0.000000
,F,65.25,120.3
  0.000000 0.000000
Meeks, Kalvin R.  0.000000 0.000000
,M,57.25,210.2


cont...
  • you ___must___ read [this](http://stackoverflow.com/q/5431941/2173917) first. – Sourav Ghosh May 04 '15 at 12:31
  • And also please indent your code – Eregrith May 04 '15 at 12:32
  • Should I use EOF instead? – Danny Trevino May 04 '15 at 12:35
  • use `fgetc()` instead of `fscanf()` for that. – Iharob Al Asimi May 04 '15 at 12:46
  • 3
    Some of your quote characters are non-ASCII typographic quote marks - did you paste this from a word document? Also, the reason for the quotes is that there are commas inside the name field. – Random832 May 04 '15 at 12:49
  • Leave the commas, just detect them in your fscanf formats they are field delimiters. As for the quotes it's easier to read them in as part of the name, which you then tweak the string in your program. Skip the first line using format "%[^\n]\n". Read a line with scanf( " %s., %lf , %lf., %lf \n",candidate.name, &candidate.age,&candidate.height,&candidate.weight); – phil May 04 '15 at 12:59
  • @rhubarbdog `"%s"` will not scan in `"Tanner, Mark C."` due to its spaces and only scan in `"Tanner,"`. – chux - Reinstate Monica May 04 '15 at 14:50

2 Answers2

1

Your code contains lots of problems. There are too many to mention , so here is the fix:

If the file contains data in the form:

Name,Gender,Height,Weight

and then,

"Tanner, Mark C.",M,71.8,180.25
"Jinglehiemmerschmitt, John J.",M,70.75,185.3
"Parker, Sarah J.",F,65.25,120.3

then the below fix will work out.

After the fopen, you can use

fscanf(candidate_data, "%*[^\n]");
fgetc(candidate_data);

The first line scans and discards everything until a newline character. The second line consumes the newline character. After this, use

fscanf(candidate_data, " \"%[^\"]\",%c,%lf,%lf", name, gender, height, weight);

Assuming you have already declared a char array of considerable size named name, a char of name gender and two doubles of names height and weight, here is the breakdown of the above fscanf:

  • (space) scans and discards all whitespace characters until the first non-whitespace character.
  • \" scans the " from the file and discards it.
  • %[^\"] scans everything until a " and stores it in name.
  • \" scans the " from the file and discards it.
  • , scans and discards a comma.
  • %c scans a character and stores it in gender.
  • , scans and discards a comma.
  • %lf scans a double and stores it in height.
  • , scans and discards a comma.
  • %lf scans a double and stores it in weight.

Now you can print each value. Read more data by putting the above fscanf in a loop.

But how do you know when the data has ended? Check the return value of fscanf. fscanf returns the number of input items successfully matched and assigned, which can be fewer than provided for, or even zero in the event of an early matching failure.

In your case, fscanf will return 4 if all data was successfully scanned. So, just read on data until fscanf does not return 4.


As suggested by @chux, You can prevent buffer overflows by using
fscanf(candidate_data, " \"%49[^\"]\",%c,%lf,%lf", name, gender, height, weight);

The 49 tells scanf to scan a maximum of 49 characters for name(+1 for the NUL-terminator)

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
  • 1
    `" \"%[^\"]",%c,%lf,%lf"` --> `" \"%[^\"]\",%c,%lf,%lf"` (add slash) Further Suggestion `" \"%49[^\"]\", %c ,%lf ,%lf"` (add spaces, width) – chux - Reinstate Monica May 04 '15 at 14:44
  • @chux , Thanks. Missed the slash. As per the OP's format of the text file, the spaces aren't required. Added the other suggestion. – Spikatrix May 04 '15 at 14:59
  • Recommend adding @Random832 comment about input file using various quote makes `"Tanner, Mark C.”` `"` vs. `”`. – chux - Reinstate Monica May 04 '15 at 15:05
  • @chux , BTW, How do I scan `”` and print it in the console? `fscanf` doesn't seem to work as expected and printing `”` also prints weird things in the console. – Spikatrix May 05 '15 at 05:44
  • `”` (and this is not `"`) is a non-ASCII character. To read this in from the console and to print out correctly is system specific - unable to provide general solution. Printing usually involves using `wprintf()` and `wchar_t`. – chux - Reinstate Monica May 05 '15 at 15:38
0

If each line contains all fields, you can use str(r)chr+atof instead, e.g.

char line[100];
while( fgets(line,100,candidate_data) )
{
  char *p = strrchr(line,',');
  weight = atof(p+1); *p=0;
  p = strrchr(line,',');
  height = atof(p+1);
  gender = *--p;
  *strrchr(line,'"')=0;
  strcpy( name, strchr(line,'"')+1 );
}
user411313
  • 3,930
  • 19
  • 16