Fscanf into a structure - c

I'm trying to fscanf some data into a struct, the compiler is OK with the code but when I try to print it, it doesn't even print the text. This is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct xy {
unsigned x;
unsigned y;
} myStruct;
int main(void)
{
FILE *myFile;
myStruct *xy;
myFile = fopen("filename.txt", "rb");
if(fscanf(myFile, "%u %u", &xy->x, &xy->y) != 2)
fprintf(stderr, "Error!"); exit(1);
fclose(myFile);
printf("x: %u, y: %u\n", xy->x, xy->y);
return 0;
}
Do I need to allocate space for this? If I have to, could you please show me how to go about doing that?

Your do not have a structure there. Simply a pointer on a structure.
You can either allocate memory for it with malloc() or declare the structure localy :
myStruct xy;
There is no need to use malloc in this example.
Fixed :
#include <stdio.h>
#include <stdlib.h>
typedef struct xy {
unsigned int x;
unsigned int y;
} myStruct;
int main(void)
{
FILE *myFile;
myStruct xy;
if ((myFile = fopen("filename.txt", "rb")) == NULL)
return (1);
if(fscanf(myFile, "%u %u", &xy.x, &xy.y) != 2)
{
fprintf(stderr, "Error!");
return (1);
}
fclose(myFile);
printf("x: %u, y: %u\n", xy.x, xy.y);
return 0;
}

Related

C problem with passing pointer to struct to function

I have a problem passing structure pointer to a function with fscanf().
Here's my struct:
typedef struct {
int health;
int y;
int z;
} save;
in main I have:
save save = { 0 }; //init with zeros
loadgame(&save);
health = save.health;
and my function loadgame() looks like that:
bool loadgame(save* save) {
FILE* fptr;
fptr = fopen("savegame.txt", "r");
if (fptr == NULL)
return 0;
fscanf(fptr, "health= %d", save->health);
return 1;
};
my savegame.txt file has line:
health= 5
and my function doesn't change save->health, after finish of this function my health equals zero.
I tried to do my function like that and it also has the same solution in function loadgame() I changed
fscanf(fptr, "health= %d", save-health);
to
fscanf(fptr, "health= %d", &(save-health));
fscanf(fptr, "health= %d", save->health); -> fscanf(fptr, "health= %d", &save->health);
Here you have working verison to play with https://godbolt.org/z/5CuZwR
As in my example always check the result of the scanf
Looks like your fscanf is passing the value of save->health instead of it's address.
You need to do
fscanf(fptr, "health= %d", &save->health);
Since -> has precedence over & this will give you the address of the health member.
fscanf needs a pointer so it knows where to save the value.
Other than that your code has a bunch of other small issues.
I have addressed those in the comments below:
#include <stdio.h>
#include <stdbool.h>
typedef struct {
int health;
int y;
int z;
}save_tp;
//using the same name for a typedef and a variable is a bad idea;
//typedef struct{...} foo; foo foo; prevents you from declaring other varibles of type foo
//as the foo variable overshadows the foo typedef name;
//better give types a distinct name
bool loadgame(save_tp* save){
FILE* fptr;
fptr = fopen("savegame.txt", "r");
if (fptr == NULL)
return false;
bool r = (1==fscanf(fptr, "health= %d", &save->health)); //needs an address + may fail
fclose(fptr); //need to close the file or you'd be leaking a file handle
return r;
} //shouldn't have a semicolon here
int main(void)
{
save_tp save={0};
if (!loadgame(&save)) perror("nok");
else printf("ok, health=%d\n", save.health);
}

Unsure of how to store integers from a file to a struct in c

