Having problems with my file read, using a struct - c

I got my struct the right way, and it seems like a lot of this is working. However I got a small problem with my strings reading this garbage in my file read. I am trying to just pull a name, date, and state. And it keeps producing this odd form of "]][]]]][[[[[[" before the actual date, name, or state. How do I get my struct to read the file without getting this garbage feedback.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <cstring>
#include <exception>
//functions called
void get_info(int id[], char name[][20], char state[][5], char dis_code[], float balance[], char due_date[][40]);
void print_list(int id[], char name[][20], char state[][5], char dis_code[], float balance[], char due_date[][40]);
//why is it void?
int main(void)
{
FILE *pFile;
int choice = 0;
char buf[40];
/*
int id[sizeof(buf)];
char name[sizeof(buf)][20];
char state[sizeof(buf)][5];
char dis_code[sizeof(buf)];
float balance[sizeof(buf)];
char due_date[sizeof(buf)][40];
*/
struct fileinfo
{
int id[40];
char name[40][20];
char state[40][5];
char dis_code[40];
float balance[40];
char due_date[40][40];
} info;
printf("WELCOME. \n");
while (choice != 5)
{
printf("press number for action\n");
printf("OPEN FILE - 1 \n");
printf("LIST THE TABLE - 2 \n");
printf("SEARCH THE TABLE -3 \n");
printf("ADD A NEW ROW - 4 \n");
printf("EXIT THE PROGRAM - 5 \n");
gets_s(buf);
choice = atoi(buf);
if (choice == 1)
{
pFile = fopen("ASSIGNV1.dat", "r");
if (pFile != NULL)
{
int i = 0;
for (i = 0; i < 8; i++)
{
//get id
fgets(buf, sizeof(buf), pFile);
info.id[i] = atoi(buf);
//get name
fgets(buf, sizeof(buf), pFile);
info.name[i][strlen(info.name[i]) - 1] = '\0';
//get state
fgets(buf, sizeof(buf), pFile);
info.state[i][strlen(info.state[i]) - 1] = '\0';
//get discount code
fgets(buf, sizeof(buf), pFile);
info.dis_code[i] = buf[0];
//get balance
fgets(buf, sizeof(buf), pFile);
info.balance[i] = atof(buf);
//get due date
fgets(buf, sizeof(buf), pFile);
info.due_date[i][strlen(info.due_date[i]) - 1] = '\0';
printf("ID \t\t %i \n", info.id[i]);
//problem with name
printf("NAME \t\t %s \n", info.name[i]);
//problem with state
printf("STATE \t\t %s \n", info.state[i]);
printf("DISCOUNT CODE \t %c \n", info.dis_code[i]);
printf("BALANCE \t %.2f \n", info.balance[i]);
//problem with due_date
printf("DUE DATE \t %s \n\n", info.due_date[i]);
}
}
printf("\n\nfile was opened and loaded\n\n");
}
}
printf("\n\n PROGRAM WILL END NOW");
system("pause");
}
My text file is this:
125
LIPSO FACTO
SC
A
118.03
07/12/1998
193
GRADE BIT
OR
A
522.83
03/31/2003
237
MORE MATZOES
TN
846.29
01/11/2011
305
AIR BANGLEDESH
VT
A
3064
01/06/2005
485
FRED'S TATOOS
VT
C
2000.04
09/01/2007
520
WORLD WIDE WICKETS
WI
6280.43
04/29/1999
693
TAMMALIZATION
SC
B
3728
10/06/2009
746
REPLACEMENT PARTS
GA
C
5601.31
06/08/2003

probably you are missing to use strcpy().you have to copy buf to info.name[i] and to info.state[i].

The below 3 statements doesn't make sense as you have not copied the string, but trying to terminate the string. Please copy the string then terminate it
info.name[i][strlen(info.name[i]) - 1] = '\0';
info.state[i][strlen(info.state[i]) - 1] = '\0';
info.due_date[i][strlen(info.due_date[i]) - 1] = '\0';

Related

Save structure function leaves a spare place in a file instead of writing an array

#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.

How to remove the spaces and newline when writing in file? [duplicate]

