while循环使程序崩溃

时间:2014-06-20 18:10:08

标签: c while-loop cycle fgets scanf

首先,对不起我的英语,因为我不是一个讲英语的人。 我们是一群试图编写这段代码(用C语言编写)的学生,以解决几周前我们给出的练习。 这个程序可能工作或不工作,但问题是:它在中央while循环时崩溃,它用于读取使用命令行传递给程序的文件(在argv [1]中指定的文件,换句话说)第二次重复。

代码如下:

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

使用Code :: Blocks 13.12编译此代码,文件的第一行被正确读取(好吧,我实际上知道可以使用fscanf而该字符串可能有点长,但都使用fscanf或者减少字符串大小显然没有解决问题),然后循环到达它的末尾(“打印一切都好”1),并且当再次调用fgets时,程序崩溃。 我无法解决这个问题。你知道为什么它在那时真的崩溃了吗?是Code :: Blocks错误还是(更可能)代码错误? 非常感谢。

顺便说一句,文件示例如下:

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

1 个答案:

答案 0 :(得分:1)

你正在编写超出struct alimento magazzino[4];的末尾,它只能从索引0到3进行寻址。在你离开while循环之后,如果在第137行发生了if(!trovato_alimento),你可以将内容分配给magazzino [4](因为在最终的for循环之后i = 4)并覆盖你的堆栈。

停止崩溃的一个可能的变化是将第20行更改为: struct alimento magazzino[5];

这可能不是你想要做的,所以你必须从那里弄明白。