You are here:

C++/How to differentiate integer and alphabets

Advertisement


Question
Dear Sir,
I have previously asked a question on how to differentiate integers and alphabets when reading from a .txt file. thank you so much for your kind advise. But too bad my previous question was too vague. Below is the sample .txt file which i would read from.
"
Data Logged on September 16, 2006, at 15:09:27

Datalog_Params

Log_Mode = 2
Sampling_Factor = 8
Defined_Sample_Size = 4000
Captured_Sample_Size = 4000
Delay_Sample = 0
Static_Sample = 10


Smp_No.      AN_EnB_HYG   BY_Cmd_HDA   IJ_MJK_Value
0       -20001       -20000          -69
1       -20001       -20001          121
2       -20001       -20001          -90
.          .          .          .
.          .          .          .
.          .          .          .
.          .          .          .
3999        65536      1420544          305   
"
So what I need to do is to actually read the figures from some coloums (for e.g AN_EnB_HYG & IJ_MJK_Value)...from sample no.0 to 3999. And calculate the max, min and average for the figures under AN_EnB_HYG & IJ_MJK_Value.. Every information besides these 2 coloums of figures are redundant to me..Please advise...thanks!  

Answer
In fact you have all the information you require in my answer to your previous question. I assume you have some experience in writing C as you claimed in your original question.

The way to proceed is as follows:

1/ Note that the lines at the start of the file are not required. So read and throw them away until you reach the first line that is not one of the header lines (i.e. the first line of table data). How you determine this is up to you: maybe there are always a fixed number of lines of information and column headings at the start of the file, or maybe you check each line read to see if it contains the table column heading strings (e.g. you see if the first text on the line is "Smp_No."). You can use a modified form of the do while loop using fgets I showed in my original answer. You might find the C string functions such as strncmp of use as well (include string.h).

2/ The table has 4 values per line of which, in the example you give, only 2 are required. Assuming the values are all in the range of values that fit into the int type your compiler uses then you can read the values for each row in the table using fscanf thus:

   int field0 = 0;
   int field1 = 0;
   n = fscanf( inputFile, "%*d%d%*d%d", &field0, &field1 );

That is you read all integer values but ignore the values from the first and third columns (the %*d format specifiers) and keep those from the second and forth columns (the %d format specifiers).

Alternatively, you can treat the unwanted columns as strings and read but ignore them using a %*s format specification:

   n = fscanf( inputFile, "%*s%d%*s%d", &field0, &field1 );

In the code lines above I have specified that the read integer values be placed into scalar integer variables field0 and field1. I would think it more likely that you would read this data into values one line (row) at a time using a loop until the end of the file (or end of the table at least) or you have read enough values and place the values into an array or some other container:

   #define MYPROGRAM_MAX_ROWS_OF_DATA    1000
   #define MYPROGRAM_NUMBER_OF_COLUMNS   2

   /* Array index values for each column */
   #define MYPROGRAM_BY_Cmd_HDA          0
   #define MYPROGRAM_IJ_MJK_Value        1

   ...

   int data[MYPROGRAM_MAX_ROWS_OF_DATA][MYPROGRAM_NUMBER_OF_COLUMNS];

   ...





   int row = 0;
   int  n = 0;
   while ( row < MYPROGRAM_MAX_ROWS_OF_DATA && ! feof(inputFile) )
   {
       n = fscanf( inputFile, "%*d%d%*d%d"
         , &data[row][MYPROGRAM_BY_Cmd_HDA]
         , &data[row][MYPROGRAM_IJ_MJK_Value]
         );
       if ( 2==n )
       {
         ++row; /* OK, increment row count */
       }
       else
       {
         break; /* error or EOF, break out from data reading loop */
       }
   }

In the above code I use a 2 dimension array to store the read values. It can store many rows of data but only two elements can be stored for each row as only two columns are read and stored from each row of data in the file.

The loop continues until either there is no further space to store data or the end of file is reached. Within the loop one row of data is read using fscanf and the format specification string shown above. However the pointers to where to store the read and converted integer values are now the addresses for the elements for the columns of the current row in the array. Note that we require the address of operator ( & ) as we are not specifying (just) the first element of the array (i.e. specifying &data[0][0] would be the same as just specifying data, but this does not work for any of the other elements of the array).

An alternative would be to use a single dimension array of elements of a user defined struct type which contains fields for each of the columns read from the table:

   #define MYPROGRAM_MAX_ROWS_OF_DATA    1000

   ...

   /* Structure to contain the data for each row */
   typedef struct tag_table_data
   {
       int BY_Cmd_HDA;
       int IJ_MJK_Value;
   }
   table_data;

   ...

   table_data data[MYPROGRAM_MAX_ROWS_OF_DATA];

   int row = 0;
   int  n = 0;
   while ( row < MYPROGRAM_MAX_ROWS_OF_DATA && ! feof(inputFile) )
   {
       n = fscanf( inputFile, "%*d%d%*d%d"
         , &data[row].BY_Cmd_HDA
         , &data[row].IJ_MJK_Value
         );
       if ( 2==n )
       {
         ++row; /* OK, increment row count */
       }
       else
       {
         break; /* error or EOF, break out from data reading loop */
       }
   }

Note that you will probably wish to check for various conditions after the loop.  A value of n (the returned value from fscanf) of 2 or EOF can indicate success.

2 because everything was read correctly but the while loop conditions were no longer met as either the limit of the number of rows that could be stored was reached or the end of file was reached, as detected by feof. Both are OK, although you might wish to check the value of row to see if it is maxed out as you may be missing some data if it is. If so increase its value.

EOF because nothing was read and converted for the row before end of file was reached (OK) _or_ there was a read error (BAD). To determine which check the error indicator for the stream using ferror, and if set (ferror returns a non-zero value) then call errno to get the specific error condition code.

If n is another value (e.g. 1) then fscanf failed to read and convert a whole row of values and maybe the data file is corrupted.

The code I show here is for example and demonstration purposes only. It may contain errors and typos etc. If so, then I am sorry and apologise. It is _not_ production quality. For example you may wish to use a more sophisticated memory allocation scheme for storing the read values or use a different container type that supports dynamically allocated elements and resizing etc.

I shall not answer further C questions on this subject. Remember I am a C++ expert not a C expert!  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.