Struct fscanf in file C - c

In file I need to read some inputs:
this is an example:
8 15
[1,1] v=5 s=4#o
[4,2] v=1 s=9#x
typedef struct{
int red2;
int stupac2;
int visina;
int sirina;
char boja[10];
}Tunel;
FILE* fin = fopen("farbanje.txt", "r");
Tunel* tuneli = malloc(sizeof(Tunel)*50);
// if(fin!=0)
fscanf(fin,"%d %d", &r,&s);
printf("%d %d", r,s);
int p=0;
while (fscanf(fin, "[%d,%d]", &tuneli[p].red2, &tuneli[p].stupac2) == 2)
{
p++;
}
for(i=0;i<p;i++)
{
printf("[%d,%d]", tuneli[i].red2, tuneli[i].stupac2);
}
Problem is that it wont read me properly inputs from here: [1,1] v=5 s=4#o
Last line where i use printf shows some random numbers.

Agree it is better to use fgets
But if you want to continue to use your current approach,
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int red2;
int stupac2;
int visina;
int sirina;
char boja[10];
}Tunel;
int main(){
int r, s, i;
FILE*fin=fopen("farbanje.txt", "r");
if(fin==NULL) {
printf("error reading file\n");
return 1;
}
Tunel *tuneli=(Tunel*)malloc(sizeof(Tunel)*50);
fscanf(fin,"%d %d\n", &r,&s);
printf("%d %d", r,s);
int p=0;
while (fscanf(fin, " [%d,%d]%*[^\n]", &tuneli[p].red2, &tuneli[p].stupac2) == 2)
{
p++;
}
fclose(fin);
for(i=0;i<p;i++)
{
printf("[%d,%d]", tuneli[i].red2, tuneli[i].stupac2);
}
}

Last line where i use printf shows some random numbers....
The random numbers you see are because the buffers to print were not properly populated yet.
This example shows how to read the file, using fgets() to read a line buffer, then use sscanf() to parse the first two values from the lines. (read in-code comments for a few other tips.)
int main(void)//minimum signature for main includes 'void'
{
int r = 0;
int s = 0;
char line[80] = {0};//{initializer for arrays}
int p = 0;
Tunel *tuneli = malloc(sizeof(*tuneli)*50);
if(tuneli)//always test return of malloc before using it
{
FILE *fin = fopen(".\\farbanje.txt", "r");
if(fin)//always test return of fopen before using it
{
fgets(line, sizeof(line), fin);
sscanf(line, "%d %d", &r, &s);
while(fgets(line, sizeof(line), fin))
{
sscanf(line, " [%d,%d]", &tuneli[p].red2, &tuneli[p].stupac2);
//note space ^ here to read only visible characters
printf("[%d,%d]\n", tuneli[p].red2, tuneli[p].stupac2);//content is now populated corretly
p++;
}
fclose(fin);//close when finished
}
free(tuneli);//free when done to prevent memory leaks
}
return 0;
}

Related

Wrong output for reading data from file into program

