How to Read and Add Numbers from txt file in C - c

I am trying to make a program that reads numbers from a text file named numbers.txt that contains different numbers in each line.
For example:
8321
12
423
0
...
I have created this program, but it does not work properly. I have tried many things and don't know what to do. Can someone guide me in the right direction? Thank you!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 1000
int main(int argc, char *argv[]) {
char str[MAX_LEN];
FILE *pFile = fopen(argv[1], "r");
int num;
int sum = 0;
int count = 0;
if (pFile == NULL) {
printf("Error opening file.\n");
return 1;
}
while (!feof(pFile) && !ferror(pFile)) {
if (fscanf(pFile, "%d", &num) == 1) {
count++;
while (strcmp(fgets(str, MAX_LEN, pFile), "\0") == 0) {
printf("%s", str);
//sum = sum + (int)(fgets(str, MAX_LEN, pFile));
printf("\n");
}
}
}
fclose(pFile);
printf("count = %d \n", count);
printf("sum = %d \n", sum);
return 0;
}

strcmp(fgets(str, MAX_LEN, pFile),"\0") is wrong in many ways. For one, the argument of strcmp must be a string (which a null pointer isn't), but fgets returns NULL on error or end of file. You need to check that it didn't return NULL and then you can compare the string in str. However, there is no need to strcmp against "\0" (or, in this case equivalently, "") to detect the end of file, because that's when fgets returns NULL.
Another issue is that you are reading with both fscanf and fgets – pick one and stick with it. I recommend fgets since it's generally easier to get right (e.g., on invalid input it's a lot harder to recover from fscanf and make sure you don't get stuck in an infinite loop while also not losing any input). Of course you need to parse the integer from str after fgets, though, but there are many standard functions for that (e.g., strtol, atoi, sscanf).
Don't use !feof(file) as the loop condition (see, e.g., Why is “while ( !feof (file) )” always wrong?). If you are reading with fgets, end the loop when it returns NULL.

You can use strtok to split the numbers in each line, then using atoi function to convert string to int.
For example:
while(fgets(str, MAX_LEN, pFile)) {
// if the numbers are separated by space character
char *token = strtok(str, " ");
while(token != NULL) {
sum += atoi(token);
strtok(NULL, " ");
}
}
if there is only one number per line, you do not need to use strtok:
while(fgets(str, MAX_LEN, pFile)) {
sum += atoi(str);
// OR
sscanf(str,"%d\n", &new_number)
sum += new_number;
}

Your program has multiple problems:
no test if a command line argument was passed.
while (!feof(pFile) && !ferror(pFile)) is always wrong to iterate through the file: feof() gives valid information only after a actual read attempt. Just test if the read failed.
if fscanf(pFile, "%d", &num) == 1) add the number instead of just counting the numbers.
strcmp(fgets(str, MAX_LEN, pFile), "\0") will fail at the end of the file, when fgets() returns NULL.
If the file only contains numbers, just read these numbers with fscanf() and add them as you progress through the file.
Here is a modified version:
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *pFile;
int num
int sum = 0;
int count = 0;
if (argc < 2) {
printf("Missing filename\n");
return 1;
}
if ((pFile = fopen(argv[1], "r")) == NULL) {
printf("Error opening file %s\n", argv[1]);
return 1;
}
while (fscanf(pFile, "%d", &num) == 1) {
sum += num;
count++;
}
fclose(pFile);
printf("count = %d \n", count);
printf("sum = %d \n", sum);
return 0;
}

Related

get 3 (max) digit integer from txt file

