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.
Related
I have a file .txt containing some values formatted like this:
0,30,25,10
Now, I open up the file and store it into an array
char imposta_tratt[300];
FILE *fp;
fp = fopen("/home/pi/Documents/imposta_trattamento.txt", "r");
if (fp == 0) return;
fread(imposta_tratt, sizeof(imposta_tratt), 1, fp);
fclose(fp);
Now I expect to have the array filled with my data. I have the values separated by a , so I go on and parse it:
const char delim[2] = ",";
int t=0;
char *token = strtok(imposta_tratt, delim);
while (token!=NULL){
strcpy(tratt[t],token);
token = strtok(NULL, delim);
tratt[t]=token;
t++;
}
Here, referring to what's in the file .txt, I expect to have tratt[0]=0; tratt[1]=30; tratt[2]=25; and so on, but seems like I am missing something since it's not like this.
All I want is to have the values of the txt file stored in single variables. Can someone help?
What you are trying to achieve can simply be done using fgets():
bool read_file_content(const char *filename, const size_t tsizemax, int tratt[tsizemax], size_t *tsize, const char *delim)
{
// Attempt to open filename.
FILE *fp = fopen(filename, "r");
if (!fp) return false; // Return false upon failure.
// Try to read one line. If you have more, you need a while loop.
char imposta_tratt[300];
if (!fgets(imposta_tratt, sizeof imposta_tratt, fp)) {
fclose(fp);
return false;
}
*tsize = 0;
char tmp[300]; // Temporary buffer. Used for conversion into int.
char *token = strtok(imposta_tratt, delim);
while (token && *tsize < tsizemax) {
strncpy(tmp, token, sizeof tmp);
tratt[(*tsize)++] = atoi(tmp);
token = strtok(NULL, delim);
}
fclose(fp);
return true;
}
const char *filename: The file you want to parse.
const size_t tsizemax: The maximum size of your tratt array. It is important to control the size, otherwise your code will have buffer overflow (think of when your file has more than 100 tokens, for example).
int tratt[tsizemax]: The array that will hold the values.
size_t *tsize: The number of tokens read (used in combination of tsizemax).
const char *delim: The delimiter(s), in your case a ,.
This is your main():
int main(void)
{
int tratt[100];
size_t size = 0;
if (!read_file_content("in.txt", 100, tratt, &size, ",")) {
puts("Failed");
return 1;
}
for (size_t i = 0; i < size; ++i)
printf("%d\n", tratt[i]);
}
Output:
0
30
25
10
Suppose "in.txt" has contents
0,30,25,10
The below program uses fscanf to read the integers into the tratt array, one-by-one. As we read integers using fscanf, we make sure it's return value is as expected. If not, we close the file and exit. In the event that the return value of fscanf is not as expected, the program also prints which type of error occurred. Currently, if any error occurs, the program stops. However, you can make the program behave differently depending on the error that occurred if you like.
As output, the program prints all of the integers read into the tratt array. The output is
0
30
25
10
Now this program assumes we know the number of elements we want to read into tratt. If we do not, we could allow for dynamically allocating more memory should the array need more elements or perhaps "in.txt" could contain a data structure, say, at the beginning/end of the file that records information about the file, such as the number of numbers in the file and the data type (a binary file would be best suited for this). These are just a couple of the possibilities.
A better approach might be to read characters in one-by-one (say, using getc) and use strtol to convert a sequence of character digits to a long int (I would have taken an approach similar to this).
Nevertheless, this approach is more succinct and should suffice.
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "in.txt"
#define MAX_LEN 4
int main(void) {
int i, tratt[MAX_LEN];
FILE *fp = fopen(FILE_NAME, "r"); /* open file for reading */
/* if cannot open file */
if (fp == NULL) {
printf("Cannot open %s\n", FILE_NAME);
exit(EXIT_FAILURE);
}
/* read integer, checking return value of scanf as expected */
if (fscanf(fp, "%d", &tratt[0]) != 1) {
if (ferror(fp))
printf("fscanf: read error\n");
else if (feof(fp))
printf("fscanf: end of file\n");
else
printf("fscanf: matching failure\n");
fclose(fp);
exit(EXIT_FAILURE);
}
for (i = 1; i < MAX_LEN; i++)
/* read comma plus integer, checking return value of scanf */
if (fscanf(fp, ",%d", &tratt[i]) != 1) {
if (ferror(fp))
printf("fscanf: read error\n");
else if (feof(fp))
printf("fscanf: end of file\n");
else
printf("fscanf: matching failure\n");
fclose(fp);
exit(EXIT_FAILURE);
}
fclose(fp); /* close file */
/* print integers stored in tratt */
for (i = 0; i < MAX_LEN; i++)
printf("%d\n", tratt[i]);
return 0;
}
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);
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;
}
I am trying to read values from a file and after some operation write to another file. Here facing a slight issue as I am also trying to save values in a 2D Array and displaying it. My file read and file write are showing correct results but my program throws an exception when it comes to display matrix part.
#include <stdio.h>
#include <ctype.h>
#ifndef NULL
#define NULL ((void *) 0)
#endif
int main(void)
{
FILE *file = NULL; //for file read
FILE *fptr = NULL; //for file write
int mat[182][274];
// code to read and display number from file
// open file for reading
file = fopen("file.txt", "r");
fptr = fopen("file1.txt", "w");
int i = 0,j=0;
fscanf (file, "%d", &i);
while (!feof (file))
{
symbol = fgetc(file);
if (symbol == '\n' || feof(file))
{
fprintf (fptr,"\n");
printf("\n");
}
else{
j=255-i;
mat[i][j]=j;
fprintf (fptr,"%d ", j);
fprintf (fptr," ");
printf ("%d ", j);
}
fscanf (file, "%d", &i);
}
fclose (file);
fclose (fptr);
//Facing issue in this part
int k;
int l;
for (k=0;k<=182;k++)
{
for(l=0;l<=274;l++)
{
printf("%d ", mat[k][l]);
}
}
return 0;
}
Arrays in C start at 0 and end at (array_size - 1).
As you're accessing memory just outside the array, you're most likely experiencing segmentation faults.
To fix this issue, change these lines:
for (k=0;k<182;k++)
{
for(l=0;l<274;l++)
{
printf("%d ", mat[k][l]);
}
}
Notice that I changed the relational operators from <= and >= to < and >, respectively.
Along with that, you may need to fully initialize your array. Odd values may be printed if the array is not initialized. (#Weather Vane).
However, to best be sure if this is the case, we need file.txt and file1.txt.
I have a .txt file that I am using to learn some basic C.
Here is the txt file:
8
12 48 15 65 16 82 9 72
Here is my C program:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv){
char num = 0;
//int[] arr = 0;
if (argc != 2){
return 0;
}
FILE *inputFile = fopen(argv[1], "r");
if (inputFile == NULL){
printf("Error1\n");
return 0;
}
while(!feof(inputFile)){
num = fgetc(inputFile);
printf("%c\n",num);
}
if(!feof(inputFile)){
printf("error");
return 0;
}
}
My goal is the get an array of the second line, based on the amount of values in the first line.... essentially, we want an array with 8 values, that stores {12, 48, ....}
You are using a wrong function to read integers: in spite of returning an int, function fgetc is reading individual characters (why getchar returns an int?).
In order to read space-separated integers, use fscanf instead, and check the return value to decide that you have reached the end of file:
int n;
while (fscanf(inputFile, " %d", &n) == 1) {
printf("%d\n", n);
}
Note that the loop above avoids using feof to detect the end of file condition (why using feof is wrong?)
If you aim to read a series of numbers (and nothing else), regardless of the number of line breaks in between, you could simply use fscanf as follows:
int num;
while(fscanf(inputFile, "%d", &num) == 1) {
printf("%d\n",num);
}
Note that fscanf returns the number of values successfully read in according to the format specifier, i.e. it returns 1 as long as an integral value could have been read in (and 0 otherwise).