Search code examples
cfileinputoutputstructure

How to get data from file and put the result in a new file in C?


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!


Solution

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