First of all, sorry for my english, since I'm not too much an english speaking person. We are a group of students who tried to write this piece of code (in C language) in order to solve an exercise we were given a few weeks ago. This program may work or not work, but the problem is: it crashes when the central while loop, which is used to read the file passed to the program using the command line (the file specified in argv[1], in other terms) repeats itself for the second time.
The code is the following one:
#include <stdio.h>
#include <stdlib.h>
#define VERO 1
#define FALSO 0
struct alimento{
char tipo_alimento;
float consumo;
int mesi_considerati;
float controllo_mese;
float spesa_totale;
float spesa_media_mensile;
};
int main(int argc, char* argv[])
{
FILE *fp;
int i;
struct alimento magazzino[4];
float vect[3];
char alimento;
int flag_decrescente = VERO;
int trovato_alimento = VERO;
float consumo_forfettario =0;
float acquisto_mensile;
char stringa[100];
//inizializzare mesi_considerati!!!!
//controllo parametri
if(argc!=2)
{
printf("Numero parametri non corretto\n");
exit(EXIT_FAILURE);
}
//apertura file
if((fp=fopen(argv[1], "r"))==NULL)
{
printf("Errore nell'apertura del file\n");
exit(EXIT_FAILURE);
}
/* fscanf(fp,"%c %f %f %f", &alimento, &vect[0], &vect[1], &vect[2]);
printf("\n\n\n\n\n%c %f %f %f\n", alimento, vect[0], vect[1], vect[2]);
fgetc(fp);
fscanf(fp,"%c %f %f %f", &alimento, &vect[0], &vect[1], &vect[2]);
printf("\n%c %f %f %f\n", alimento, vect[0], vect[1], vect[2]);
fgetc(fp);
fscanf(fp,"%c %f %f %f", &alimento, &vect[0], &vect[1], &vect[2]);
printf("\n%c %f %f %f\n", alimento, vect[0], vect[1], vect[2]);
fgetc(fp);
*/
while((fgets(stringa, 100, fp))!=NULL)
{
sscanf(stringa, "%c %f %f %f", &alimento, &vect[0], &vect[1], &vect[2]);
printf("\n%c %f %f %f\n", alimento, vect[0], vect[1], vect[2]);
//controllo se è decrescente
flag_decrescente = VERO;
for(i=0; (i<2)&&(flag_decrescente); i++)
{
if(vect[i]>vect[i+1])
{
flag_decrescente = FALSO;
}
}
//METTO L'ALIMENTO IN MAGAZZINO E VI ASSOCIO IL CONSUMO MENSILE
/* se il flag è decrescente il consumo è la differenza tra vect[2] - vect[0]*/
if(flag_decrescente == VERO)
{
trovato_alimento = FALSO;
for(i=0; (i<4)&&(!trovato_alimento); i++)
{
if(magazzino[i].tipo_alimento == alimento)
{
trovato_alimento = VERO;
magazzino[i].consumo += (vect[0]-vect[2]);
magazzino[i].mesi_considerati++;
//controllo la corrispondenza tra un mese e l'altro
//scelta della quantita' acquistata in base all'alimento
if(alimento == 'F') acquisto_mensile = 150;
else if(alimento == 'V') acquisto_mensile = 1200;
else if(alimento == 'Z') acquisto_mensile = 40;
else if(alimento == 'L') acquisto_mensile = 60;
//stampo se ho discordanza
if(vect[0]!=(magazzino[i].controllo_mese+acquisto_mensile))
{
printf("Alimento %c: le scorte %.2f sono differenti rispetto le rimanenze %.2f sommate all'acquisto mensile %.2f\n", alimento, vect[0], magazzino[i].controllo_mese, acquisto_mensile);
}
magazzino[i].controllo_mese = vect[2];
}
}
if(!trovato_alimento)
{
magazzino[i].tipo_alimento = alimento;
magazzino[i].consumo += (vect[0]-vect[2]);
magazzino[i].mesi_considerati++;
magazzino[i].controllo_mese = vect[2];
}
}
else
{
//devo inserire un consumo forfettario
if(alimento == 'F') consumo_forfettario = 150;
else if(alimento == 'V') consumo_forfettario = 1000;
else if(alimento == 'Z') consumo_forfettario = 30;
else if(alimento == 'L') consumo_forfettario = 50;
trovato_alimento = FALSO;
for(i=0; (i<4)&&(!trovato_alimento); i++)
{
if(magazzino[i].tipo_alimento == alimento)
{
trovato_alimento = VERO;
magazzino[i].consumo += consumo_forfettario;
magazzino[i].mesi_considerati++;
//ho già l'alimento quindi devo controllare eventuale discordanza
if(alimento == 'F') acquisto_mensile = 150;
else if(alimento == 'V') acquisto_mensile = 1200;
else if(alimento == 'Z') acquisto_mensile = 40;
else if(alimento == 'L') acquisto_mensile = 60;
if(vect[0]!=(magazzino[i].controllo_mese + acquisto_mensile))
{
printf("Alimento %c: le scorte %.2f sono differenti rispetto le rimanenze %.2f sommate all'acquisto mensile %.2f\n", alimento, vect[0], magazzino[i].controllo_mese, acquisto_mensile);
magazzino[i].controllo_mese = vect[2];
}
}
}
if(!trovato_alimento)
{
magazzino[i].tipo_alimento = alimento;
magazzino[i].consumo += consumo_forfettario;
magazzino[i].mesi_considerati++;
magazzino[i].controllo_mese = vect[2];
}
}
printf("everything is ok here1\n");
}
//calcolo della spesa totale
for(i=0; i<4; i++)
{
if(magazzino[i].tipo_alimento == 'V')
{
magazzino[i].spesa_totale = magazzino[i].consumo * 0.02;
magazzino[i].spesa_media_mensile = magazzino[i].spesa_totale = magazzino[i].mesi_considerati;
}
else if(magazzino[i].tipo_alimento == 'F')
{
magazzino[i].spesa_totale = magazzino[i].consumo * 0.20;
magazzino[i].spesa_media_mensile = magazzino[i].spesa_totale = magazzino[i].mesi_considerati;
}
else if(magazzino[i].tipo_alimento == 'Z')
{
magazzino[i].tipo_alimento = magazzino[i].consumo * 0.7;
magazzino[i].spesa_media_mensile = magazzino[i].spesa_totale = magazzino[i].mesi_considerati;
}
else if(magazzino[i].tipo_alimento == 'L')
{
magazzino[i].tipo_alimento = magazzino[i].consumo * 1.05;
magazzino[i].spesa_media_mensile = magazzino[i].spesa_totale = magazzino[i].mesi_considerati;
}
printf("tutto ok\n");
}
return 0;
}
Compiling this code with Code::Blocks 13.12, the first line of the file is correcly read (well, I actually know an fscanf could be used instead and that string is maybe a bit long, but both using fscanf or reducing string size apparently doesn't solve the problem), then the loop arrives at its end ("everything is ok here1" is printed) and, when fgets is called again, the program crashes. I wasn't able to to solve this problem. Do you know why it is actually crashing at that point? Is is a Code::Blocks bug or (more probably) a code error? Thanks a lot in advance.
By the way, a file example is the following one:
F 250.50 165.18 135.50
L 68.50 42.00 22.50
Z 52.00 24.50 17.00
V 1200.00 750.50 50.00
F 285.50 215.50 155.50
L 82.50 85.00 20.00
Z 57.00 32.00 12.00
V 950.00 650.00 250.00
You are writing beyond the end of struct alimento magazzino[4];
which is only addressable from indexes 0 to 3. After you get out of the while loop, if if(!trovato_alimento)
on line 137 happens, you assign stuff to magazzino[4] (since i=4 after the final for-loop) and overwrite your stack.
one possible change to stop the crash is to change line 20 to:
struct alimento magazzino[5];
This probably isn't exactly what you meant to do, tho, so you will have to figure it out from there.