fscanf only scans in the first value of my file - c

#include <stdio.h>
#include <stdlib.h>
struct account{
int accountId;
char *name;
double amount;
};
int main(int argc, char **argv)
{
FILE *file=fopen(argv[1],"r");
struct account *Ptr;
int i,j;
int size=0;
fscanf(file,"%d",&size);
if(size==0)
{
printf("Unable to open file");
return 0;
}
printf("%d",size);
Ptr=malloc(sizeof(struct account)*size);
for(i=0;i<size;i++)
{
fscanf(file,"%d%s%lf\n",&(Ptr+i)->accountId,(Ptr+i)->name,&(Ptr+i)->amount);
}
for(j=0;j<size;j++)
{
printf("%d%s%lf\n",((Ptr+j)->accountId),(Ptr+j)->name,((Ptr+j)->amount));
}
fclose(file);
free(Ptr);
return 0;
}
This is used to read in the input file
2
2 Harry 23.45
8 Sally 100.91
Somehow the code reads in the first 2 for size and the second 2 during the for loop but nothing else

Your code has undefined behavior, because you are reading data into an uninitialized pointer:
fscanf(file,"%d%s%lf\n",&(Ptr+i)->accountId,(Ptr+i)->name,&(Ptr+i)->amount);
// ^^^^
// This pointer is uninitialized ----------------------+
There are three ways to address this:
Make name an array, rather than a pointer, e.g. char name[MAX_NAME], or
Use malloc to allocate space to name before reading data into it.
Read into a temporary buffer, then malloc the exact number of chars.

Related

Structures Program not working as intended (Bug)

I have been working on reading data from a file, which contains student name and age in the format:
John
12
Jane
13
Julia
18
Here's the program I wrote:
#include <stdio.h>
#include <stdlib.h>
struct record{
char name[50];
int age;
};
int main(){
FILE *fp;
fp=fopen("sample2.txt","r");
struct record a[50];
int counter=1;
int i=0;
while (!EOF){
if (counter%2!=0){
fgets(a[i].name,50,fp);
counter++;
}
if (counter%2==0){
a[i].age=getw(fp);
counter++;
i++;
}
}
return 0;
}
However, on printing a[0].name, I am not getting expected output. Can someone help?
As already pointed out in the comments, EOF is a value defined in stdio.h and does not say anything about your file descriptor. I also would recommend you to use fscanf (As long you are sure that the names in the file are all of the correct length). fscanf takes a string similar to printf, specifying the elements you are expecting and returns the number of possible matches. Also it helps you with converting your data to the correct datatypes. So the code could look like this:
#include <stdio.h>
#include <stdlib.h>
struct record
{
char name[50];
int age;
};
int main ()
{
FILE *fp;
fp = fopen ("sample2.txt", "r");
struct record a[50];
int i = 0;
while (fscanf(fp, "%s\n%d\n", (char *) a[i].name, &a[i].age) > 0) {
i++;
}
printf("%s %d\n", a[1].name, a[1].age);
return 0;
}

C function returning different values while calling from main function

