Read in Numbers from a File in C - 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.

Related

program in C read txt file = find min, max, avg

I need to write a program that opens a txt file and lists how many numbers are there (e.g. there are 25 numbers below) and then lists which number is the largest (max) and which is the smallest (min). The program then makes an average of these numbers.
So far, my program only write how many numbers I got there. When I try to make the formula to the maximum, I simply stop and can't move.
Can you help me? How do I do that by reading the rows and evaluating the largest number?
#include <stdio.h>
FILE *input;
int open()
{
if ((input = fopen("data.txt", "r")) == NULL)
{
printf("Error! opening file");
return 0;
}
}
int rows_reading ()
//Here i dont know what to do
{
input = fopen ("data.txt", "r");
}
void main ()
{
char c;
int linesCount = 0;
float max, min;
float a;
float n;
int count = 0;
input = fopen ("data.txt", "r");
while ((c = fgetc(input)) !=EOF)
{
if(c =='\n')
linesCount++;
} // this works
while ((c = getc(input)) !=EOF)
{
for (a = 0; a < count; a++){
if (a > max)
max = a;
}
} //this not work
printf("In file is %d numerical values. Max value is %d"linesCount, max);
return ;
} ```
Hints only since it's classwork and you'll become a better developer if you nut it out yourself :-)
The idea is to scan all the numbers and remember which was the largest and smallest. For the average, you also need to accumulate a sum of all those number along with the count.
For example, consider the following pseudo-code:
def getMinMaxAvg(inputFile):
set sum, count, smallest, largest all to zero
set value to inputFile.getNumber()
if none available, return error indication
while true
if count is zero or value is less than smallest:
set smallest to value
if count is zero or value is greater than largest:
set largest to value
add value to sum
add one to count
set value to inputFile.getNumber()
if none available, return (smallest, largest, sum / count)
That's basically the flow you need. The first important thing here is the inputFile.getNumber(), the thing that gets your numbers. Your use of fgetc will input single characters, you'll probably want to use fscanf with the "%d" specifier, so you can input integers.
Just make sure you check the return value to ensure it worked okay:
int myInt; FILE *fileHandle = fopen(...);
if (fscanf(fileHandle, "%d", &myInt) != 1)
// Did not scan properly, needs to be handled.
// Now, myInt contains your value.
You're reading your file character by character, which isn't a good way to read numbers. If the file contains the number "137" you will read '1', then '3', then '7'. It works for counting lines since you can just count the number of '\n' characters, which you're doing.
Does the file contain a list of numbers, one number per line? If so, you should use fgets to read the file one line at a time. Then you can use atoi to convert the string into an integer and look for the max, min, etc. One gotcha that you have to look out for us that fgets will store the \n in the string it returns, so you may need to remove it.
If your file contains numbers separated by spaces then you might consider fscanf, which may work too for lines...? Not really sure about that since it's been ages since I used fscanf.

How to read a comma as a flag for next variable in C?

The input file will have the name of a lake on one line, then a comma, then the volume of that lake in units of hundreds of cubic miles. The next line will contain the name of another lake, a comma, then it's volume, etc, etc. Each line of the file contains exactly the name of a lake, a comma, and a float value for volume.The name of a lake may contain more than one word; for example "dead horse lake", but it will be on one formatted line. The volume may have decimals in it, as 16.9. Your program will use a subroutine that takes as arguments the name of a lake and its volume. This subroutine will then print out the name of the lake on one line to the screen, followed by a set of consecutive asterisks denoting the volume in units of hundreds of cubic miles on the next line rounded to the nearest hundred cubic miles. For example, if the lake is 15.6 cubic miles in volume, the subroutine will print out 16 asterisks on the line following the name of the lake.
Right now my program only reads the first line and displays the name and asterisk, but any other information in my lakes.txt file is not read and the program terminates. Could someone please tell me what I am doing wrong? The original project was one without the comma, but the prof. decided to add a comma in there. I just changed the %19 to %20 and added a comma in the brackets. I do not know what difference it made, but it worked. I would like to understand why.
I'm new to SO. Sorry if my text is a little off. I'm a new programmer and I would really love to understand and become a good programmer. The more elaborate and in depth your answers are, the more helpful they are to me. Thank you for your help!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
void asterisks_code( char lake[257], float vol );
int main()
{
char lake[257], tempt[100];
float vol;
FILE *fp;
fp = fopen( "lakes.txt", "r" );
if( fp == NULL) {//starts 1st if statement
printf( "File does not exist.");
return 0;
}//closes 1st if statement
while( ( fgets( tempt, sizeof (tempt), fp ) ) != NULL ) {
if (sscanf(tempt, " %19[A-Za-z, ]%f", lake, &vol) != 2) {//starts 2nd if statement
fprintf(stderr, "Unexpected data\n");
break;
}//closes 2nd if statement
asterisks_code( lake, vol );
}//closes while loop
fclose( fp );
return 0;
}//closes main function
void asterisks_code( char lake[257], float vol )
{//start of asterisks_code function
int counter;
printf( "%s\n", lake );
for( counter = 0; counter < roundf(vol); counter++ ) {//start of for loop
printf( "*" );
}//closes for loop
printf( "\n" );
}//closes asterisk_code function
I feel for you. Your professor has misguided you from the very start.
First of all, fgets( tempt, sizeof (tempt), fp ) doesn't guarantee that a full line will be read from fp. If sizeof tempt bytes are read and there are more left in the line, the leftover lines will be left on the stream for the next call to fgets. I've written solutions to that problem in another answer, but in all honesty you don't need fgets. You could use it if you wanted to, but all you need to solve this exercise is fscanf and fgetc.
I thoroughly advise reading only one element at a time using fscanf... at least until you've read and fully understood the fscanf manual (it's very lengthy, suggesting that it's quite complex and easy to get wrong... hmmmm!). Even so, you should still at least read it before you try to use it.
Start by writing a function to read your 19-byte wide field...
int read_lake_name(FILE *fp, char *lake) {
int n = fscanf(fp, "%19[^,]", lake);
int left_over = 0;
fscanf(fp, "%*[^,]%n", &left_over);
if (left_over > 0) {
puts("WARNING: Lake name was longer than 19 bytes and has been discarded...");
}
fgetc(fp);
return n;
}
If more than 19 bytes are provided, there will be some left-over on the stream. Those bytes need to be discarded. Notice the * in the second fscanf, and that there's no corresponding array argument? That's an example of assignment suppression using fscanf; the left-over bytes will be read and discarded, rather than assigned into an array. The %n directive instructs fscanf to assign the number of bytes fscanf has read into left_over, which tells us whether or not the lake's name was truncated. Following that, fgetc is called to discard the remaining comma.
This code is great at reading (and truncating) 19 bytes of user input, up to the next comma, but it won't read the volume. Once you've read those up-to-19-bytes and discarded the comma (and any trailing data prior to the comma), you'll need to read a floating point value, then discard anything prior to the newline, and discard the newline (of course)...
int read_lake_volume(FILE *fp, float *v) {
int n = fscanf(fp, "%f", v);
int left_over = 0;
fscanf(fp, "%*[^\n]%n", &left_over);
if (left_over > 0) {
puts("WARNING: Lake volume contained trailing invalid characters which have been discarded...");
}
fgetc(fp);
return n;
}
Do you notice any similarities here? With these two virtually identical functions it should be trivial to construct a working loop, but here goes:
while (read_lake_name(fp, name) == 1 && read_lake_volume(fp, &vol) == 1) {
write_asterisks(name, vol);
}

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

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.

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.

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