Using ANSI C how to Read a .csv file

Posted on 2016-10-31
Last Modified: 2016-11-01
I am using a bash shell script to parse a .csv file to create a text file that I read using ANSI C to fill some arrays.  I would like to learn how to read the .csv file just using C.  I only need the last 5 columns of the .csv file.  The .csv file has a one line descriptive header that needs to be skipped,  I have attached a modified version of the C code as well as the .csv file.
Question by:dwortman
LVL 19

Expert Comment

ID: 41867146
You could use a modified scanf to read the CSV entries.  Putting a "*" after the % in a match omits that bit of data.  You can also match the commas between the fields in the scanf string (no need to have spaces).

Reading directly from the csv file:
    fscanf(InputFile, "%*12[0-9/],%*d,%*3[A-Z],%*f,%*f,%*f,%f,%f,%f,%f,%f\n", &A_Array[i], &B_Array[i], &C_Array[i], 
									  &D_Array[i], &E_Array[i]);

Open in new window

The first field matches 12 characters of 0 to 9 or slash, matching the initial date field.  an alternative could be
Similarly, the %*3[A-Z] matches the timezone field.
The next three %*f miss out the next three floating point values.
The last 5 %f collect the values you want.

To skip the header line, you could have something like this, just before your "for i" loop:
    fscanf(InputFile, "%*s\n")
LVL 33

Expert Comment

ID: 41867222
fscanf is a dangerous function if you can't guarantee the input file is always valid.

you better read the file line by line and parse the input either by using strtok or by stepping from one delimiter to the next.

#include stdio.h

#define MAX_LINE 1024
#define MAX_TOKEN 256

int main(int nargs, char** szargs)
      FILE * pfile = NULL;
      char    buf[MAX_LINE] = { 0 };   // always use a sufficient maximum size 
      int nlines = 0;
      char * pbuf;

      if (nargs != 2) return -1;  //error no file path given
      pfile = fopen(szargs[1], "rt");
      if (pfile == NULL) return -2;  // file doesn't exist or already opened exclusively

      while (pbuf = fgets(buf, sizeof(buf), pfile))
             char * p = pbuf;
             int ntoken = 0;
             while ((p=strchr(p, ';')) != NULL || (p = strchr(p, '\n)) != NULL)
                   int     len = p - pbuf;
                   char  sztoken[MAX_TOKEN];
                   if (len >= MAX_TOKEN) return -3;  // token too Long
                   strncpy(sztoken, pbuf, len);
                   // do something with sztoken
                   // for example copy it into table[nlines][ntoken];
                   pbuf = p+1;
      return 0;        

Open in new window

note, the above is not tested.

LVL 40

Expert Comment

ID: 41867372
It's worth noting that parsing out CSV file is actually quite complicated because there are various different flavours of CSV and so you need to know how to correctly handle the flavour you are using. You'd probably be better of not re-inventing the wheel and using a purpose built library, such a libcsv.
LVL 19

Expert Comment

ID: 41867464
I guess there are potential problems with fscanf, but the only data being read here is floating point values - all that will happen with a malformed line is that the scanf will fail to match the line so will not return the value 11 (the number of matched fields).   Adding a check for a return code of 11 would be sensible here.  Problems tend to happen with strings, but the only 2 here are length-limited in the scanf format, and are anyway discarded. fscanf() also does the format conversion for you, so you don't have to add strtof() calls to convert the strings that strtok() returns.

The format seems to pretty simple here - no embedded quotes, not complex data structures, just simple values separated by commas. Using a library might be overkill (and some environments may have policies against using extra libraries), and rolling your own is often a useful learning exercise.

Author Comment

ID: 41868430

I like the way you are approaching this problem because I can basically understand it.  However, when I compile it I get the following errors:  (Please see attached file with my comments).
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.


Author Comment

ID: 41868640
I found a syntax error in my code.  I need to check things out and will get back to close this ticket out.

LVL 19

Accepted Solution

simon3270 earned 500 total points
ID: 41868666
Have you still got the backslash at the end of the first part of the line?  You don't need it (you are already within parentheses, you don't need to tell the compiler that the line hasn't finished!)  I think what's happened is that you have a space after the \ - if you have a \, it must be the last thing on the line.

As for the complaint about "]" in your comment, put [code] before the line of code, and [/code] after it.  I found that the easiest way when sending you the updated line.  An alternative would be to change all of the [i] to []i] - that stops the text interpreter from treating your [i] as an instruction to start using italics, and just treats it as a string of 3 characters.

(Edit - took me a while to write this comment so that the square brackets came out right - didn't spot that you'd already corrected it!)

Author Comment

ID: 41868735

The only problem now is that the 1st is not being skipped.  What you suggested to skip the first line looks like it should work.


Author Comment

ID: 41868914

I got it figured out.

Thanks for the help.

Author Closing Comment

ID: 41868915
Thanks for the help.

Featured Post

ScreenConnect 6.0 Free Trial

Discover new time-saving features in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode ( They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now