Leggere righe da file

streghettaalice
Salve ,
ho un problemino su un semlice esercizio,contare numero di righe di un file di testo:
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>/*per il controllo di lettere*/
 
 #define LEN_STR 1000
 
 int main(int argc,char *argv[])
 {
   FILE *fp;
   int conta=0;
   char str[LEN_STR];
   
   if(argc!=2){ /*se l'utente ha inserito più di un nomi*/
     fprintf(stderr,"usage :maius filename\n");
	 exit(EXIT_FAILURE);
	 }
	 
  if((fp=fopen(argv[1],"rb"))==NULL){   //N.B. "rb"  così posso aprire sia file binari che testuali
    fprintf(stderr,"Can't open %s\n",argv[1]);
    exit(EXIT_FAILURE);
    }
	
   
 
 while((str=fgets(str,sizeof(str),fp))!=NULL){
       
   	   
	  conta =conta+1;
	   
	}
	
	printf("Il numero di righe e':%d",conta);
	fclose(fp);
	
	return 0;
	}
	
	
	

Mi dice che è incompatibile il tipo char[1000] perchè deve essere char *.
Eppure per come l'ho dichiarato str è di tipo char *(è il puntatore al vettore str[])

Risposte
apatriarca
Riporta meglio l'errore del tuo compilatore. Penso sia comunque più facile (e più corretto nel caso ci siano righe molto lunghe - più lunghe di 999 caratteri) contare i caratteri uguali a '\n' nel file..

streghettaalice
dice
"error:incompatible types when assigning to type 'char[1000]' from type 'char * ' "

