How to read every n lines from txt file in C - c

I am reading from a text file and the file is in the format
value1: 5
value2: 4
value3: 3
value4: 2
value5: 1
and then it repeats.
I know how to grab the data I need from one line, but I've searched everywhere and looked through various books and resources and I can't figure out a way to read from every 10 lines instead of one line.
This is what I have so far and I am aware that it has a couple mistakes and I have extra variables and it is incomplete but I am able to compile and all it does is print the first value from the file. my printf is mostly just a test to see what I'm reading from the file.
#include <stdio.h>
#include <math.h>
int main()
{
int line = 0;
int time = 0;
int switch0 = 0;
int switch1 = 0;
int switch2 = 0;
int switch3 = 0;
int pot = 0;
int temp = 0;
int light = 0;
FILE *infile = fopen("data.txt", "r");
FILE *outfile = fopen("matlab.csv", "w");
if (infile == NULL)
{
printf("Error Reading File\n");
exit(0);
}
fprintf(outfile, "Time,Switch0,Switch1,Switch2,Switch3,Potentiometer,Temperature,Light");
fscanf(infile, "time: %d\nswitch0: %d\nswitch1: %d\nswitch2: %d\nswitch3: %d\npotentiometer: %d\n temperature: %d\n light: %d\n",
&time, &switch0, &switch1, &switch2, &switch3, &pot, &temp, &light) != EOF;
printf("%d\n %d\n %d\n %d\n %d\n %d\n %d\n %d\n", time, switch0, switch1, switch2, switch3, pot, temp, light);
}
tl;dr how to read every 10 lines of text file and save into array
Thanks in advance

I know how to grab the data I need from one line
Well that's a good start. If you can read one line, you can read one line n times, right?
I've searched everywhere and looked through various books and resources and I can't figure out a way to read from every 10 lines instead of one line.
It's just more of the same. You could, for example, write a function that reads exactly one line and returns the data. Then call that function the requisite number of times.
If you really want to read all the data from n lines at once, you can do that to. Instead of your code:
fscanf(infile, "time: %d\n", &time[100]);
you can make the format string more extensive:
fscanf(infile, "time: %d\nswitch1: %d\nswitch2: %d\npotentiometer: %d\n",
&time, &switch1, &switch2, &potentiometer);
The \n is just another character to fscanf() -- you don't have to stop reading at the end of one line.
Be careful with this approach, though. It leaves you open to problems if you have a malformed file -- everything will break if one of the lines you expect happens to be missing or if one of the labels is misspelled. I think you'd be better off reading one line at a time, and reading both the label and the value, like:
fscanf(infile, "%s %d\n", &label, &value);
Then you can look at the string in label and figure out which line you're dealing with, and then store the value in the appropriate place. You'll be better able to detect and recover from errors.

Related

My program creates a file named date.in but it is not inserting all the numbers