I've been working on a program to read data from file into a program and print it:
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
int e;
float f;
static char a[50];
FILE *fp;
fp = fopen("new_input.txt", "r");
if (fp == NULL)
exit(0);
while (1)
{
p = fgets(a, 50, fp);
if (p == NULL)
break;
printf("%s", a);
printf("\n");
fscanf(fp, "%d", &e);
printf("%d", e);
printf("\n");
fscanf(fp, "%f", &f);
printf("%f", f);
printf("\n");
}
fclose(fp);
return 0;
}
Contents of file new_input.txt are:
Girik
12
19.98
Nikhil
13
90.89
On running on OnlineGdb however I get the following output:
Girik
12
19.980000
12
19.980000
khil
13
90.889999
Can someone explain the problem with my code?
I'm concerned about incomplete name "Nikhil" in output and printing of the value 12 and 19.99 twice.
Link to code:
https://onlinegdb.com/r1ufoP8-d
The problem arises because the last fscanf does not parse the \n, so when the cycle restarts the fgets will parse it and print it, naturally the next fscanf is not able to parse the string ("Nikhil", which was not parsed), because it expects an int, it's downhill from there, as the values are not parsed, what's printed is the old values of e and f from the previous cycle.
If you change your last fscanf so it parses the \n everything works fine:
Live demo
while (1)
{
p = fgets(a, 50, fp);
if (p == NULL)
break;
printf("%s", a);
fscanf(fp, "%d", &e);
printf("%d", e);
printf("\n");
fscanf(fp, "%f\n", &f); //<--here
printf("%.2f", f);//.2f specifier so it prints only 2 decimal places
printf("\n");
}
The pointer is also unnecessary you can use fgets itself as a condition i.e.:
while (fgets(a, sizeof a, fp)) //will read until the end of the file
{
printf("%s", a);
//... same code
}
Anyway, here is a version you can use that will render you the expected result and output, and, I would argue, is better:
Live demo
#include <stdio.h>
#include <stdlib.h>
int main()
{
int e;
float f;
static char a[50];
FILE *fp;
fp = fopen("new_input.txt", "r");
if (fp == NULL){
return EXIT_FAILURE;
}
// will parse until \n or 49 characters max (given the container size)
while (fscanf(fp, " %49[^\n]", a) > 0)
// ^ space - will discard any blank characters
{
printf("%s\n", a);
if(fscanf(fp, "%d", &e) > 0){
printf("%d\n", e);
}
if(fscanf(fp, "%f", &f) > 0){
printf("%.2f\n", f);
}
}
fclose(fp);
return EXIT_SUCCESS;
}
I also added the checks for the fscanf returns which is always a good practise.
Or even:
//...
while (fscanf(fp, " %49[^\n]%d%f", a, &e, &f) == 3)
{
printf("%s\n%d\n%.2f\n", a, e, f);
}
//...
However, the best solution, I believe, is to parse everything with fgets and convert the values with sscanf or strtol/strtof, it's a more robust option. Give it a try.
For "read data from file into a program and print it", you can use e.g. fgets or fscanf. Both uses are included in the following adaption of your example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
int e;
float f;
static char a[50];
FILE *fp;
// use fgets
printf("\nVersion with using fgets\n\n");
fp = fopen("new_input.txt", "r");
if (fp == NULL) exit(0);
while(fgets(a, 50, fp)!=NULL)
{
printf("%s", a);
}
fclose(fp);
// use fscanf
printf("\nVersion with using fscanf\n\n");
fp = fopen("new_input.txt", "r");
if (fp == NULL) exit(0);
while(fscanf(fp,"%s\n",a)!=EOF)
{
printf("%s\n", a);
}
fclose(fp);
return 0;
}
COMMENTS:
Size of a[50] needs to be larger than maximum line size.
You can also fscanf for numbers (if you are sure, that it is a number).
Check, if string is integer or float (locale) is a new topic.
Another option: With the assumption that you can rely on the format in "new_input.txt" (to account for the comment of Devolus).
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
int g;
float f;
static char a[50];
FILE *fp;
fp = fopen("new_input.txt", "r");
if (fp == NULL) exit(0);
while(fscanf(fp,"%s\n",a)!=EOF){
printf("%s\n", a);
fscanf(fp,"%d\n",&g);
printf("%d\n", g);
fscanf(fp,"%f\n",&f);
printf("%f\n", f);
}
fclose(fp);
return 0;
}

c lang text file input sum of digits in rows