minomic
Ciao l'errore è qui:
while((str=fgets(str,sizeof(str),fp))!=NULL){

che invece deve essere
while((fgets(str,sizeof(str),fp))!=NULL){

Non l'ho provato ma così dovrebbe andare bene. Facci sapere.

claudio862
Il tipo char[1000] non è uguale al tipo char *. Il primo è un array di char, il secondo un puntatore a char. Gli array "decadono" (cioè vengono convertiti) in puntatori quasi ovunque, ma i puntatori non possono essere convertiti in array. Inoltre gli array non sono assegnabili, non puoi scrivere str = un altro array.
Puoi risolvere semplicemente ignorando il valore restituito da fgets(), come suggerito da minomic.


Infine qui c'è un'imprecisione:
fp=fopen(argv[1],"rb");   //N.B. "rb"  così posso aprire sia file binari che testuali

Il parametro "b" non serve per aprire o meno file binari/testuali, ma per interpretare correttamente il loro contenuto. Se apri un file in modo testuale (senza usare "b"), i caratteri di "a capo" vengono convertiti automaticamente nella sequenza usata dal sistema operativo. Esempio:
FILE * fp = fopen("file.txt", "w");
fputc('\n', fp);

Se questo programma viene eseguito su Windows il file file.txt conterrà "\r\n", su Linux "\n" e sui vecchi Mac "\r". Indipendentemente dal carattere usato dal sistema come terminatore di riga, nel sorgente tu usi sempre '\n'.

Se invece apri il file in modo binario, non c'è nessuna conversione, si leggono e scrivono esplicitamente i caratteri. Esempio:
FILE * fp = fopen("file.txt", "wb");
fputc('\n', fp);

Su qualsiasi sistema il file file.txt conterrà "\n".

Quando lavori su file di testo, aprili sempre in modalità testuale (senza usare "b").

apatriarca
Aggiungendo a quanto detto da claudio86, se si apre il file in modalità testuale qualsiasi sequenza di caratteri per andare a capo (in Windows è una sequenza di due caratteri) verrà convertita in un singolo carattere ottenibile attraverso la escape sequence \n. Aprendolo in modalità binaria, sarebbe necessario verificare tutte le possibili sequenze per andare a capo separatamente.

streghettaalice
Ho un altro dubbio quesa volta nel leggere vettori da un file
#include <stdio.h>
#include <stdlib.h>

#define NAME_LEN 25
#define MAX_PARTS 100

struct part{
 int number;
 char name[NAME_LEN+1];
 int on_hand;
 }inventory[MAX_PARTS];
 
 int num_parts;
 
 void print(void);
 
 int main(void)
 {
   FILE *fp;
   int i;
   int n;
   
   
   if((fp=fopen("inventory.dat","rb+"))==NULL){
     fprintf(stderr,"Can't open inventory file\n");
	 exit(EXIT_FAILURE);
	 }
	 
	 num_parts=fread(inventory,sizeof(struct part),MAX_PARTS,fp);
	 /*num_parts è numero di elementi letti*/
	 
	 for(i=0;i<num_parts;i++)
	   inventory[i].on_hand=0;/*azzero la quantità disponibile*/
	   
	   
	   rewind(fp);/*devo riportare il file all'inizio*/
	   
	   
	   fwrite(inventory,sizeof(struct part),num_parts,fp);
	   /*scrivo il vettore modificato sul file*/
	   
	   rewind(fp);
	   fread(inventory,sizeof(struct part),num_parts,fp);
	 
	  
	 
	   
	   fclose(fp);
	   
	   return 0;
	   }
	   
	   
	   




Per prima cosa non so come "creare " quel file binario.
Come seconda se adesso volessi leggere il vettore dal file e stamparlo per vedere se ho fatto bene??

claudio862
"streghettaalice":
Per prima cosa non so come "creare " quel file binario.
Come seconda se adesso volessi leggere il vettore dal file e stamparlo per vedere se ho fatto bene??


Usa le due funzioni "writeInventoryToFile()" e "readInventoryFromFile()". La prima crea un inventario e lo scrive nel file, la seconda legge l'inventario da file e lo stampa a schermo.

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

#define NAME_LEN 25
#define MAX_PARTS 100

struct part{
    int number;
    char name[NAME_LEN+1];
    int on_hand;
}inventory[MAX_PARTS];

void print(void);

void writeInventoryToFile(const char * filename)
{
    int i;
    FILE * fp;
    int check;
    if ((fp = fopen(filename, "wb")) == NULL){
        fprintf(stderr, "Can't open inventory file\n");
        exit(EXIT_FAILURE);
    }

    const int num_parts = 30;
    struct part newInventory[num_parts];

    /* Inizializzo l'inventario */
    for(i = 0; i < num_parts; i++) {
        newInventory[i].number = i+1;
        newInventory[i].on_hand = rand() % 10;
        sprintf(newInventory[i].name, "Part n° %d", i+1);
    }

    /* Scrivo l'inventario su file */
    check = fwrite(newInventory, sizeof(struct part), num_parts, fp);

    /* Controllo di aver scritto correttamente */
    if (check != num_parts) {
        fprintf(stderr, "Can't write inventory to file\n");
        exit(EXIT_FAILURE);
    }

    fclose(fp);
}

void readInventoryFromFile(const char * filename)
{
    int i;
    FILE * fp;
    if ((fp = fopen(filename, "rb")) == NULL){
        fprintf(stderr, "Can't open inventory file\n");
        exit(EXIT_FAILURE);
    }

    int num_parts;
    struct part newInventory[MAX_PARTS];

    num_parts = fread(newInventory, sizeof(struct part), MAX_PARTS, fp);
    /*num_parts è numero di elementi letti*/

    /* Stampo l'inventario */
    for(i = 0; i < num_parts; i++) {
        newInventory[i].number = i+1;
        newInventory[i].on_hand = rand() % 10;
        sprintf(newInventory[i].name, "Part n° %d", i+1);

        printf("%d: %s, quantity: %d\n",
            newInventory[i].number,
            newInventory[i].name,
            newInventory[i].on_hand);
    }

    fclose(fp);
}

int main(void)
{
    FILE *fp;
    int i;
    const char * filename = "inventory.dat";
    int num_parts;

    readInventoryFromFile(filename);
    return 0;

    if ((fp = fopen(filename, "rb+")) == NULL){
        fprintf(stderr, "Can't open inventory file\n");
        exit(EXIT_FAILURE);
    }

    num_parts = fread(inventory, sizeof(struct part), MAX_PARTS, fp);
    /*num_parts è numero di elementi letti*/

    for(i = 0; i < num_parts; i++) {
        inventory[i].on_hand = 0; /*azzero la quantità disponibile*/
    }


    rewind(fp);/*devo riportare il file all'inizio*/


    fwrite(inventory, sizeof(struct part), num_parts, fp);
     /*scrivo il vettore modificato sul file*/

    rewind(fp);

    fread(inventory, sizeof(struct part), num_parts, fp);


    fclose(fp);

    return 0;
}

streghettaalice
Se dovessi leggere delle lettere da un file di testo utilizzere:
while((ch=getc(fp))!=EOF){



E se invece dovessi estrarre degli interi da un file di testo e salvarli in un vettore?
In questo caso ho scritto :
int main(int argc,char *argv[])
 {
   FILE *fp;
  
   int i=0;
   int j=0;
   int ch;/*sennò non possiamo confrontare con EOF*/
   char vettore[100][200];
   
   int k;

   int n;
   
   if(argc!=2){ /*se l'utente ha inserito più di un nomi*/
     fprintf(stderr,"usage :fnumcar filename\n");
	 exit(EXIT_FAILURE);
	 }
	 
  if((fp=fopen(argv[1],"r"))==NULL){   
    fprintf(stderr,"Can't open %s\n",argv[1]);
    exit(EXIT_FAILURE);
    }
	

	
 while((ch=getc(fp))!=EOF){
     
         if(isdigit(ch))
 {
           i=i+1;/*i sarà il numero di parole*/
		   j=0;
        }
          while(isdigit(ch))
	   {
	   
	     vettore[i][j]=ch;
		 ch=getc(fp);
		 j=j+1;/*j conteggia il numero di lettere in una parola*/
		 
		 }
	   
		
}  
	
			
			

	   
	   

	   return 0;
	   
	   }
	
	

Ma non mi piace in questo modo non saprei come ad esempio ordinare il vettore (in base al numero più grande)

claudio862
Allora, innanzitutto ti consiglio di indentare meglio il codice. È difficile interpretare quello che fa nel modo in cui l'hai scritto tu, mi ci è voluto un bel po' di impegno. Qui una guida in proposito.

In merito a leggere interi da un file di testo, il tuo metodo funziona. Alla fine potresti scorrere l'array di "stringhe" e generare il numero corrispondente in un altro array, usando ad esempio "sscanf()".

Un modo più semplice è invece usare la funzione fscanf(). Assumendo che il file contenga numeri separati da spazi, si usa così:

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

int main(int argc,char *argv[])
{
    FILE *fp;

    int vettore[100];

    if(argc!=2){ /*se l'utente ha inserito più di un nomi*/
        fprintf(stderr,"usage :fnumcar filename\n");
        exit(EXIT_FAILURE);
    }

    if((fp=fopen(argv[1],"r"))==NULL){
        fprintf(stderr,"Can't open %s\n",argv[1]);
        exit(EXIT_FAILURE);
    }

    int i = 0;
    while (!feof(fp)) {
        int r = fscanf(fp, "%d", & vettore[i]);
        if (r != 1) {
            // fscanf() restituisce il numero di campi letti
            // correttamente. Se non è 1, c'è stato un errore
            // (alla posizione corrente non c'è un numero,
            // oppure abbiamo raggiunto la fine del file).
            break;
        }
        i++;
    }

    printf("Ho letto i numeri:\n");
    for (int k = 0; k < i; ++k) {
        printf("%d\n", vettore[k]);
    }


    return EXIT_SUCCESS;
}

streghettaalice
Ho provato ma non mi stampa il vettore..
Perchè questo va bene se nel file di testo ci sono solo numeri, ma io sto supponendo che ci sono sia lettere che numeri e devo estrarre quest'ultimi.

claudio862
Usa la funzione sscanf(), che è simile a scanf() ma invece di leggere dallo standard input legge una stringa qualsiasi.

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

int main(int argc,char *argv[])
{
    FILE *fp;

    int i = 0;
    int ch;
    int vettore[100];

    if (argc != 2) {
        fprintf(stderr, "usage :fnumcar filename\n");
        exit(EXIT_FAILURE);
    }

    if ((fp = fopen(argv[1],"r")) == NULL){
        fprintf(stderr, "Can't open %s\n", argv[1]);
        exit(EXIT_FAILURE);
    }

    while ((ch = getc(fp)) != EOF) {
        // Continuo a leggere caratteri finché non leggo una cifra.

        if (isdigit(ch)) {
            // Ho letto una cifra. Leggo tutte le cifre successive
            // e le copio nell'array di caratteri "buffer".

            char buffer[100];
            int j = 0;
            while (isdigit(ch))
            {
                buffer[j] = ch;
                ch = getc(fp);
                j = j + 1;
            }

            // Aggiungo lo zero finale.
            buffer[j] = 0;

            // Ora "buffer" contiene una stringa numerica. Estraggo
            // il numero con la funzione "sscanf".
            sscanf(buffer, "%d", & vettore[i]);

            i = i + 1;
        }
    }

    printf("Ho letto i numeri:\n");
    for (int j = 0; j < i; ++j) {
        printf("%d\n", vettore[j]);
    }

    return 0;
}

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