I am trying to read multiple different data types (char, int, float) from a text file directly into a Structure.
readData() {
char filename[100];
int linesread;
int i = 0;
printf("Enter the assets text file that you wish to read: \n");
scanf("%s", filename);
if ((fp = fopen(filename, "r")) == NULL) {
printf("Error opening data file\n");
readData();
} else {
while (fscanf(fp, "%s %c %s %lf %lf %d %d %d", &assets[i].name, &assets[i].type, &assets[i].location, &assets[i].longi, &assets[i].lati, &assets[i].speed, &assets[i].fuelTime, &assets[i].readyTime != EOF)) {
i++;
}
}
fclose(fp);
linesread = i;
for (i = 0; i < linesread; i++) {
printf("%s %s %s %lf %lf %d %d %d\n", &assets[i].name, &assets[i].type, &assets[i].location, &assets[i].longi, &assets[i].lati, &assets[i].speed, &assets[i].fuelTime, &assets[i].readyTime);
}
This Should read this out (when it decides to co-operate) and save it into the structure:
Angle_Lifeboat L Angle 51.685 -5.102 25.0 600 120
Angle_ILB L Angle 51.685 -5.102 25.0 180 30
Broad_Haven_ILB L Broad_Haven 51.713 -5.113 25.0 180 30
But instead reads this
ngle_Lifeboat LAngle Angle 0.000000 0.000000 0.000000 4231936 4231940
Angle_ILB LAngle Angle 0.000000 0.000000 0.000000 4232008 4232012
Broad_Haven_ILB LBroad_Haven Broad_Haven 0.000000 0.000000 0.000000 4232080 4232084
I am pretty new to C, so go easy on me. Any help you can give would be massively appreciated
EDIT: Stucture -->
typedef struct assets{
char name[25];
char type[1];
float longi;
float lati;
char location[20];
int speed;
int fuelTime;
int readyTime;
} assets;
In c programming i do think there is already an in build function to do the above ...
try using fread http://www.tutorialspoint.com/c_standard_library/c_function_fread.htm
fread(&my_struct, sizeof(my_struct), 1, fp);
BLUEPIXY correctly noticed the != EOF bad position; correct is:
… &assets[i].readyTime) != EOF) {
We cannot print the character in assets[i].type as a string with %s, because that 1-char-array type[1] doesn't have (room for) the terminating null character; we must print it as a string with precision .1 or a character:
printf("…%.1s…\n", …assets[i].type…); // need no & operator
or
printf("…%c…\n", …*assets[i].type…); // need * operator
The conversion specification %lf is for a pointer to double (rather than float); the floats need the conversion specification %f.
Since the speed values are 25.0, we cannot read them as integers with %d; we rather need to read a float variable with %f, either a temporary variable which is then assigned to assets[i].speed, or by defining float speed; in assets.
Related
I have created the following program
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
const double PI = 3.14159;
int main()
{
char str[120];
double distance, azimuth;
double delta_x = 0;
double delta_y = 0;
FILE *fp = fopen("input.txt", "r");
if (fp == NULL)
return -1;
fgets(str, sizeof(str), fp); //skip first line
while (fgets(str, sizeof(str), fp)) {
if (strcmp("Dig here!", str) == 0)
break;
printf(str);
sscanf(str, "go %f feet by azimuth %f\n", &distance, &azimuth);
printf("distance %f azimuth %f\n", distance, azimuth);
delta_y += distance * sin(azimuth * (PI/180));
delta_x += distance * cos(azimuth * (PI/180));
}
printf("%d %d", delta_x, delta_y);
fclose(fp);
return 0;
}
input.txt looks something like this
Stand at the pole with the plaque START
go 500 feet by azimuth 296
go 460 feet by azimuth 11
Dig here!
However the output gives
go 500 feet by azimuth 296
distance 0.000000 azimuth 0.000000
I'm sure it's a dumb error I am missing but I can't seem to find it, any help would be appreciated.
The "%f" format specifier of scanf is for float type:
f – Matches an optionally signed floating-point number; the next pointer must be a pointer to float.
If you wish to parse a double type then use the l format specifier in combination with f:
l – Indicates either that the conversion will be one of d, i, o, u, x, X, or n and the next pointer is a pointer to a long int or unsigned long int (rather than int), or that the conversion will be one of e, f, or g and the next pointer is a pointer to double (rather than float).
So, you should change your format string as follows:
sscanf(str, "go %lf feet by azimuth %lf\n", &distance, &azimuth);
printf("distance %lf azimuth %lf\n", distance, azimuth);
Note that fgets may contain trailing '\n', in other words if a newline is read, it is stored into the buffer. Therefore before you compare the input coming from fgets against "Dig here!", you have to remove the newline first.
There is many options to do this, in the comments below you can see a good one or you can use the following approach with strcspn function:
str[strcspn(str, "\r\n")] = '\0'; /* works for any combination of CR and LF */
if(strcmp("Dig here!", str) == 0)
break;
Here's my code
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int x = 0;
int y = 0;
float a[5][2]; //array
float b[3][2]; //array
float c[2][2]; //array
FILE *fr;
//int c;
float power;
char unit[5];
//int N; //Number of sensors
float TI; //Time interval
//char M; //Midpoint
//char T; //Trapezoid
//int SR; //Sample Rate
fr = fopen("sensor_0.txt","r");
/*fr = fopen("sensor_1.txt","r");
fr = fopen("sensor_2.txt","r");
*/
//----------------------------------------------------------------------------------------------------------------------------
printf("The contents of %s file are :\n", "sensor_0.txt");
while ( !feof( fr ) )
{
fscanf(fr, "%f %f %s",&TI, &power, unit);
//printf("%f, %f \n", TI,power); //print
a[x][y] = TI;
a[x][++y]= power;
x++;
y = 0;
}
fclose(fr);
//----------------------------------------------------------------------------------------------------------------------------
printf("%s", "hello");
return 0;
}
Why isn't my string printing out anything after the while loop?
If I uncomment the same line inside the while loop, it prints properly. I've also tried just adding simple printf("hello") yet nothing seems to work after the while loop.
Edit - minor formatting.
output should just be
700 25.18752608 mW
710 26.83002734 mW
720 26.85955414 mW
730 23.63045233 mW
I suspect the file has 5 lines, not 4.
Your test of !feof() fails because you have not hit the end of file yet when you try to read the 6th line. fscanf fails but you do not test the return value. So you store TI and power beyond the end of the 2D array, invoking undefined behavior.
Changing the loading code this way should fix the problem:
while (x < 5 && fscanf(fr, "%f %f %4s", &TI, &power, unit) == 3) {
a[x][0] = TI;
a[x][1] = power;
x++;
}
if (x != 5) {
printf("incomplete input\n");
}
Doing what chqrlie suggested worked.
"instead of while ( !feof( fr ) ) that is incorrect, use while (fscanf(fr, "%f %f %4s",&TI, &power, unit) == 3)"
I am trying to read a file that has the following contents:
1.0000000e+01 2.9265380e+03 5.0821200e+02 4.3231640e+01
2.0000000e+01 1.0170240e+04 9.2798610e+02 4.0723180e+01
3.0000000e+01 2.1486260e+04 1.1832420e+03 1.0328000e+01
4.0000000e+01 3.3835080e+04 1.1882285e+03 -9.3307000e+00
5.0000000e+01 4.5250830e+04 1.0899705e+03 -1.0320900e+01
6.0000000e+01 5.5634490e+04 9.8935650e+02 -9.8019000e+00
7.0000000e+01 6.5037960e+04 8.9134700e+02 -9.8000000e+00
but I can't seem to find a proper way to read the scientific notation. Here is what I have of the code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
// This is the array to store the input
double time[24], altitude[24], velocity[24], acceleration[24];
double var1, var2, var3, var4;
//This is the pointer declaration for opening a file
FILE * fp = fopen("rocket.txt", "r");
int i = 0;
while(fscanf(fp,"%g %f %f %f", &var1, &var2, &var3, &var4) > 0){
time[i] = var1;
altitude[i] = var2;
velocity[i] = var3;
acceleration[i] = var4;
printf("Time: %f \n", &time[i]);
i++;
}
printf("Time: %f", &time[0]);
fclose(fp);
return(0);
}
I've tried multiple combinations of %f, %g, %d to try and print out the result but I can never get the right thing.
If anyone can point me on the right direction I will greatly appreciate it.
What you want to use is %lf for input and %e for output in scientific notation:
scanf("%lf", &input);
printf("%e\n", input);
You could use a, e, f, or g in the conversion specifier like this:
fscanf(fp, "%a", &input); // NOTE: only with C99 compilers
fscanf(fp, "%e", &input);
fscanf(fp, "%f", &input);
fscanf(fp, "%g", &input);
They will all work for parsing floats, but for doubles you will need to use the length modifier "l" like this:
fscanf(fp, "%le", &input);
To print the values, you can use any of the specifiers but you don't need the length modifier "l":
printf("%e ", input); // or f or g (or a C99 compilers only)
printf("%le ", input); // produces the same thing
A really helpful reference is here:
http://en.cppreference.com/w/c/io/fscanf
I am scanning lines from a textfile and putting elements into specific arrays, sscanf is working fine and inserting variables into arrays as well BUT printing out first element of string array result in segmentation fault(printing works for first elements from other arrays and for rest elements in string array)
Here is my code:
char **shipTable = NULL;
char *notimportant;
double *dirTable;
double *numTable;
double *speedTable;
double *latTable;
double *lngTable;
void scanShips(){
char fname[30];
char line[150];
char shipname[10];
double lat;
double lng;
double speed;
double dir;
int numofShips;
numofShips=1;
FILE *myfile;
printf("give file name containing ships /n");
scanf("%s",fname);
myfile = fopen(fname,"rt");
fgets(line,80,myfile);
sscanf(line, "%d %d %d %d %d %d", &day, &month, &year, &h, &min, &sec);
while ( fgets( line,100,myfile) != 0 ) {
sscanf(line, "%s %lf %lf %lf %lf", shipname, &lat, &lng, &dir, &speed);
printf("%s",shipname);
printf("\n");
shipTable = realloc( shipTable, numofShips*sizeof(char*) );
latTable = realloc( latTable, numofShips*sizeof(double) );
lngTable = realloc( lngTable, numofShips*sizeof(double) );
dirTable = realloc( dirTable, numofShips*sizeof(double) );
speedTable = realloc( speedTable, numofShips*sizeof(double) );
shipTable[numofShips-1]=malloc((10)*sizeof(char));
strcpy (shipTable[numofShips-1],shipname);
dirTable[numofShips-1]=dir;
speedTable[numofShips-1]=speed;
latTable[numofShips-1]=lat;
lngTable[numofShips-1]=lng;
numofShips++;
//printf("%d",numofShips);
}
fclose ( myfile);
//note:
printf("%s",shipTable[0]);//<---Segmentation fault
printf("%s",shipTable[1]);//<---Perfectly fine, as well as rest fo the array
printf("%f",dirTable[0]);//<---Perfectly fine, as well as rest of "double" arrays
Example file :
13 11 2011 13 04 00
GW1927 52.408 -4.117 1.000 0.000
GS452 51.750 -4.300 5.000 10.000
EI597 52.100 -6.000 90.000 12.000
EI600 52.000 -5.900 10.000 15.000
EI601 54.000 -5.900 10.000 15.000
Shipname length will never be longer than 9 chars.
Your program is incomplete. Once I make it complete (by adding necessary #includes, defining day, month, etc.), it compiles and works just fine.
Conclusion: you are not telling us the whole story, and the bug is in the code that you didn't show.
I am trying to do what's been done here Read co-ordinates from a txt files using C Program . The data that I am trying to input is in this format:
f 10 20 21
f 8 15 11
. . . .
f 11 12 25
The only difference in my point structure is that I have a an extra char to store the letter in the first column (which may or may not be the letter f). I guess im either declaring my char wrong, or I'm calling it in printf incorrectly. Either way, I only get the first line read and then my program terminates. Any ideas ?
Here is my MWE below
#define FILEPATHtri "/pathto/grid1DT.txt"
#define FILEPATHorg "/pathto/grid1.txt"
#define MAX 4000
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
typedef struct
{
float x;
float y;
float z;
char t[1];
}Point;
int main(void) {
Point *points = malloc( MAX * sizeof (Point) ) ;
FILE *fp ;
fp = fopen( FILEPATHtri,"r");
int i = 0;
while(fscanf(fp, "%s %f %f %f ", points[i].t, &points[i].x, &points[i].y, &points[i].z ) == 4 )
{
i++;
}
fclose(fp);
int n;
for (n=0; n<=i; n++){
printf("%c %2.5f %2.5f %2.5f \n", points[i].t, points[n].x, points[n].y, points[n].z ); }
printf("There are i = %i points in the file \n And I have read n = %i points ",i,n);
return 0;
}
Since there's only 1 char in there, not a string just use a single char in your code:
char t;
}Point;
Then when you read it in:
while(fscanf(fp, "%c %f %f %f ", &points[i].t, &points[i].x, &points[i].y, &points[i].z ) == 4 )
{
I'll note that having an array of 1 char, at the end of a structure, sets you up for the struct hack which might not have been your intentions... A good reason to use just char t instead of char t[1]
Also this line:
for (n=0; n<=i; n++){
Should be
for (n=0; n<i; n++){
One last note... if you wanted to print the character out that you read in the prints at the bottom, you should be using n:
// note your previous code was points[i].t
printf("%c %f %f %f \n", points[n].t, points[n].x, points[n].y, points[n].z ); }
Check this
while(fscanf(fp, "%c %f %f %f ", points[i].t, &points[i].x, &points[i].y, &points[i].z ) == 4 )
{
i++;
}
fclose(fp);
int n;
for (n=0; n<i; n++){
printf("%c %2.5f %2.5f %2.5f \n", points[n].t, points[n].x, points[n].y, points[n].z ); }
printf("There are i = %i points in the file \n And I have read n = %i points ",i,n);
getch();
return 0;
}
modification are since only a single character is read %s modified to %c also in printf its not points[i].t its points[n].t . Also the limit checking in for loop is also corrected to n<i