I have written a program which read values from a the file. The data in the file is in following format.
100 Full Name SomeDetails.
234 Full Name SomeDetails
Following is the program which i wrote.
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAX 10
struct student
{
int rollno;
char name[20];
char course[25];
};
int main()
{
FILE *fptr;
fptr=fopen("records.txt","r");
struct student s[10];
int i=0,tstudent=0;
char che;
char line[100];
//SECTION : 1.1 -> READING NUMBER OF LINES
while(!feof(fptr))
{
che=fgetc(fptr);
if(che=='\n')
{
tstudent++;
}
}
printf("Total Lines in File = %d\n",tstudent);
fclose(fptr);
//SECTION : 1.2 -> READING RECORDS FROM FILE
fptr=fopen("records.txt","r");
char newString[20][20];
int ii,j,ctr;
j=0;
ctr=0;
for(i=0; i<tstudent; i++)
{
fgets(line,100,fptr);
printf("Value of Line %d = %s",i,line);
for(ii=0; ii<=(strlen(line)); ii++)
{
// if tab or NULL found, assign NULL into newString[ctr]
if(line[ii]=='\t'||line[ii]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=line[ii];
j++;
}
}
}
for(ii=0; ii < ctr; ii++)
{
printf("\n%s",newString[ii]);
}
printf("Value of ctr = %d",ctr);
fclose(fptr);
}
Above code is working fine, BUT all the code is in main function, but i want to make a separate function which can be called from main file and return me every data of file in two dimensional or one dimensional array as return value.
Any help/suggestions would be appreciated.
I tried following CODE as a separate function.. NOT WORKING.
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
char readfile(int tstudent,FILE* filename)
{
//FUNCTION TO READ RECORDS FROM FILE.
FILE *fptr;
int i,k;
char line[100];
char newString[20][20];
int j=0,ctr=0;
fptr=fopen("records.txt","r");
for(i=0; i<tstudent; i++)
{
fgets(line,100,fptr);
printf("Value of Line %d = %s",i,line);
for(k=0; k<=(strlen(line)); k++)
{
// if tab or NULL found, assign NULL into newString[ctr]
if(line[k]=='\t'||line[k]=='\0')
{
newString[ctr][j]='\0';
ctr++; //for next word
j=0; //for next word, init index to 0
}
else
{
newString[ctr][j]=line[k];
j++;
}
}
}
return newString;
}
I defined a new variable char results[] in main function.. and tried to called the function as follows
results[]=readfile(tstudent,fptr)
but when trying to read results.. its showing garbage
char readfile(int tstudent,FILE* filename)
...
char newString[20][20];
...
return newString;
That can't be a good thing, right? You define readFile to return one single character (not a pointer, just one byte) and then return an array instead. We should not be surprised the compiler complained.
If you "fix" that be redefining the return type, you still have a problem because newString is an automatic local variable. The storage (memory) it defines is undefined outside the function.
The easiest way for a function to populate a structure (or array) in C is for the caller to pass it as a function parameter. So you wind up with something more like:
int readfile( FILE* input, char newString[][20], int tstudent )
where newString is defined the same way as you have it, but by the caller, not in readfile. Cf. the stdio functions like fgets; most of them require the caller to define the buffer they read into.
I'll just point out a few more mistakes.
Whenever you call a function -- especially an I/O function -- check for errors. You may want to read tstudent records, but how many are there? If you ask for 5 and find only 1, what then? Your read loop must test for end-of-file, and readfile must return the number of records read, else the caller will never know. Compare with how fread(3) works. Those Unix guys knew a thing or two about how to define a function!
Now your function looks something like this:
int readfile( FILE* input, char newString[][20], int tstudent ) {
char line[100], *s;
int i=0;
for( ; i < tstudent && (s = fgets(line, sizeof(line), input)) != NULL; i++ ) {
/* do stuff with line */
}
/* check for EOF/error if s is NULL, and report */
return i;
}

Can't deallocate memory in my C program

I need your help deallocating memory in below program. I tried as you can see in main, but no success. Can not get how to do it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char name[25];
char street[25];
char citystate[25];
char zip[6];
}student;
typedef student *studinfo;
/*function prototypes*/
void getinfo(student *details[], int *);
int main(void)
{
int count = 0;
student *studptr[49];
getinfo(studptr, &count);/*call getinfo function to get student info*/
/*int i = 0;
for (i; i<count; i++) {
free(studptr[i]->name);
free(studptr[i]->street);
free(studptr[i]->citystate);
free(studptr[i]->zip);
} */
return 0;
}
Below is a function to get the info from the file. I will use this info later on in sort function and in display function to display the results. After that I should deallocate the memory.
void getinfo(student *details[], int *count)
{
char s[100];
studinfo info;
/*Get student information*/
while (gets(s) != NULL) {
info = (studinfo)malloc(sizeof(student));
strcpy(info->name, s);
gets(info->street);
gets(info->citystate);
gets(info->zip);
details[(*count)++] = info; /*Increase the pointer to next position*/
} /* End of while loop*/
} /* End of getinfo */
There are three problems with your code:
You are trying to free components of struct student. Since these component arrays were not allocated with malloc, you cannot free them; you need to free only the struct itself.
You are using gets, which can cause buffer overruns. You should use fgets instead, passing buffer size, and stdin for the FILE* parameter.
You copy s[100] into info->name. This can potentially overrun the buffer, because info->name fits only 25 characters.
Once you fix these issues, your program should run correctly.
It should be:
int i;
for (i = 0; i < count; i++) {
free(studptr[i]);
}
Since you allocated each student as a single block, you free them the same way.

