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
Related
I'm trying to assign 'hp' , 'd', 's', 'status' respectively from an input file which has the content '600 144 100 Rain' . I have sucessfully assigned 3 of the numbers to hp,d,s ,but the 'Rain' string remains undone
since it appeared blank screen everytime I try adding it in. Here is my C code :
#include <stdio.h>
int read_file(int *hp, int *d, int *s, char t[]) {
FILE *infile, *outfile;
infile = fopen("input1.inp", "r");
// input1.inp's content is "600 144 100 Rain"
fscanf(infile, "%d %d %d %s", &hp, &d, &s, t);
printf("hp = %d\n",hp ) ;
printf("d = %d\n",d ) ;
printf("s = %d\n",s ) ;
printf("status = %s", t) ;
fclose(infile);
return 0;
}
If I odd the 'Rain' string out then my code run perfectly.
Can someone show me how to do it properly, what mistake did I make ?
Please notice that declaring variables in the parameter area is compulsory for me , I need it to pass the variables to the main part . Thank you !
You are invoking undefined behavior by passind data having wrong type to fscanf() and printf(). Be careful because hp, d and s are pointers.
The part
fscanf(infile, "%d %d %d %s", &hp, &d, &s, t);
printf("hp = %d\n",hp ) ;
printf("d = %d\n",d ) ;
printf("s = %d\n",s ) ;
should be
fscanf(infile, "%d %d %d %s", hp, d, s, t);
printf("hp = %d\n",*hp ) ;
printf("d = %d\n",*d ) ;
printf("s = %d\n",*s ) ;
Also the results of fopen() and fscanf() should be checked.
Here is some simple code that prints struct values
in_hotel_info function is used to get struct inputs.(And yes, I use 'gets' because my professor forced me to use it sadly). And also When I put "0" as an input, it ends and returns its input numbers.
And I used sscanf to scan strings and numbers.
#include <stdio.h>
typedef struct hotel_info hotel;
struct hotel_info
{
char name[30];
int rank;
double popular;
double far;
char breakfast;
};
int in_hotel_info(struct hotel_info *p);
void out_hotel_info(struct hotel_info *p, int N, int G, double D);
int main(void)
{
hotel hotels[100];
hotel *p;
int number = 0, ranks, fars, i;
number = in_hotel_info(hotels);
p = hotels;
printf("%d\n", number);
getchar();
for (; p < p+number; p++)
{
printf("%s %d %lf %lf %c\n", p->name, p->rank, p->popular, p->far, p->breakfast);
}
}
int in_hotel_info(struct hotel_info infos[])
{
char inputs[100];
hotel* p;
p = infos;
int cnt = 0;
while (1)
{
gets(inputs);
if (strcmp(inputs, "0") == 0)
{
break;
}
else
{
sscanf(inputs, "%s %d %lf %lf %c", p->name, &p->rank, &p->popular, &p->far, &p->breakfast);
}
p++;
cnt++;
}
return cnt;
}
The problem is, when I tried to print
for (; p < p+number; p++)
{
printf("%s %d %lf %lf %c\n", p->name, p->rank, p->popular, p->far, p->breakfast);
}
what I expected is
mike 2 3.5 4.24 Y
but I constantly got a segmentation error.
The problem is, when I tried to print
for (; p < p+number; p++)
{
printf("%s %d %lf %lf %c\n", p->name, p->rank, p->popular, p->far, p->breakfast);
}
the problem is p < p+number is always true when number is strictly positive, so the for never ends and you access out of the array with an undefined behavior (your segmentation fault).
you have additional problems
gets is very dangerous to use because it can write out of the array, use fgets or scanf (secifying max length to read), in the considered case you can read a number then check if it is 0 or not
in in_hotel_info in case the user enter more than than entrie you write out of the array, you need to get the max number of element to read in argument
when you read p->name in case the enter name longer than 29 you write out of the array, limit the size using %29s rather than %s. ALso to bypass spaces at the beginning of the name use %29s (with a space before)
you do not check scanf returns 5, so you do not detect invalid inputs
The getchar(); in main is strange
i have this data in file
ATOM 1 N MET A 1 25.909 16.164 -8.037
ATOM 2 CA MET A 1 25.498 14.786 -8.206
ATOM 3 C MET A 1 26.612 13.934 -8.806
ATOM 4 O MET A 1 27.442 14.402 -9.588
this is my full code
#include<stdio.h>
#include<math.h>
typedef struct prot {
char atom[10];
int atomno;
char site[10];
char residue[10];
char chain;
int residueno;
float x, y, z;
} Td;
int main()
{
FILE*fd;
fd=fopen("2zoi.pdb","r+");
Td data[1300];
char buffer[1300];
int a=0;
while(fgets(buffer, 1300, fd))
{
sscanf(buffer, "%s %d %s %s %c %d %f %f %f",data[a].atom,&data[a].atomno,data[a].site,
data[a].residue,&data[a].chain,&data[a].residueno,&data[a].x, &data[a].y, &data[a].z);
printf("%s %d %s %s %c %d %6.3f %6.3f %6.3f \n",data[a].atom,data[a].atomno,data[a].site,
data[a].residue,data[a].chain,data[a].residueno,data[a].x, data[a].y, data[a].z);
a++;
}
//---user input
int fr,sr;
int fa,sa;
int i=0;
float x1,x2,y1,y2,z1,z2;
float distance=0;
printf("Enter first no of atom :");
scanf("%d",&fa);
printf("Enter second no of atom :");
scanf("%d",&sa);
while(data[i].atomno>=0)
{
if(fa==data[i].atomno)
{
x1=data[i].x;
y1=data[i].y;
z1=data[i].z;
}
else if(sa==data[i].atomno)
{
x2=data[i].x;
y2=data[i].y;
z2=data[i].z;
}
i++;
}
printf("%f %f %f",x1,y1,z1);
printf("%f %f %f",x2,y2,z2);
//distance= sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2) + pow((z2 - z1), 2));
//printf("%6.3f",distance);
return 0;
}
the problem is at this part
printf("%f %f %f",x1,y1,z1);
printf("%f %f %f",x2,y2,z2);
i try to return to values from above loop where the value for x1,y1,z1 is for the first atom and x2,y2,z2 for second atom.
when i input 3 and 4, it gives answer
26.612 13.934 -8.806
27.442 14.402 -9.588
which is correct. but when i input 1 and 2, it gives rubbish answer. it seems like i cant input number 2 also number 10.did i do any mistake?
You have a big problem with data array values: not all elements of the array are set to 0 then the final loop can be broken.
You can use memset to reset to 0 all bytes of data array.
#include<stdio.h>
#include<math.h>
#include <string.h>
typedef struct prot
{
char atom[10];
int atomno;
char site[10];
char residue[10];
char chain;
int residueno;
float x, y, z;
} Td;
int main()
{
FILE*fd;
Td data[1300];
char buffer[1300];
size_t a=0;
fd=fopen("2zoi.pdb","r+");
if (fd != NULL)
{
memset(data, 0x00, sizeof(data));
while ((fgets(buffer, 1300, fd)) && (a < sizeof(data)/sizeof(data[0])))
{
sscanf(buffer, "%s %d %s %s %c %d %f %f %f",data[a].atom,&data[a].atomno,data[a].site,
data[a].residue,&data[a].chain,&data[a].residueno,&data[a].x, &data[a].y, &data[a].z);
printf("%s %d %s %s %c %d %6.3f %6.3f %6.3f \n",data[a].atom,data[a].atomno,data[a].site,
data[a].residue,data[a].chain,data[a].residueno,data[a].x, data[a].y, data[a].z);
a++;
}
//---user input
int fr,sr;
int fa,sa;
size_t i=0;
float x1,x2,y1,y2,z1,z2;
float distance=0;
printf("Enter first no of atom :");
scanf("%d",&fa);
printf("Enter second no of atom :");
scanf("%d",&sa);
while ((data[i].atomno>=0) && (i < sizeof(data)/sizeof(data[0])))
{
if(fa==data[i].atomno)
{
x1=data[i].x;
y1=data[i].y;
z1=data[i].z;
}
else if(sa==data[i].atomno)
{
x2=data[i].x;
y2=data[i].y;
z2=data[i].z;
}
i++;
}
printf("%f %f %f\n",x1,y1,z1);
printf("%f %f %f\n",x2,y2,z2);
}
else
{
fprintf(stderr, "Error opening file\n");
exit(1);
}
return 0;
}
You should check the fopen return value (as you can see in code posted), but as a standard rule: you should always check functions return values.
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 want to read a .dat file whose first line consists of a float and all consecutive lines are "int * int" or "int / int" and print or return whether the float is a result each division or multiplication.
I am very unpleased with the results that I am getting. My experience is limited to only a couple of hours doing C. Therefore I have no idea what is missing for the program to do what the code is looking like it would do.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int countlines(FILE* f){
int nLines = -1;
char xLine[10];
while(fgets(xLine,10,f)!=NULL){
nLines+=1;
}
return nLines;
}
int main(){
FILE * fPointer = fopen("test.dat", "r");
float dpFloat;
char oprnd[10];
int frstInt;
int scndInt;
//get float from first line
fscanf(fPointer, "%f", &dpFloat);
//count amount of lines below float
int amtLines = countlines(fPointer);
//loop through the other lines and get
int i;
for (i = 0; i < amtLines; i++){
fscanf(fPointer, "%d %s %d", &frstInt, oprnd, &scndInt);
//checking what has been read
printf("%d. %d %s %d\n", i, frstInt, oprnd, scndInt);
//print 1 if firstline float is quot/prod of consecutive line/s
//else 0
if (strcmp(oprnd,"*") ==1) printf("%i\n", (frstInt*scndInt)==dpFloat);
if (strcmp(oprnd,"/") ==1) printf("%i\n", (frstInt/scndInt)==dpFloat);
}
fclose(fPointer);
return 0;
}
Problem 1: strcmp returns 0 when its arguments are equal, not 1.
Problem 2: frstInt/scndInt will truncate the result. Fix it by adding 1.0* to the expression.
The lines
if (strcmp(oprnd,"*") ==1) printf("%i\n", (frstInt*scndInt)==dpFloat);
if (strcmp(oprnd,"/") ==1) printf("%i\n", (frstInt/scndInt)==dpFloat);
need to be
if (strcmp(oprnd,"*") == 0) printf("%i\n", (frstInt*scndInt)==dpFloat);
if (strcmp(oprnd,"/") == 0) printf("%i\n", (1.0*frstInt/scndInt)==dpFloat);
// ^^^ ^^^
Please be aware of the pitfalls of comparing floating point numbers. It's best to compare them within a tolerance. See Comparing floating point numbers in C for some helpful tips.