This question already has answers here:
Removing trailing newline character from fgets() input
(14 answers)
Closed 2 years ago.
The code is working fine but whenever I type the words second time and it comes to seeing the result in a file, it gives me the result like this. How to handle this?
Name, DOB, ID, Phone
Name
, DOB, ID, Phone
The Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 50
int main(){
FILE * fw = fopen("new.csv", "a");
char* listing[] = {"Name", "Date of birth","ID card number","Phone number"};
char data[4][LEN], name[LEN], amount[LEN], dob[LEN], id[LEN], option;
int i, done=0;
do{
for (i = 0; i < 4; i++) {
printf("Enter your %s: ", listing[i]);
fgets(data[i], LEN, stdin);
if(strcmp(data[i], "\n") == 0){
fgets(data[i], LEN, stdin);
}
else{
data[i][strlen(data[i])-1] = '\0';
}
}
fprintf(fw, "%s, %s, %s, %s\n", data[0], data[1], data[2], data[3]);
printf("Do you want to continue [y/n]: ");
scanf("%s", &option);
}
while(option == 'y');
fclose(fw);
return 0;
}
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 50
int main() {
FILE * fw = fopen("new.csv", "a");
char * listing[] = {
"Name",
"Date of birth",
"ID card number",
"Phone number"
};
char data[4][LEN], name[LEN], amount[LEN], dob[LEN], id[LEN], option;
int i, done = 0;
do {
for (i = 0; i < 4; i++) {
printf("Enter your %s: ", listing[i]);
fgets(data[i], LEN, stdin);
while (strcmp(data[i], "\n") == 0) { //<------Changed if condition to while loop
fgets(data[i], LEN, stdin);
}
data[i][strlen(data[i]) - 1] = '\0';
}
fprintf(fw, "%s, %s, %s, %s\n", data[0], data[1], data[2], data[3]);
printf("Do you want to continue [y/n]: ");
scanf("%s", & option);
}
while (option == 'y');
fclose(fw);
return 0;
}
I changed the if statement to while loop where you checked if input is '\n'.

Im having a problem with reading a file, then assigning it to a struct array and printing it back out

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;
}

C language - structure

When execute second fscanf, console stop working. What did I do wrong?
The input file contains:
3
minsu 50 80 40
sarah 30 60 40
jason 70 80 90
The code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef struct studentT {
char *name;
int literature;
int math;
int science;
}studentT;
int main()
{
studentT student[3];
int count;
char *inputFileName = malloc(sizeof(char)*30);
char *outputFileName = malloc(sizeof(char) * 30);
float avg;
int i = 0;
scanf("%s %s", inputFileName, outputFileName);
FILE *fp = fopen(inputFileName, "r");
if (fp == NULL)
{
printf("file is not exist");
return 1;
}
fscanf(fp, "%d", &count);
for (i = 0; i < (int)count; i++)
{
//printf("!");
fscanf(fp, "%s %d %d %d", student[i].name, &student[i].literature, &student[i].math, &student[i].science);
//printf("2");
printf("%s %d %d %d\n", student[i].name, student[i].literature, student[i].math, student[i].science);
//printf("333\n");
}
fclose(fp);
free(inputFileName);
free(outputFileName);
return 0;
}
The name field in your studentT struct is a char *. You pass that pointer to scanf without initializing it to anything. So scanf reads an uninitialized pointer and tried to dereference it. This invokes undefined behavior.
The simplest way to fix this is to change name to be an array large enough to hold any string you expect. Then you can write to the array:
typedef struct studentT {
char name[20];
int literature;
int math;
int science;
}studentT;
Alternately, you can use malloc to allocate space dynamically:
student[i].name = malloc(20);
fscanf(fp, "%19s %d %d %d", student[i].name, &student[i].literature,
&student[i].math, &student[i].science);

Load content of a file line by line into an array in C

