#c #while-loop #cycle #fgets #scanf
#c #цикл while #цикл #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 corretton");
exit(EXIT_FAILURE);
}
//apertura file
if((fp=fopen(argv[1], "r"))==NULL)
{
printf("Errore nell'apertura del filen");
exit(EXIT_FAILURE);
}
/* fscanf(fp,"%c %f %f %f", amp;alimento, amp;vect[0], amp;vect[1], amp;vect[2]);
printf("nnnnn%c %f %f %fn", alimento, vect[0], vect[1], vect[2]);
fgetc(fp);
fscanf(fp,"%c %f %f %f", amp;alimento, amp;vect[0], amp;vect[1], amp;vect[2]);
printf("n%c %f %f %fn", alimento, vect[0], vect[1], vect[2]);
fgetc(fp);
fscanf(fp,"%c %f %f %f", amp;alimento, amp;vect[0], amp;vect[1], amp;vect[2]);
printf("n%c %f %f %fn", alimento, vect[0], vect[1], vect[2]);
fgetc(fp);
*/
while((fgets(stringa, 100, fp))!=NULL)
{
sscanf(stringa, "%c %f %f %f", amp;alimento, amp;vect[0], amp;vect[1], amp;vect[2]);
printf("n%c %f %f %fn", alimento, vect[0], vect[1], vect[2]);
//controllo se è decrescente
flag_decrescente = VERO;
for(i=0; (i<2)amp;amp;(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)amp;amp;(!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 %.2fn", 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)amp;amp;(!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 %.2fn", 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 here1n");
}
//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 okn");
}
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. Пожалуйста, покажите свой код здесь , а не на каком-то внешнем сайте.
2. Извините! Я добавил код вместе с примером файла.
Ответ №1:
Вы пишете дальше конца struct alimento magazzino[4];
, который можно адресовать только с индексов от 0 до 3. После выхода из цикла while, если if(!trovato_alimento)
происходит строка 137, вы присваиваете материал magazzino[4] (поскольку i = 4 после последнего цикла for) и перезаписываете свой стек.
одним из возможных изменений для предотвращения сбоя является изменение строки 20 на: struct alimento magazzino[5];
Вероятно, это не совсем то, что вы хотели сделать, поэтому вам придется разобраться с этим оттуда.
Комментарии:
1. Большое вам спасибо! Нам, конечно, придется переосмыслить этот код, чтобы заставить его работать (к сожалению, на данный момент он работает не очень), но здорово, что мы выяснили, почему он на самом деле зависал.