I am working on a programm which gets a data about books (in a structure) from a file. Then it searches for the cities where the cheapest books are sold. Generally, this programm gets a file (input_data.txt) like:
2
Book Title 1
10
200
Author 1
2021
Publisher 1
City 1
Book Title 2
15
150
Author 2
2022
Publisher 2
City 2
As a result, it outputs the output_data.txt file, which has cities with the cheeapest books:
City 1
There is my code on C:
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
struct izdatel {
int god;
char naz[100];
char gor[100];
};
struct Book {
char title[100];
int price;
int numPages;
char author[100];
struct izdatel publisherInfo;
};
void check_number(const char name[], int *s, FILE *input_data) {
int ret_code;
do {
//printf("Input %s:\n", name);
ret_code = fscanf(input_data, "%d", s);
while (getchar() != '\n'); // clear the buffer (as not using fgets)
} while (ret_code != 1 || *s <= 0);
}
void check_year(const char name[], int *s, FILE *input_data) {
int ret_code;
do {
//printf("Input %s (between 1458 and 2024):\n", name);
ret_code = fscanf(input_data, "%d", s);
while (getchar() != '\n');
} while (ret_code != 1 || *s < 1458 || *s > 2024);
}
void check_string(const char name[], char s[], FILE *input_data) {
int invalid_input;
do {
invalid_input = 0;
//printf("Input %s:\n", name);
fscanf(input_data, "%s", s);
while (getchar() != '\n');
for (int i = 0; i < strlen(s); i++) {
if (!isalpha(s[i]) && !isspace(s[i])) {
invalid_input = 1;
printf("Invalid input. Please enter a string without numbers or special characters.\n");
break;
}
}
} while (invalid_input || strlen(s) == 0);
}
void input(struct Book *books, const int numStructs, FILE *input_data) {
fscanf(input_data, "%d", &numStructs);
while (getchar() != '\n');
for (int i = 0; i < numStructs; i++) {
//printf("Book #%d\n", i + 1);
check_string("Title", books[i].title, input_data);
check_number("Price", &books[i].price, input_data);
check_number("Number of pages", &books[i].numPages, input_data);
check_string("Author", books[i].author, input_data);
//printf("Publishing company:\n");
check_year("Year of publication", &books[i].publisherInfo.god, input_data);
check_string("Publisher name", books[i].publisherInfo.naz, input_data);
check_string("Publishing city", books[i].publisherInfo.gor, input_data);
}
}
void solution(struct Book *books, const int numStructs, FILE *output_data){
float minPrice = books[0].price;
for (int i = 0; i < numStructs; i++) {
if (books[i].price < minPrice) {
minPrice = books[i].price;
}
}
fprintf(output_data, "\nCities where the cheapest books are published:\n");
for (int i = 0; i < numStructs; i++) {
if (books[i].price == minPrice) {
fprintf(output_data, "%s\n", books[i].publisherInfo.gor);
}
}
}
int main() {
int numStructs;
FILE *inputFile;
struct Book books[numStructs];
// input file
char *inputFilename = "input_data.txt";
char *outputFilename = "output_data.txt";
inputFile = fopen(inputFilename, "r");
FILE *outputFile = fopen(outputFilename, "w");
if (inputFile == NULL || outputFile == NULL) {
printf("Error opening files.\n");
return 1;
}
if (inputFile) {
input(books, numStructs, inputFile);
solution(books, numStructs, outputFile);
} else {
printf("Failed to open the input file.\n");
}
fclose(inputFile);
fclose(outputFile);
return 0;
}
I've been racking my brain solving this problem. Please, help me. I will be truly grateful!
To do short, review everything.
To do long, First of all:
int numStructs; // is const on all fonction call why not here to?
struct Book books[numStructs]; // numStructs not define and use
The parsing is your only problem on a program like that. You need to find patterns in your file to know what information you have. You also want to avoid thing like that :
char title[100];
You never know the size of the string you gonna have in your input file. Take a sheet of paper and think about it. No one here will give you a ready to use code.