sscanf till end of file in c - c

I have a C program that creates a binary file from a text file.
/*makeBinry.c*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char *argv[]){
char *ptext, *btext="file.bin";
if(argc != 2){
printf("Using default \"text.txt\" file to create mnemonics table\n");
ptext = "text.txt";
}else{
ptext = argv[2];
}
FILE *fp, *fb;
if(!(fp=fopen(ptext, "r"))){
fprintf(stdout, "Error: File %s is not available\n", ptext);
exit(1);
}
if(!(fb = fopen(btext, "wb"))){
fprintf(stdout, "Error: File %s is cannot be opened to write\n", btext);
exit(1);
}
int i, j, k;
char s[8], c, stringed[20];
while(!feof(fp)){
memset(stringed, '\0', sizeof(stringed));
fscanf(fp, "%X %d %c %d %[^\n]s", &i, &j, &c, &k, s);
sprintf(stringed, "%X %d %c %d %[^\n]s", &i, &j, &c, &k, s);
fwrite(stringed, 1, strlen(stringed), fb);
}
fprintf(stdout, "Success: %s file successfully created\n", btext);
fclose(fp);
fclose(fb);
return 0;
}
I have another program that reads the data in the binary file and stores into an array.
/*mainProg.c*/
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
typedef struct opStruct{
int hexv, fv, kv;
char str[8], key;
} node;
node* makeTable(char *filename){
FILE *fp;
if(!(fp = fopen(filename, "rb"))){
fprintf(stdout, "Error: Unable to open file %s\n", filename);
exit(1);
}
int hv, fv, kv;
char s[8], c, str[20];
while(!(feof(fp))){
sscanf(fp,"%X %d %c %d %[^\n]s", &hv, &fv, &c, &kv, str);
fprintf(stdout, "%X %d %c %d %s", hv, fv, c, kv, str);
}
fclose(fp);
return NULL;
}
int main(){
int i;
char *filename = "file.bin";
node *t_table = makeTable(filename);
return 0;
}
When I run the mainProg.c the program goes into an infinite loop. I figured it is because fp is never increased. How could I increase the file pointer and still use sscanf to read the binary file in the formatted manner? I'm not allowed to use fread(). Since currently, I'm not creating the table the function makeTable returns NULL.
Also, since the number of lines in the binary file would be unknown, how can I create the array dynamically using realloc?

the following code
properly handles error conditions
actually produces a binary file, rather than just another text file
uses the returned value from fscanf() rather than the faulty feof()
uses perror() so system error message is displayed on stderr
follows the axiom: only one statement per line and (at most) one variable declaration per statement
error checking for the calls to fwrite(), fclose() could be added but they are VERY unlikely to produce an error
and now the code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct record
{
unsigned int hv;
int fv;
int kv;
char c;
char s[8];
};
int main(int argc, char *argv[])
{
char *ptext, *btext="file.bin";
if(argc != 2)
{
printf("Using default \"text.txt\" file to create mnemonics table\n");
ptext = "text.txt";
}
else
{
ptext = argv[1];
}
FILE *fp;
FILE *fb;
if(!(fp=fopen(ptext, "r")))
{
perror( "fopen for read of text file failed" );
fprintf(stdout, "Error: File %s is not available\n", ptext);
exit(1);
}
if(!(fb = fopen(btext, "wb")))
{
perror( "fopen for write of binary file failed" );
fprintf(stdout, "Error: File %s is cannot be opened to write\n", btext);
fclose( fp ); // cleanup
exit(1);
}
struct record myRecord;
// produce binary file from text input
// note: leading space in format string, to consume any left over newline, etc
while(5 == fscanf(fp, " %X %d %c %d %7[^\n]",
&myRecord.hv,
&myRecord.fv,
&myRecord.c,
&myRecord.kv,
myRecord.s) )
{
fwrite( &myRecord, sizeof myRecord, 1, fb );
}
fprintf(stdout, "Success: %s file successfully created\n", btext);
fclose(fp);
fclose(fb);
return 0;
}
/*mainProg.c*/
#include <stdio.h>
#include <stdlib.h>
//#include <malloc.h>
#include <string.h>
//typedef struct opStruct
//{
// int hexv, fv, kv;
// char str[8], key;
//} node;
struct record
{
unsigned int hv;
int fv;
int kv;
char c;
char s[8];
};
//node* makeTable(char *filename)
void makeTable( char *filename )
{
FILE *fp;
if(!(fp = fopen(filename, "rb")))
{
fprintf(stdout, "Error: Unable to open file %s\n", filename);
exit(1);
}
// implied else, fopen successful
struct record myRecord;
// use fscanf() not sscanf()
while( fread( &myRecord, sizeof myRecord, 1, fp) )
{
//sprintf( , "%X %d %c %d %s\n" hv, fv, c, kv, s );
//fprintf(stdout, "%s", str );
fprintf( stdout, "\n%X", myRecord.hv );
fprintf( stdout, " %d", myRecord.fv );
fprintf( stdout, " %c", myRecord.c );
fprintf( stdout, " %d", myRecord.kv );
fprintf( stdout, " %8.8s", myRecord.s );
}
fprintf( stdout, "\n" ); // force flush
fclose(fp);
//return NULL;
} // end function: makeTable
int main( void )
{
//int i;
char *filename = "file.bin";
//node *t_table = makeTable(filename); // raises compiler warning about unused variable
makeTable(filename);
return 0;
} // end function: main

