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

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

Related

How to assign a double value to a double pointer within a struct?

I am trying to read 8000 double values from a file, then set a data field in two struct arrays equal to those values so that I can pass the arrays into an FFT function. Whenever I try to do this equalization, I get a Segmentation Fault.
#include <stdio.h>
#include <stdlib.h>
#include "simpleFFT.h"
#include "simpleFFT_data.h"
extern void testPrint(void);
extern double readFile(void);
extern void emxInit_real_T(emxArray_real_T);
int main() {
FILE *fp;
emxArray_real_T *Timeptr;
emxArray_real_T Time[4000];
emxArray_real_T *gFzptr;
emxArray_real_T gFz[4000];
Timeptr = &Time[0];
gFzptr = &gFz[0];
emxInit_real_T(*Timeptr);
emxInit_real_T(*gFzptr);
printf("Timeptr = %p\n", Timeptr->data);
printf("gFzptr = %p\n\n", gFzptr->data);
double fValues[8000]; //This array will hold all numbers from the foo.txt file
int timeCount = 0;
int gFzCount = 0;
int n = 0;
int i = 5;
double fmax;
fp = fopen("foo.txt", "r");
if (fp == NULL) {
printf("FAILURE");
return 0;
} else {
printf("SUCCESS\n");
}
printf("File Opened!\n\n\n");
while (fscanf(fp, "%lf", &fValues[n]) != EOF) {
if ((n % 2) == 0) {
fscanf(fp, ",");
Timeptr->data[timeCount] = fValues[n]; // SEGMENTATION FAULT HERE
timeCount++;
} else {
fscanf(fp, "\n");
gFzptr->data[gFzCount] = fValues[n]; // SEGMENTATION FAULT HERE IF LINE ABOVE IS COMMENTED OUT
gFzCount++;
}
n++;
}
fclose(fp);
//fmax = simpleFFT(Time, gFz);
printf("fValues[5] = %lf", fValues[5]);
//printf("Time->data[%d] = %lf, gFz->data[%d] = %lf\n", i, Time->data[i], i, gFz->data[i]);
printf("fPeak = %lf", fmax);
return EXIT_SUCCESS;
}
Here is the struct that I am using:
struct emxArray_real_T {
double *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
Here is the fault message from the debugger in CLion:

Segmentation fault 11, issue using pointers and returning them

i keep getting a segmentation fault when running this program. I'm attempting to read the files (inserted into the command line), and allocate the x and y coordinates in each file to a dynamically allocated memory struct called POINTS (using the function called readPoints). After they have been saved into these structs, i then pass them to the function calls calc where the x and y values are multiplied, and then added onto the next x and y multiplied.. so on. Could someone please explain to me where i went wrong! I am not great at pointers.
Thank you in advance.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
float xcord;
float ycord;
}POINTS;
int readPoints(char* file, int numofpoints);
int calc(POINTS* points, int numofpoints);
int main(int argc, char* argv[])
{
int numoffiles;
FILE* file;
int result, i;
numoffiles = argc;
POINTS* pointer;
int numofpoints;
if(numoffiles == 1)
{
printf("Please enter a file\n");
}
for(i=1; i<numoffiles; i++)
{
file = fopen(argv[i], "r");
fscanf(file, "%d", &numofpoints);
pointer = readPoints(file, numofpoints);
if( pointer == NULL)
{
printf("Error return from readPoints function");
}
result = calc(&pointer[i], numoffiles);
printf("%12f", result);
free(pointer);
}
}
int readPoints(char* file,int numofpoints)
{
int i, j;
POINTS* Pointstructs;
Pointstructs = (POINTS*)malloc((numofpoints)*sizeof(POINTS));
if(file == NULL)
{
printf("Error transferring file into readPoints\n");
}
for(i=0; i<numofpoints; i++)
{
fscanf(*file, "%f, %f", &Pointstructs[i].xcord, &Pointstructs[i].ycord);
printf("%f, %f", Pointstructs[i].xcord, Pointstructs[i].ycord);
}
return Pointstructs;
}
int calc(POINTS* points, int numofpoints)
{
int i=0, j=0;
int answer;
while(i<numofpoints && j<numofpoints)
{
answer += points[i].xcord * points[j].ycord;
i++;
j++;
}
return answer;
}
readpoints functions should take its first argument as file pointer BCS fopen returns FILE pointer but u are using char pointer. fscanf first argument should be a file pointer. Pls correct it

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

Fscanf into a structure

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

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.

Resources