//ok, thanks for help. i edited the code, passed a pointer and now the it prints the number from particular row, prints the number of that row, and prints the sum off all consiquent numbers. Good so far, but...
What i want do do next, is to assign each of the sums to an array, so i can use for loop to check whether the resulting sum equals to any previous resulting sums. i use tab[n]==result;
unfortunatelly after the while loop is done, all the array elements are empty...thanks//
include
include
int main()
{
int result =0;
read_ints("numbers.txt", &result);
}
void read_ints (const char* file_name, int *result)
{
FILE* file = fopen ("numbers.txt", "r");
int i = 0;
int n=1; //row number//
int tab[n]; //array
if (file == NULL)
{
printf("unable to open file %s", file_name);
}
fscanf (file, "%d", &i);
while (!feof (file))
{
printf ("%d ", i);
*result += i;
tab[n]==result;
printf("row number: %d \n", n);
n++;
printf("\n sum of this number and all numbers before is: %d\n", *result);
fscanf (file, "%d", &i);
}
printf("\nnumber from row number one is ... : %d\n", tab[1]);
fclose (file);
}
Your code is mostly right. You're just calling read_ints incorrectly. You should pass in a pointer to result if you want a value returned.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void read_ints (const char* file_name, int *result) {
FILE* file = fopen (file_name, "r");
int i = 0;
if (file == NULL) {
printf("unable to open file %s\n", file_name);
return;
}
fscanf (file, "%d", &i);
while (!feof (file))
{
printf ("%d ", i);
*result += i;
printf("\n suma tej liczby ze wszystkimi poprzednimi wynosi: %d\n", *result);
fscanf (file, "%d", &i);
}
fclose (file);
}
int main() {
int result =0;
read_ints("liczby.txt", &result);
}
the following proposed code:
properly checks for errors
properly passes the error text to stderr, including the text reason the system thinks the error occurred.
uses the returned value from fscanf() to control the loop
properly contains a 'prototype' for the sub function
properly uses void inside the parens of main() and the prototype of the sub function that receives no parameters.
consistently indents the code, for readability
cleanly compiles
documents why each header file is included
And now, the proposed code:
#include <stdio.h> // FILE, perror(), fopen(), printf(), fclose()
#include <stdlib.h> // exit(), EXIT_FAILURE
void read_ints ( void );
int main( void )
{
read_ints();
}
void read_ints ()
{
FILE* file = fopen ("liczby.txt", "r");
if( !file )
{
perror( "fopen to read liczby.txt failed" );
exit( EXIT_FAILURE );
}
int i = 0;
int result = 0;
while ( fscanf ( file, "%d", &i) == 1 )
{
printf ("%d ", i);
result=result+i;
printf("\n suma tej liczby ze wszystkimi poprzednimi wynosi: %d\n", result);
}
fclose (file);
}
//ok, the code looks better now, but still, the result values doesnt seem to store in the tab[] array. this is due to lack of a pointer or bad declaration of the array(?).
i intented it to be a dynamic array, so that i dont need to declare the specific size of the array.//
#include <stdio.h>
#include <stdlib.h>
void read_ints(const char* file_name, int *result);
int main()
{
int result =0;
read_ints("numbers.txt", &result);
}
void read_ints (const char* file_name, int *result)
{
FILE* file = fopen ("numbers.txt", "r");
int i = 0;
int n=0; //row number//
int m;
int tab[m]; //array//
if (file == NULL)
{
printf("unable to open file %s", file_name);
}
while ( fscanf (file, "%d", &i) ==1)
{
n++;
printf ("%d\n ", i);
*result += i;
printf("\n we are at row nr. %d sum of this number and all numbers before is: %d\n", n, *result);
tab[n]==*result;
}
printf("\nnumber from row number one is ... : %d\n", tab[1]); //this does not work properly //
fclose (file);
}

fscanf always returns 0(CLOSED)

