0

I am practicing with C Functions, malloc, realloc and files. The program is still at the beginning but when complete it should perform different tasks decided by the user: the main function asks the user for a number that connects it to different functions of the program.

My problem is with the function "CaricaFile()" that should let the user enter a file name, load this file that has different temperatures and times recorded, and load these data in a dynamic array; every time the function starts, it won't let me insert any file name and the program continues with an "Invalid argument" error.

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define NOME_FILE_MAX 25

typedef struct {
    short int ore;
    short int minuti;
    float temperatura;
}t_rilevazione;

t_rilevazione *rilevazioni;
int i = -1;
int dimrilevazione = sizeof(t_rilevazione);

int CaricaFile() {
    char nome_file[NOME_FILE_MAX];
    printf("Inserire il nome del file da caricare, estensione compresa: ");
    fgets(nome_file, NOME_FILE_MAX, stdin);
    for (int q = 0; nome_file[q] != '\0'; q++) {
        if (nome_file[q] == '\n') nome_file[q] = '\0';
    }
    FILE *input_stream = fopen(nome_file, "r");
    if (input_stream == NULL) {
        perror("Impossibile trovare il file");
        return 0;
    }
    else {
        rilevazioni = malloc(dimrilevazione);
        if (rilevazioni = NULL) {
            perror("Problema con l'allocazione della memoria");
            return 0;
        }
        i = 0;
        while (feof(input_stream) != 1) {
            fscanf(input_stream, "%d:%d\n", &rilevazioni[i].ore, &rilevazioni[i].minuti);
            fscanf(input_stream, "%f", &rilevazioni[i].temperatura);
            realloc(rilevazioni, (i + 1 * dimrilevazione));
            if (rilevazioni == NULL) {
                perror("Problema con la riallocazione della memoria");
                return 0;
            }
            i++;
        }
        fclose(input_stream);
        printf("File caricato con successo.\n");

        return 1;
    }
}

int StampaVettore() {
    if (i >= 0) {
        int p;
        printf("I parametri registrati sono...\n");
        for (p = 0; p != i; p++) {
            printf("%d:%d\n%f\n", rilevazioni[p].ore, rilevazioni[p].minuti, rilevazioni[p].temperatura);
        }
        return 1;
    }
    else {
        printf("Nessun valore registrato.\n");
        return 0;
    }
}

int OrdinaVettore() {

}

int CalcolaMedia() {

}

int RicercaOrario() {

}

int SalvataggioFile() {

}

int main(void) {
    short int op;
    do {
        printf("Di seguito le operazioni che e' possibile effetuare con il programma:\n");
        printf("[1] Carica un file di testo\n");
        printf("[2] Stampa i record acquisiti dal file\n");
        printf("[3] Ordina il vettore dei record del file\n");
        printf("[4] Calcola la media delle temperature\n");
        printf("[5] Ricerca un determinato orario\n");
        printf("[6] Salva su file i record del programma\n");
        printf("[0] Esci dal programma\n");
        printf("Digitare il numero corrispondente all'operazione desiderata.\n");
        do {
            scanf("%d", &op);
            if (op < 0 || op > 6) {
                printf("Operazione non consentita. Riprovare\n");
            }
        } while (op < 0 || op > 6);
        if (op == 1) CaricaFile();
        if (op == 2) StampaVettore();
        if (op == 3) OrdinaVettore();
        if (op == 4) CalcolaMedia();
        if (op == 5) RicercaOrario();
        if (op == 6) SalvataggioFile();
        if (op == 0) printf("Uscita in corso...");
    } while (op != 0);
    return 0;
}

Strange thing is that if I take the CaricaFile function alone bringing it to its own program as a Main function, it works without problems (at least, there is some problem but that's because I still can't understand well how to use dynamic arrays and so on)

What could I do? Thank you

RaiN
  • 15
  • 5
  • Have you trued using a debugger like GDB to see where it is going wrong? Also can you please indicate which of your error messages it is giving. – Marshall Asch Mar 26 '17 at 17:13
  • `while (feof(input_stream) != 1) {` http://stackoverflow.com/q/5431941/905902 – wildplasser Mar 26 '17 at 17:18
  • Hello, and thank you for your answer; the fact is that even using Visual Studio 2017 as IDE (and so I am using its debugger) there isn't a true error to show because the program compiles without any problem, it doesn't crash etc. but it just skips the fgets, doesn't ask the user to insert a file name, and gives "Invalid argument" error – RaiN Mar 26 '17 at 17:22

2 Answers2

0

One bug is that you read an int into a short with scanf:

short int op;
...
scanf("%d", &op);

This invokes undefined behavior because the pointed to type does not match the format specifier. Another bug is that you do not test the return value from scanf.

Jens
  • 69,818
  • 15
  • 125
  • 179
  • Thank you, I am fixing it with the "h" of half, so "%hd" – RaiN Mar 26 '17 at 17:23
  • @RaiN I'd use `int op;` since you don't gain anything and type more if you use a short. An `int` is the natural machine word size in C. – Jens Mar 26 '17 at 17:24
0

'realloc(rilevazioni, (i + 1 * dimrilevazione));'

realloc returns a value - you should look up realloc in the man pages or Google and take careful note. Look carefully at the above call.. As it is, it cannot possibly modify the 'rilevazioni' argument that is passed by value.

Also, why are you multiplying 'dimrilevazione' by 1? That will not change its value and so is a waste of typing.......... (think!).

Also, I can't see any free() calls anywhere?

ThingyWotsit
  • 366
  • 2
  • 4
  • Hello, my idea was to realloc one "dimrilevazione" more at the end of every cycle, so the "i" element has to keep count of the records stored in the array and at the same time multiply it for the dimrilevazione, this way I should realloc every time the space I need (at least I hope); however, i starts at 0 and it is always 1 number less than the space I need, so my idea was to do (i+1) * (dimrilevazione): even when i = 1 it should realloc the space I need, but it seems that I am not doing this correctly (?) – RaiN Mar 26 '17 at 17:45
  • Okay, I should make the "i" start at 1 so at the first cycle it reallocs 2 * dimrilevazione, thank you for noting this – RaiN Mar 26 '17 at 17:47
  • Please look up realloc() in the man pages, especially the value returned!. Then Google 'C operator precedence' - look at your code again, '(i+1) * (dimrilevazione)' is NOT what you posted in the question:( – ThingyWotsit Mar 26 '17 at 17:47