[C] Gestione File E Vettori

davicos
Salve a tutti,
vorrei fare un programma che letti da file dei nomi di persona conti quante volte ogni nome è comparso. Si tenga presente che il numero delle righe del file non è noto a priori ma al massimo possono comparire quattro nomi diversi.
Esempio contenuto del file:

lucia
alessandro
lucia
davide
marco
davide
marco

Nomi totali quattro con le rispettive molteplicità.
Come soluzione ho pensato a mettere ogni nome in un vettore (tanto la dimensione la conosco) e quel nome confrontarlo con tutti nomi presenti nel vettore, ma non so come copiare il nome dentro un vettore (che sarà una matrice con indice variabile e lunghezza totale del nome costante). Ho provato con il comando strcmp ma non funziona. Come fare?
Grazie!

Risposte
packy95
Il comando strcmp confronta due stringhe, non copia niente. Per quello potresti provare "strcpy".
Se posso chiederlo, usi allocazione dinamica o statica?

davicos
Si scusa mi sono confuso intendevo la strcpy. Per allocazione statica o dinamica non capisco cosa vuoi dire..

packy95
Intendo se usi dei puntatori per creare un vettore(nel tuo caso anche una stringa) o una matrice. Comunque se riesci posta il codice, altrimenti è difficile vedere cosa c'è che non va nel programma.

davicos
#include
#include



#define n 4
#define lun 20
#define max 20
int main(int argc, char* argv[])
{
int riga[lun +1], i=0;
char nome[20 +1], v[n][max];
FILE *f;
f = fopen("testo.txt","r");

if(f == NULL)
{
printf("errore");
return (1);
}

while(fgets(riga, lun, f) != NULL)
{

printf("%s", riga);
sscanf(riga,"%s", nome);
printf("\n");

v[max] = nome;

strcpy(v, nome);
i++;

printf("nome: %s \n", v[max]);


}


return 0;
}


Questo è solo la parte iniziale perchè non funzionando non ho fatto la parte dei contatori per i nomi. Il printf dopo ogni fine ciclo l'ho messo solo per verificare che effettivamente il nome era stato copiato nel vettore ma escono cose strane quindi il problema penso sia proprio questo.
Non utilizzo né funzioni né puntatori. Per adesso volevo solo fare una prova molto terra terra.
Grazie.

davicos
Il codice è un pò difficile da leggere perchè non so che comandi usare per il formato in questo sito, quindi se mi dite come fare..

packy95
Allora, ad occhio ho trovato questi errori:
1)cosa volevi fare con questa istruzione?
v[i][max] = nome;

toglila. Stai praticamente mettendo un array di char in un char. E' un errore dimensionale oltre che di sintassi.

2)Quando stampi la stringa devi fare così:
printf("nome: %s \n", v[i]);

Facendo come hai fatto tu, praticamente stampi l'ultimo carattere della riga "i", e siccome quella riga non è piena fino all'ultima posizione, stampa caratteri a caso.

Non ho testato il programma ma prova a cambiare come ti ho detto e vedi cosa succede.

P.S. per inserire codice nel forum c'è il tag "Code". :smt039

davicos
La prima mi ero dimenticato di toglierla infatti non c'entra nulla, l'avevo messa per provare.

Il programma in definitiva è questo:


#include <stdio.h>
#include <string.h>

#define n 4
#define lun 20
#define max 20

int main(int argc, char* argv[])
{
    int riga[lun +1], i=0;
    char nome[20 +1], v[n][max];
    FILE *f;
    f = fopen("testo.txt","r");
    
    if(f == NULL)
    {
        printf("errore");
        return (1);
    }
    
    while(fgets(riga, lun, f) != NULL)
    {   
        
        printf("%s", riga);
        sscanf(riga,"%s", nome);
        printf("\n");
        
        strcpy(v[i], nome);
        i++;
        
        printf("nome: %s \n", v[i]);
        
        
    }
    
    
    return 0;
}

packy95
Quindi hai risolto?

davicos
No, per come è il programma adesso non funziona, mi stampa alcuni caratteri strani ed altri invece non stampa niente.

packy95
il problema potrebbe essere nella sscanf e nella fgets dato che la variabile "riga" è di tipo intero.
A cosa ti serve sscanf? Prova a fare semplicemente:
 while(fgets(nome, lun, f) != NULL)
    {          
        strcpy(v[i], nome);
        printf("nome: %s \n", v[i]);
        i++;
    }


Devi incrementare la "i" dopo che stampi, altrimenti vai a finire nella posizione successiva dove non è ancora stato scritto niente.
Se funziona puoi cambiare "nome" direttamente con v dato che non fai altre operazioni. Ma questo è solo per farlo breve.

davicos
Risolto, avevo fatto confusione con i cicli e stampava altro.
In definitiva è così:

#include <stdio.h>
#include <string.h>

#define max_nomi 10
#define lun 20
#define max 20

int main(int argc, char* argv[])
{
    int riga[lun +1], i=0, y=0;
    
    char s[max +1], nome[max_nomi][max +1];
    
    FILE *f;
    f = fopen("testo.txt","r");
    
    if(f == NULL)
    {
        printf("errore");
        return (1);
    }
    
    while(fgets(riga, lun, f) != NULL)
    {   
        
        printf("%s", riga);
        sscanf(riga,"%s \n", s);
        
             
        strcpy(nome[i], s);
        i++;
       
        
        
    }
    
    
    for(int i=0; i<max_nomi; i++)
    {
        
        printf("Nome: %s \n", nome[i]);
       
    }
    
    return 0;
}

davicos
Il problema più grande adesso è quello di mettere i nomi una sola volta in un vettore.
In linea di massima dovrebbe esser così: leggo il primo nome e lo metto dentro il vettore. Leggo il secondo nome e lo confronto con tutte le celle del vettore e se tale nome non è ripetuto allora lo metto dentro il vettore nella cella successiva e così via. Il problema è che il nome ripetuto può essere in una qualsiasi posizione del vettore quindi almeno una volta NON è presente e quindi me lo andrà a copiare. Mi sono spiegato?
Come faccio a fare in modo che non copi il nome anche se solo una volta lo ha trovato nel vettore?

packy95
Non capisco come faccia a funzionare se la fgets prende come primo parametro una stringa, mentre ne tuo programma c'è un intero (http://www.cplusplus.com/reference/cstdio/fgets/) :smt017 :smt017 . Comunque se dici che funziona...
Per quanto riguarda il tuo problema, si può fare in tanti modi. Un modo semplice è quello di scorrere il vettore con un ciclo e controllare se c'è il nome in analisi. Se esiste già, attivi un flag (semplicemente poni True una variabile booleana). Alla fine del ciclo (cioè fuori) controlli: se il flag è False scrivi il nome nell'ultima posizione, altrimenti niente.
Spero di aver capito il problema.

davicos
Si hai capito bene. Ci proverò allora. Grazie di tutto!

packy95
Figurati!

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