I have two structs that I have to fill with student data. The data is in the format:
age, name, grade, age, group, turn
and in the header of the file is the number of student in the data.
struct school //school
{
char group; //A,B,C,D,E,F
char turn; //Morning, AFTERNOON
};
struct student
{
char *name;
char *grade;
int age;
struct school *E;
}student[6];
I tried to save first the data from a text with only the age, name, and grade to see if I could do it:
void get_file(const char* file, int *n){ //n is the amount of students
FILE* fptr;
fptr = fopen(file, "r");
if (fptr == NULL){
printf( "\n Error \n");
exit(1);
}
char* temp;
int tam = 0;
fscanf(fptr, "%d", n); //size of the list of students
for(int i= 0; i < *n; i++){
fscanf(fptr, "%d,%s,%s", &student.age[i],temp, student[i].grade);
tam = strlen(temp);
student[i].name = (char*)malloc(tam * sizeof(char));
strcpy(student[i].name, temp);
printf("%s\n", student[i].name);//to see if it's correct the content
}
fclose(fptr);
}
But, student.name store for example "Josh, A+" when it should only be "Josh". How can I fix this?
It's for an assignment.
EDIT:
My data looks like this
4 //size of list
Josh,A,20,D,M
Amber,B,23,E,M
Kevin,C,22,D,A
Adam,A+,21,C,A
Using the Remy Lebeau's solution, I got this
void get_file(const char* file, int *n){
*n = 0;
FILE* fptr = fopen(file, "r");
if (fptr == NULL){
printf( "\n Error \n");
exit(1);
}
char name[80];
char grade[2];
fscanf(fptr, "%d", n); //size of the list of students
for(int i = 0; i < *n; i++){
fscanf(fptr, "%80[^,],%2[^,],%d,%c,%c", &student[i].age, name, grade,&student[i].group, &student[i].turn);
student[i].name = strdup(name);
student[i].grade = strdup(grade);
}
fclose(fptr);
}
But I got a problem, because I made this change
struct student
{
char *name;
char *grade;
int age;
struct school E; //it was struct school *E
}student[6];
to pass the information, but my Teacher said that I couldn't change it, so how can I load information in struct school *E?
There are multiple problems with your call to fscanf():
&student.age[i] needs to be &student[i].age.
temp and student::grade are uninitialized pointers, they don't point anywhere, so reading data to memory pointed by them is undefined behavior. fscanf() will not allocate memory for you, you need to pre-allocate char[] buffers yourself for fscanf() to then read into.
%s reads non-whitespace characters including ',', which is why your code is not stopping on the , following Josh. Try using %[^,] instead of %s for that field.
Try something more like this:
void get_file(const char* file, int *n){
*n = 0;
FILE* fptr = fopen(file, "r");
if (fptr == NULL){
printf( "\n Error \n");
exit(1);
}
char name[256];
char grade[5];
fscanf(fptr, "%d", n); //size of the list of students
for(int i = 0; i < *n; i++){
fscanf(fptr, "%d,%255[^,],%4s", &student[i].age, name, grade);
student[i].name = strdup(name);
student[i].grade = strdup(grade);
printf("%d %s %s\n", student[i].age, student[i].name, student[i].grade);
}
fclose(fptr);
}
UPDATE:
The file data you have now shown does not match the format you described, which your code is expecting. You described (and coded) the file data as:
age, name, grade, age, group, turn (why 2 ages?)
But what you have shown looks more like:
name, grade, age, group, turn
You changed your format string in fscanf() to this new format, but you didn't change the order of the variables being read into to match this format. So, you are reading the name value into your age field, the grade value into the name field, and the age value into the grade field.
Also, you are not even attempting to handle group and turn correctly. They reside in a completely different structure, which you are not allocating any memory for. You need to allocate a school object, read group and turn into it, and then assign it to student[i].E.
With that said, try something more like this:
struct school
{
char group; //A,B,C,D,E,F
char turn; //Morning, AFTERNOON
} school[6];
struct student
{
char *name;
char *grade;
int age;
struct school *E;
}student[6];
void get_file(const char* file, int *n){
*n = 0;
FILE* fptr = fopen(file, "r");
if (fptr == NULL){
printf( "\n Error \n");
exit(1);
}
char name[81];
char grade[3];
fscanf(fptr, "%d", n); //size of the list of students
for(int i = 0; i < *n; i++){
student[i].E = &school[i]; // or, use malloc() instead, if needed...
fscanf(fptr, " %80[^,],%2[^,],%d,%c,%c", name, grade, &(student[i].age), &(student[i].E->group), &(student[i].E->turn));
student[i].name = strdup(name);
student[i].grade = strdup(grade);
}
fclose(fptr);
}
I have a code and my question is how to send structure array information to file and then scan it. I have some functions, but my function Write doens't write correctly to file.
typedef struct School
{
char Lesson[50];
char TeachersName[50];
char TeachersLastName[50];
int Credits;
int NumberOfStudents;
} School;
void Write(struct School sAmlendraInfor[]);
int main()
{
School sAmlendraInfor[MAX_SIZE] = {{"Math","NAME_A","LAST_NAME_A",120,60},
{"History","NAME_B","LAST_NAME_B",60,33}};
Scan(sAmlendraInfor);
Print(sAmlendraInfor);
Write(sAmlendraInfor);
}
void Write(struct School sAmlendraInfor[])
{
int chars;
FILE *fp;
fp = fopen("\student.bin", "wb");
if(fp == NULL)
{
printf("Error opening file\n");
exit(1);
}
chars = fwrite (&sAmlendraInfor, sizeof(School), 1, fp);
printf("Number of items written to the file: %d\n", chars);
fclose(fp);
}
I'm trying to read a text file in C. And I want to put the info in a struct.
I think I'm reading the file correctly but when I have to print the info, all the data is filled by the last line of the text.
Do you know why?
#include <stdio.h>
#define MAXCHAR 1000
int main() {
struct lumi {
char *domini;
char *disponible;
};
struct lumi registre[256];
int i = 0;
FILE *fp;
char str[MAXCHAR];
char* filename = "fitxer.txt";
fp = fopen(filename, "r");
if (fp == NULL){
printf("Could not open file %s",filename);
return 1;
}
while (fgets(str, MAXCHAR, fp) != NULL){
registre[i].domini = str;
registre[i].disponible = "offline";
i = i+1;
}
printf("%s", registre[0].domini);
printf("%s", registre[1].domini);
printf("%s", registre[2].domini);
printf("%s", registre[3].domini);
fclose(fp);
return 0;
}
The .txt I tried is
Hi
My
Name
Is
Create a function to read a text file and transfer their name to a dynamic vector of structures.
I'm reading the file but it doesn't appear nothing on the screen.
typedef struct aluno student;
struct aluno{
char name[50], address[50], number[9];
int year;enter code here
};
student *lerFicheiroTexto(char *nameFile, int *tam){
FILE *f1;
student buffer;
student *aux;
student *vetor = NULL;
f1 = fopen(nameFile, "rt");
if(f1 == NULL){
printf("Error opening the file text");
return NULL;
}
while(fscanf(f1, "%s %s %d %s", buffer.name, buffer.address, &buffer.year, buffer.number) == 3){
printf("%s\t%s\n%d\n%s\n", buffer.name, buffer.address, buffer.year, buffer.number);
aux = realloc(vetor, sizeof(student)*(*tam+1));
if(aux == NULL){
//realocation failled
printf("Reallocation failled. Maintain tam \n");
(*tam) = 0;
return NULL;
}
else{
vetor = aux;
vetor[(*tam)] = buffer;
}
(*tam)++;
}
fclose(f1);
return vetor;
}
I would need to have your input file to test this but I changed your code a bit.
I'm also a student so my apologies if I've done something wrong.
From what I see, I believe your code could be improved like so:
Definition of struct:
typedef struct aluno {
char name[50], address[50], number[9];
int year;
} Aluno;
Function to read the file and build your array:
Aluno* lerFicheiroTexto(char* nameFile, int tamanho)
{
FILE* file = fopen(nameFile, "r");
if (file == NULL) {
printf("Error opening the file text");
return NULL;
}
Aluno* listaAlunos = malloc(sizeof(Aluno));
char line[255];
while (fgets(line, 255, file) != NULL) {
Aluno currAluno;
sscanf(line, "%s %s %d %s", currAluno.name, currAluno.address, currAluno.year, currAluno.number);
listaAlunos[tamanho] = currAluno;
listaAlunos = realloc(listaAlunos, sizeof(Aluno) * ++tamanho);
}
fclose(file);
return listaAlunos;
}
Hello i have a structure with couple of variables and i try to write and read them from/to binary files but when i read them i see only strange symbols and i dont know what i messed up,i have tried couple of variants but none of them works
typedef struct catalog
{
char num[20];
char name[80];
char author[50];
double price;
int year;
char publisher[80];
} Catalog;
Catalog* createCatalogData()
{
Catalog* c = malloc(sizeof(*c));
if (!c)
{
// Ups... add error handling
exit(0);
}
printf("Add num ");
getString(&c->num);
printf("Add name ");
getString(&c->name);
printf("add author ");
getString(&c->author);
printf("Add price ");
if (scanf("%lf", &c->price) != 1)
{
// Ups... add error handling
exit(0);
}
printf("Add publisher");
getString(&c->publisher);
printf("Add year");
if (scanf("%d", &c->year) != 1)
{
// Ups... add error handling
exit(0);
}
char *filePath = malloc(strlen(c->num) + 13);
char *folderName = "Catalogs\\";
strcpy(filePath, folderName);
strcat(filePath, c->num);
strcat(filePath, ".bin");
FILE *file = fopen(filePath, "wb");
if (file == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fwrite(&c->num,1, strlen(c->num), file);
fwrite(&c->name,1, strlen(c->name), file);
fwrite(&c->author,1, strlen(c->author), file);
fwrite(&c->price, 1, sizeof(double), file);
fwrite(&c->publisher,1, strlen(c->publisher), file);
fwrite(&c->year,1, sizeof(int), file);
fclose(file);
return c;
}
Catalog* readCatalogData(char *filePath)
{
Catalog* c = malloc(sizeof(*c));
FILE* fh;
fopen_s(&fh, filePath, "rb");
//check if file exists
char *ptr;
//read line by line
const size_t line_size = 300;
char* line = malloc(line_size);
int counter = 0;
char* date;
fread(c->num, 1, 21, fh);
fread(c->name, 1, 80, fh);
fread(c->author, 1, 50, fh);
fread(&c->price, 1, sizeof(double), fh);
fread(c->publisher, 1, 80, fh);
fread(c->year, 1, sizeof(int), fh);
return c;
}
When you do e.g.
fwrite(&c->num,1, strlen(c->num), file);
you write a variable number of bytes without any terminator. When you read the file you have no idea how many bytes to actually read.
The above fwrite call actually contains another error, in that you write a pointer and not the actual data in c->num.
Instead of writing the data members one by one, write the whole structure in one single call:
fwrite(c, sizeof c, 1, file);
And when reading the file read the whole structure in a single fread call.
Important note (and as noted by Attie in a comment): If you intend to make this portable, then you should use serialization to read and write the data, as the size of the structure might not be the same on all platforms.
For simple code and just "experimenting" then it will work fine.