Write a C program that reads from the keyboard a natural number n
with up to 9 digits and creates the text file data.out containing the
number n and all its non-zero prefixes, in a single line, separated by
a space, in order decreasing in value. Example: for n = 10305 the data
file.out will contain the numbers: 10305 1030 103 10 1.
This is what I made:
#include <stdio.h>
int main()
{
int n;
FILE *fisier;
fisier=fopen("date.in","w");
printf("n= \n");
scanf("%d",&n);
fprintf(fisier,"%d",n);
while(n!=0)
{
fisier=fopen("date.in","r");
n=n/10;
fprintf(fisier,"%d",n);
}
fclose(fisier);
}
Few things:
Function calls may return error. You need to check that every time.
fisier=fopen("date.in","w");
This should have been followed by an error check. To understand more on what it return, first thing you should do is read the man page for that function. See man page for fopen(). If there is an error in opening the file, it will return NULL and errno is set to a value which indicates what error occurred.
if (NULL == fisier)
{
// Error handling code
;
}
Your next requirement is separating the numbers by a space. There isn't one. The following should do it.
fprintf(fisier, "%d ", n);
The next major problem is opening the file in a loop. Its like you are trying to open a door which is already open.
fisier=fopen("date.in","r");
if(NULL == fisier)
{
// Error handling code
;
}
while(n!=0)
{
n=n/10;
fprintf(fisier,"%d",n);
}
fclose(fisier);
A minor issue that you aren't checking is the number is not having more than 9 digits.
if(n > 999999999)
is apt after you get a number. If you want to deal with negative numbers as well, you can modify this condition the way you want.
In a nutshell, at least to start with, the program should be something similar to this:
#include <stdio.h>
// Need a buffer to read the file into it. 64 isn't a magic number.
// To print a 9 digit number followed by a white space and then a 8 digit number..
// and so on, you need little less than 64 bytes.
// I prefer keeping the memory aligned to multiples of 8.
char buffer[64];
int main(void)
{
size_t readBytes = 0;
int n = 0;
printf("\nEnter a number: ");
scanf("%d", &n);
// Open the file
FILE *pFile = fopen("date.in", "w+");
if(NULL == pFile)
{
// Prefer perror() instead of printf() for priting errors
perror("\nError: ");
return 0;
}
while(n != 0)
{
// Append to the file
fprintf(pFile, "%d ", n);
n = n / 10;
}
// Done, close the file
fclose(pFile);
printf("\nPrinting the file: ");
// Open the file
pFile = fopen("date.in", "r");
if(NULL == pFile)
{
// Prefer perror() instead of printf() for priting errors
perror("\nError: ");
return 0;
}
// Read the file
while((readBytes = fread(buffer, 1, sizeof buffer, pFile)) > 0)
{
// Preferably better way to print the contents of the file on stdout!
fwrite(buffer, 1, readBytes, stdout);
}
printf("\nExiting..\n\n");
return 0;
}
Remember: The person reading your code may not be aware of all the requirements, so comments are necessary. Secondly, I understand english to a decent level but I don't know what 'fisier' means. Its recommended to name variables in such a way that its easy to understand the purpose of the variable. For example, pFile is a pointer to a file. p in the variable immediately gives an idea that its a pointer.
Hope this helps!
To draw a conclusion from all the comments:
fopen returns a file handle when successfull and NULL otherwise. Opening a file twice might result in an error (it does on my machine), such that fisier is set to NULL inside the loop. Obvioulsy fprintf to NULL wont do anything.
You only need to call fopen once, so remove it from the loop. After that it will work as intended.
It's alwas good to check if the fopen succeeded or not:
FILE *fisier;
fisier=fopen("date.in","w");
if(!fisier) { /* handle error */ }
You print no spaces between the numbers. Maybe that's intended, but maybe
fprintf(fisier,"%d ",n);
would be better.

Return value 3221225725 while scanning two files

For input two files "cl-clean-history" and "cd-clean-history" of similar structure of:
"Lift Convergence"
"Iterations" "cl"
1 1.14094e+00
2 1.14094e+00
and
"Drag Convergence"
"Iterations" "cd"
1 0.14094e+00
2 0.14094e+00
I want to write a program to read the values in second columns in both files and compute its divisor.
My program code is:
#include <stdio.h>
#include <errno.h>
int main (void)
{
double max_cl_cd, cl_cd_temp;
int lines_file;
int tab_line;
double tab_scan_file[200000][4];
int ch=0;
FILE *result_search_cl;
FILE *result_search_cd;
max_cl_cd=0.0;
if((result_search_cl=fopen("cl-clean-history","r"))==NULL)
{
printf("Unable to open input file\n");
}
else
{
lines_file = 0;
FILE *result_search_cd = fopen("cd-clean-history", "r");
FILE *result_search_cl = fopen("cl-clean-history", "r");
while (EOF != (ch=getc(result_search_cd)))
if ('\n' == ch)
++lines_file;
printf("Number of lines in file: %d \n",lines_file);
for (tab_line=0;tab_line<=lines_file;tab_line++) {
fscanf(result_search_cd,"\n");
fscanf(result_search_cd,"\n");
fscanf(result_search_cd,"%d",&tab_scan_file[tab_line][0]);
fscanf(result_search_cd,"\t");
fscanf(result_search_cd,"%f",&tab_scan_file[tab_line][1]);
fscanf(result_search_cd,"\n");
fscanf(result_search_cl,"%d",&tab_scan_file[tab_line][2]);
fscanf(result_search_cl,"\t");
fscanf(result_search_cl,"%f",&tab_scan_file[tab_line][3]);
fscanf(result_search_cl,"\n");
cl_cd_temp=tab_scan_file[tab_line][3]/tab_scan_file[tab_line][1];
if (cl_cd_temp>max_cl_cd)
{
max_cl_cd=cl_cd_temp;
}
printf("%f %f\n",tab_scan_file[tab_line][0],tab_scan_file[tab_line][1]);
}
fclose(result_search_cd);
fclose(result_search_cl);
}
printf("%f %f\n",tab_scan_file[tab_line][0],tab_scan_file[tab_line][1]);
return 0;
}
In my opinion there is something bad in scanf lines, but I don't see what exactly is bad. The first two scans of "\n" are intented to jump two first lines in file. I know that the second option is to perform loop starting from third line (for(tab_line=3; etc.) The %d scans integer value in first column and %f scans float value in second column in both files. Unfortunately, while running in Dev C++ the process exits with return value 3221225725. I found on stackoverflow.com that this value means heap corruption. How to overcome this problem?
I think you should read the fscanf documentation again:
Anyway, fscanf accepts as a second argument a format, so something like "%d" (the one you have used some lines later). When you invoke
fscanf(result_search_cd,"\n");
"\n" is not an identifier. You should replace this line with something like
while (getc(result_search_cd) != "\n"); //Skip first line
while (getc(result_search_cd) != "\n"); //Skip second line