Related

Is there any encoding problems?

I am trying to write these parameters in a file .txt, but when I open the file (even before that it shows me a warining about the encoding) it appers like a bug, full of ????, like this:
$�U�z�G��?xpto%�U\���(\�?xpto&�Uףp=
��?xpto'�UR���Q�?xpto(�U�������?xpto)�UH�z�G�?xpto*�U��(\���?xpto+�U>
ףp=�?xpto,�U���Q��?xpto-�U433333�?xpto
I've searched a lot about but as it is a specifically error, i cannot find nothing about it.
What is happening?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
typedef struct
{
int age;
double height;
char name[64];
} Person;
void printPersonInfo(Person *p)
{
printf("Person: %s, %d, %f\n", p->name, p->age, p->height);
}
int main (int argc, char *argv[])
{
FILE *fp = NULL;
int i;
Person p = {35, 1.65, "xpto"};
/* Validate number of arguments */
if(argc != 2)
{
printf("USAGE: %s fileName\n", argv[0]);
return EXIT_FAILURE;
}
/* Open the file provided as argument */
errno = 0;
fp = fopen(argv[1], "w");
if(fp == NULL)
{
perror ("Error opening file!");
return EXIT_FAILURE;
}
/* Write 10 itens on a file */
for(i = 0 ; i < 10 ; i++)
{
p.age = p.age+1;
p.height = p.height+0.03;
fwrite(&p, sizeof(Person), 1, fp);
}
fclose(fp);
return EXIT_SUCCESS;
}
The fwrite function is writing the binary representation of the struct p to the file. If you want to write text, use fprintf:
fprintf(fp, "%d %f %s\n", p.age, p.height, p.name);

How to parse table from txt file in C variables?

I have a text file in this format:
#Name #Company #ID
Name1 Brand1 1234
Name2 Brand2 5678
And a struct:
struct MyStruct{
char name[TEXT_LEN];
char company[TEXT_LEN];
char ID[TEXT_LEN];
};
typedef struct MyStruct Data_t;
What I want... is to load the data from text file in appropriate variables. It should ignore first line because those are headers...
This is what I've been trying so far but without success:
int loadDataFromFile(Data_t *items, long len, char *inputFile)
{
FILE *fp;
if ((fp = fopen(inputFile, "r")))
{
for (long i = 0; i < len; i++)
{
/*fscanf(fp, "%s %s %s\n", items[i].name, items[i].company, items[i].ID);*/
//this is commented part was not working part... More about this in EDIT
fscanf(fp, "%s %s %s\n", items[i].name, items[i].company, items[i].ID);
printf("Name: %s", items[i].name); // For first item it prints:
// Name: #Name
}
}
return 0;
}
What is wrong here?
EDIT
I've replaced the code but now it reads first line as well. Is there a way to ignore header of file (first line)?
Try This,
#include <stdio.h>
#define TEXT_LEN 100
typedef struct
{
char name[TEXT_LEN];
char company[TEXT_LEN];
char ID[TEXT_LEN];
}Data_t;
int loadDataFromFile(Data_t *items, long len, char *inputFile) // change len as unsigned
{
FILE *fp;
char ch;
long i;
if ( ( fp = fopen(inputFile, "r") ) )
{
while( ( ch = getc(fp) != '\n') && ch!=EOF ); //To ignore first line
printf("Reading...\n");
for (i = 0; i < len && (fscanf(fp, "%s %s %s", items[i].name, items[i].company, items[i].ID) == 3); i++)
{
printf("\n#Name: %s #Company: %s #ID: %s", items[i].name, items[i].company, items[i].ID);
}
}
else
{
printf("File Error");
return 0;
}
return i;
}
int main()
{
Data_t data[2];
int n;
if(n=loadDataFromFile(data,2,"Txt")) //2 is number of line
{
printf("\n\nReaded !\n");
for(int i=0;i<n;i++)
printf("\n#Name: %s #Company: %s #ID: %s",data[i].name,data[i].company,data[i].ID);
}
return 0;
}
Txt:
#Name #Company #ID
Name1 Brand1 1234
Name2 Brand2 5678
Output:
Reading...
#Name: Name1 #Company: Brand1 #ID: 1234
#Name: Name2 #Company: Brand2 #ID: 5678
Readed !
#Name: Name1 #Company: Brand1 #ID: 1234
#Name: Name2 #Company: Brand2 #ID: 5678
[Done] exited with code=0 in 1.227 seconds
the following proposed code:
cleanly compiles
performs the desired functionality
properly discards the first line of the input file (the column headers)
properly checks for errors
properly checks that the data array is not overflowed
assures the fields in the data array are not overflowed when calling sscanf()
properly assures the input file can be read
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#define TEXT_LEN 21
struct MyStruct
{
char name[TEXT_LEN];
char company[TEXT_LEN];
char ID[TEXT_LEN];
};
typedef struct MyStruct Data_t;
long loadDataFromFile( Data_t *items, long len, char *inputFile )
{
FILE *fp = fopen(inputFile, "r");
if( ! fp )
{
perror( "fopen to read file failed" );
exit( EXIT_FAILURE );
}
// read/discard first line:
char buffer[1024];
if( ! fgets( buffer, sizeof( buffer ), fp ) ) // column header line
{
perror( "fgets failed to read column headers from input file" );
exit( EXIT_FAILURE );
}
long i = 0;
while( i < len && fgets( buffer, sizeof( buffer ), fp ) )
{
if( sscanf(buffer, "%20s %20s %20s", items[i].name, items[i].company, items[i].ID) != 3 )
{
break;
}
printf("Name: %s", items[i].name);
i++;
}
return i;
}
you coult try changin
fscanf(fp, "%s %s %s\n", items[i].name, items[i].company, items[i].ID);
to
fscanf(fp, "%s\t%s\t%s\n", items[i].name, items[i].company, items[i].ID);
and also iterating on the file lines could be done better by using something like this
while (!EOF) {/*Code*/}

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);
}

Better way to convert string to integer

I wrote this code to read a variable in a .txt file, ignore the first character and convert into a integer.It works but looks dumb, is there a better way to do this? I'm using just one string here but it's supposed to work with four.
void read(char a[])
{
int i;
char a1[3];
for (i = 0; i<3; ++i){
a1[i]= a[i+1];
}
int b1 = atoi(a1);
}
int main()
{
FILE *file;
file = fopen( "file.txt", "r");
if (file == NULL) {
printf( "Arquivo nao encontrado\n");
}
char a[4];
fscanf(file, "%s\n",&a);
read(a);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char filename[] = "file.txt";
FILE *fp = fopen(filename, "r");
if (fp == 0)
{
fprintf(stderr, "Failed to open file %s for reading\n", filename);
return(EXIT_FAILURE);
}
int value;
if (fscanf(fp, "%*c%d", &value) != 1)
{
fprintf(stderr, "Failed to read integer value from file %s\n", filename);
fclose(fp);
return EXIT_FAILURE;
}
printf("Read %d\n", value);
fclose(fp);
return 0;
}
The %*c reads a single character but does not assign it. The * to suppress an assignment is a general mechanism in the scanf()
family of functions.
Untested code.

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)

Resources