PROBLEMA Ciclo infinito

Pubblicità

AITUS95

Nuovo Utente
Messaggi
109
Reazioni
11
Punteggio
39
Buonasera a tutti, sto cercando di risolvere una vulnerabilità presente nel seguente codice:
C:
#include <stdio.h>


int main (void){

   puts ("Inserisci la quantita' e il numero del prodotto per calcolarne il guadagno.");
   puts ("Inserisci '-1' per terminare.");

   // Input dei dati
   printf ("%s", "NUMERO PRODOTTO: ");
   int prodotto;
   scanf ("%d", &prodotto);

   // Inizializza totale a 0
   double totale = 0.0;

   // Ripeti fino all'inserimento del valore -1
   while (prodotto != -1){

    // Inserimento della quantita di prodotto venduto
    int quantita;
    scanf ("%d", &quantita);

    // Determina il prodotto poi esegui il calcolo

    switch (prodotto){

    case 1:
        totale += 2.98 * quantita;
        break;

    case 2:
        totale += 4.50 * quantita;
        break;

    case 3:
        totale += 9.98 * quantita;
        break;

    case 4:
        totale += 4.49 * quantita;
        break;

    case 5:
        totale += 6.87 * quantita;
        break;

    default:
        printf ("Numero di prodotto non valido: %d\n", prodotto);
        printf ("                    Quantita': %d\n", quantita);


    }

    // Passa al prodotto successivo
    printf ("%s", "NUMERO PRODOTTO: ");
    scanf ("%d", &prodotto);

   }

   // Stampa il guadagno totale
   printf ("Il guadagno settimanale e': $ %.2f", totale);

   }

in pratica quando un utente inserisce un carattere anzichè un intero, il programma genera un ciclo infinito, come potrei risolvere ?
 
in pratica quando un utente inserisce un carattere anzichè un intero, il programma genera un ciclo infinito, come potrei risolvere ?

non usando printf e scanf per cominciare :D
non puoi passare a C++ ed usare cin e cout?
Se puoi, allora la risposta è qui.

Il testo che sto seguendo è focalizzato solo sul C quindi preferirei risolverlo utilizzando questo linguaggio se è possibile, tornando a noi, ho provato a sostituire scanf aggiungendo prodotto = getchar() nell'intestazione di while, trattando cosi i valori corrispondenti in caratteri, ma mi ritorna sempre lo stesso errore.


Inviato da iPhone tramite App ufficiale di Tom\\\'s Hardware Italia Forum
 
Quand'è così, allora devi fare l'abitudine a leggere la documentazione. Io stesso non sapendo nulla delle funzioni che stai usando, posso mostrarti come aproccierei il problema:

1) google scanf
2) leggi le parti salienti, sopratutto cosa succede quando gli si passa un input diverso da quello che si aspetta di ricevere:
Citando da quella pagina:
If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror). And, if either happens before any data could be successfully read, EOF is returned.
3)feof e ferror sono entrambi link, guardiamo ad esempio il secondo.
Citando dalla pagina di ferror:
Checks if the error indicator associated with stream is set, returning a value different from zero if it is.

This indicator is generally set by a previous operation on the stream that failed, and is cleared by a call to clearerr, rewind or freopen.

Ok, quindi sappiamo che se un errore di lettura succede usando scanf una flag viene settata e possiamo controllarla chiamando ferror(). Se ritorna un valore diverso da 0, qualcosa è andato storto, ma abbiamo comunque delle funzioni per ripristinare lo stream (da usare prima di chiedere un nuovo input all'user).
E da li continui, leggendo ad esempio come usare una di quelle funzioni per ripristinare lo stream.

Ripeto, queste informazioni senza mai aver usato scanf in vita mia, percui è davvero importante che fai l'abitudine a navigare attraverso la documentazione :)
 
Ultima modifica:
Quand'è così, allora devi fare l'abitudine a leggere la documentazione. Io stesso non sapendo nulla delle funzioni che stai usando, posso mostrarti come aproccierei il problema:

1) google scanf
2) leggi le parti salienti, sopratutto cosa succede quando gli si passa un input diverso da quello che si aspetta di ricevere:
Citando da quella pagina:
If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror). And, if either happens before any data could be successfully read, EOF is returned.
3)feof e ferror sono entrambi link, guardiamo ad esempio il secondo.
Citando dalla pagina di ferror:
Checks if the error indicator associated with stream is set, returning a value different from zero if it is.

This indicator is generally set by a previous operation on the stream that failed, and is cleared by a call to clearerr, rewind or freopen.