First of all I am new to files in c, so it may be a simple question,
however I still didn't find a solution:
let's say that's the content of my file:
99
blah blah
...
...
I want to scan only the number from the beginning (it is always in a separate line)
My question is how to make it take the number (99) as one number and stop scanning.
int main(){
FILE* fp = fopen(file_name, "r");
int integer;
...
fclose(fp);
printf("%d", integer);
}
output for the file example:
99
-the nuber can be between 1 and 100-
I want to scan only the number from the beginning (it is always in a separate line).
That's a good hint, suggesting a line by line parsing of the input. You can use a combination of fgets(1) and sscan(2) to read that number.
fgets will read up to a certain number of character from a stream and store those character into a buffer. If it finds a newline, it stops reading, store the newline into the buffer followed by the null-terminator. Otherwise it only adds the terminator. If it fails, it returs a NULL pointer.
sscanf works basically like scanf or fscanf, but it reads from a character array, not from a stream.
It's also better to always check the return value of those library function.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 1024
int main(void)
{
char const *file_name = "data.txt";
FILE *in_file = fopen(file_name, "r");
if (!in_file) {
fprintf(stderr, "Error while reading \"%s\": %s", file_name, strerror(errno));
return EXIT_FAILURE;
}
char buffer[BUF_SIZE];
int number = 0;
while( fgets(buffer, BUF_SIZE, in_file) ) {
if ( sscanf(buffer, "%d", &number) == 1 ) {
if ( 0 < number && number < 100 ) {
printf("%d", number);
break;
}
}
}
fclose(in_file);
return EXIT_SUCCESS;
}
Example.
Some references of the functions used in the previous snippet
1) fgets: man-pages or cppreference.
2) sscanf: man-pages or cppreference
Why not use scanf? (fscanf to be more precise):
On success, the function returns the number of items of the argument
list successfully filled.
(source: cppreference)
So just check how many values did you read, if 0 that means it's not a number so you can just skip that string, for that you can use "%*" prefix to ignore the data.
You also said:
I want to scan only the number from the beginning (it is always in a
separate line)
so after you read the number just skip the whole line with "%*[^\n]" (reads
data until a new line symbol is encountered)
int num;
int scanReturn;
FILE* f = fopen("file.txt", "r");
...
do {
scanReturn = fscanf(f, "%d", &num);
if(scanReturn == 0)
{
scanReturn = fscanf(f, "%*s");
}
else if(scanReturn != EOF)
{
fscanf(f, "%*[^\n]");
printf("%d, ", num);
}
} while(scanReturn != EOF);
fclose(f);

using EOF instead of feof