Reading and Writing to Files in C

I'm fairly new to C. This is the first program I've written involving reading and writing to files. So far, I was able to read the file, perform the operations I need but I am having trouble with 2 things.
Whatever the file is, it omits the last line when reading. For example if the file has:
3
5
6
It will only read the 3 and 5. But if I leave an empty/blank line at the bottom it'll read all three. Any ideas as why that is?
I now need to take what I did, essentially converting volts to milliVolts, microVolts, etc. and write it back to the file. What I have been doing up until now is reading it from the file and working through the console. So essentially, I want write the last two printf statements to the file. I had some attempts at this but it wasn't working and I couldn't seem to find decent support online for this. When I tried, it would completely erase what was in the file before.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
FILE * file = fopen ("bacon.txt", "r");
float voltage = 0, voltageArray[100], voltageToMilli = 0,voltageToMicro = 0, voltageToKilo = 0, voltageToMega = 0;
int i = 1, j = 0;
fscanf (file, "%f", &voltage);
while (!feof (file)) {
printf("Line # %d\n", i);
printf ("The voltage is: %f\n", voltage);
voltageArray[j] = voltage;
fscanf (file, "%f", &voltage);
printf("The voltage in Element %d is: %f Volts",j,voltageArray[j]);
voltageToMilli = voltageArray[j] * 1000;
voltageToMicro = voltageArray[j] * 1000000;
voltageToKilo = voltageArray[j] * 0.001;
voltageToMega = voltageArray[j] *0.000001;
printf("\nThe voltage is %f Volts, which is: %f milliVolts, %f microVolts, %f kiloVolts, %f megaVolts",voltageArray[j],voltageToMilli,voltageToMicro,voltageToKilo,voltageToMega);
printf("\n\n");
i++;
j++;
}
fclose (file);
return (0);
}
Please try to keep explanations clear and simple as I am a beginner in C. Thank you!
For the first issue, the problem is that the loop logic is incorrect. On each iteration is stores the previous read data, reads the next data and then goes back to the top of the loop. The problem with this is that the next data is not stored until the next iteration. But after reading the last data item (and before storing it into the array) the feof check is always false. Refer to this question for why checking feof as a loop condition is almost always wrong.
Here is an example of how you could restructure your code to read all the items as intended:
int rval;
while ((rval = fscanf(file, "%f", &voltage)) != EOF) {
if (rval != 1) {
printf("Unexpected input\n");
exit(-1);
}
voltageArray[j] = voltage;
/* Do the rest of your processing here. */
}
problem is in the file there is nothing after the last number,
so, after reading the last number from the file, feof(file) is true.
and the while exits.
simplest fix is change it to this
while(fscanf (file, "%f", &voltage) == 1) {
and remove the other fscanf calls.
this works because that fscanf() call will return 1 when it is able
to read a number and either 0 or EOF (which is a negative number)
otherwise.

Having Trouble Taking information From .txt File and putting it in a .csv file in C

This is for a school project and I am having quite some difficulty with it. I am working in Visual Studio 2012. I am very new to C so sorry in advance.
Project Over View
Take Data from a text file (Manhattan_temp_data.txt) and write it into a .csv file (TemperatureData.csv). The ultimate goal is to have a spread sheet that can be used to create a visual representation of the temperature data for 1 year in Manhattan.
My text file looks as follows (Exactly 366 Lines)
Year Month Day Mean
1896 5 1 61.5
1896 5 2 63
1896 5 3 64.5
1896 5 4 -99 <The -99 means no collected data>
My .csv file looks as follows
Year \t Month \t Day \t Mean \t Interpolated Mean
Here is My Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>
//Structure for my Text file read
typedef struct TempTXTData{
int Year;
int Month;
int Day;
double Mean;
} TempTXTData_t;
int main ()
{
FILE *FPT; //Represents My Text File
FILE *FPC; //Represents My .csv File
int i;
TempTXTData_t TempData[366];
//Where I open both my text and .csv files
FPT= fopen("Manhattan_temp_data.txt", "r");
if( FPT == NULL )
{
printf("Load Failure Press any key to exit...\n");
exit(EXIT_FAILURE);
}
FPC= fopen("TemperatureData.csv", "w");
if( FPC == NULL )
{
fclose(FPT);
printf("Load Failure Press any key to exit...\n");
exit(EXIT_FAILURE);
}
//Function where I take data from my .txt file and input it into my .csv file
for(i=1; i<366 && fscanf(FPT, "%f %f %f %f", &TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean) !=4; i++)
{
for (i=1; i<366; i++)
fprintf(FPC, "%f, %f, %f, %f \n",&TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean);
}
//Closing Files
fclose(FPT);
fclose(FPC);
getch();
return 0;
}
Problems
When I run the code I get and open my excel sheet all my rows and columns are the same. The first Three Columns are all 0 while the final column is -9.3E+61.
My guess is that I am not getting the data from my .txt file which makes me believe I have an error in this line...
for(i=0; i<366 && fscanf(FPT, "%f %f %f %f", &TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean) !=4; i++)
Thanks for your Time,
Alex
There are few things but yet, no solution (can't test right now):
C array are indexed from 0 to size - 1 (which you actually do using < operator), so your loop should iterate from 0. Either you want to avoid the comment text, in that case you should keep the start index to 1 and store in TempData[i-1] otherwize, change the index to 0.
There is no reason for your datatypes for year / month / day not to be int.
The Spreadsheet is uninteresing here. First of all, you should look at the CSV file. There might be something to configure for excel to parse the data correctly.
Finally, and since you get an error because of that, your input file Manhattan_temp_data.txt should be opened read only (r).
Bonus one, I know that you windows guys have to put some C function to avoid closing terminal, but you should at least use a more standard function, such as getchar(). Doesn't cost much for you, and will compile on other operating systems as well.
Hope this will help you a bit, or at least to edit your post to fit the actual problems.
You need to add a newline character at the end of the format string this way
fprintf(FPC, "%f \t %f \t %f \t %f \t\n",&TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean);
/* ^ this character is newline.
And since your Year, Month and Day are int's you have to use the %d specifier
fprintf(FPC, "%d \t %d \t %d \t %f \t\n",&TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean);
And you dont pass the address of the fields to fprintf but instead the fields remove the &
fprintf(FPC, "%d \t %d \t %d \t %f \t\n", TempData[i].Year, TempData[i].Month, TempData[i].Day, TempData[i].Mean);
And a suggestion, check that fscanf read exactly the number of arguments you want to read in your case change this
fscanf(FPT, "%f \t %f \t %f \t %f \t", &TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean) !=EOF
to this
fscanf(FPT, "%d \t %d \t %d \t %f \t\n", &TempData[i].Year, &TempData[i].Month, &TempData[i].Day, &TempData[i].Mean) != 4
since fscanf returns the number of items succesfully matched, from the Linux manual pages
Also, your fscanf will fail with the first line of your file, thus not updating the stream pointer staying at the beginig of the file, so you must read the entire line and use sscanf otherwise you will not be able to skip the first line and continue reading, instead your code will abort reading at the first line and you will end up with an empty file.
RETURN VALUE
These functions return 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.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read
error occurs, in which case the error indicator for the stream (see ferror(3)) is set, and errno is set indicate the error.
One more thing, your format string could be
"%d\t%d\t%d\t%f\n"
you don't need the extra spaces and the last \t character.
This code, should do it
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
//Structure for my Text file read
typedef struct TempTXTData{
int Year;
int Month;
int Day;
double Mean;
} TempTXTData_t;
int main ()
{
FILE *FPT; //Represents My Text File
FILE *FPC; //Represents My .csv File
int i;
int done;
TempTXTData_t TempData[366];
//Where I open both my text and .csv files
//FPT= fopen("Manhattan_temp_data.txt", "r");
FPT = fopen("data.dat", "r");
if (FPT == NULL)
{
printf("Load Failure Press any key to exit...\n");
exit(EXIT_FAILURE);
}
FPC= fopen("TemperatureData.csv", "w");
if( FPC == NULL )
{
fclose(FPT);
printf("Load Failure Press any key to exit...\n");
exit(EXIT_FAILURE);
}
done = 0;
for (i = 1 ; (i < 366) && (done == 0) ; i++)
{
char buffer[1024];
char *pointer;
/* using fgets is better as was mentioned in other answers */
pointer = fgets(buffer, sizeof(buffer), FPT);
if (pointer != NULL)
{
int matched;
matched = sscanf(pointer, "%d%d%d%lf", &(TempData[i].Year), &(TempData[i].Month), &(TempData[i].Day), &(TempData[i].Mean));
if (matched == 4)
fprintf(FPC, "%d,%d,%d,%f\n", TempData[i].Year, TempData[i].Month, TempData[i].Day, TempData[i].Mean);
}
else
done = 1;
}
//Closing Files
fclose(FPT);
fclose(FPC);
return 0;
}
You edited the question potentially destroying previous answers, which is not a good manoeuvre.
Since you changed the year, month, day elements into int (from double), you have to change the scanf() and printf() strings. One of the gotchas with scanf() is that %f is for reading float values and %lf is for reading double values, but printf() uses %f for printing both (because float values are converted to double during the function call).
You don't skip the heading line of the file; that's a problem.
Were it me, I'd read a line at a time using fgets() and then scan the line that was read with sscanf(). This allows me to detect mis-formatted data more easily.
It seems curious that the years you're dealing with have but 128 days; most of the ones I encounter have 365 or 366 (a problem now fixed in the question!).
Don't test fscanf() for EOF; test for 'gave me the correct number of values'.
Arrays in C start at index 0.
Your code nests the input and output loops; this is mildly disastrous since you print 366 result values for the first row read, then another 366 for the next row read, and so on. Note that most of those values are undefined; they needn't be zeros or anything useful like that. You only want to print after you've read everything (especially when you get to interpolate missing values). You don't want to print addresses. You do want to print newlines.
enum { MAX_DAYS_PER_YEAR = 366 };
char line[4096];
/* Skip header line */
if (fgets(line, sizeof(line), FPT) == 0)
{
fputs("Empty file!\n", stderr);
exit(1);
}
/* Read up to 366 input lines */
for (i = 0; i < MAX_DAYS_PER_YEAR; i++)
{
if (fscanf(FPT, "%d %d %d %lf", &TempData[i].Year, &TempData[i].Month,
&TempData[i].Day, &TempData[i].Mean) != 4)
break;
}
/* Print only the lines that were read */
for (j = 0; j < i; j++)
fprintf(FPC, "%d\t%d\t%d\t%.2f\n", TempData[i].Year, TempData[i].Month,
TempData[i].Day, TempData[i].Mean);
This produces tab-separated data (a TSV file), but it is common to refer to such files as CSV files, even though the C is blatantly inaccurate. (DSV for 'delimiter separated values' is an accurate but rare term for such files. The output file is a DSV with tab delimiters, in contrast to a DSV with comma separators.)

