File in c

Mikki0222
Salve a tutti. Stavo svolgendo questo esercizio sui file in c. Scrivi una funzione che passati due file, scriva nel secondo solo le righe numeriche in cui la prima cifra sia maggiore della somma di tutte le altre cifre a partire dalla seconda. Io l'ho svolto così, ma non riesco a capire perché mi copia tutte le righe e non solo quelle che rispettano la proprietà della traccia. Dove è l'errore?



#include <stdio.h>
#include <stdlib.h>

void copiarighe(char*filein, char*fileout);
int main (void) {
 char buffer[100];
 int i;
 int prop;
 int somma;
 copiarighe("file1.txt", "file2.txt");
 return 0;
 }

void copiarighe(char*filein, char*fileout) {
 char buffer[100];
 int i;
 int dim;
 int prop;
 int somma = 0;
 FILE*fin = fopen(filein, "r");
 FILE*fout = fopen(fileout, "w");
 
 //Controllo di corretta apertura
 if(fin != NULL) {
    while(fgets(buffer, 100, fin) != NULL) {
    somma = 0;
    i = 0;
    prop = 0;
    while ((buffer[i] != '\0') && (prop == 0)) {
        if((buffer[i] >= '0') && (buffer[i] <= '9')) {
        somma += (buffer[i+1] -'0');
        }
          if(buffer[0] > somma) {
           prop = 1;
          }
      i++;
    }
    if(prop == 1) {
    fputs(buffer,fout);
    }
 }
}
fclose(fin);
fclose(fout);
}
    

Risposte
apatriarca
Il ciclo è in effetti sbagliato perché il confronto tra la prima cifra e la somma avviene all'interno del ciclo in cui viene calcolata la somma.

Prova ad usare qualche funzione aggiuntiva in modo da semplificarti la logica del programma. Per esempio puoi considerare una funzione che ti calcola la somma delle cifre in una stringa.

Alcuni commenti:
1. Non è necessario dichiarare le variabili all'inizio del blocco e quando si fa sarebbe preferibile fornire un valore iniziale.
2. [tt]isdigit[/tt] è una funzione/macro standard per verificare che un carattere è una cifra (di fatto è molto probabilmente implementata esattamente come hai fatto tu ma può comunque essere utile sapere che esiste [tt]ctype.h[/tt] per cose del genere).
3. Sarebbe utile una formattazione del codice più uniforme.

Mikki0222
Grazie per consigli, proverò a seguirli.

Mikki0222
Buonasera a tutti. Perdonatemi se ritorno in questo forum, ma non riesco a venirne a capo! Ho provato ad apportare alcune modifiche al programma e effettuare il controllo della prima cifra nel primo while, ma questa volta mi stampa solo l'ultima stringa che soddisfa la richiesta della traccia, come mai? Scusatemi ancora.
#include <stdio.h>
#include <stdlib.h>

void copiarighe(char*filein, char*fileout);
int main (void) {
 copiarighe("file4.txt", "file5.txt");
 return 0;
} 

void copiarighe(char*filein, char*fileout) {
 char buffer[100];
 int i;
 int prop;
 int somma = 0;
 FILE*fin = fopen(filein, "r");
 FILE*fout = fopen(fileout, "w");
 
 //Controllo di corretta apertura
 if(fin != NULL) {
    while(fgets(buffer, 100, fin) != NULL) {
    i = 0;
    somma = 0;
    while (buffer[i] != '\0')  {
        if((buffer[i] >= '0') && (buffer[i] <= '9')) {
        somma += (buffer[i+1] -'0');
        }
     i++;
    }
    if(buffer[0] > somma) {
     prop = 1;
    } else {
    prop = 0;
    }
  }  
  if(prop == 1) {
    fputs(buffer,fout);
  } 
}
fclose(fin);
fclose(fout);
}

apatriarca
La riga va stampata all'interno del ciclo di lettura e non dopo aver letto tutte le stringhe.

Mikki0222
Grazie mille, non mi ero resa conto di questo errore! Grazie ancora!

vict85
A parte alcuni commenti stilistici, vedo alcuni problemi:

[list=1][*:3oyou8ih] Stai scrivendo fuori dal ciclo come ha detto apatriarca;[/*:m:3oyou8ih]
[*:3oyou8ih] Non stai controllando se [inline]fout[/inline] sia o meno nullo;[/*:m:3oyou8ih]
[*:3oyou8ih] Stai chiamando [inline]fclose[/inline] su [inline]fin[/inline] anche nel caso in cui sia nullo;[/*:m:3oyou8ih]
[*:3oyou8ih] [inline]fgets[/inline] contiene [inline]\n[/inline] nel caso in cui raggiunge la fine di una riga (ma devi tenere conto che il file potrebbe non finire con [inline]\n[/inline] e quindi che l'ultima riga è un caso a se stante). Se la riga è più grande del buffer allora [inline]fgets[/inline] copia i \(99\) caratteri, aggiunge [inline]\0[/inline] all'indice \(99\) e ritorna. Alla prossima chiamata continuerà nella stessa riga. Quindi non puoi dare per scontato che una linea corrisponda ad una singola chiamata a [inline]fgets[/inline]. Devi controllare e gestire il caso di una riga divisa su due o più chiamate a [inline]fgets[/inline].[/*:m:3oyou8ih][/list:o:3oyou8ih]

L'ultimo punto è forse un po' tecnico e magari il professore non lo considerava neanche, ma è una problematica che potresti affrontare a livello professionale.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.