I am a beginner in C programming, and I am trying to write a simple code to read a text file and write its content into an array, then print it on console. However, I always get 0.0000, and I could not solve the problem.
#include <stdio.h>
#include <stdlib.h>
int numOfLines(FILE *fp1);
void printarr(float arr[], int size);
float *filetoArr(FILE *fp, int arrsize);
int main(int argc, const char *argv[]) {
char *fileName1 = argv[1];
FILE *fp1 = fopen(fileName1, "r");
printf("File name: %s", fileName1);
int size = numOfLines(fp1);
printf("Number of lines in the file: %d\n", size);
float *arr = filetoArr(fp1, size);
printarr(arr, size);
free(arr);
fclose(fp1);
}
void printarr(float *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%f ", *(arr + i));
}
}
float *filetoArr(FILE *fp, int arrsize) {
int size = arrsize;
float *arr = (float *)malloc(sizeof(float) * size);
for (int i = 0; i < size; i++) {
fscanf(fp, "%f\n", (arr+i));
}
return (arr);
}
int numOfLines(FILE *fp1) {
int numberOfLines = 0;
char c;
do {
c = getc(fp1);
if (c == '\n') {
numberOfLines++;
}
} while (c != EOF);
return numberOfLines;
}
your numOfLines goes to the end of the file.
You have to rewind(fp1) to reset your file handle to position 0, or fscanf hits the end of the file, and doesn't read anything (check return code from fscanf: it should be 1 I bet you're getting 0 all the time)
There are multiple problems in your code:
you read the whole file in numOfLines(): you must reset the file pointer to the beginning of file with rewind(fp1); so fscanf() can read the file instead of hitting the end of file immediately.
the variable c used to read bytes from the file must be defined as an int for the test for end of file to be reliable. Otherwise, depending on whether char is signed or not by default, the EOF would never match or could potentially match the character \377 as end of file erroneously.
you do not check for failure to open the file.
Although returning 0 is implicit for function main() since C99, it is advisable to write the return 0; statement explicitly for better clarity.

c, 2d char array and fopen

I'm trying to make a program that reads a file with list of names. The number of those names can vary, as well as the names lengths. I want to store them in an array of arrays of char, and read each row as a string to later open the file that corresponds to the name in question. But when I try to open the first one, I have an error opening file.
I'm totally out of ideas.
Help, please?
Here is the code relevant to this action:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
int glimps(char *fname);
int write_av(char *fname, int NumbFiles);
int clr(char *fname);
int readFile(char *fname, int i);
double *dalpha, *alpha, *Ln_t, *LnLnA, Conc;
long *time, *weights, *Lmax, Nmax;
char *av_file, **in_files, *antetka;
/****************************************************************************/
int main(int argc, char *farg[])
{
int i, NumbFiles, flag;
long row;
char *a1;
FILE *fp;
av_file = farg[1];
printf("av_file = %s\n",av_file);
NumbFiles = glimps(av_file);
in_files = (char **) malloc (sizeof(char *) * NumbFiles);
for (i=0 ; i<NumbFiles ; i++)
in_files[i] = (char *) malloc (sizeof(char) * 200);
Lmax = (long *) calloc((size_t) NumbFiles, sizeof(long));
if((in_files == NULL)||(Lmax==NULL)) printf("Грешка при read алок.\n, "), exit(-1);
if (flag = readFile(av_file, -1))
printf("Error in read av_file %s\n", av_file), exit(-1);
weights = (long *) calloc((size_t) Nmax, sizeof(long));
for(i = 0; i<Nmax; i++) weights = 0;
for(i = 0; i<NumbFiles; i++)
{
//if (flag = readFile(&(*in_files[i]), i))
if (flag = readFile(in_files[i], i))
printf("Error in in_files[%d], %s\n",i, &(*in_files[i])), exit(-1);
}
if (flag = write_av(av_file, NumbFiles))
printf("Error in write_av(%s)\n,", av_file), exit(-1);
exit(0);
}
/****************************************************************************/
int glimps(char *fname)
{
FILE *fp;
char buf[140];
int cnt=0;
fp = fopen (fname, "r");
while (fgets(buf,140,fp) )
{
cnt++;
}
fclose(fp);
return (cnt);
}
/****************************************************************************/
int readFile(char *fname, int k)
{
int cnt=0;
FILE *fp;
char buf[200], dummy[13];
printf("fname is %s\n", fname); getchar();
fp = fopen (fname, "r");
if(fp==(NULL)) return(-1);
if(!strcmp(fname,av_file) )
{
while (fgets(in_files[cnt++],200,fp) );
}
else
{
printf("read TUK!\n"); getchar();
fgets(buf,200,fp);
sscanf(buf,"%s %s %s %s %s %s %s %ld %s %s %lf\n",
dummy, dummy,dummy,dummy,dummy,dummy,dummy, &Lmax[k],
dummy, dummy, &Conc);
fgets(buf,200,fp);
sscanf(buf,"%s\n", antetka);
printf("read TUK!\n"); getchar();
while (fgets(buf,200,fp))
{
sscanf(buf,"%ld %lf %lf %s %lf %lf\n",
&time[cnt], &dalpha[cnt], &alpha[cnt], dummy, &Ln_t[cnt],
&LnLnA[cnt]);
weights[cnt++]++;
}
}
fclose(fp);
return (0);
}
...
Console Output:
> ./avr alpha_cubeL.C0.010
av_file = alpha_cubeL.C0.010
fname is alpha_cubeL.C0.010
fname is alpha_cubeL100C0.010
Error in read in_files[0], alpha_cubeL100C0.010
> ls alpha_cubeL100C0.010
alpha_cubeL100C0.010
What happens is that in the readFile function, you read the main file given as argument to make (from the content) several file names in in_files[i], but fgets reads lines including the CR or CRLF (ie the end of line character(s)). Thus later in the program, readFile fails as it tries to open filename + CR [LF].
You may just add a trim function near the top of your program, like
void trim(char *s) {
int i,l = strlen(s);
for (i=l-1 ; i>=0 && (s[i]==10 || s[i]==13) ; i--) s[i] = 0;
}
that removes CR and/or LF that end a string s, and then change the readFile function to trim the file names read in each line, like
while (fgets(in_files[cnt++],200,fp) ) {
trim(in_files[cnt-1]); // cnt-1, or do the cnt++ here (and not above...)
}
Then the files can be opened...
(this is probably not the only problem in this program, but this is a good start)