Where does the error occur when I store the pointer to a array?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct record
{
char*title;
char* year;
char* length; //in minutes
} record;
void read(record* list[]);
void test(record* list[]);
int main(int args, char* argv[])
{
record* list[1024];
read(list); //add record to list (pass by reference)
test(list);
write(list);
return 0;
}
void test(record* list[])
{
int i;
for(i=0; i<1024; ++i)
{
if(list[i]!=NULL)
{
printf("%s index %d \n", list[i]->title ,i);
}
}
}
void read(record* list[])
{
int j; //ini a array of pointer initially point to null
for(j=0;j<1024;++j)
list[j]=NULL;
FILE* input=fopen("input.txt","r"); //file in
if(!input)
{
printf("Error"); exit(1);
}else
{
int i=0; //index for adding elements to array
char temp[100];
while(!feof(input))
{
record* current_record=(record*)malloc(sizeof(record));
fgets(temp,sizeof(temp),input); //temp is a line of file
char deli[]=" ";
char* result=NULL;
result=strtok(temp,deli); //titile info
current_record->title=result;
result=strtok(NULL,deli); //year
current_record->year=result;
result=strtok(NULL,deli); //length
current_record->length=result;
list[i]=current_record; //add to array
printf("%s \n",current_record->title);
++i;
}
fclose(input);
}
}
This is what my program does:
1. read a file line by line
2. store all the info in a line to a struct and store all the structs to a array. This array is a array of pointers. When elements unused, the pointer points to null.
3. test method. I want to print the data in a struct in this array.
Test method printed a weird output. Could anyone help me what the problem is? Dont tell me how to fix. Thank you.
input.txt:
zombieland 2009 88
avatar 2009 178
watchmen 2009 215
You error is that you don't keep copies of data read from the file.
When you read data you put that data into local variable temp. Then you set various pointers to different places in temp (you should copy to different memory). When you read another line, you override the contents of temp but the pointers still point to the same place
step 1 read zombieland 2009 88
pointers ^ ^ ^
step 2 read avatar 2009 178
oldpointers ^ ^ ^
newpointers ^ ^ ^
In short: copy the result of strtok() to a brand new malloc'd memory.
Oh! And don't forget to free() the memory when you no longer need it (probably at the end of the program).

Segmentation error in Xcode, debugger cant help me

I have been going crazy trying to figure out what is done wrong. I admit I am inexperienced when it comes to C, but I don't know what is wrong. Is the way that I am accessing/using the struct incorrect?
EDIT: I keep getting EXC_BAD_ACCESS in debugger.
#include <stdio.h>
#include <string.h>
#define MAX_STRING 20
#define MAX_PLYR 16
typedef struct {
char pname[MAX_STRING];
int runs;
char *s;
} Team_t;
int
main(void)
{
Team_t *team_data[MAX_PLYR];
int i;
char *p;
char name[MAX_STRING];
FILE *inp;
inp = fopen("teamnames.rtf", "r");
for (i = 0; i < MAX_PLYR;) {
while ((fgets(name, MAX_STRING, inp) != NULL));
printf("Name(i): %s\n", name);
strcpy(team_data[i]->pname, name);
i++;
}
fclose(inp);
return(0);
}
Edit: Here's what's changed, still getting Segmentation Error
#include <stdio.h>
#include <string.h>
#define MAX_STRING 20
#define MAX_PLYR 16
typedef struct {
char pname[MAX_STRING];
int runs;
char s;
} Team_t;
int
main(void)
{
Team_t team_data[MAX_PLYR];
char name[MAX_STRING];
int i;
FILE *inp;
inp = fopen("teamnames.rtf", "r");
for (i = 0; i < MAX_PLYR; i++) {
((fgets(name, MAX_STRING, inp)));
if (feof(inp)) {
printf("End of stream\n");
i = MAX_PLYR;
}
else {
if (ferror(inp)) {
printf("Error reading from file\n");
}
printf("Name(i): %s\n", name);
strcpy(team_data[i].pname, name);
}
}
fclose(inp);
return(0);
}
You declare team_data but you don't allocate it; therefore it's pointing off into random memory, as are the imaginary contents of the array. You need to actually create the array, something like
Team_t *team_data[MAX_PLYR] = (Team_t**) malloc(MAX_PLYR * sizeof(Team_t *));
Use structs, not pointers (or if you insist using pointers the allocate space for those structs)
Team_t team_data[MAX_PLYR];
fgets(team_data[i].pname, MAX_STRING, inp)
when you write
Team_t *team_data[MAX_PLYR];
you are not allocating any memory for the actual Team_t records, instead you are setting up an array of pointers to records.
If instead you would write
Team_t team_data[MAX_PLYR];
you would have allocated the records. When you then want to copy into the team_data array you write instead
strcpy( team_data[i].name, name );

Resources