Ok, quindi sappiamo che se un errore di lettura succede usando scanf una flag viene settata e possiamo controllarla chiamando ferror(). Se ritorna un valore diverso da 0, qualcosa è andato storto, ma abbiamo comunque delle funzioni per ripristinare lo stream (da usare prima di chiedere un nuovo input all'user).
E da li continui, leggendo ad esempio come usare una di quelle funzioni per ripristinare lo stream.

Ripeto, queste informazioni senza mai aver usato scanf in vita mia, percui è davvero importante che fai l'abitudine a navigare attraverso la documentazione :)

Sono funzioni che ancora devo affrontare ma cercherò di approfondire, ti ringrazio.


Inviato da iPhone tramite App ufficiale di Tom\\\'s Hardware Italia Forum
 

Ecco questo è proprio quella che cercavo, solo che in questo caso non saprei come implementarla in un istruzione di selezione multipla, già il default per se dovrebbe catturarmi il carattere non valido ma non lo fa, se inserisco invece isalpha(prodotto) in un istruzione di selezione singola if all'interno di while per deviare l'errore continua a darmi l'errore di ciclo infinito
 
Buonasera a tutti, sto cercando di risolvere una vulnerabilità presente nel seguente codice:
C:
#include <stdio.h>


int main (void){

   puts ("Inserisci la quantita' e il numero del prodotto per calcolarne il guadagno.");
   puts ("Inserisci '-1' per terminare.");

   // Input dei dati
   printf ("%s", "NUMERO PRODOTTO: ");
   int prodotto;
   scanf ("%d", &prodotto);

   // Inizializza totale a 0
   double totale = 0.0;

   // Ripeti fino all'inserimento del valore -1
   while (prodotto != -1){

    // Inserimento della quantita di prodotto venduto
    int quantita;
    scanf ("%d", &quantita);

    // Determina il prodotto poi esegui il calcolo

    switch (prodotto){

    case 1:
        totale += 2.98 * quantita;
        break;

    case 2:
        totale += 4.50 * quantita;
        break;

    case 3:
        totale += 9.98 * quantita;
        break;

    case 4:
        totale += 4.49 * quantita;
        break;

    case 5:
        totale += 6.87 * quantita;
        break;

    default:
        printf ("Numero di prodotto non valido: %d\n", prodotto);
        printf ("                    Quantita': %d\n", quantita);


    }

    // Passa al prodotto successivo
    printf ("%s", "NUMERO PRODOTTO: ");
    scanf ("%d", &prodotto);

   }

   // Stampa il guadagno totale
   printf ("Il guadagno settimanale e': $ %.2f", totale);

   }

in pratica quando un utente inserisce un carattere anzichè un intero, il programma genera un ciclo infinito, come potrei risolvere ?
In C purtroppo devi sempre prenderti la briga di pulire lo stdin e controllare anche l'input!.
Visto che lo scanf lo avevi settato in modo da ricevere un intero, quando inserivi un char lo scanf ti ritornava 0 come valore ma l'input rimaneva nel buffer, in quel caso ti dovevi assicurare di pulirlo con la funzione sotto descritta da me, siccome non lo pulivi il prossimo scanf automaticamente si sarebbe mangiato l'input nel buffer un esempio è questo codice:

C:
#include "stdio.h"

int main(void) {

  int a;
  char c;
  printf("Dammi a\n");
  scanf("%d", &a); /** se inserici un char a varrà 0 ma il char rimarrà nel buffer **/
  printf("\nA vale : %d", a);
  scanf("%c", &c);
 /** Ora scanf automaticamente si mangerà il valore rimasto nel buffer che guarda caso appartiene al char da te immesso impedendoti di assegnare un valore al tuo char questo **/
  
  printf("\n Il char è : %c", c);

  return 0;
}

Praticamente il tuo programma non andava in un loop infinito perchè inserivi un char, ma perchè non contrallavi e ripulivi il l'input e il buffer dello stdin. Ti ho rifattorizzato il codice, è sicuramente da aggiustare ma sono andato di fretta e dovresti continuarlo a fare tu.

1) Ho aggiunto la funzione flush che ti pulisce il buffer dopo ogni input.
2) Ti ho messo un do while perchè logicamente è più sensato.
3) i cicli while vanno sempre controllati con dei valori booleani è più comodo e intuitivo.
4) ti ho fatto un esempio di do while per controllare l'input del prodotto, fin quando non è nel range di -1 e 5 chiederà in continuazione di inserire il numero del prodotto.

Comunque si normalmente dovresti usare delle funzioni per controllare l'input ma visto che è un esercizio scolastico o dei libri è normale che all'inizio ti chieda svolgerlo in questa maniera. Comunque ti consiglio di studiarti meglio il buffer dello stdin e stdout


C:
#include <stdio.h>

void flush(int var){
  while(var != '\n' && getchar() != '\n');
}

int main(){

   int prodotto;
   int quantita;

   double totale;
   int loop = 1;

   puts ("Inserisci la quantita' e il numero del prodotto per calcolarne il guadagno.");
   puts ("Inserisci '-1' per terminare.");


   // Ripeti fino all'inserimento del valore -1
   do{

      do{
        printf("NUMERO PRODOTTO ?: ");
        scanf("%d", &prodotto);
        flush(prodotto);

        if(prodotto > 5){
         puts("Inserisci un numero compreso tra -1 e 5");
        }

        }while(prodotto > 5);


        if(prodotto == -1){
          loop = 0;
          break;
        }


      // Inserimento della quantita di prodotto venduto
      printf("Inserisci la quantita: ");
      scanf("%d", &quantita);
      flush(quantita);

      // Determina il prodotto poi esegui il calcolo
      switch (prodotto){

      case 1:
          totale += 2.98 * quantita;
          break;

      case 2:
          totale += 4.50 * quantita;
          break;

      case 3:
          totale += 9.98 * quantita;
          break;

      case 4:
          totale += 4.49 * quantita;
          break;

      case 5:
          totale += 6.87 * quantita;
          break;

      default:
          printf ("Numero di prodotto non valido: %d\n", prodotto);
          printf ("                    Quantita': %d\n", quantita);
    }

    // Passa al prodotto successivo
    printf("NUMERO PRODOTTO ?: ");
    scanf("%d", &prodotto);
    flush(prodotto);
  }while(loop);

   // Stampa il guadagno totale
   printf("Il guadagno settimanale e': $ %.2f", totale);

   }
 
Ultima modifica:
Pubblicità
Pubblicità
Indietro
Top