none
fscanf - reading "comma seperted file"

    Question

  • Hi,

    I am reading information from an external file, into a variable array in my program.  I notice that if the file is larger - with extra columns the program crashes.  Is there a way to alter the program so that it can accept varying column's of data.

     

    void ReadFile(void)

    {

    double fVal_1, fVal_2,fVal_3;

    int ret = 0;

    FILE *infile;

    infile = fopen("C:\\File.csv");

    if(infile == NULL)

    {exit(0);

    }

    ret = fscanf(infile,"%s",chrX); //Skip past headers in file

    while(1)

    {

    ret = fscanf(infile,"%lf,%lf,%lf",

    &fVal_1,&fVal_2,&fVal_3);

    if(ret ==EOF) break;

    Table[i] = fVal_1;

    Table[i] = fVal_2;

    Table[i] = fVal_3;

    i++;

    }

    close(infile);

    }

    }

     

    So if the file is more then 3 columns it crashes, but I dont want it to.

     

    Friday, April 30, 2010 6:29 PM

Answers

  • Read one line at a time into a buffer using fscanf(infile, "%[^\n]", buf);

    Now use strtok_s with comma (,) as a delimiter to extract the values.

    You can store these values in a vector of floats after converting it to float using atof.


    «_Superman_»
    Microsoft MVP (Visual C++)
    • Proposed as answer by jinzai Friday, April 30, 2010 7:29 PM
    • Marked as answer by Jeffs_Programs Friday, April 30, 2010 8:33 PM
    Friday, April 30, 2010 6:47 PM

All replies

  • Read one line at a time into a buffer using fscanf(infile, "%[^\n]", buf);

    Now use strtok_s with comma (,) as a delimiter to extract the values.

    You can store these values in a vector of floats after converting it to float using atof.


    «_Superman_»
    Microsoft MVP (Visual C++)
    • Proposed as answer by jinzai Friday, April 30, 2010 7:29 PM
    • Marked as answer by Jeffs_Programs Friday, April 30, 2010 8:33 PM
    Friday, April 30, 2010 6:47 PM
  • <<_Superman_>> is right! (Not at all unusual.)

    That code looks like something taken from a more fixed parser...you are reading a maximum of 3 variables from the file...in order to make that different, you would have to change the function call to provide more variables. Also, that code is not intended to be used in a loop, and that While(1) loop is not at all useful in my opinion, unless you want an endless loop that will require user intervention (Ctrl-C, for example) to break. It is used in a lot of C text to allow you to have a program continue to run, but...its pretty worthless, even for that.

     

    In console apps, you can use _kbhit to drive such a loop, like this:

    while(_kbhit() == 0)

    Another thing about fscanf when parsing strings like are doing to skip this header...if that string does not comply with fscanf's notion of a string, you will fail to read the entire header. In your case, you need to find out more specific things about that header. As your code stands, a space in the text of the header will cause fsscanf to quit reading, and I think that you probably want it to read until it reaches a carriage return/line feed pait. That is pretty typical of CSVs that I have used in the past that have any additional information in the beginning of the file. (Often field names are put there, for example.)

     

    Anyway, here is your code back...it compiles and runs, but...it is dependent on the CSV file being precisely what it expects, another bugaboo in processing these types of files. Ultimately, Superman has given you the best way to do this, in my opinion...

    #include <stdlib.h>
    #include <conio.h>
    #include <iostream>
    
    using namespace std;
    
    void ReadFile(void)
    
    {
    	int ret = 0;
    	FILE *infile;
    
    	char chrX[256];
    	int i = 0;
    	double Table[3];
    
    
    	infile = fopen("C:\\File.csv", "r");
    	if(infile == NULL) exit(0);
    
    	ret = fscanf(infile,"%s",chrX); //Skip past headers in file
    	cout << "Header : " << chrX << endl;
    
    	ret = fscanf(infile,"%lf,%lf,%lf",
    	&Table[0],&Table[1],&Table[2]);
    	fclose(infile);
    	cout << "Value #1 :" << Table[0] << endl;
    	cout << "Value #2 :" << Table[1] << endl;
    	cout << "Value #3 :" << Table[2] << endl;
    	cout << "Press any key to exit." << endl;
    	while (_kbhit() == 0);
    
    }
    
    int main()
    {
    	ReadFile();
    }
    
    
    Friday, April 30, 2010 7:27 PM