I created two structs to store values in.
struct pair {
int x_pos;
int y_pos;
};
struct coordinates_header {
int length;
struct pair data[1000];
};
typedef struct coordinates_header coordinates;
coordinates *coords;
I then try to store data from a file using
char line[max_read];
int x, y;
FILE *in_file = fopen(filename, "r");
int i = 0;
coordinates *new = (coordinates *)coords;
while (fgets(line,max_read,in_file) != NULL) {
sscanf(line,"%d %d", &x, &y);
new -> data[i].x_pos = x;
new -> data[i].y_pos = y;
i++;
}
new -> length = i;
Then I try to print out the values
int print_struct(void *coords) {
coordinates *new = (coordinates *)coords;
for (int i = 0; i < new -> length; i++) {
printf("%d, %d\n", new->data[i].x_pos, new->data[i].y_pos);
}
return 0;
}
And then I get a segmentation fault
I was wondering if someone could point out where the error is. I have no experience with void but require the flexibility for the structure in some functions I'm going to use.
The file read will have the form
100 30
50 200
.. ..
I believe their are some mistakes in your code:
Instead of using coordinates *coords;, which is just a dangling pointer not pointing anywhere in memory, you should just declare a structure member coordinates coords.
Their is no need for void* pointers in your code. You would be better off using coordinates *coords to access the address of the structure member coordinates coords, instead of void *coords.
You are not checking the return value of FILE *in_file, which could return NULL if not opened properly.
It is always good to check the result of sscanf(), just incase two x and y coordinates were not found on a line.
With these recommendations, you can write your code like this:
#include <stdio.h>
#include <stdlib.h>
#define NUMCOORDS 1000
#define MAXREAD 100
typedef struct {
int x_pos;
int y_pos;
} coords_t;
typedef struct {
coords_t coords[NUMCOORDS];
int length;
} coordinates_t;
void print_struct(coordinates_t *coordinates);
int main(void) {
coordinates_t coordinates;
char line[MAXREAD];
FILE *in_file;
int i = 0;
in_file = fopen("coords.txt", "r");
if (in_file == NULL) {
fprintf(stderr, "Error reading file.\n");
exit(EXIT_FAILURE);
}
while (fgets(line, MAXREAD, in_file) != NULL) {
if (sscanf(line, "%d %d", &coordinates.coords[i].x_pos,
&coordinates.coords[i].y_pos) != 2) {
fprintf(stderr, "two coordinates(x, y) not found.\n");
exit(EXIT_FAILURE);
}
i++;
}
coordinates.length = i;
print_struct(&coordinates);
fclose(in_file);
return 0;
}
void print_struct(coordinates_t *coordinates) {
int i;
for (i = 0; i < coordinates->length; i++) {
printf("%d, %d\n", coordinates->coords[i].x_pos, coordinates->coords[i].y_pos);
}
}

Using a char array as input to module to scan a file in C

I am trying to use the getStats function twice - once for each input file. I am supposed to be using a char array called statFile[]to pass as the argument to the prototype to select which file it is to work with. Currently I know how to use one file at a time (by explicit naming the file in the prototype) to make it work, but do not understand how to use it for both inputs. Thanks in advance!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define AUBURN "auburn2013.txt" //input data files
#define ALABAMA "alabama2013.txt" //input data files
#define NUMGAMES 13
int getStats( char statFile[], int compPass[], int attPass[], int numYds[], int numTD[] );
void analysis( int compPass[], int attPass[], int numYds[], int numTD[], double aveYds[], double pectCmp[], int tdPts[], int numGames[]);
int main(void)
{
int compPass[NUMGAMES],
attPass[NUMGAMES],
numYds[NUMGAMES],
numTD[NUMGAMES];
double bamaStats,
auburnStats,
setAuburn,
setBama;
FILE *au = fopen("auburn2013.txt","r");
FILE *al = fopen("alabama2013.txt","r");
if (al == NULL)
printf("Error Opening File\n");
else if (au == NULL)
printf("Error Opening File\n");
bamaStats = getStats(ALABAMA, compPass, attPass, numYds, numTD);
return 0;
}
int getStats( char statFile[], int compPass[], int attPass[], int numYds[], int numTD[] )
{
int i,
p,
k = sizeof(compPass[NUMGAMES]);
FILE *al = fopen("alabama2013.txt","r");
while (fscanf(al ,"%d %d %d %d", &compPass[i], &attPass[i], &numYds[i], &numTD[i]) !=EOF)
{
i++;
}
printf("Number of Games with data: %d\n", i);
for(p=0; p<8 ; p++)
{
printf("%d %d %d %d\n", compPass[p], attPass[p], numYds[p], numTD[p]);
}
return 0;
}
You are already passing in the stat file name, so need to change:
FILE *al = fopen("alabama2013.txt","r");
to
FILE *al = fopen(statFile,"r");
You can do that like this:
#include <stdio.h>
#include <assert.h>
void print_fname(char **farray, int fnum)
{
int i;
assert(farray != NULL);
for (i = 0; i < fnum; ++i) {
assert(farray[i] != NULL);
printf("file name %d: %s\n", i + 1, farray[i]);
}
}
int main()
{
char *farray[] = {"file1", "file2"};
print_fname(farray, 2);
return 0;
}
Hope can help.

set member of pointer to ponter of a Structure in a function

