When I was working on the C Programming Language, I wanted to do a little program to revise these previous knowledge points. And this is the program which it seems there are some problems with it.
This program is supposed to collect information from input and print it in the file "reg.txt" in a format.
However, after typing the first line and press the enter, the program quits, but I can't figure it out what's wrong with it.
#include <stdio.h>
int main()
{
FILE *fp;
struct profile
{
char *name;
char *surname;
int year;
int month;
int day;
} people[10];
int temp;
int i = 0;
char *line;
fp = fopen("reg.txt", "a");
while (fgets(line, 256, stdin)
{
sscanf(line, "%s %s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
++i;
}
temp = i-1;
for (i = 0; i <= temp; ++i)
fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);
fclose(fp);
return 0;
}
I've taken Ed Heal's advice and I was aim to check the return value of 'sscanf'. What's strange is that the program doesn't really reach the 'printf' part. I thought may there are some problems with the loop?
#include <stdio.h>
int main()
{
FILE *fp;
void filecopy(FILE *, FILE *);
struct profile
{
char *name;
char *surname;
int year;
int month;
int day;
} people[10];
int temp;
int i = 0;
char *line;
int j;
fp = fopen("reg.txt", "a");
while (fgets(line, 256, stdin) != NULL)
{
j = sscanf(line, "%s %s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
++i;
}
temp = i-1;
//for (i = 0; i <= temp; ++i)
// fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);
printf("%d",j);
fclose(fp);
return 0;
}
Even after making sure line has allocated memory, you should be getting a segfault on your sscanf when it tries to write to people[0].name and people[0].surname because those pointers will be undefined.
You need to allocate memory for these strings, either statically or dynamically (with malloc).
Printing log statements can also help quite a bit to gather some insight.
#include <stdio.h>
int main()
{
FILE *fp;
typedef struct
{
char name[64];
char surname[64];
int year;
int month;
int day;
} profile;
profile people[10];
int temp;
int i = 0;
char line[512];
printf("Starting profile line parser...\n");
printf("Please enter up to 10 people in the format: (name surname year/month/day)\n");
printf("Enter EOF to exit. (Linux: CTRL+D Windows CTRL+Z)\n");
fp = fopen("reg.txt", "a");
while (gets(line) != NULL)
{
sscanf(line, "%63s %63s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
++i;
}
printf("Processed %d lines.\n", i);
temp = i-1;
for (i = 0; i <= temp; ++i)
{
fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);
}
fclose(fp);
printf("Done with profile line parser...\n");
return 0;
}
EDIT: Because gets is deprecated, here is a fgets alternative.
Further reading on gets: Why is the gets function so dangerous that it should not be used?
EDIT: Also adding chux's buffer overflow protection.
Further reading on preventing buffer overruns with scanf: Read no more than size of string with scanf()
#include <stdio.h>
int main()
{
FILE *fp;
typedef struct
{
char name[64];
char surname[64];
int year;
int month;
int day;
} profile;
profile people[10];
int temp;
int i = 0;
char line[512];
printf("Starting profile line parser...\n");
printf("Please enter up to 10 people in the format: (name surname year/month/day)\n");
printf("Enter EOF to exit. (Linux: CTRL+D Windows CTRL+Z)\n");
fp = fopen("reg.txt", "a");
while (fgets(line, 512, stdin) != NULL)
{
sscanf(line, "%63s %63s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
++i;
}
printf("Processed %d lines.\n", i);
temp = i-1;
for (i = 0; i <= temp; ++i)
{
fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);
}
printf("Done with profile line parser...\n");
fclose(fp);
return 0;
}
You need to allocate memory before you use line with gets
#include <stdio.h>
int main()
{
FILE *fp;
struct profile
{
char *name;
char *surname;
int year;
int month;
int day;
};
struct profile people[10];
int temp;
int i = 0;
char line[256]; //you can also do dynamic allocation by using malloc
fp = fopen("reg.txt", "a");
// while (gets(line) != NULL) //use fgets instead gets
while( fgets(line, 256, stdin) ) //specify required buffer len
{
sscanf(line, "%s %s %d/%d/%d", people[i].name, people[i].surname, &(people[i].year), &(people[i].month), &(people[i].day));
++i;
}
temp = i-1;
for (i = 0; i <= temp; ++i)
fprintf(fp, "NAME: %s %s\nBIRTHDAY: %d/%d/%d\n", people[i].name, people[i].surname, people[i].year, people[i].month, people[i].day);
fclose(fp);
return 0;
}
Related
#include <stdio.h>
struct BirdHome{
char area[500];
char heightcm[100];
char feederquantity[10];
char hasNest[5];
};
struct Bird{
char isRinged[5];
char nameSpecies[50];
char birdAgeMonths[500];
struct BirdHome hom;
char gender[6];
};
struct Bird birds;
int main(void){
FILE *oput;
int max=100;
int count = 0;
char filename[100];
printf("file name? : ");
scanf("%s", &filename);
count = load(filename, &birds, max);
if (count == 0)
printf("No structures loaded\n");
else (
printf("Data loaded\n")
);
save(&birds, oput);
return 0;
}
int load(char *filename, struct Bird *birds, int max){
int count = 0;
FILE *fp = fopen(filename, "r");
char line[100 * 4];
if (fp == NULL)
return 1;
while (count < max && fgets(line, sizeof(line), fp) != NULL){
sscanf(line, "%s %s %s %s %s %s %s %s", birds[count].isRinged, birds[count].nameSpecies,
birds[count].birdAgeMonths, birds[count].hom.area,
birds[count].hom.heightcm, birds[count].hom.feederquantity,
birds[count].hom.hasNest,birds[count].gender);
count++;
}
fclose(fp);
return count;
}
int save (struct Bird *birds, FILE *oput){
int i;
oput=fopen("birdssave.txt","w");
for (i=0;i<3;i++){
fprintf(oput,"%s %s %s %s %s %s %s %s\n",birds[i].isRinged, birds[i].nameSpecies,
birds[i].birdAgeMonths, birds[i].hom.area,
birds[i].hom.heightcm, birds[i].hom.feederquantity,
birds[i].hom.hasNest,birds[i].gender);
}
fclose(oput);
}
Well, the problem was said in the description of the question. Somehow, the load function works properly (at least I think so, because it runs properly and the success message is always displayed) and the save function runs without errors, but it doesn't write the needed info inside a file and just leaves gaps.
True sparrow 3 30 20 2 False Male
False crane 24 200 100 6 True Female
False griffin 14 300 80 1 False Male
This is a text file which my program used to write and load. I think this can somehow help you to find my mistakes in this code.
The load function is made unproperly so it doesn't work. The normal functions does a lot more things to do. Here is the text of it with the needed commentaries
int load(char * filename){
FILE * fp;
char *c;
int m = sizeof(int);
int n, i;
/*prepare memory for info*/
int *pti = (int *)malloc(m);
if ((fp = fopen(filename, "r")) == NULL){
perror("Error occured while opening file");
return 1;
}
/*read the quantity of structures*/
c = (char *)pti;
while (m>0){
i = getc(fp);
if (i == EOF) break;
*c = i;
c++;
m--;
}
/*get the number of elements*/
n = *pti;
/*prepare memory for read massive of structures*/
struct bird * ptr = (struct bird *) malloc(3 * sizeof(struct bird));
c = (char *)ptr;
/*after save we read massive by symbols*/
while ((i= getc(fp))!=EOF){
*c = i;
c++;
}
/*sort the elements and printing in console*/
printf("\n%d birds in the file stored\n\n", n);
for (int k = 0; k<n; k++){
printf("%d %s %s %d %d %d %d %s %s \n", k + 1,
ptr[k].isRinged,ptr[k].nameSpecies,ptr[k].birdAgeMonths,ptr[k].homearea,
ptr[k].homeheightcm,ptr[k].homefeederquantity,ptr[k].homehasNest,ptr[k].gender);
}
free(pti);
free(ptr);
fclose(fp);
return 0;
}
At least, the save function can be untouched only because algorhytmically it does the same as the normal code.
Im currently having to take an input.txt file, where it goes something like
3
Sarah 90 40 30
John 23 55 33
help 34 99 74
as an input file,
and read it into a struct array, then create an output.txt.
I seem to be having a problem with the assignment. I tried fscanf, fgetc, fgets, strtok, delim and everything i could find on the internet, but due to my sloppy pointer knowledge, i seem to be stuck.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct studentT{
char *name;
int literature;
int math;
int science;
}studentT;
int main(void)
{
printf("Start of main\n");
FILE *fptr;
int i;
fptr = fopen("input.txt", "r");
//reading first line to dynamically allocate studentT
printf("dynamically allocating studentT\n");
char tempsize[4];
//fgets(tempsize,1,fptr);
//i=atoi(&tempsize[0]);
fscanf(fptr,"%d",&i);
struct studentT* record = malloc(i*sizeof(*record));
printf("i has interger value %d\n", i);
//line counter ignoring line 0; reading 1 and 2.
char line[24];
char buffer[24];
char delim[] = " ";
char *array[4];
int *darray[4];
printf("entering while loop\n");
fgets(buffer,24,fptr);
int idx =0;
while(fgets(line, sizeof(line),fptr)!=NULL &&idx<i)
{
puts(line);
char *buf = strtok(line, delim);
int iter =0;
while(buf!=NULL)
{
if(iter = 0){
array[iter]=buf;
buf = strtok(NULL,delim);
}
for(iter=1;iter<4;iter++){
*darray[iter] =atoi(buf);//
printf("%d,",*darray[iter]);
buf=strtok(NULL, delim);
}
}
record[idx].name=array[0];
record[idx].literature=*darray[1];
record[idx].math=*darray[2];
record[idx].science=*darray[3];
// printf("array value: %s %d %d %d\n",array[0], array[1], array[2], array[3]);
// printf("value after casting: %s %zu %zu %zu\n", array[0], (uintptr_t)array[1], (uintptr_t)array[2], (uintptr_t)array[3]);
//sscanf(buf,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
printf("%s\n", line);
//fscanf(fptr,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
line[strlen(line)-1]='\0';
printf("in idx loop %d %s %d %d %d\n\n", idx, record[idx].name, record[idx].literature, record[idx].math, record[idx].science);
idx++;
}
//output of file
printf("output commencing\n\n\n");
int tempave;
FILE *fout;
char *str1 = "Name Literature Math Science Ave.\n";
char *str2 = "Ave. ";
char *str3 = "Sarah\t 96\t 90\t 80\t 88.67";
char *str4 = "Minsu\t 55\t 70\t 76\t 67.00";
char *str5 = "Nara\t 88\t 70\t 96\t 84.67";
char *str6 = "79.67 76.67 84.00 80.11";
fout = fopen("output.txt", "w");
fprintf(fout,"%s\n", str1);
for(int idx=0;idx<i;idx++){
tempave = (record[idx].math+record[idx].literature+record[idx].science)/3;
fwrite(&record[idx],sizeof(struct studentT),1,fout);
fprintf(fout, "%d\n",tempave);
}
//fprintf(fout, "%s\n %s\n %s\n %s %s\n",str3,str4,str5,str2,str6);
fprintf(fout,"%s",str2);
float mathave,litave,sciave;
for(int idx=0;idx<3;idx++){
mathave+=record[idx].math;
litave+=record[idx].literature;
sciave+=record[idx].science;
}
mathave=mathave/3;
sciave=sciave/3;
litave=litave/3;
fprintf(fout,"%f %f %f",litave, mathave, sciave);
fclose(fptr);
fclose(fout);
}
edit: colleague mentioned I should malloc arrays so the code now looks uglier:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct studentT{
char *name;
int literature;
int math;
int science;
}studentT;
int main(void)
{
printf("Start of main\n");
FILE *fptr;
int i;
fptr = fopen("input.txt", "r");
//reading first line to dynamically allocate studentT
printf("dynamically allocating studentT\n");
char tempsize[4];
//fgets(tempsize,1,fptr);
//i=atoi(&tempsize[0]);
fscanf(fptr,"%d",&i);
struct studentT* record = malloc(i*sizeof(*record));
printf("i has interger value %d\n", i);
//line counter ignoring line 0; reading 1 and 2.
char line[24];
char buffer[24];
char delim[] = " ";
char *array[4];
int darray[4];
printf("entering while loop\n");
fgets(buffer,24,fptr);
int idx =0;
while(fgets(line, sizeof(line),fptr)!=NULL &&idx<i)
{
puts(line);
char *buf = strtok(line, delim);
int iter =0;
while(buf!=NULL)
{
if(iter = 0){
array[iter] = malloc(sizeof(char)*strlen(buf));
strcpy(array[iter],buf);
buf = strtok(NULL,delim);
}
for(iter=1;iter<4;iter++){
darray[iter] = (int*)malloc(sizeof(char)*strlen(buf));
memcpy(&darray[iter],buf,(sizeof(char)*strlen(buf)));//
buf=strtok(NULL, delim);
}
}
record[idx].name=malloc(sizeof(char)*strlen(array[0]));
strcpy(record[idx].name,array[0]);
record[idx].literature=darray[1];
record[idx].math=darray[2];
record[idx].science=darray[3];
// printf("array value: %s %d %d %d\n",array[0], array[1], array[2], array[3]);
// printf("value after casting: %s %zu %zu %zu\n", array[0], (uintptr_t)array[1], (uintptr_t)array[2], (uintptr_t)array[3]);
//sscanf(buf,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
printf("%s\n", line);
//fscanf(fptr,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
line[strlen(line)-1]='\0';
printf("in idx loop %d %s %d %d %d\n\n", idx, record[idx].name, record[idx].literature, record[idx].math, record[idx].science);
idx++;
}
//output of file
printf("output commencing\n\n\n");
int tempave;
FILE *fout;
char *str1 = "Name Literature Math Science Ave.\n";
char *str2 = "Ave. ";
char *str3 = "Sarah\t 96\t 90\t 80\t 88.67";
char *str4 = "Minsu\t 55\t 70\t 76\t 67.00";
char *str5 = "Nara\t 88\t 70\t 96\t 84.67";
char *str6 = "79.67 76.67 84.00 80.11";
fout = fopen("output.txt", "w");
fprintf(fout,"%s\n", str1);
for(int idx=0;idx<i;idx++){
tempave = (record[idx].math+record[idx].literature+record[idx].science)/3;
fwrite(&record[idx],sizeof(struct studentT),1,fout);
fprintf(fout, "%d\n",tempave);
}
//fprintf(fout, "%s\n %s\n %s\n %s %s\n",str3,str4,str5,str2,str6);
fprintf(fout,"%s",str2);
float mathave,litave,sciave;
for(int idx=0;idx<3;idx++){
mathave+=record[idx].math;
litave+=record[idx].literature;
sciave+=record[idx].science;
}
mathave=mathave/3;
sciave=sciave/3;
litave=litave/3;
fprintf(fout,"%f %f %f",litave, mathave, sciave);
fclose(fptr);
fclose(fout);
}
I have wrote a new version of what you need with comments. Hopefully, you can understand what is happening and fix your code or you can use this as well. You may need to change the name of the inputfile and outputfile to work with your input file.
#include <stdio.h>
#include <stdlib.h>
struct student {
char *name;
int literature;
int math;
int science;
};
typedef struct student Student;
int main(void) {
FILE* inputFile;
FILE* outputFile;
int first_read; //check to see if the number of students value was read
int readNumStudents; //count of how many students are there
int i; //tracking students struct array
Student* students; //array of student structs
readNumStudents = 0;
first_read = 0;
i = 0;
inputFile = fopen("input.txt", "r"); //might have to change to whatever your file name is
outputFile = fopen("output.txt", "w"); //might have to change to whatever you want the output file name to be
//checking for null file pointers
if(inputFile == NULL){
printf("Failed to open input file.\n");
exit(1);
}
if(outputFile == NULL){
printf("Failed to open output file.\n");
exit(1);
}
//read file until end of file is reached
while(!feof(inputFile)){
if (first_read == 0){// check to see if first line was read. if not read, then write the value to readNumStudents variable
fscanf(inputFile, "%d", &readNumStudents);
first_read = 1; //set the value to 1. this means that the number of students was read.
students = (Student*) malloc(sizeof(Student) * readNumStudents);//allocate Student structs for the number of given students fro input file. (ie. 3 structs)
if(students == NULL){//check for null
printf("Failed to allocate memory for students.\n");
break;
}
//If not null, then for every struct allocate memory for the name string because its char* not char name[50]
for(int j = 0; j < readNumStudents; j++){
students[j].name = (char*) malloc(sizeof(char) * 50);
if(students[j].name == NULL){//check for null
printf("Failed to allocate memory for name.\n");
exit(1);
}
}
} else {//this means that the first line was read. now read the names and scors
//since you know the format of the input file (string int int int) you can use fscanf with "%s %d %d %d" and the adress of the struct values
fscanf(inputFile, "%s %d %d %d", students[i].name, &(students[i].literature), &(students[i].math), &(students[i].science));
i++;//used to point to next student structure
}
}
//Go thorugh every struct and write each value to outputfile
for(int j = 0; j < i; j++){
fprintf(outputFile, "%s %d %d %d\n", students[j].name, (students[j].literature), (students[j].math), (students[j].science));
}
//free all the allocated memory and files
fclose(inputFile);
fclose(outputFile);
//you need to free the char array on top of the studnets struct array. so loop through every student to free it
for(int j = 0; j < i; j++){
free(students[j].name);
}
free(students);
return 0;
}
I'm a newbie in C.
Could you help me please. There is a structure First name, Last Name, gender, age. Entries must be entered from the keyboard. I need to save this information in a file and then show on the screen all entries with gender == Male and save them in a separate file.
Thank you!
There is a code for reading a structure from file, but I can't understand how to check gender == Male.
#include "stdafx.h"
#include <cstdio>
int _tmain(int argc, _TCHAR* argv[])
{
FILE *file;
struct Person {
char name[20];
char gender[20];
unsigned age;
};
struct Person SinglePerson[10];
char i=0;
file = fopen("e:\\Test.txt", "r");
while (fscanf (file, "%s%s%u", SinglePerson[i].name, &(SinglePerson[i].gender), &(SinglePerson[i].age)) != EOF) {
printf("%s %s %u\n", SinglePerson[i].name, SinglePerson[i].gender, SinglePerson[i].age);
i++;
}
file = fopen("e:\\fprintf.txt", "w");
while (scanf ("%s%s%u", SinglePerson[i].name, &(SinglePerson[i].gender), &(SinglePerson[i].age)) != EOF) {
fprintf(file, "%s %s %u\n", SinglePerson[i].name, SinglePerson[i].gender, SinglePerson[i].age);
i++;
}
fread;
return 0;
}
Worked! I did it ))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define M 2 // M plus 1 is equals to number of structres
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
FILE *file;
struct Person {
char name[20];
char gender[20];
unsigned age;
};
struct Person SinglePerson[1];
char i=0;
char counter = 0;
void InputFromKeyboard () {
file = fopen("Input.txt", "w");
while(scanf("%s%s%u", SinglePerson[i].name, SinglePerson[i].gender, &(SinglePerson[i].age)) == 3 && i <= M) {
fprintf(file, "%s %s %u\n", SinglePerson[i].name, SinglePerson[i].gender, SinglePerson[i].age);
counter++;
i++;
if (i == M+1) {
break;
}
}
fclose(file);
};
void OutputToFile () {
file = fopen("Output.txt", "w");
for (i = 0; i < counter; i++) {
if (strcmp(SinglePerson[i].gender, "Male") == 0) {
fprintf(file, "%s %s %u\n", SinglePerson[i].name, SinglePerson[i].gender, SinglePerson[i].age);
}
}
fclose(file);
}
void OutputToScreen () {
file = fopen("Output.txt", "r");
for (i = 0; i < counter; i++) {
if (strcmp(SinglePerson[i].gender, "Male") == 0) {
printf("%s %s %u\n", SinglePerson[i].name, SinglePerson[i].gender, SinglePerson[i].age);
}
}
fclose(file);
}
int main(int argc, char *argv[]) {
InputFromKeyboard();
OutputToFile();
OutputToScreen();
return 0;
}
I'm trying to retrieve informations by many plain-text files, which will be then stored in a proper struct. To do so, I'm using a function that takes member of the struct to populate and source of the plain-text file where the informations are stored.
Posting my "test" code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _elem
{
const char *title;
int ok;
int almost;
int nope;
int hits;
float last_rank;
};
typedef struct _elem Chapter;
Chapter *generate_array(const char *source, int *elems);
int engine_start(Chapter *elem, char *source);
int main()
{
const char path_f[100];
int elements = 0;
int i = 0;
Chapter *dict;
printf("Insert the name of the source:\n");
scanf("%s", path_f);
printf("\nGenerating dictionary, please wait...\n");
dict = generate_array(path_f, &elements);
if (dict == NULL)
{
printf("Aborting.\n");
exit(1);
}
while (i < elements)
{
printf("Element %d:\n", (i + 1));
printf("\nTitle: %s\n", dict[i].title);
printf("Ok: %10d\n", dict[i].ok);
printf("Almost: %5d\n", dict[i].almost);
printf("Nope: %8d\n", dict[i].nope);
printf("Hits: %8d\n", dict[i].hits);
printf("Rank: %8.2f\n", dict[i].last_rank);
printf("\n");
i++;
}
return EXIT_SUCCESS;
}
Chapter *generate_array(const char *source, int *elems)
{
FILE *src;
int sources;
int i = 0;
char **srcs;
Chapter *generated;
src = fopen(source, "r");
if (src == NULL)
{
printf("[!!] Error while reading file!\n");
return NULL;
}
fscanf(src, "%d", &sources);
if (sources <= 0)
{
printf("[!!] Wrong number of sources, exiting.\n");
return NULL;
}
srcs = (char **) malloc(sizeof(char *) * sources);
while (i < sources && !feof(src))
{
srcs[i] = (char *) malloc(sizeof(char) * 100);
fscanf(src, "%s", srcs[i++]);
}
fclose(src);
generated = (Chapter *) malloc(sizeof(Chapter) * i);
*elems = i;
i = 0;
while (i < *elems)
{
if(engine_start( &generated[i], srcs[i] )) i++;
else
{
printf("[!!] Error in file %s, aborting.\n", srcs[i]);
return NULL;
}
}
return generated;
}
int engine_start(Chapter *elem, char *source)
{
FILE *parser;
int done = 0;
parser = fopen(source, "r");
if (parser == NULL) printf("[!!] Error while opening %s, aborting.\n", source);
else
{
fgets(elem->title, 100, parser);
fscanf(parser, "%d %d %d %d %f", &(elem->ok), &(elem->almost),
&(elem->nope), &(elem->hits),
&(elem->last_rank) );
fclose(parser);
done = 1;
}
return done;
}
Now this is the main file where are stored paths to the other plain-text files:
lol.dat
5
lold/lol1.dat
lold/lol2.dat
lold/lol3.dat
lold/lol4.dat
lold/lol5.dat
And one example of lolX.dat:
Qual'รจ la vittoria di cristo?
3 4 5 12 44.9
I'm getting SIGSEGV after the first iteration of "engine_start", probably due to FILE *parser (but I can be totally wrong, I don't know at this point).
Someone can guide me through this problem? Thank you.
Make the following changes and try-
struct _elem
{
char *title; // allocate the memory for this.
int ok;
int almost;
int nope;
int hits;
float last_rank;
};
You need to allocate memory for element title before assigning something to it.
int engine_start(Chapter *elem, char *source)
{
FILE *parser;
int done = 0;
parser = fopen(source, "r");
if (parser == NULL) printf("[!!] Error while opening %s, aborting.\n", source);
else
{
elem->title=(char *)malloc(100); // include this line.
fgets(elem->title, 100, parser);
fscanf(parser, "%d %d %d %d %f", &(elem->ok), &(elem->almost),
&(elem->nope), &(elem->hits),
&(elem->last_rank) );
fclose(parser);
done = 1;
}
return done;
}
I have this file with the following contents:
Bob Human, 1
John Cat, 3
Mary Dog, 2
How can I properly use fscanf to have each string and integer in a struct.
typedef struct {
char name[20];
char surname[20];
int code;
} entry;
Then I create an array of _entry_
entry a[3];
How will _a_ get each value properly using fscanf?
EDIT :
I have tried this:
while(TRUE) {
nscan=fscanf(infile, "%s %s d%c", temp.name, temp.surname, &temp.code, &termch);
if(nscan==EOF) break;
if(nscan!=4 || termch!='\n') {
printf("Error\n");
}
RecBSTInsert(&a, temp);
}
But it seems to pass the last line twice.
You're close, but you're not handling the comma properly.
As usual, it's much easier to read whole lines, then parse them. So let's do that.
Try:
char line[1024];
if(fgets(line, sizeof line, infile) != NULL)
{
nscan = sscanf(line, "%s %[^,], %d", temp.name, temp.surname, &temp.code);
}
The return value will be 3 if all the fields converted, else you have an error.
#include <stdio.h>
typedef struct{
char name[20];
char surname[20];
int code;
} entry;
int main(){
entry temp, a[3];
FILE *infile = fopen("data.txt", "r");
int i=0, n;
while(fscanf(infile, "%19s %19[^,], %d", temp.name, temp.surname, &temp.code)==3){
a[i++] = temp;
if(i==3)break;
}
fclose(infile);
n = i;
for(i=0;i<n;++i){
printf("%s %s, %d\n", a[i].name, a[i].surname, a[i].code);
}
return 0;
}