I am coding a song database. For now, the data of 2 songs are stored in a text file, one struct field per line. I would like to copy the content of the file line by line into an array, and I do not get why the program crashes after calling load(). Is it a problem related to fgets()? Or when I replace '\n' by '\0'?
Here are the interesting parts of the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "functions.h"
int main()
{
int menu;
bool exit = false;
/*char title[256];
char artist[256];
char album[256];*/
int year;
Song **songs = NULL; // base pointer to the array (of pointers to struct)
FILE *f; // pointer to a file structure
int n = 0; // height of array at the beginning (= number of pointers to struct)
int i;
f = fopen("database.txt", "r+");
if(f == NULL)
return 0;
count_songs_db(f, &n); // will modify n (height of array) according to the number of existing songs
printf("n = %d\n", n);
songs = (Song**)malloc(n*sizeof(Song));
load(f, songs, n);
// MENU
for(i = 0 ; i < n ; ++i)
free(songs[i]);
free(songs);
fclose(f);
return 0;
}
functions:
void count_songs_db(FILE *f, int *n) // calculate how many songs there are already in the database.
{
int c, n_lines = 0;
while ((c = getc(f)) != EOF)
if (c == '\n')
++n_lines; // count number of lines
*n = n_lines/6; // 1 song = 6 lines. Changes the height of array accordingly.
rewind(f); // go back to beginning of file, to be able to load the db
}
void load(FILE *f, Song **songs, int n) // load existing songs (in the file) into the array
{
int i;
for(i = 0 ; i < n ; ++i)
{
fgets(songs[i]->title, 256, f); // reads a line of text
songs[i]->title[strlen(songs[i]->title)-1] = '\0'; // to replace \n by \0 at the end // not working?
fgets(songs[i]->artist, 256, f);
songs[i]->title[strlen(songs[i]->artist)-1] = '\0';
fgets(songs[i]->album, 256, f);
songs[i]->title[strlen(songs[i]->album)-1] = '\0';
fscanf(f, "%d\n", &(songs[i]->year)); // use it like scanf
fgets(songs[i]->genre, 256, f);
songs[i]->title[strlen(songs[i]->genre)-1] = '\0';
fscanf(f, "%d:%d\n", &(songs[i]->length.m), &(songs[i]->length.s));
}
for(i = 0 ; i < n ; ++i)
{
printf("Title: %s\n", songs[i]->title);
printf("Artist: %s\n", songs[i]->artist);
printf("Album: %s\n", songs[i]->album);
printf("Year of release: %d\n", songs[i]->year);
printf("Genre: %s\n", songs[i]->genre);
printf("Length: %d:%d\n", songs[i]->length.m, songs[i]->length.s);
}
}
struct:
typedef struct Length {
int m, s;
} Length;
typedef struct Song {
char title[256];
char artist[256];
char album[256];
int year;
char genre[256];
Length length;
} Song;
Thanks for your help.
Edit: I modified the code to use a simple array of struct. Here is the add_song() function and save() function:
void add_song(Song *songs, int *n)
{
printf("Title: ");
read(songs[*n].title, MAX_SIZE); // another function is used instead of scanf(), so the user can enter string with spaces. Also more secure.
printf("Artist: ");
read(songs[*n].artist, MAX_SIZE);
printf("Album: ");
read(songs[*n].album, MAX_SIZE);
printf("Year of release: ");
songs[*n].year = read_long(); // still have to check the user inputs (ie. year has to be between 1900 and 2017)
printf("Genre: ");
read(songs[*n].genre, MAX_SIZE);
printf("Length: \nmin: ");
songs[*n].length.m = read_long();
printf("sec: ");
songs[*n].length.s = read_long();
++(*n);
}
void save(FILE *f, Song *songs, int n) // save song in file
{
fprintf(f, "%s\n%s\n%s\n%d\n%s\n%d:%d\n", songs[n-1].title, songs[n-1].artist, songs[n-1].album, songs[n-1].year, songs[n-1].genre, songs[n-1].length.m, songs[n-1].length.s); // use it like printf. Prints the data in the file.
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct Length {
int m, s;
} Length;
typedef struct Song {
char title[256];
char artist[256];
char album[256];
int year;
char genre[256];
Length length;
} Song;
void count_songs_db(FILE *f, int *n) // calculate how many songs there are already in the database.
{
int c, n_lines = 0;
while ((c = getc(f)) != EOF)
if (c == '\n')
++n_lines; // count number of lines
*n = n_lines / 6; // 1 song = 6 lines. Changes the height of array accordingly.
rewind(f); // go back to beginning of file, to be able to load the db
}
void load(FILE *f, Song *songs, int n) // load existing songs (in the file) into the array
{
int i;
for (i = 0; i < n; ++i)
{
fgets(songs[i].title, 256, f); // reads a line of text
songs[i].title[strlen(songs[i].title) - 1] = '\0'; // to replace \n by \0 at the end // not working?
fgets(songs[i].artist, 256, f);
songs[i].title[strlen(songs[i].artist) - 1] = '\0';
fgets(songs[i].album, 256, f);
songs[i].title[strlen(songs[i].album) - 1] = '\0';
fscanf(f, "%d\n", &(songs[i].year)); // use it like scanf
fgets(songs[i].genre, 256, f);
songs[i].title[strlen(songs[i].genre) - 1] = '\0';
fscanf(f, "%d:%d\n", &(songs[i].length.m), &(songs[i].length.s));
}
for (i = 0; i < n; ++i)
{
printf("Title: %s\n", songs[i].title);
printf("Artist: %s\n", songs[i].artist);
printf("Album: %s\n", songs[i].album);
printf("Year of release: %d\n", songs[i].year);
printf("Genre: %s\n", songs[i].genre);
printf("Length: %d:%d\n", songs[i].length.m, songs[i].length.s);
}
}
int main()
{
int menu;
bool exit = false;
/*char title[256];
char artist[256];
char album[256];*/
int year;
Song *songs = NULL; // base pointer to the array (of pointers to struct)
FILE *f; // pointer to a file structure
int n = 0; // height of array at the beginning (= number of pointers to struct)
int i;
f = fopen("database.txt", "r+");
if (f == NULL)
return 0;
count_songs_db(f, &n); // will modify n (height of array) according to the number of existing songs
printf("n = %d\n", n);
songs = (Song*)malloc(n * sizeof(Song));
load(f, songs, n);
// MENU
free(songs);
fclose(f);
return 0;
}

Resources