I am trying to read values from my text file and store them in struct array. My text file has these values:
names.txt
Num_of_rec: 5
3 7 10 1 red
5 6 8 2 red
9 9 16 5 blue
13 4 19 2 green
12 8 15 4 blue
And my code so far is this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ERROR -1
#define MAXLEN 256
struct Point {
float x;
float y;
};
struct Rectangle {
struct Point top_left;
struct Point bottom_right;
char color[7];
};
int main() {
int i, N;
char junk[MAXLEN];
struct Rectangle *data;
FILE *fp;
fp = fopen("names.txt", "r");
fscanf(fp,"%s %d\n",junk,&N);
printf("No: %d", N);
data = (struct Rectangle *) malloc(N*sizeof(struct Rectangle));
for(i=0; i<N; i++) {
fscanf(fp, "%lf %lf %lf %lf %s", data[i].top_left.x, data[i].top_left.y, data[i].bottom_right.x, data[i].bottom_right.y);
}
return 0;
}
I want to add all these values in a struct array(data), but I don't know how to do this properly. Until now the output is:
No: 5
and it just crash. I don't understand if the problem is the method that I am using to read the values from the file and store them to the struct array, or something else.
fscanf(fp, "%lf %lf %lf %lf %s", data[i].top_left.x, data[i].top_left.y, data[i].bottom_right.x, data[i].bottom_right.y);
There are three problems regarding fscanf:
fscanf takes pointers, you pass in values
fscanf expects 5 pointers, you only provide 4 values.
format specifier %lf expects a pointer to a double type
Changing the above statement to the follow should solve the crash.
fscanf(fp, "%f %f %f %f %s", &data[i].top_left.x, &data[i].top_left.y, &data[i].bottom_right.x, &data[i].bottom_right.y, data[i].color);
Related
The code tries to get names of 3 students and their marks in 3 subjects and print total score as well as average of score of each student along with their names.
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int main() {
char *names[3];
int test1[3],test2[3],test3[3];
for(int i=0;i<3;i++)
{
scanf("%s",&(*(names+i)));
scanf("%d",&test1[i]);
scanf("%d",&test2[i]);
scanf("%d",&test3[i]);
}
int j=0;
while(j<3){
printf("%s",*(names+j));
printf(" %d ",test1[j]+test2[j]+test3[j]);
printf("%.f\n",(test1[j]+test2[j]+test3[j])/3.0);
j++;
}
return 0;
}
But when I run this code, I am not getting output of any of the printf's written in while loop . Can anyone help me please?
The variable names is an array of pointers. But you never make these pointers actually point anywhere. Any attempt to dereference them will lead to undefined behavior.
Also the type of &names[i] (which is what &(*(names+i)) really is) is char **, which is not what the scanf format %s expects. Mismatching format specifier and argument type also leads to undefined behavior.
What you should use is an array of arrays of characters:
char names[3][256];
and let the sub-arrays decays to pointers to their first element (the expression names[i] decays to &names[i][0] which have the type char *):
scanf("%255s", names[i]);
Note that I added a length specifier to avoid writing out of bounds of names[i].
Then print as a normal string:
printf("%s %d %f\n", names[j],
test1[j] + test2[j] + test3[j],
(test1[j] + test2[j] + test3[j]) / 3.0);
For starters you included too many headers.
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
Actually only declarations from the header <stdio.h> are used in the program. So remove all other headers and leave only the header <stdio.h>
#include <stdio.h>
In this declaration
char *names[3];
there is declare an uninitialized array of pointers that have indeterminate values.
So this call of scanf
scanf("%s",&(*(names+i)));
that should be written at least like
scanf("%s",*(names+i));
because the expression &(*(names+i)) has the type char ** but the function expects an argument of the type char * invokes undefined behavior.
To store strings you need to declare an array of character arrays as for example
char names[3][100];
But in any case your approach with declaring four arrays looks is not good.
It will be better to declare a structure as for example
enum { NumberOfStudents = 3, NumberOfMarks = 3, MaxNameLen = 100 };
struct Student
{
char name[MaxNameLen];
unsigned int marks[NumberOfMarks];
};
In this case you could declare only one array of three object of the type struct Student.
Here is a demonstration program
#include <stdio.h>
int main( void )
{
enum { NumberOfStudents = 3, NumberOfMarks = 3, MaxNameLen = 100 };
struct Student
{
char name[MaxNameLen];
unsigned int marks[NumberOfMarks];
};
struct Student students[NumberOfStudents];
printf( "Enter information about %d srudents.\n", NumberOfStudents );
for (int i = 0; i < NumberOfStudents; i++)
{
printf( "Name of student #%d: ", i + 1 );
scanf( "%99s", students[i].name );
printf( "Enter his %d marks: ", NumberOfMarks );
for (int j = 0; j < NumberOfMarks; j++)
{
scanf( "%u", &students[i].marks[j] );
}
}
puts( "\nHere are the students with their total and average marks." );
for (int i = 0; i < NumberOfStudents; i++)
{
printf( "%s: ", students[i].name );
unsigned total = 0;
for (int j = 0; j < NumberOfMarks; j++)
{
total += students[i].marks[j];
}
printf( "%u %.1f\n", total, ( double )total / NumberOfMarks );
}
}
The program output might look like
Enter information about 3 srudents.
Name of student #1: Tom
Enter his 3 marks: 4 5 3
Name of student #2: Mary
Enter his 3 marks: 5 5 4
Name of student #3: Bob
Enter his 3 marks: 6 6 4
Here are the students with their total and average marks.
Tom: 12 4.0
Mary: 14 4.7
Bob: 16 5.3
I am having a problem to save all elements in when ı print it prints first line, or it prints with errors and bugs, ı want to start from second line.
Text in file:
5 5 7
H 1 1 MILK White liquid produced by the mammals
H 2 1 IN Used to indicate inclusion within space, a place, or limits
H 3 3 BUS A road vehicle designed to carry many passengers
H 5 3 DAN The name of a famous author whose surname is Brown
V 1 1 MIND A set of cognitive faculties, e.g. consciousness, perception, etc.
V 3 3 BAD Opposite of good
V 2 5 ISBN International Standard Book Number
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char *word; //word and corresponding hint
char *clue;
int x; //Starting x and y positions
int y;
char direction; //H for horizontal, V for vertical
int f; //solved or not
} Word_t;
int main()
{
int nrWords=7;
FILE * fpointer = fopen("puzzle2010.txt","r");
loadTextFile(fpointer,nrWords);
return 0;
}
Word_t* loadTextFile( FILE* fpointer, int nrWords ){
Word_t* tfile;
int deta,dete,data;
int i=0;
char skip[100];
tfile = (Word_t*) malloc(sizeof(Word_t)*nrWords);
for(i=0;i<nrWords;i++){
if(i==0){
fscanf(fpointer,"%d %d %d ",&data,&dete,&deta);
printf("%d %d %d \n",data,dete,deta);
}
else{
fscanf(fpointer,"%c %d %d %s %s ",&tfile[i].direction,&tfile[i].x,&tfile[i].y,tfile[i].word,&tfile[i].clue);
printf("%c %d %d %s %s ",tfile[i].direction,tfile[i].x,tfile[i].y,tfile[i].word,tfile[i].clue);
}
}
fclose(fpointer);
}
I have a text file where info looks like this:
he he 5 5 5 5 5 5 5 5 5 5 5
ne ne 5 5 5 5 5 5 5 5 5 5 5
and I can keep adding to it.
What I want to do is have a function that reads that info and puts in into struct array, but I'm having trouble with pointers and figuring out how to read one line, then next one etc. I'm aware function that reads atm is broken, I tried bunch of stuff and could not figure it out. Sorry if its a bit silly question.
Source.c
int main(void) {
int opcija=0;
U *ucenici=NULL;
while(opcija !=4){
printf("Odaberite opciju:\n 1.Stvaranje datoteke ucenici.txt\n 2.Upisivanje novog ucenika\n 3.Pregled ucenika\n 4.Izlaz iz programa\n");
scanf("%d", &opcija);
switch (opcija) {
case 1:
kreiranje();
break;
case 2:
dodavanje();
break;
case 3:
void citanje1(U *ucenici);
int j=brojanjelinija();
for (int i = 0;i < j; i++) {
printf("%d. %s %s\n", i + 1, ucenici[i].ime, ucenici[i].prezime);
}
}
}
return 0;
}
void citanje1(U **ucen) {
FILE* pok = NULL;
pok = fopen("ucenici.txt", "r");
int broj = brojanjelinija();
ucen = (U**)malloc(broj * sizeof(U*));
for (int i = 0;i < broj;i++) {
fscanf(pok, "%s %s %d %d %d %d %d %d %d %d %d %d %d \n", ucen[i]->ime, ucen[i]->prezime, ucen[i]->dan, ucen[i]->mjesec, ucen[i]->godina, ucen[i]->mat, ucen[i]->hrv, ucen[i]->eng, ucen[i]->hidr, ucen[i]->fiz, ucen[i]->term, ucen[i]->oet, ucen[i]->tehmat);
}
free(ucen);
}
Header.h
#ifndef HEADER_H
#define HEADER_H
typedef struct ucenik{
char ime[10];
char prezime[10];
int* dan;
int* mjesec;
int* godina;
int* mat;
int* hrv;
int* eng;
int* hidr;
int* fiz;
int* term;
int* oet;
int* tehmat;
}U;
void kreiranje(void);
void dodavanje();
int brojanjelinija();
void citanje1(U);
#endif // HEADER_H
All your ucinek data members that you want to use to store integers should actually store int instead of int*:
int dan;
int mjesec;
...etc...
Remember that a pointer tells the compiler where to find some other data, rather than storing a meaningful value itself.
Your fscanf line should then change to pass pointers to the integers, which you can get using the & operator:
fscanf(pok, "%s %s %d %d %d %d %d %d %d %d %d %d %d\n",
ucen[i]->ime, ucen[i]->prezime, &ucen[i]->dan, &ucen[i]->mjesec,
&ucen[i]->godina, &ucen[i]->mat, &ucen[i]->hrv, &ucen[i]->eng,
&ucen[i]->hidr, &ucen[i]->fiz, &ucen[i]->term, &ucen[i]->oet,
&ucen[i]->tehmat);
Those pointers tell fscanf where to store the parsed values.
I never use fscanf without checking the returned value either: it says how many values were successfully parsed from the input and stored. If it's not the number you're expecting, you should print an error message.
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.
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