[C] Leggere file comprese le tabulazioni

di il
11 risposte

[C] Leggere file comprese le tabulazioni

Salve a tutti!
Ho un banale problema che spero possiate velocemente aiutarmi a risolvere.
Il problema è il seguente:
Devo leggere un file che presenta del testo separato da tabulazioni e a volte spazi.
Per intenderci meglio in C avrebbe questa faccia:
scritta\tscritta\nscritta\tscritta\n
o in alcuni casi questa:
scritta scritta\nscritta scritta\n
Dopo averlo letto devo farne un backup in un nuovo file, io ho fatto così:
char reading[1024];

FILE *file;
FILE *backup = 0;
		
// Backing up hosts file
file = fopen(path,"r");
	
if (!file)
	fatal("while opening file with r parameter ");
else
	{
		backup = fopen(tempbackupPATH, "w");
		if (!backup)
			fatal("while opening backup with w parameter ");
		else
			{
				while ((fscanf (file, "%s",&reading)) > 0)
					{
						fprintf (backup, "%s", reading);
						memset(&reading, 0, sizeof(reading));
					}
			}	
fclose(backup);
fclose(file);
Il codice funziona quando il file non contiene tabulazioni, ma se esse sono presneti, lo riscrive seza di esse, con il testo tutto attaccato.


Come posso fare per leggere anche le tabulazioni?

Ho letto googlando che fgets() legge anche le tabulazioni. E' vero? Se è così, sapendo che fgets si ferma raggiunto un carattere newline come posso fare a leggere un file di più righe quidni con più caratteri newline?

Grazie a tutti!
Resto in attesa

11 Risposte

  • Re: [C] Leggere file comprese le tabulazioni

    Ciao Ananke Melior,

    In realtà è possibile includere nei format di conversione il `matching`...

    La fgets si ferma dopo un EOF oppure dopo carattere di newline. Legge fino alla dimensione passata -(meno) 1 aggiungendo il carattere '\0' terminatore al buffer. Restituisce il ptr oppure NULL sia per EOF che per errore.
    
      while (fgets(line,SIZE,fp_in))
        if ((fprintf (fp_out,"%s",line))<0)
          break;
      if (ferror(fp_in) || ferror(fp_out))
        perror ("Error");
    
    Per i file binari devi usare la fread/fwrite
    
      size_t len;
      while ((len=fread(line,1,SIZE,fp_in)))
        if (fwrite(line,1,len,fp_out)!=len)
          break;
      if (ferror(fp_in) || ferror(fp_out))
        perror ("Error");
    
  • Re: [C] Leggere file comprese le tabulazioni

    Ciao Ixamit!
    A quanto sembra in questo forum tu sei l'unico che possiede ogni risposta ad ogni mia domanda.

    Non ho capito bene cosa devo fare con i file binari, ti espongo i dubbi:
    SIZE come lo definisco?
    line lo definisco come un array di caratteri quindi ad ogni ciclo in line si inserisce un nuovo carattere in coda agli altri o devo definire line come un solo carattere?
    fp_in è il puntatore al file con caratteristiche rb?
    Se srivo un file binario con lo stesso nome di uno gia esistente nella stessa cartella, il nuovo file sostituirà semplicemente quello nuovo giusto? Eventualmente posso usare ab per append?


    Grazie mille, a presto
  • Re: [C] Leggere file comprese le tabulazioni

    Ciao Ananke Melior,

    I file binari utilizzano tutta la codifica ASCII da 0x00 a 0xFF.
    I file testuali utilizzano il set ASCII dei caratteri visibili ($man 3 isprint) più altri caratteri speciali di controllo non visibili se non nel contesto della formattazione (spazio, tab, LF...).

    La fgets/fprintf scartano per esempio il carattere \0x00 che viene interpretato come fine stringa.
    
    max@studio:~> echo -e "\x00A\x09B" > foo
    max@studio:~> hexdump -C foo
    00000000  00 41 09 42 0a                                    |.A.B.|
    00000005
    
    
    #include <stdio.h>
    
    #define SIZE 8
    int main (int argc, char **argv)
    {
      FILE *fp_in, *fp_out=stdout;
      char line[SIZE];
      
      if (argc!=2 && argc!=3)
      {
        fprintf (stderr,"%s\tSRC [DST]\n",argv[0]);
        return -1;
      }
      if ((fp_in=fopen (argv[1],"rb"))==NULL)
      {
        fprintf (stderr,"Cannot read `%s` file\n",argv[1]);
        perror ("Error");
        return -1;
      }
      if (argc==3)
      {
        if ((fp_out=fopen (argv[2],"wb"))==NULL)
        {
          fprintf (stderr,"Cannot write `%s` file\n",argv[2]);
          perror ("Error");
          fclose (fp_in);
          return -1;
        }
      }
      
    #ifdef FGETS
      fprintf (stderr,"** using fgets/fprintf **\n");
      while (fgets(line,SIZE,fp_in))
        if ((fprintf (fp_out,"%s",line))<0)
          break;
      if (ferror(fp_in) || ferror(fp_out))
        perror ("Error");
    #else
      fprintf (stderr,"** using fread/fwrite **\n");  
      size_t len;
      while ((len=fread(line,1,SIZE,fp_in)))
        if (fwrite(line,1,len,fp_out)!=len)
          break;
      if (ferror(fp_in) || ferror(fp_out))
        perror ("Error");   
    #endif
    
      if (fp_out!=stdout)
        fclose (fp_out);
      fclose (fp_in);
        
      return 0;
    }
    
    
    max@studio:~> gcc prova.c -DFGETS
    max@studio:~> ./a.out foo
    ** using fgets/fprintf **
    max@studio:~>
    max@studio:~> gcc prova.c
    max@studio:~> ./a.out foo
    ** using fread/fwrite **
    A       B
    max@studio:~> 
    
    NOTA:
    La modalità di apertura del file per inary è implicita in tutti i sistemi POSIX -Linux incluso-. Aggiungerlo è comunque buona norma per retro-compatibilità con il C89 e per altri sistemi non-UNIX.
  • Re: [C] Leggere file comprese le tabulazioni

    @Ananke, giustamente come dice ixamit con un fscanf è un po' difficile far quel che chiedi, una possibile soluzione sarebbe caricare il file in memoria e "splittarlo" a mano:
    
    /* ...
        carico il file: */
    char *string, **words;
    int length, j;
    FILE *fd;
    
    if ( !(fd = fopen ("tuofile.txt", "rb")) ) 
         exit (EXIT_FAILURE);
    
    fseek (fd, 0, SEEK_END);
    length = ftell (fd);
    rewind (fd);
    string = (char *) malloc (length * sizeof (char));
    fread (string, sizeof (char), length, fd);
    fclose (of);
    
    /* splitto, ovvero divido le parole considerando come
       spazio uno dei caratteri presenti nella lista che
       passo alla funzione */
    
    words = string_split (string, " \n\t");
    free (string);
    
    /* ... 
       fai qualcosa con words
       ...
    */
    
    for ( j = 0; words[j]; j++ )
          free (words[j]);
    free (words);
    
    Come possibile funzione string_split potresti scrivere qualcosa tipo:
    
    char **string_split (char *buffer, char *limit)
    {
     char **l_str, *tmp;
     int mem = 1, j, k, i;
     
     l_str = (char **) malloc (sizeof (char *));
     for ( j = 0; j < bytes; j += ++k) {            
           tmp = (char *) malloc (sizeof (char));
           for ( k = 0; (j + k) < bytes; k++ ) {
                 for ( i = 0; limit[i] != '\0' && buffer[j + k] != limit[i]; i++ );
                 if ( limit[i] )
                      break;
                 
                 tmp[k] = buffer[j + k];
                 tmp = (char *) realloc (tmp, (k + 2) * sizeof (char));
           }
           tmp[k] = '\0';
           if ( !*tmp  ) {
                free (tmp);
                continue;
           }
           l_str[mem - 1] = strdup (tmp);
           free (tmp);
           l_str = (char **) realloc (l_str, ++mem * sizeof (char *));
           l_str[mem - 1] = NULL;
     }
     
     return l_str;
    }
    
    Ciauz
  • Re: [C] Leggere file comprese le tabulazioni

    Ciao Ananke Melior,
    A quanto sembra in questo forum tu sei l'unico che possiede ogni risposta ad ogni mia domanda.
    Probabilmente non suscita interesse rispondere. Ma, ti ha appena risposto una persona con ottima preparazione ed esperienza in rapporto all'età. Questo ragazzo scrive veramente bene!
  • Re: [C] Leggere file comprese le tabulazioni

    Vi ringrazio tutti e due.
    Ixamit hai perfettamente ragione, Style { HdS619 } ha scritto veramente bene.

    Adesso proverò ad implementarlo bene all'interno dei miei programmi ed eventualmente vi aggiorno sulle problematiche incontrate. Altrimenti, se tutto come spero va bene, potremo considerare il thread risolto.

    Grazie ancora a tutti e due,
    a presto

    EDIT:
    Riguardo alla funzione di backup epr cui mi serviva leggere anche le tabulazioni ho risolto con i metodi che mi avete spiegato sopra. Grazie di nuovo.
    Ho provato poi ad inserirla in un programma ed ad inviare i dati binari letti ad un server così da riscrivere di la il medesimo file. Una sorta di download artigianale per piccoli files. Purtroppo però non riesco a impostare corrtetamente il ciclo.
    Come posso fare?

    Per l'invio ho fatto così:
    FILE *dwfile;
         
    
        if ((dwfile=fopen (dwfile_name,"rb"))==NULL)
    		{
    			fprintf (stderr,"Cannot read `%s` file\n",dwfile_name);
    			perror ("Error");
    			return;
    		}
        
        size_t len_file;
        while (fread(block,1,BLOCK_SIZE,dwfile) > 0)
    		{
    			send(remoteSocket, block,strlen(block),0);
    		}
    	
    	memset(&block, 0, sizeof(block));
    	strcpy(block,"Download compleated!EnD");
    	send(remoteSocket, block,strlen(block),0);
    
        fclose(dwfile);
           
        return;
    }

    Per la ricezione così:
    if ((dwfile=fopen (dwfile_name,"ab"))==NULL)
    		{
    			fprintf (stderr,"Cannot write `%s` file\n",dwfile_name);
    			perror ("Error");
    			return;
    		}
    	
    	while (1)
    		{
    			memset(&block, 0, sizeof(block));
    			len=recv(remoteSocket, block, sizeof(block), 0);
    			length = strlen(block);
    			if(length && block[length -1] ==  'D'){
    				if(length && block[length -2] ==  'n'){
    					if(length && block[length -3] ==  'E'){
    						block[length-1] = '\0';
    						block[length-2] = '\0';
    						block[length-3] = '\0';
    						printf ("%s",block);
    						break;
    					}
    				}
    			}
    			else
    				{
    					fwrite(block,1,BLOCK_SIZE,dwfile);
    				}
    		}
    	if (len<0)
    		fatal("while recv ");
    	else if (len==0){
    		printf ("Connection closed by server. Bye!\n");
    		exit(0);}
    		
    	fclose(dwfile);


    Sapreste dirmi dove sbaglio?
    Grazie della disponibilità, a presto.
  • Re: [C] Leggere file comprese le tabulazioni

    Ciao Ananke Melior,
    Sapreste dirmi dove sbaglio?
    Grazie della disponibilità, a presto.
    Sbagli perchè utilizzi fread con un buffer che gestisci come input di caratteri alias stringa/testo. La fread andrebbe benissimo, ma devi trovare i riferimenti della riga all'interno del blocco altrimenti usa fgets

    Quando leggo con fgets la dimensione è data da strlen
    Quando leggo con fread la dimensione è data dal numero di elementi restituiti dalla funzione stessa.

    Detto questo, il tutto si può riassumere in

    Trasmissione:
    
      ...
      size_t len;
      //
      // Leggo fino a end-of-file o errore
      while ((fgets(block,1,BLOCK_SIZE,dwfile)) > 0)   
      {
        //
        // La dimensione è data dalla lunghezza della stringa
        len=strlen(block);                                  
        //
        // Invio. Se errore esco
        if ((send(remoteSocket, block,len,0))!= len)
          break;
      }
      if (errno)
        perror ("Uh-oh...");
      ...
      ...
      // Semplice invio. 
      // Il carattere '\n' serve a fare il flush del socket
      send(remoteSocket, "!EnD\n",5,0);
      ...
      ...
    
    Ricezione:
    
      ...
      size_t len;
      //
      // Ricevo fino a chiusura della connessione o errore
      // la lunghezza mi viene fornita dalla funzione stessa
      while ((len=recv(remoteSocket, block, sizeof(block), 0))>0)
      {
        //
        // Scrivo su file il blocco x la lunghezza ricevuta
        // se errore esco
        if ((fwrite(block,1,len,dwfile))!=len)
          break;
        ...
        ...
        //
        // Eseguo dei test
        if (!strcmp(block,"!EnD\n"))
          break;
        ...
        ...
      }
      if (errno)
        perror ("Uh-oh...");
      ...
    
    Un esempio, in questo messaggio di risposta ho scritto quasi 2Kb, ho schiacciato circa duemila tasti:
    - ho un block da 1Kb, la fread mi carica al massimo 1Kb, termina con 2 iterazioni.
    - ho un block da 1Kb, la fgets mi carica al massimo 134b (la riga + lunga), termina con 75 iterazioni (il numero di righe)
  • Re: [C] Leggere file comprese le tabulazioni

    Ciao Ixamit.
    Ho provato a modificare il codice seguendo le tue indicazioni. Putroppo sembra continuare a non funzionare.
    Ecco come ho fatto:
    Invio:
    FILE *dwfile;
         
    
        if ((dwfile=fopen (dwfile_name,"rb"))==NULL)
    		{
    			fprintf (stderr,"Cannot read `%s` file\n",dwfile_name);
    			perror ("Error");
    			return;
    		}
        
        while ((fgets(block,BLOCK_SIZE,dwfile)) > 0)   
    		{                          
    			send(remoteSocket, block,strlen(block),0);
    		}
    	
        fclose(dwfile);
           
        return;

    Ricezione:
    	if ((dwfile=fopen (dwfile_name,"ab"))==NULL)
    		{
    			fprintf (stderr,"Cannot write `%s` file\n",dwfile_name);
    			perror ("Error");
    			return;
    		}
    	
    	while (1)
    		{
    			memset(&block, 0, sizeof(block));
    			len_bin=recv(remoteSocket, block, sizeof(block), 0);
    			length = strlen(block);
    			if(length && block[length -1] ==  'D'){
    				if(length && block[length -2] ==  'n'){
    					if(length && block[length -3] ==  'E'){
    						block[length-1] = '\0';
    						block[length-2] = '\0';
    						block[length-3] = '\0';
    						printf ("%s",block);
    						logging(block);
    						break;
    					}
    				}
    			}
    			else
    				{
    					fwrite(block,1,len_bin,dwfile);
    				}
    		}
    	if (len_bin<0)
    		fatal("while recv ");
    	else if (len_bin==0){
    		printf ("Connection closed by server. Bye!\n");
    		exit(0);}

    So che potrei gestire meglio gli errori ma al momento così mi è più chiaro da leggere. Cosa sbaglio?
    A presto e grazie ancora
  • Re: [C] Leggere file comprese le tabulazioni

    Ciao Ananke Melior,

    Ho provato sui 2 programmini scritti nell'altro 3d e funziona. A questo punto mi dovresti dire:
    1) Come è fatto il file da trasferire. Parli di tabulazioni, scrivi in append, aggiungi la stringa "End" è testuale o cosa?
    2) Cosa intendi per "continuare a non funzionare". Non compila? esegue un errrore in run-time? non trasmette? non riceve?

    foo:
    
    max@studio:~> ln -s test2.c  foo
    max@studio:~> ll foo
    lrwxrwxrwx 1 max users 7 15 set 10.22 foo -> test2.c
    max@studio:~> 
    
    client:
    
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    
    #define BLOCK_SIZE 8
    #define FAMILY AF_INET
    #define PORT 7777
    
    /** get sockaddr, IPv4 or IPv6 */
    void *get_in_addr(struct sockaddr *sa)
    {
      if (sa->sa_family == AF_INET)
        return &(((struct sockaddr_in*)sa)->sin_addr);
    
      return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    int main (int argc, char **argv)
    {
      int sock,x;
      struct addrinfo hints,*servinfo, *p;
     
      char host_addr[INET6_ADDRSTRLEN];
      char port[16];
    
      ssize_t len;
      char block[BLOCK_SIZE];
     
     
      if (argc!=2)
      {
        fprintf (stderr, "Usage:\t%s host\n",argv[0]);
        return -1;
      }
     
      snprintf (port,sizeof(port),"%d",PORT);
     
      memset(&hints, 0, sizeof (hints));
      hints.ai_family =FAMILY;
      hints.ai_socktype = SOCK_STREAM;
      if ((x=getaddrinfo(argv[1], port, &hints, &servinfo)) != 0)
      {
        fprintf (stderr,"getaddrinfo: %s\n", gai_strerror(x));
        return -1;
      }
      for(p=servinfo;p;p=p->ai_next)
      {
        if ((sock=socket(p->ai_family, p->ai_socktype, p->ai_protocol))<0)
        {
          perror("Warning: socket");
          continue;
        }
       
        inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), host_addr, sizeof (host_addr));
        printf ("try connecting to %s port %s...\n",host_addr,port);   
        if ((connect(sock, p->ai_addr, p->ai_addrlen))<0)
        {
          perror ("Warning: connect");
          continue;
        }
        printf ("Good one. Done\n");
        break;
      }
    
    
    
    
    
    
    
     /*
      for (;;)
      {   
        fgets (block, BLOCK_SIZE, stdin);
        if ((len=send(sock, block,strlen(block),0))<1)
          break;
        if (strcmp(block,"EXIT\n")==0)
          break;
    
      }
      
    */
      /**
       *
       * 
       * patching 4U
       * 
       * 
       */
      #include <errno.h>
      #define dwfile_name "foo"
      int remoteSocket=sock;
      FILE *dwfile;
      if ((dwfile=fopen (dwfile_name,"rb"))==NULL)
      {
        fprintf (stderr,"Cannot read `%s` file\n",dwfile_name);
        perror ("Error");
        return;
      } 
      //
      // Leggo fino a end-of-file o errore
      while ((fgets(block,BLOCK_SIZE,dwfile))>0)   
      {
        //
        // La dimensione è data dalla lunghezza della stringa
        len=strlen(block);                                 
        //
        // Invio. Se errore esco
        if ((send(remoteSocket, block,len,0))!= len)
          break;
      }
      if (errno)
        perror ("Uh-oh...");
      
      freeaddrinfo(servinfo);
      close (sock);
     
      return 0;
    }
    
    server non patchato (basta modificare la printf con fprintf):
    
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    #define BLOCK_SIZE 8
    #define FAMILY AF_INET
    #define PORT 7777
    
    int main ()
    {
      int sock_in,client_sock;
      struct sockaddr_in addr_in;
      ssize_t len;
      char block[BLOCK_SIZE];
     
      sock_in=socket(AF_INET,SOCK_STREAM,0);
     
      addr_in.sin_family=FAMILY;
      addr_in.sin_addr.s_addr=INADDR_ANY;
      addr_in.sin_port=htons(PORT);
     
      if ((bind(sock_in,(struct sockaddr*) &addr_in,sizeof(addr_in)))<0)
        perror ("bind");
     
      if ((listen(sock_in,1))<0)
        perror ("listen");
     
      printf ("Waiting connection....\n");
      if ((client_sock=accept(sock_in,0,0))<0)
        perror ("accept");
     
      printf ("done\n");
      while ((len=recv(client_sock, block, sizeof(block)-1, 0))>0)
      {
        block[len]='\0';
        printf ("%s",block);
        if (strcmp(block,"EXIT\n")==0)
          break;
      }
     
      if (len<0)
        perror ("recv");
      else if  (len==0)
        printf ("connection closed by peer. Bye!\n");
      else
        printf ("connection closed\n");
     
      close (client_sock);
      close (sock_in);
     
     
      return 0;
    }
    
    term:
    
    max@studio:~> gcc server.c -o server
    max@studio:~> gcc client.c -o client
    max@studio:~> ./server &
    [1] 10918
    Waiting connection....
    max@studio:~> ./client localhost
    try connecting to 127.0.0.1 port 7777...
    done
    Good one. Done
    /**
     *  Copyright (C) 2007, Max Cavallo <ixamit_at_gmail_dot_com>
     *
     *  This program is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License as published by
     *  the Free Software Foundation; either version 2 of the License, or
     *  (at your option) any later version.
     *
     *  This program is distributed in the hope that it will be useful,
     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *  GNU General Public License for more details.
     *
     *  You should have received a copy of the GNU General Public License
     *  along with this program; if not, write to the Free Software
     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     *
    */
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    #define DEBUG
    #define ETHER_SRC "prod_list.txt"
    #define ETHER_DST "prod_list.dat"
    
    int16_t n_prod=0;
    unsigned char *prod=NULL;
    
    struct _ethernet_prod
    {
      unsigned char id[3];
      unsigned char prod[64];
    };
    
    int build_prod ()
    {
      struct _ethernet_prod ethernet_prod;
      
      int z[3];
      FILE *fp_src,*fp_dst;
        
      if ((fp_src=fopen(ETHER_SRC,"r"))==NULL)
      {
            fprintf (stderr,"Cannot read file \'%s\'. Abort!",ETHER_SRC);
            return 1;
      }
      if ((fp_dst=fopen(ETHER_DST,"w"))==NULL)
      {
            fprintf (stderr,"Cannot write file \'%s\'. Abort!",ETHER_DST);
            return 1;
      }
      
      fwrite (&n_prod,sizeof(int16_t),1,fp_dst);
      while (!feof(fp_src))
      {
            memset (&ethernet_prod, 0, sizeof (struct _ethernet_prod));
            if ((fscanf (fp_src,"%2X%2X%2X %63[^\n]s",&z[0],&z[1],&z[2],ethernet_prod.prod))>0)
            {
              ethernet_prod.id[0]=(char)(z[0] & 0xFF);
              ethernet_prod.id[1]=(char)(z[1] & 0xFF);
              ethernet_prod.id[2]=(char)(z[2] & 0xFF);
    
              fwrite (&ethernet_prod,1,sizeof(struct _ethernet_prod),fp_dst);
              n_prod++;
              
              #ifdef DEBUG
              printf ("%02X-%02X-%02X %s \n",z[0],z[1],z[2],ethernet_prod.prod);
              #endif
            }
      }
      fseek(fp_dst,0L, SEEK_SET);
      fwrite (&n_prod,sizeof(int16_t),1,fp_dst);
      
      fclose (fp_dst);
      fclose (fp_src);
      
      return 0;
    }
    
    void free_prod ()
    {
      if (prod)
      {
            free (prod);
            prod=NULL;
            n_prod=0;
      }
    }
    void alloc_prod ()
    {
      FILE *fp;
      int i=0;
      
      if ((fp=fopen(ETHER_DST,"r"))==NULL)
      {
            fprintf (stderr,"Cannot read file \'%s\'. Abort!",ETHER_DST);
            return;
      }
      fread (&n_prod,sizeof(int16_t),1,fp);
      
      if ((prod=malloc (n_prod*sizeof (struct _ethernet_prod))))
      {
            while (!feof(fp))
            {
              if ((fread (prod+i,1,sizeof(struct _ethernet_prod),fp))>0)
                    i+=sizeof(struct _ethernet_prod);
            }
      }
      fclose (fp);
    }
    
    unsigned char *search_prod (char a, char b, char c)
    {
      char x[3];
      int start=0,end=n_prod-1,pivot,r;
      struct _ethernet_prod ethernet_prod;
      
      x[0]=a; x[1]=b; x[2]=c;
      while (start<=end)
      {
            pivot=(start+end)/2;
            memcpy (&ethernet_prod,prod+(pivot*sizeof(struct _ethernet_prod)),sizeof(struct _ethernet_prod));
            if ((r=memcmp(&ethernet_prod,&x[0],3))==0)
              return (prod+(pivot*sizeof(struct _ethernet_prod)))+3;
            if (r<0)
              start=pivot+1;
            else
              end=pivot-1;
      }
      return (unsigned char *)"Unknow";
    
    }
    
    
    /*******************************************
     * MULTICAST ADDRESS
     ********************************************/
    struct _multicast_address
    {
      unsigned char id[6];
      short int len;
      unsigned int typefield;
      unsigned char prod[64];
    };
    
    static struct _multicast_address multicast_address[]=
    {
      { "\x01\x00\x0C\xCC\xCC\xCC"  ,6, 0x0802,"CDP (Cisco Discovery Protocol), VTP (VLAN Trunking Protocol)"},
      { "\x01\x00\x0C\xCC\xCC\xCD"  ,6, 0x0802,"Cisco Shared Spanning Tree Protocol Address"},
      { "\x01\x80\xC2\x00\x00\x00"  ,6, 0x0802,"Spanning Tree Protocol (for bridges) IEEE 802.1D"},
      { "\x01\x80\xC2\x00\x00\x08"  ,6, 0x0802,"Spanning Tree Protocol (for provider bridges) IEEE 802.1AD"},
      { "\x01\x80\xC2\x00\x00\x02"  ,6, 0x8809,"Ethernet OAM Protocol IEEE 802.3ah (A.K.A. \"slow protocols\""},
      { "\x01\x00\x5E"                              ,3, 0x0800,"IPv4 Nulticast (RFC 1112)"},
      { "\x33\x33"                                  ,2, 0x86DD,"IPv6 Nulticast (RFC 2464)"},
    };
    
    unsigned char *search_multicast (unsigned char address[6])
    {
      int i,end=sizeof(multicast_address)/sizeof(multicast_address[0]);
      for (i=0;i<end;i++)
            if (!strncmp (multicast_address[i].id,address,multicast_address[i].len))
              return multicast_address[i].prod;
      return (unsigned char *)"Multicast Unknow";
    }
    
    
    
    /**
    int main ()
    {
      //build_prod ();
      alloc_prod ();
      printf ("%s\n",search_prod (0x00,0x24,0x1D));
      free_prod ();
      return 0;
    }
    */
    connection closed by peer. Bye!
    [1]+  Done                    ./server
    max@studio:~> 
    
  • Re: [C] Leggere file comprese le tabulazioni

    Ciao.
    Scusa la mancanza di precisione nell'esposizione.
    Ecco qua:

    Le tabulazioni rigurdavano un file precedente. Nell'ultimo thread sto parlando di leggere e scrivere in binario un file su due diversi pc. Quindi ad esempio un'immagine jpg. Utilizzo "append" perchè penso che sia necesario ogni volta che ricevo "un pezzo del file" aggiungerlo dopo i pezzi ricevuti precedentemente al nuovo file.

    Il programma si compila senza warning. Non incontra nessun errore in runtime che ne causi la chiusura. Semplicemente il file ricevuto ha dimensione ridotta rispetto all'originale. Ad esmepio invece di 4 MB è grosso 64 kb.
    Dopo questa ricezione il programma prosegue la sua normale esecuzione.

    A presto
  • Re: [C] Leggere file comprese le tabulazioni

    Ciao Ananke Melior,
    Nell'ultimo thread sto parlando di leggere e scrivere in binario un file su due diversi pc
    allora si deve usare fread/fwrite...

    client patch:
    
      ...
      /**
       *
       * 
       * patching 4U
       * 
       * 
       */
      #include <errno.h>
      #define dwfile_name "foo"
      int remoteSocket=sock;
      FILE *dwfile;
      if ((dwfile=fopen (dwfile_name,"rb"))==NULL)
      {
        fprintf (stderr,"Cannot read `%s` file\n",dwfile_name);
        perror ("Error");
        return -1;
      } 
      //
      // Leggo fino a end-of-file o errore
      while ((len=fread(block,1,BLOCK_SIZE,dwfile))>0)   
      {
        //
        // Invio. Se errore esco
        if ((send(remoteSocket, block,len,0))!= len)
          break;
      }
      if (errno)
        perror ("Uh-oh...");
      
      freeaddrinfo(servinfo);
      close (sock);
     
      return 0;
    
    }
    
    patch server:
    
      ...
    /**
       *
       * 
       * patching 4U
       * 
       * 
       */
      
      #define dwfile_name "foo.new"
      FILE *dwfile;
      if ((dwfile=fopen (dwfile_name,"wb"))==NULL)
      {
             fprintf (stderr,"Cannot write `%s` file\n",dwfile_name);
             perror ("Error");
             return -1;
      }
      while ((len=recv(client_sock, block, sizeof(block)-1, 0))>0)
      {
        if ((fwrite (block,1,len,dwfile))!=len)
          break;
      }
      if (len<0)
        perror ("recv");
      else if  (len==0)
        printf ("connection closed by peer. Bye!\n");
      else
        printf ("connection closed\n");
     
      fclose (dwfile);
      close (client_sock);
      close (sock_in);
      
      return 0;
    }
    
    term:
    
    max@studio:~># creo un link simbolico all'eseguibile 'grep'
    max@studio:~> ln -s /bin/grep foo
    max@studio:~># eseguo server in background
    max@studio:~> ./server &
    [1] 2585
    Waiting connection....
    max@studio:~># eseguo client
    max@studio:~> ./client localhost
    try connecting to 127.0.0.1 port 7777...
    Good one. Done
    done
    max@studio:~> connection closed by peer. Bye!
    
    [1]+  Done                    ./server
    
    max@studio:~># verifico le dimensioni dei 2 binari
    max@studio:~> ll /bin/grep foo.new
    -rwxr-xr-x 1 root root  130664 18 feb  2011 /bin/grep
    -rw-r--r-- 1 max  users 130664 16 set 15.16 foo.new
    max@studio:~># abilito il bit di esecuozione per l'utente su foo.new 
    max@studio:~> chmod u+x foo.new
    max@studio:~>#eseguo il binario
    max@studio:~> ./foo.new 
    Uso: ./foo.new [OPZIONE]... MODELLO [FILE]...
    Usare "./foo.new --help" per ulteriori informazioni.
    max@studio:~> 
    
    Attenzione! nel mio caso il client chiude la connessione dopo l'invio del file, il server intercetta la chiusura ed esce da giro di ricezione. Se la connessione rimanere aperta il server non capisce quando il file è terminato e rimane in attesa sulla recv.
    Un modo semplice per ovviare al problema consiste di inviare una stringa di informazione sul NOME e DIMENSIONE prima del trasferimento (quello che più o meno fa HTTP (vedi RFC 2616 sezioni 4.4, 9.3 e 14.13)).

    Thread chiuso per OT
    ~Max
Devi accedere o registrarti per scrivere nel forum
11 risposte