Linguaggio C, matrice di caratteri in un file

di il
13 risposte

Linguaggio C, matrice di caratteri in un file

Ho un file contenente una matrice di caratteri. Devo semplicemente inserirla all'interno di una matrice allocata dinamicamente.

La matrice nel file è questa:
a b b d h f
g h i j k k
b d d h j l
main.c
int main(int argc, char** argv){
    char* nomefile = "file1.txt";
    
    int n_righe = 0, n_colonne = 0;
    char** mat = leggi_matrice(nomefile, &n_righe, &n_colonne);
}

funzione.c

char** leggi_matrice(const char* nomefile, int *r, int *c)
{
	char buffer[200], *res, **mat, temp;
	int i = 0, j = 0;
	
	FILE *f = fopen(nomefile, "r");
	if(nomefile == NULL)
		printf("Errore apertura file. \n");
	else
	{
		//Acquisizione numero di colonne
		res = fgets(buffer, 200, f);
		while(res[i] != '\0')
		{
			if(res[i] == ' ')
				*c = *c +1; 
			i++;
		}
		*c = *c +1; //In una stringa di caratteri, separati ognuno
				   //da uno spazio, gli elementi della stringa sono
				   //*c spazi +1
		printf("\nNumero colonne: %d\n", *c);
		
		//Riposiziono il cursore all'inizio del file
		fseek(f, 0, 0);
		
		
		//Conto il numero della righe
		while(1)
		{
			res = fgets(buffer, 200, f);
			if(res == NULL)
				break;
			*r = *r + 1;
		}
		
		printf("\nNumero righe: %d\n", *r);
		

		
		//Allocazione dinamica della memoria
		mat = (char**) malloc (*c * sizeof(char*));
		for(i = 0; i < *c; i++)
			mat[i] = (char*) malloc (*r * sizeof(char));
		
		fseek(f, 0, 0);
		
		//Caricamento della matrice da file

		while(!feof(f))
		{
			for(i = 0; i < *r; i++)
				for(j = 0; j < *c; j++)
				{
					fscanf(f, "%c", &temp);
					if((temp != ' ')&&(temp != '\0'))
						mat[i][j] = temp;

				}
		
		}

		fclose(f);	
		
		//Stampa della matrice
		for(i = 0; i < *r; i++)
		{
			for(j = 0; j < *c; j++)
				printf("%c", mat[i][j]);
			//printf("\n");
		}
			
	}
}
Il compilatore non da errori, e mi stampa:

Numero colonne: 6

Numero righe: 3


Il che è giusto, quindi il file lo legge.

Mi sono accorto però che:

while(!feof(f))
{
for(i = 0; i < *r; i++)
for(j = 0; j < *c; j++)
{
fscanf(f, "%c", &temp);
if((temp != ' ')&&(temp != '\0'))
mat[j] = temp;

}

}


Non lo legge! Infatti, mettendo dei printf prima e dopo il ciclo questi me li stampa, mentre nel ciclo non ci entra proprio. Ho uno stesso algoritmo identitco, solo che la matrice è di int e funziona. Perché questo no? Grazie