Read comma separated numbers from a file in C

I have a problem when trying to read a file with comma separated numbers, I want to have a function that creates arrays of integers (not knowing how many parameters the array has at first) in a file like this:
1,0,3,4,5,2
3,4,2,7,4,10
1,3,0,0,1,2
and so on. The result I want is something like
int v[]={1,0,3,4,5,2}
for every line in the file (obviously with the values in each line) so I can add this array to a matrix. I tried using fscanf, but I can't seem to make it stop at the end of each line. I also tried fgets, strtok, and many other suggestions I found on the Internet, but I don't know how to do it!
I'm using Eclipse Indigo in a 32-bit machine.
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *fp;
int data,row,col,c,count,inc;
int *array, capacity=10;
char ch;
array=(int*)malloc(sizeof(int)*capacity);
fp=fopen("data.csv","r");
row=col=c=count=0;
while(EOF!=(inc=fscanf(fp,"%d%c", &data, &ch)) && inc == 2){
++c;//COLUMN count
if(capacity==count)
array=(int*)realloc(array, sizeof(int)*(capacity*=2));
array[count++] = data;
if(ch == '\n'){
++row;
if(col == 0){
col = c;
} else if(col != c){
fprintf(stderr, "format error of different Column of Row at %d\n", row);
goto exit;
}
c = 0;
} else if(ch != ','){
fprintf(stderr, "format error of different separator(%c) of Row at %d \n", ch, row);
goto exit;
}
}
{ //check print
int i,j;
// int (*matrix)[col]=array;
for(i=0;i<row;++i){
for(j=0;j<col;++j)
printf("%d ", array[i*col + j]);//matrix[i][j]
printf("\n");
}
}
exit:
fclose(fp);
free(array);
return 0;
}
With the following code you will store the CSV into a multidimensional array :
/* Preprocessor directives */
#include <stdio.h>
#include <stdlib.h>
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
const char filename[] = "file.csv";
/*
* Open the file.
*/
FILE *file = fopen(filename, "r");
if ( file )
{
int array[10][10];
size_t i, j, k;
char buffer[BUFSIZ], *ptr;
/*
* Read each line from the file.
*/
for ( i = 0; fgets(buffer, sizeof buffer, file); ++i )
{
/*
* Parse the comma-separated values from each line into 'array'.
*/
for ( j = 0, ptr = buffer; j < ARRAYSIZE(*array); ++j, ++ptr )
{
array[i][j] = (int)strtol(ptr, &ptr, 10);
}
}
fclose(file);

Resources