Reading a data file - unwanted extra value at the end of array - c

I'm fairly new to programming so apologies for any silly errors/oversights.
I'm trying to write a program that reads a data file with 3 columns of numbers and puts them into arrays. I'd like to be handle files of up to, say 100 elements.
The issue is that after I read a data file which I know to contain 20 elements, an extra value or 0.00000 is slapped onto the end of each array, so it has written 21 values instead of the 20 I want.
My code looks like this:
#include <stdio.h>
#include <cpgplot.h>
#include <stdlib.h>
#include <math.h>
#define MAXELEMENTS 100
int main()
{
/*Declare variables*/
float volume[MAXELEMENTS], temp[MAXELEMENTS], pressure[MAXELEMENTS];
int cnt = 1;
int i;
FILE *f;
char headings[MAXELEMENTS];
char filename[100];
/*Prompt user for file name*/
printf("Please enter the name of the file: ");
scanf("%s", &filename);
f = fopen(filename, "r");
if(f == NULL)
{
printf("File not found\n");
exit(EXIT_FAILURE);
}
/* Buffer line to read the headings of the data*/
fgets(headings, MAXELEMENTS, f);
/* Read records from the file until the end is reached*/
while(!feof(f) && cnt<MAXELEMENTS){
if (fscanf(f, "%f %f %f\n", &volume[cnt], &temp[cnt], &pressure[cnt]) > 0) cnt++;
}
So when I print out the arrays I get the 20 values I want PLUS an unwated 0.000000 value at the end of each. This created a lot of problems later when I try and plot some of the data.
From the searching I've done here and elsewhere it looks like it is the while(!feof(f)... loop that's the problem.
I'd be really grateful if anyone can help me get arrays just containing the values in the .dat file.
Thanks

The array index beggin in 0 like in volume[0], that is, you initialize cnt=0; not 1.
Additionaly,
if (fscanf(f, "%f %f %f\n", &volume[cnt], &temp[cnt], &pressure[cnt]) > 0)
cnt++;
else
break;
This break will probably solve the problem.
EDIT:
The code i can use to print:
i =0; // here you begging actualy with 0 or 1? Is here alrready corrected?
while (i < cnt)
{ printf("%f\t %f\t %f\n", volume[i], temp[i], pressure[i]);
i++; ....
Is here allready corrected? Is not, you print one more from 0 to cnt-1, and enter from 1 to cnt-1. Only why at ende and not at begging of the array have you the 0? Anyway, cold you test initializing cnt to 0? Is this exactly what do you use?

Check out how you are printing out the array. Your indices might be off leading to a trailing 0.0 value. Also you should initialize cnt=0.

Related

Reading first 5 characters from a file using fread function in C

How do i read some 5 to 10 characters from a sample txt file using an fread funtion.
I have the following code:
#include <stdio.h>
main()
{
char ch,fname[20];
FILE *fp;
printf("enter the name of the file:\t");
gets(fname);
fp=fopen(fname,"r");
while(fread(&ch,1,1,fp)!=0)
fwrite(&ch,1,1,stdout);
fclose(fp);
}
when i enter any sample filename..it prints all the data of the file.
my question is how to print only the first 5 to 10 characters from the sample file.
Your while loop runs until read reaches the end of the file (reads 0 bytes for the first time).
You will want to change the condition by using a for loop or a counter.
i.e. (these are suggestions, not the full working code):
int counter = 10;
while(fread(&ch,1,1,fp)!=0 && --counter)
fwrite(&ch,1,1,stdout);
or
int i;
for(i=0; i < 10 && fread(&ch,1,1,fp) > 0 ; i++)
fwrite(&ch,1,1,stdout);
Good luck!
P.S.
To answer your question in the comments, fread allows us to read the data in "atomic units", so that if a whole unit isn't available, no data will be read.
A single byte is the smallest unit (1), and you are reading one unite (of a single byte), this is the 1,1 part in the fread(&ch,1,1,fp).
You could read 10 units using fread(&ch,1,10,fp) or read all the bytes unrequited for a single binary int (this won't be portable - it's just a demo) using int i; fread(&i,sizeof(int),1,fp);
read more here.
Here is a modified version of your code. Check the comments at the lines that are modified
#include <stdio.h>
#define N_CHARS 10 // define the desired buffer size once for code maintenability
int main() // main function should return int
{
char ch[N_CHARS + 1], fname[20]; // create a buffer with enough size for N_CHARS chars and the null terminating char
FILE *fp;
printf("enter the name of the file:\t");
scanf("%20s", fname); // get a string with max 20 chars from stdin
fp=fopen(fname,"r");
if (fread(ch,1,N_CHARS,fp)==N_CHARS) { // check that the desired number of chars was read
ch[N_CHARS] = '\0'; // null terminate before printing
puts(ch); // print a string to stdout and a line feed after
}
fclose(fp);
}

Get numbers only from a text file using c

/edited/
I'm new here.
I have a text file that reads:
6
<cr>
R 0
R 1
R 4
R 36
R 0
R 4
This is what I have. I want to read each line into an array so that I can convert that array into an integer so I can print only the numbers of whichever line I want later.
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int main()
{
FILE *fr; /*declares file pointer*/
int i, j, num[32];
char array[32][32], input_file[32], line[32];
printf("Enter file: ");
fflush(stdin);
scanf("%s", input_file);
fr = fopen(input_file, "r");
for(i=0;i<32;i++)
for(j=0;j<32;j++){
array[i][j] = \'0';
}
for(i=0;i<32;i++){
line[i] = '\0';
}
if(fr != NULL){
while(fgets(line, sizeof(line), fr) != NULL){
strcpy(array[i],line);
num[i] = atoi(array[i]);
i++;
printf("%d\n", num[i]);
}
}fclose(fr);
else{
perror(input_file);
}
}
I'm not getting any errors but it isn't printing the right thing; this is what it prints:
-370086
-370086
-370086
-370086
-370086
-370086
-370086
-370086
Can anyone explain to me what is going wrong?
I think I'd handle this a bit differently. Though you haven't stated it explicitly, I'm going to assume that the first number is telling us how many more lines of letters/numbers we're going to read (not including the blank line). So, we want to read that, then read the rest of the lines, ignoring any leading non-digits, paying attention only to the numbers.
If that's correct, we can simplify the code somewhat:
int num_lines;
int i;
int *numbers;
fscanf(infile, "%d", &num_lines); // read the number of lines.
numbers = malloc(sizeof(int) * num_lines); // allocate storage for that many numbers.
// read that many numbers.
for (i=0; i<num_lines; i++)
fscanf(infile, "%*[^0123456789]%d", numbers+i);
// the "%*[^0123456789]" ignores leading non-digits. The %d converts a number.
There are several issues:
You're never setting input_file to anything, so you seem to be opening a random file.
You're double-using i in the nested loops.
You're not showing array at all, so it's impossible to tell how it's declared.
You are increasing the loop index before using it to print the number, so you're always "missing" and printing the number in the next (not yet written) slot.
You should use memset() to clear the arrays if you're worried. There's no need to clear arrays that are going to be overwritten, such as line which is written to by fgets().
Assuming array is a char array, when you do:
...
strcpy(array[i],line);
num[i] = atoi(array[i]);
...
Your actually converting the entire line and not the integer in it. You should consider using fscanf, or at least search for the integer inside the line variable and convert it.
Doing atoi(array[i]) is the same as atoi("R 32\n") for example.

Simple count how many integers are in file in C

Im currently learning C through random maths questions and have hit a wall. Im trying to read in 1000 digits to an array. But without specifiying the size of an array first i cant do that.
My Answer was to count how many integers there are in the file then set that as the size of the array.
However my program returns 4200396 instead of 1000 like i hoped.
Not sure whats going on.
my code: EDIT
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
FILE* fp;
const char filename[] = "test.txt";
char ch;
int count = 0;
fp = fopen(filename, "r");
if( fp == NULL )
{
printf( "Cannot open file: %s\n", filename);
exit(8);
}
do
{
ch = fgetc (fp);
count++;
}while (ch != EOF);
fclose(fp);
printf("Text file contains: %d\n", count);
return EXIT_SUCCESS;
}
test.txt file:
731671765313306249192251196744265747423553491949349698352031277450632623957831801698480186947885184385861560789112949495459501737958331952853208805511
125406987471585238630507156932909632952274430435576689664895044524452316173185640309871112172238311362229893423380308135336276614282806444486645238749
303589072962904915604407723907138105158593079608667017242712188399879790879227492190169972088809377665727333001053367881220235421809751254540594752243
525849077116705560136048395864467063244157221553975369781797784617406495514929086256932197846862248283972241375657056057490261407972968652414535100474
821663704844031998900088952434506585412275886668811642717147992444292823086346567481391912316282458617866458359124566529476545682848912883142607690042
242190226710556263211111093705442175069416589604080719840385096245544436298123098787992724428490918884580156166097919133875499200524063689912560717606
0588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450
Any help would be great.
You forgot to initialize count, so it contains random garbage.
int count = 0;
(But note that with this change it's still not going to work, since %d in a scanf format means read as many digits as you find rather than read a single digit.)
Turn on your compiler's warnings (-Wall), it will tell you that you didn't initialize count, which is a problem: it could contain absolutely anything when your program starts.
So initialize it:
int count = 0;
The other problem is that the scanfs won't do what you want, at all. %d will match a series of digits (a number), not an individual digit. If you do want to do your counting like that, use %c to read individual characters.
Another approach typically used (as long as you know the file isn't being updated) is to use fseek/ftell to seek to the end of the file, get the position (wich will tell you its size), then seek back to the start.
The fastest approach though would be to use stat or fstat to get the file size information from the filesystem.
If you want number of digits thin you tave to do it char-by-char e.g:
while (isdigit(fgetc(file_decriptor))
count++;
Look up fgetc, getc and scanf in manpages, you don't seem to understand whats going on in your code.
The way C initializes values is not specified. Most of the time it's garbage. Your count variable it's not initialized, so it mostly have a huge value like 1243435, try int count = 0.

Read in Numbers from a File in C

I have a file called points.dat which reads something like:
5
2 5
-1 18
0 6
1 -1
10 0
The first number is how many ordered pairs there are. The next 5 lines contain those ordered pairs. What can I do to read in the first number, determine how many points there are (from here I can malloc an array of structs to store the points in).
My problem is that fgetc doesn't really do the job here. What if the first number is two digits? Say the first number is 10. fgetc will only retrieve the '1'. Also, fgets doesn't really work, since you need to supply it the length of the amount of characters you want to read in. The same applies for fscanf.
The real trouble comes in when it's time to retrieve the ordered pairs. I have no idea how to do this either. My only thoughts so far is look at a line: if it sees non-spaces or non-'\n's, it will read in the number as the x coordinate of point 1. Loop. Get y coordinate. Once it hits a '\n', it will now move on to the next line, and begin looking for values to store in the next struct in the array of structs.
(While doing this, I also need to be sure atoi can convert all of these into integers... ).
If anyone has any ideas to help, they are appreciated.
For the first line use int numValuesRead = fscanf(file, "%d", &totnums);
Then, use numValuesRead = fscanf(file, "%d %d", &num1, &num2); to read the other lines.
fscanf returns the number of value read. You should always check it.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x, y;
} Point;
int main ()
{
int numOf;
Point *myPoints = NULL;
FILE *myfile = fopen ("myfile.txt","r");
if (myfile == NULL)
perror ("Error opening file"); //or return 1;
else
{
fscanf(myfile, "%d", &numOf);
myPoints = (Point *)malloc(sizeof(Point) * numOf);
while ( !feof (myfile) && numOf-- )
{
fscanf(myfile, "%d %d", &(myPoints[numOf].x), &(myPoints[numOf].y));
}
}
fclose(myfile);
//Do stuff with array
free ((void *)myPoints);
getchar();//Press enter to close debugger etc.
return 0;
}
Sorry for the delay.

c language : read file content as numbers and add them together

I have the following in a text file called: values.txt
1 4
2.5 3.76
122 10
277.543
165.4432
I am trying to read the content of this text file, and add each two pairs together and output the result ...
the output would be something like this :
1 Pair:(1, 4) = 5
2 Pair:(2.5, 3.76)= 6.26
and so on ..
I am opening the file like this
int c;
FILE myfile;
myfile= fopen("values.txt", "r");
if ( myfile == NULL ) {
printf("Cannot open TEXT file\n");
return 1;
}
double aa,bb;
while ( (c = getc(myfile) ) != EOF ) {
// HERE SHOULD I DO THE OUTPUT BUT HOW?
}
Any help is really appreciated ..
Language = C
The following code does what you expect. myfile should be declared as FILE*. fopen returns a pointer to FILE structure. If the file is very large, I would recommend reading in buffers of big size (eg: 65535 etc) and parse it char by char and convert it to float values. It reduces system call overhead which takes more time than processing text to float values.
#include <stdio.h>
#include <string.h>
main(int argc, char *argv[])
{
FILE* myfile;
myfile = fopen("values.txt", "r");
if ( myfile == NULL ) {
printf("Cannot open TEXT file\n");
return 1;
}
double aa,bb;
while (2 == fscanf(myfile, "%lf %lf", &aa, &bb)) {
printf("%lf\n", aa+bb);
}
return 0;
}
For this simple task, use double a, b;
if (fscanf(myfile, "%lf %lf", &a, &b) == 2)
printf("%f + %f = %f\n", a, b, a+b);.
looks like a homework problem but fscanf can read the string into a variable like:
int n;
fscanf (myfile,"%d",&n);
You haven't shown what you need as output for the single-value lines, but this looks like a case for fgets() and sscanf(), unless you really want the two lines with a single value to be processed as a unit.
char buffer[256];
int rownum = 0;
while (fgets(buffer, sizeof(buffer), myfile) != 0)
{
double aa, bb;
int n = sscanf(buffer, "%lf %lf", &aa, &bb);
if (n == 2)
printf("%d Pair:(%g, %g) = %g\n", ++rownum, aa, bb, aa+bb);
else if (n == 1)
printf("%d Solo:(%g) = %g\n", ++rownum, aa, aa);
else
{
printf("Failed to find any numbers in <<%s>>\n", buffer);
}
}
If you used fscanf(myfile, "%g %g", &aa, &bb), then it would read over newlines (they count as white space) looking for numbers, so it would read one number from one line, and the second from another line. This is not usually what people are after (but when it is what you need, it is extremely useful). Error recovery with fscanf() tends to be more fraught than with fgets() and sscanf().
its in c++ sorry :( i dont know c
this is a very simple logic code for simple minde :D im a begineer too, i havent tested this prog so sorry if something goes wrong but exactly
on a same principle was working my parser and it worked fine. so this is a true method. not very efficent but...
do not use this program straight away, understand it's logic this will help you alot. copying that wont give you anything
...parser tutors are so rare....
int x=0;
char ch = 'r'; //i'v used this equasion to avoid error on first ckeck of ch.
it must be filled by something when program starts.
char bigch[10];
int checknumber = 0;
float firstnumber = 0;
float secondnumber = 0;
float result=0;
void clearar(char frombigar[10], int xar) //this function gets bigch as a reference which means that eny
changes made here, will directly affect bigch itself.
ths function gets the actual length of array and puts spaces
in bigch's every element to zero out numbers. we need to clear
bigch of any previous numbers. down below you'l see why i needed this.
'xar' is the x from main function. its here to tell our cleaner the
true length of filled bigar elements.
{
for (int i=0; i
}
}
int main()
{
<------------------- //here you add file opening and reading commands
while(!myfile.eof()) //while end of txt file have not been reached
{
ch=myfile.get(); //gets each letter into ch, and make cursor one step
forward in txt file for further reading.
get() does cursor forwarding automatically
if (ch!= " ") //i used space as an indicator where one number ends
//so while space havent been reahced, read letters.
{ bigch[x] = ch; //get read letter into bigch array.
x++; //icrement bigch array step
}
else
if(ch == " ") //if space is reached that means one number has ended and
{ im trying to set a flag at that moment. it will be used further.
checknumber++; the flag is simple number. first space will set checknumber to 1
second space will set it to 2. thats all.
}
if (checknumber == 1) //if our checknumber is 1, wich means that reading
of first number is done, lets make one whole float
from that bigch array.
{ firstnumber = atof(bigch); //here we get bigch, atof (array to float) command converts
bigch array into one whole float number.
clearar(bigch,x); //here we send bigch and its element step into function where
bigch gets cleaned because we dont want some ghost numbers in it.
abviously clearar function cleans bigch int main function aswell,
not only in it's teritory. its a global cleaning :)
}
else if (checknumber ==2) //here we do the same but if flag is 2 this means that two spaces
had been passed and its time to convert bigch into secondnumber.
{ secondnumber = atof(bigch); //same method of converting array into float (it hates other
not number letters, i mean if its a number its fine. if in your text
was 'a' or 's' in that case atof will panic hehe.. )
clearar(bigch,x); //same thing, we send bigch to cleaner function to kill any numbers
it, we get one space letter ( " " ) into each element of bigch.
}
checknumber = 0; if both two numbers had been read out and converted. we need to reset
space flagger. and start counting form 0; for next pair numbers.
result = firstnumber+secondnumber; well here everything is clear.
}
}

Resources