This is my new question since I'm so newbie!!! :)
I have a text file like:
3
55.33 44.27 STN1
77.26 33.44 STN2
22.11 23.12 STN5
I would like to read it in c.
so I have defined a structure in a file header entitle read_stn.h for the file like:
#include <stdio.h>
#include <sys/file.h>
typedef struct station
{
double lat, lon;
char name[5];
} station;
and try to read the file using following codes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "read_stn.h"
void read_stn(char filename[], station **sta,int *station_no)
{
FILE *fp;
int i;
char sta_str[5];
float longitude, latitude;
fp = fopen(filename,"r");
fscanf(fp,"%d",station_no);
printf("%d\n", *station_no);
*sta = (station*)malloc(*station_no*sizeof(station *));
for(i=0;i<*station_no;i++)
{
fscanf(fp,"%f %f %s", &longitude, &latitude, sta_str);
printf("%f %f %s\n", longitude, latitude, sta_str);
sta[i]->lon=(double)longitude;
sta[i]->lat=(double)latitude;
strcpy(sta[i]->name,sta_str);
}
fclose(fp);
}
and a main routine:
#include <stdio.h>
#include <stdlib.h>
#include "read_stn.h"
int main()
{
station *sta;
int i,stn_no;
read_stn("station.dat",&sta,&stn_no);
for(i=0;i<stn_no;i++)
{
printf("%d %s %f %f\n",i+1, sta[i].name, sta[i].lon, sta[i].lat);
}
free(sta);
return 1;
}
but when I tried to read file I got segmentation core dump. Is there any error in my files. I think there is something error in defining the pointer to pointer member assigning. Would you help me?
You weren't far off, a couple errors.
This:
*sta = (station*)malloc(*station_no*sizeof(station *));
should be this:
*sta = malloc(*station_no * sizeof(station));
since you want to allocate memory for several structs, not for several struct pointers.
Then this:
sta[i]->lon=(double)longitude;
sta[i]->lat=(double)latitude;
strcpy(sta[i]->name,sta_str);
should be:
(*sta)[i].lon = (double) longitude;
(*sta)[i].lat = (double) latitude;
strcpy((*sta)[i].name, sta_str);
since your dynamic array is stored at *sta, not at sta.
Full working version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct station {
double lat, lon;
char name[5];
} station;
void read_stn(char filename[], station ** sta, int *station_no) {
FILE *fp;
int i;
char sta_str[5];
float longitude, latitude;
fp = fopen(filename, "r");
fscanf(fp, "%d", station_no);
printf("%d\n", *station_no);
*sta = malloc(*station_no * sizeof(station));
for (i = 0; i < *station_no; i++) {
fscanf(fp, "%f %f %s", &longitude, &latitude, sta_str);
printf("%f %f %s\n", longitude, latitude, sta_str);
(*sta)[i].lon = (double) longitude;
(*sta)[i].lat = (double) latitude;
strcpy((*sta)[i].name, sta_str);
}
fclose(fp);
}
int main() {
station *sta;
int i, stn_no;
read_stn("station.dat", &sta, &stn_no);
for (i = 0; i < stn_no; i++) {
printf("%d %s %f %f\n", i + 1, sta[i].name, sta[i].lon, sta[i].lat);
}
free(sta);
return 0;
}
outputs:
paul#local:~/src/c/scratch/station$ ./station
3
55.330002 44.270000 STN1
77.260002 33.439999 STN2
22.110001 23.120001 STN5
1 STN1 55.330002 44.270000
2 STN2 77.260002 33.439999
3 STN5 22.110001 23.120001
paul#local:~/src/c/scratch/station$
There are some other improvements you could make, e.g. you could fscanf() directly into double rather than via a float, you should check the return from fopen() and malloc(), and things like that, but I'll leave those as an exercise to you.
Also, for future reference, in your read_stn() function, it's often easier to create a local pointer, do all your work in that, and then assign the value to the output parameter just at the end. It helps you to avoid dealing with all this indirection within your function, for instance:
void read_stn(char filename[], station ** sta, int *station_no) {
FILE *fp;
station * psta;
int st_num;
if ( (fp = fopen(filename, "r")) == NULL ) {
fprintf(stderr, "Couldn't open file %s\n", filename);
exit(EXIT_FAILURE);
}
fscanf(fp, "%d", &st_num);
printf("%d\n", st_num);
if ( (psta = malloc(st_num * sizeof(*psta))) == NULL ) {
fprintf(stderr, "Couldn't allocate memory\n");
exit(EXIT_FAILURE);
}
for ( int i = 0; i < st_num; ++i ) {
fscanf(fp, "%lf %lf %s", &psta[i].lon, &psta[i].lat, psta[i].name);
printf("%f %f %s\n", psta[i].lon, psta[i].lat, psta[i].name);
}
*sta = psta;
*station_no = st_num;
fclose(fp);
}

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