Reading information from text files, line by line

I want to learn how to read .txt files in C, line by line so that the information in each line can be used in loops etc. I don't have a homework exercise for this but I need to figure it out for a project to write a script for an astronomy package.
So in order to learn how to do this I created a file called list.txt with the numbers 1,2,3,4,5,6,7,8,9 each on separate lines and I want the program to sum the values on each line. I also created an output file called sum.txt and the program is supposed to sum the lines, and print the sum to the output file.
I am getting an error when I run the program and I'm not sure what the problem is as I don't fully understand this. I got this program in a book on C and tried to modify it to run it on my PC.
The reason I need to be able to do this is because I need to take information from each line in a list (each line containing one string). But I want to learn to do it with numbers first.
Here's the code:
#include<stdio.h>
int main(void)
{
int a, sum = 0;
FILE *ifp, *ofp;
ifp = fopen("list.txt", "r");
ofp = ("sum.txt", "w");
while (fscanf(ifp, "%d", &a) == 1)
{
sum += a;
fprintf(ofp, "The sum is %d. \n", sum);
fclose(ifp);
}
return 0;
}
You forgot to write fopen here:
ofp = ("sum.txt", "w");
Also, you should move the fclose (and possibly the fprintf) out of the while loop, since you only want to close the file after reading all the lines.
You need to close the input file after the loop and move the fprintf outside the loop too:
} // end of while loop
fprintf(ofp, "The sum is %d. \n", sum);
fclose(ifp);
Also don't forget to do error checking and ensure that you've opened the files before you go on and to IO on them.

Resources