#include <stdio.h>
int main() {
FILE *fp1, *fp2, *fp3;
int n, i, num, flag = 0;
/* open files to write even, odd seperately */
fp1 = fopen("data.txt", "r");
fp2 = fopen("even.txt", "w");
fp3 = fopen("odd.txt", "w");
fprintf(fp2, "Even Numbers:\n");
fprintf(fp3, "Odd Numbers:\n");
/* print even, odd and prime numbers in separate files */
while (!feof(fp1)) {
fscanf(fp1, "%d", &num);
if (num % 2 == 0) {
fprintf(fp2, "%d ", num);
} else {
if (num > 1) {
for (i = 2; i < num; i++) {
if (num % i == 0) {
flag = 1;
break;
}
}
}
fprintf(fp3, "%d ", num);
flag = 0;
}
}
fprintf(fp2, "\n");
fprintf(fp3, "\n");
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
I want to use EOF instead of feof. I have tried !EOF = fp1 but it doesn't work and gives an error. I just want to replace feof with EOF. can anyone indicate what is the problem in my code?
fscanf returns EOF when the end-of-file is reached:
man fscanf
#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
[...]
The scanf() function reads input from the standard input stream stdin, fscanf() reads input from the stream pointer stream, and
sscanf() reads its input from the character string pointed to by str.
[...]
RETURN VALUE
On success, these functions return the number of input items successfully matched and assigned; this 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
to indicate the error.
A solution would be to read save the return value of fscanf in a int
variable and check it agains 0 and EOF, like this:
If you want to keep using fscanf:
int ret;
while((ret = fscanf(fp1, "%d, &num)) != EOF)
{
if(ret == 0)
{
// fscanf failed to convert the input
// let it consume a charatcer and try again.
getc(fp1);
continue;
}
if(num % 2 == 0)
...
}
edit
Avoid using feof to control looping on a file like this while(!feof(fp), see Why is “while ( !feof (file) )” always wrong? for more
information about that.
edit 2
This was my original idea, but as Jonathan Leffler pointed out in the comments:
Jonathan Leffler wrote:
Your first solution demands a single number per line, which the code in the question does not
He's right, I didn't see that.
me from the past
One option would be to read the input line by line using fgets and then use
sscanf to parse the line:
char buffer[1024];
while(fgets(buffer, sizeof buffer, fp1))
{
if(sscanf(buffer, "%d", &num) != 1)
{
fprintf(stderr, "Could not read an integer, ignoring line\n");
continue;
}
if (num % 2 == 0)
...
}
Your condition for the while loop should be the fscanf() statement itself. EOF is always an integer. See the manual page for fscanf():
Return Value
The fscanf() function returns the number of fields that it successfully converted and assigned. The return value does not include fields that the fscanf() function read but did not assign.
The return value is EOF if an input failure occurs before any conversion, or the number of input items assigned if successful.
And, like everyone else I will refer you to Why is while ( !feof (file) ) always wrong?. This is essential reading on Stack Overflow for new C programmers.
#include <stdio.h>
int main(void) {
FILE *fp1, *fp2, *fp3;
int n, i, num, flag = 0, ret;
/* fopen files */
while ((ret = fscanf(fp1, "%d", &num)) != EOF) {
if (ret == 0) {
getc(fp1);
continue;
}
if (num % 2 == 0) {
fprintf(fp2, "%d ", num);
}
/* rest of the loop here */
}
/* fclose files */
}
If fscanf() fails to read a character, but does not return EOF, it can often solve things to getc(), to advance the buffer by one character. This method also works when using getchar() to advance stdin, after getting user input from scanf().

Read Line By Line Until Integer is Found C

Trying to create a program that takes in a text file and reads it line by line. It then finds the two integers that are on each line and adds them together. It then outputs the new line with the original string and total to a new text file. I need help adding the two integers, getting them from each line, and then putting the new line to a text file.
input text file
good morning hello 34 127
ann 20 45
10 11
fun program and you find the same 90 120
news paper said that 56 11
how do you like 20 5
line number 90 34
Outputs first like would look like: and then continue on
good morning hello 161
Code:
int processTextFile(char * inputFileName, char * outputFileName)
{
FILE *fp = fopen(inputFileName, "r");//open file to to read
char buff[1024];
char *p, *p1;
int num;
while (fgets(buff, 1024, fp)!=NULL)
{
printf("%s\n", buff);
while(scanf(buff, "%*[^0-9]%d", &num)== 1)
printf("%d\n", num);
//fscanf(fp, "%s", buff);
}
return 0;
}
EDIT!!!!::
So now that I've been able to accomplish this. How would I sort it by the number produced? for example:
Time is money 52
here I am 3
21
Would output to a new text file in order like
here I am 3
21
Time is money 52
My version using strcspn() is supposed to work with stdin for input and stdout for output. (so you can do executable <textfile >newtextfile)
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char line[1000];
while (fgets(line, sizeof line, stdin)) {
char *ptr;
size_t x = strcspn(line, "0123456789");
if (line[x]) {
errno = 0;
int n1 = strtol(line + x, &ptr, 10);
if (*ptr && !errno) {
errno = 0;
int n2 = strtol(ptr, &ptr, 10);
if (*ptr && !errno) {
int n3 = n1 + n2;
printf("%.*s%d\n", (int)x, line, n3);
} else {
printf("%s", line); // line includes ENTER
}
} else {
printf("%s", line); // line includes ENTER
}
} else {
printf("%s", line); // line includes ENTER
}
}
return 0;
}
The same version without the error checking
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char line[1000];
while (fgets(line, sizeof line, stdin)) {
char *ptr;
size_t x = strcspn(line, "0123456789");
int n1 = strtol(line + x, &ptr, 10);
int n2 = strtol(ptr, &ptr, 10);
int n3 = n1 + n2;
printf("%.*s%d\n", (int)x, line, n3);
}
return 0;
}
The approach should be:
open two files, one for input, one for output.
use sscanf() to read the input buffer.
scan the leading string, and then two number.
if previous sscanf() fails, only check for two number.
if either of the above scanning is success, print the sum to the output file.
A sample code, should look like
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE *fpin = fopen("ipfile", "r");//open file to to read
if (!fpin)
{
printf("Error in ipfile opening\n");
exit (-1);
}
FILE *fpout = fopen("opfile", "w");//open file to to write
if (!fpout)
{
printf("Error in opfile opening\n");
exit (-1);
}
char buff[1024] = {0};
char str[1024] = {0};
int num1 =0, num2= 0;
while (fgets(buff, 1024, fpin)!=NULL)
{
memset(str, 0, sizeof(str));
//printf("%s\n", buff);
if(sscanf(buff, "%[^0-9]%d %d", str, &num1, &num2)== 3)
fprintf(fpout, "%s %d\n", str, (num1+num2));
else if (sscanf(buff, "%d %d", &num1, &num2)== 2)
fprintf(fpout, "%d\n", (num1+num2));
}
return 0;
}
Note:
The above procedure, is a kind of workaround. If the data pattern in the file changes, lot of changes will be required to maintain a code like that. Instead of usinf sscnaf(), for a better and roubust approach, you should
read the line from file
start tokenizing the input buffer (strtok()) and check for ints as tokens (strtol()).
save the returned tokens and ints seperately.
once the strtok() returns NULL, you print the string tokens and the sum of the ints to the o/p file.
I intend not to change your code completely, so I just added some snippets for improvement.
int processTextFile(char *inputFileName, char *outputFileName) {
FILE *fp = fopen(inputFileName, "r");
FILE *out = fopen(outputFileName, "w");
char line[1024];
if (!fp) {
perror(inputFileName);
return;
}
while (fgets(line, sizeof(line), fp) != NULL) {
int num1 = 0, num2 = 0;
char textPart[1024] = "";
if ( !sscanf(line, "%[a-zA-Z' ']%d%d", textPart, &num1, &num2) {
sscanf(line, "%d%d", &num1, &num2);
}
fprintf(out, "%s %d\n", textPart, num1 + num2);
}
fclose(fp);
fclose(out);
}
Explanation:
I scanned the text file, extracted the text part and the two ints. Since I noticed that the ints are placed at the end of each line, I just used sscanf() for that matter.
sscanf(line, "%[a-zA-Z' ']%d%d", textPart, &num1, &num2);
Here, "%[a-zA-Z' ']%d%d" format specifiers means to get only alphabets and spaces.
Since it will only get letters and spaces, the line "10 11" in your input file won't be put to num1 and num2. Because the code inspects first for a string containing letters and spaces. Since 10 and 11 are not of the qualified types, then the line is just skipped.
That's why I added an if-else statement, which checks if sscanf wrote anything to memory. If sscanf returned 0, then it means that no text part is present. Just digits. So the program will scan the two digits.
if ( !sscanf(line, "%[a-zA-Z' ']%d%d", textPart, &num1, &num2) ) {
sscanf(line, "%d%d", &num1, &num2);
}
I also added file checking for input file. It checks if file doesn't exist or can't be opened by the filestream.
if (!fp) {
perror(inputFileName);
return;
}
Here is the content of output file after execution:
good morning hello 161
ann 65
21
fun program and you find the same 210
news paper said that 67
how do you like 25
line number 124

In C, how do I read a file, and store only the doubles - ignoring text before?

I need to read in a file that contains text, and then a double for that text. It is simply to get the mean and standard deviation for the set of numbers, so the text that comes before is irrelevant. For example, my input file looks a little like:
preface 7.0000
chapter_1 9.0000
chapter_2 12.0000
chapter_3 10.0000
etc..
In this case, it is finding the mean and std dev for the chapters of a book. I have the section of code below, but I'm not quite sure how to "ignore" the text, and only grab the doubles. At the moment this code prints out zeros and only exits the loop when it exceeds the array limit, which I set as a constant to 20 at the beginning of the program.
FILE *ifp;
char *mode = "r";
ifp = fopen("table.txt", mode);
double values[array_limit];
int i;
double sample;
if (ifp==NULL)
{
printf("cannot read file \n");
}
else
{
i = 0;
do
{
fscanf(ifp, "%lf", &sample);
if (!feof(ifp))
{
values[i] = sample;
printf("%.4lf \n", values[i]);
i++;
if (i>=array_limit) //prevents program from trying read past array size limit//
{
printf("No more space\n");
break;
}
}
else
{
printf("read complete\n");
printf("lines = %d\n", i);
}
}while (!feof(ifp));
fclose(ifp);
}
I think you could use fscanf(ifp, "%*[^ ] %lf", &sample) for reading from your file. The * says to ignore that particular match, the [] specifices a list of characters to match and the ^ indicates to match all characters except those in [].
Or possibly (a bit simpler) fscanf(ifp, "%*s %lf", &sample).
You have two major problems -- you're using feof which is pretty much always wrong, and you're not checking the return value of fscanf, which it what tells you whether you got a value or not (or whether you got to the eof).
So what you want is something like
while ((found = fscanf(ifp, "%lf", &values[i])) != EOF) { /* loop until eof */
if (found) {
/* got a value, so count it */
if (++i >= ARRAY_LIMIT) {
printf("no more space\n");
break;
}
} else {
/* something other than a value on input, so skip over it */
fscanf(ifp, "%*c%*[^-+.0-9]");
}
}
When reading in from a file, it's often best to use fgets to read one line at a time, then extract the parts you are interested in using sscanf:
#include <stdlib.h>
#include <stdio.h>
#define ARRAY_LIMIT 10
#define LINE_LENGTH 128
int main()
{
double values[ARRAY_LIMIT];
int i, count = 0;
double sample;
FILE *ifp = fopen("table.txt", "r");
if (ifp==NULL)
{
printf("cannot read file \n");
return 1;
}
char buff[LINE_LENGTH];
while (fgets(buff, LINE_LENGTH, ifp) != NULL)
{
if (sscanf(buff, "%*s %lf", &sample) != 1) break;
values[count++] = sample;
if (count == ARRAY_LIMIT) {
printf("No more space\n");
break;
}
}
fclose(ifp);
for (i = 0; i < count; ++i) {
printf("%d: %f\n", i, values[i]);
}
return 0;
}
fgets returns NULL if it encounters the end of the file, or if a read error has occurred. Otherwise, it reads one line of the file into the character buffer buff.
The asterisk %*s in the sscanf means that the first part of the line is discarded. The second part is written to the variable sample. I am checking the return value of sscanf, which indicates how many values have been read successfully.
The loop breaks when the end of the file is reached or the count reaches the size of the array.

Read a file then store numbers in array C

so I have this file called "score.txt" with contents
NAME
20
NAME2
2
And I'm using this code but it gets an error and I have no idea on how to put the integers from the file in an array.
int main(){
FILE* file = fopen ("score.txt", "r");
int i = 0;
fscanf (file, "%d", &i);
while (!feof (file))
{
printf ("%d ", i);
fscanf (file, "%d", &i);
}
fclose (file);
system("pause");
}
I'm only self learning and i've been trying to figure this out for 2hours already
The problem with using fscanf for input where some lines will fail the format is that the file will not be advanced per iteration of the while loop, so you get stuck.
You can get a solution by using fgets to grab the data and sscanf to grab the number:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(void) {
int i = 0;
int ret = 0;
char buf[50];
FILE *file = fopen("score.txt", "r");
if (file == NULL) {
fprintf(stderr,"Unable to open file\n");
exit(1);
}
while (fgets(buf,sizeof(buf),file)) {
ret = sscanf(buf,"%d",&i);
if (ret == 1) { // we expect only one match
printf("%d\n", i);
} else if (errno != 0) {
perror("sscanf:");
break;
}
}
fclose(file)
return(0);
}
This will output, for your input:
20
2
We check the output of sscanf as it tells us if the format has been matched correctly, which will only happen on the lines with integer, and not the 'NAME' lines. We also check for 'errno' which will be set to non-zero if sscanf encounters an error.
We used char buf[50]; to declare a char array with 50 slots, which fgets then uses to store the line its reading; however if the line is more than 50 chars in length it will be read in 50 char chunks by fgets, and you may not get the results you desire.
If you wish to store the integers you read into an array, you'll have to declare an array, then on each read assign a slot in that array to the value of the int you read i.e. int_array[j] = i (where j will have to change with each slot you use). I'll leave it as an exercise to implement this.

Resources