13 Risposte

  • Re: Linguaggio C, matrice di caratteri in un file

    Perchè da una parte leggi con fgets() e poi leggi sotto leggi con fscanf()?
    Se i tuoi caratteri hanno posizioni fisse (intendo un carattere+uno spazio+un carattere+uno spazio...) puoi tranquillamente leggere con fgets() e poi andare a prelevare i caratteri dal buffer letto, a posizioni fisse, oppure puoi prendere tutti i caratteri diversi da spazi...
    L'hai già fatto qui:
          while(res[i] != '\0')
          {
             if(res[i] == ' ')
                *c = *c +1;
             i++;
          }
          *c = *c +1; //In una stringa di caratteri, separati ognuno
                   //da uno spazio, gli elementi della stringa sono
                   //*c spazi +1
    ma invece di contare i caratteri tu conti gli spazi...
  • Re: Linguaggio C, matrice di caratteri in un file

    Ho provato così:
    
    		while(!feof(f))
    		{
    			for(i = 0; i < *r; i++)
    				for(j = 0; j < *c; j++)
    				{
    					temp = getc(f);
    					if((temp != ' ')&&(temp != '\0'))
    						mat[i][j] = temp;
    				}
    		
    		}
    		fseek(f, 0, 0);
                    //Prova per vedere se temp prende il carattere dal file
    		temp = getc(f);
    		printf("temp: %c\n", temp);
    				temp = getc(f);
    		printf("temp: %c\n", temp);
    
    		//fclose(f);	
    		
    		//Stampa della matrice
    		for(i = 0; i < *r; i++)
    		{
    			for(j = 0; j < *c; j++)
    				printf("%c", mat[i][j]);
    			printf("\n");
    		}
    E mi stampa questo:

    Numero colonne: 6

    Numero righe: 3
    temp: a
    temp:
    ??????
    ??????
    ??????


    Perché mi stampa i punti interrogativi e non i caratteri?
  • Re: Linguaggio C, matrice di caratteri in un file

    Sono sbagliati il ciclo di lettura e il ciclo di stampa.

    La lettura deve incrementare gli indici tenendo conto dei caratteri validi, non comunque con le for. Quindi deve essere
    
    i = 0;
    j = 0;
    while(!feof(f))
    {
        temp = getc(f);
    			   
        if((temp != ' ') && (temp != '\n'))
        {
           mat[i][j] = temp;
    
           i++;
           if(i==c)
           {
              i=0;
              j++;
           }
       }
    }
    
    e la visualizzazione, dato che l'array è organizzato per colonne
    
    for(j = 0; j < r; j++)
    {
       for(i = 0; i < c; i++)
           printf("%c", mat[i][j]);
    
           printf("\n");
    }
    
  • Re: Linguaggio C, matrice di caratteri in un file

    Non fare
    while(!feof(f))
  • Re: Linguaggio C, matrice di caratteri in un file

    candaluar ha scritto:


    non fare
    while(!feof(f))
    Perché?

    oregon ha scritto:


    Sono sbagliati il ciclo di lettura e il ciclo di stampa.

    La lettura deve incrementare gli indici tenendo conto dei caratteri validi, non comunque con le for. Quindi deve essere
    
    i = 0;
    j = 0;
    while(!feof(f))
    {
        temp = getc(f);
    			   
        if((temp != ' ') && (temp != '\n'))
        {
           mat[i][j] = temp;
    
           i++;
           if(i==c)
           {
              i=0;
              j++;
           }
       }
    }
    
    e la visualizzazione, dato che l'array è organizzato per colonne
    
    for(j = 0; j < r; j++)
    {
       for(i = 0; i < c; i++)
           printf("%c", mat[i][j]);
    
           printf("\n");
    }
    
    Grazie!

    L'unica cosa che non capisco è: in precedenza avevo scritto un codice che lavora su matrice di interi e funziona. Perché quello che ho fatto con i caratteri no?
    #include <stdio.h>
    #include <stdlib.h>
    
    int **leggiMatriceQuadrata(char* filename)
    {
    	FILE *fd;
    	char buf[200];
    	char *res;
    	int i = 0, j = 0, n = 0, righe, colonne, **matrice, temp, ris;
    	
    	fd = fopen(filename, "r");
    	if( fd==NULL ) 
    	{
    		perror("Errore in apertura del file");
    		exit(1);
    	}	
    	else 
    	{	
    		res = fgets(buf, 200, fd);
    		//printf("%s", res);
    		//Ciclo che serve per contare 
    		//gli elementi della PRIMA riga
    		while(res[i] != '\0')
    		{
    			if(res[i] == ' ')
    				n++;
    			i++;
    		}
    		n += 1; //In una stringa di numeri, separati ognuno
    			     //da uno spazio, gli elementi della stinga sono
    			     //n spazi + 1
    		//printf("La prima riga contiene %d elementi\n", n);
    		colonne = n;
    		
    		fseek(fd, 0, 0); //Riposiziono il cursore all'inizio del file
    		
    		i = 0;
    		
    		//Conto il numero delle righe
    		
    		while(1) 
    		{
    			res=fgets(buf, 200, fd);
    			if( res==NULL )
    				break;
    			i++;
    		}
    		//printf("Ci sono %d righe \n", i);
    		fseek(fd, 0, 0); //Riposiziono il cursore all'inizio del file
    		
    		righe = i;
    		
    		//Avendo righe e colonne posso allocare la matrice dinamicamente
    		matrice = (int **) malloc (colonne * sizeof(int*));
    		for(i = 0; i < colonne; i++)
    			matrice[i] = (int*) malloc (righe * sizeof(int));
    		
    		while(!feof(fd))
    		{
    			for(i = 0; i < righe; i++)
    				for(j = 0; j < colonne; j++)
    				{
    					fscanf(fd, "%d", &temp);
    					if((temp != ' ')&&(temp != '\0'))
    						matrice[i][j] = temp;
    				}
    		}
    		
    		fclose(fd);
    		
    		for(i = 0; i < righe; i++)
    		{
    			for(j = 0; j < colonne; j++)
    				printf("%d ", matrice[i][j]);
    			printf("\n");
    		}
    		
    		ris = simmetrica(matrice, colonne);	
    		
    		if(ris == 1)
    			printf("La matrice e' simmetrica!\n");
    		else 
    			printf("La matrice non e' simmetrica!\n");
    		
    		
    	}
    }
    Cos'ha di sbagliato questo codice di sotto?
    		while(!feof(f))
    		{
    			for(riga = 0; riga < *r; riga++)
    				for(colonna = 0; colonna < *c; colonna++)
    				{
    					temp = getc(f);
    					if((temp != ' ')&&(temp != '\0'))
    						mat[riga][colonna] = temp;
    				}
    		
    		}
  • Re: Linguaggio C, matrice di caratteri in un file

    Ma hai letto la mia risposta? Perché riproponi il codice con le for se ti ho detto che le for sono il problema?

    Perché riproponi il controllo con '\0' mentre deve essere '\n' ??

    Pensavo avessi compreso le differenze ...
  • Re: Linguaggio C, matrice di caratteri in un file

    @davide: io ti ho consigliato di togliere il while(!feof(f)) perchè rischi di fare 2 volte i 2 cicli annidati.
    Se veramente vuoi testare di non essere arrivato alla fine del file dovresti controllare dopo ogni lettura:
             int uscita = 0;      
             for(riga = 0; riga < *r; riga++)
             {
                for(colonna = 0; colonna < *c; colonna++)
                {
                   temp = getc(f);
                   if((temp != ' ')&&(temp != '\0'))
                      mat[riga][colonna] = temp;
                   if( feof(f) )
                   {
                       uscita = 1;
                       break;
                   }
                }
                if( uscita )
                    break;
          }
    Mettendo il while(!feof(f)) invece, basta che ci sia un carattere in più nel file rispetto alla tua tabella che a quel punto rifaresti nuovamente i due cicli (righe x colonne) sovrascrivendo i dati corretti precedentemente letti...
  • Re: Linguaggio C, matrice di caratteri in un file

    oregon ha scritto:


    ..non comunque con le for.

    oregon ha scritto:


    Perché riproponi il codice con le for se ti ho detto che le for sono il problema?
    Non avevo capito che il for non andasse bene, a prescindere, con le matrici di caratteri. Con quelle di interi mi funziona e vorrei sapere il perché..

    candaluar ha scritto:


    @davide: io ti ho consigliato di togliere il while(!feof(f)) perchè rischi di fare 2 volte i 2 cicli annidati.
    Se veramente vuoi testare di non essere arrivato alla fine del file dovresti controllare dopo ogni lettura:
             int uscita = 0;      
             for(riga = 0; riga < *r; riga++)
             {
                for(colonna = 0; colonna < *c; colonna++)
                {
                   temp = getc(f);
                   if((temp != ' ')&&(temp != '\0'))
                      mat[riga][colonna] = temp;
                   if( feof(f) )
                   {
                       uscita = 1;
                       break;
                   }
                }
                if( uscita )
                    break;
          }
    Mettendo il while(!feof(f)) invece, basta che ci sia un carattere in più nel file rispetto alla tua tabella che a quel punto rifaresti nuovamente i due cicli (righe x colonne) sovrascrivendo i dati corretti precedentemente letti...
    Ok, capito. Grazie
  • Re: Linguaggio C, matrice di caratteri in un file

    Davide ... continui ad usare il codice della lettura con le for ... pur avendoti detto due volte che non va bene ...

    Se non metti le for, fra l'altro, la feof, nel tuo caso, non c'è bisogno di ripeterla ...

    Se non ci capiamo dillo così evito di risponderti ...
  • Re: Linguaggio C, matrice di caratteri in un file

    Ho capito che le for non vanno bene. Ma potrei sapere il perché? C'è una spiegazione razionale? Semplice curiosità
  • Re: Linguaggio C, matrice di caratteri in un file

    Te l'ho già scritto il perché ... lo ripeto ...

    Durante la lettura, gli indici devono essere incrementati tenendo conto dei caratteri validi mentre se usi le for gli indici si incrementano per qualsiasi carattere, anche per gli spazi.

    Quindi non devi più utilizzare i cicli for nella lettura altrimenti non so più cosa dirti ...
  • Re: Linguaggio C, matrice di caratteri in un file

    Ora ho capito. Grazie per la pazienza
  • Re: Linguaggio C, matrice di caratteri in un file

    Devo chiederti un'ultimissima cosa, non mandarmi a quel paese
    		while(!feof(f))
    		{
    		    temp = getc(f);
    			    
    		    if((temp != ' ') && (temp != '\n'))
    		    {
    		       mat[i][j] = temp;
    
    		       i++;
    		       if(i==*c)
    		       {
    			  i=0;
    			  j++;
    		       }
    		   }
    		}
    Immaginando di avere questa matrice:

    ...01
    0 ab
    1 cd

    Inizialmente siamo nella cella mat[0][0] della matrice (quindi mat[0][0] = a), successivamente, con i++, viene incrementata la riga quindi mat[1][0] (quindi mat[1][0] = c). Ma non si dovrebbe incrementare la colonna, cioè mat[0][1]? Il codice però stampa bene la matrice quindi sicuramente sono io che mi sto confondendo
Devi accedere o registrarti per scrivere nel forum
13 risposte