Newsgroup: it.comp.lang.c
Titolo: Confrontare i valori di una struttura

Buon anno a tutti.
Ringrazio Cybertoldo per i consigli che mi ha dato per risolvere il mio 
problema.
Ora il mio problema e' devo confrontare gli indirizzi ip memorizzati 
nella struttura, ad esempio:
111.22.3.44   claudio
555.66.7.88   vincenzo
111.22.5.66   matteo
e se i primi due componeti sono uguali (111.22 in questo caso), gli 
utenti 'matteo' e 'claudio' fanno parte della stessa rete.
Qndi come faccio ?
Un grazie anticipato
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define NICK_LEN 10     /* Memoria allocata dall'unita' nick_name */
#define MAX_ADDRESS 100 /* Numero massimo di indirizzi ip */
typedef struct{
         int xx,
             yy,
             zz,
             mm;
         char nick_name[NICK_LEN];
         }address_t;
void carica_ip(FILE *fileip, address_t *address_ip, int dimensione);
void visualizza_file_ip(FILE *fileip, address_t *tmp);
int main(){
     address_t address[MAX_ADDRESS];
     int dimensione;
     int risposta;
     FILE *fileip;
     /* Inizio menu */
     do{
         printf("\n");
         printf("1. Inserisci gli indirizzi ip\n");
         printf("2. Visualizza gli indirizzi ip\n");
         printf("3. \n");
         printf("4. Uscita\n\n");
         printf("\nEffettua la tua scelta: ");
         scanf("%d", &risposta);
         switch(risposta){
              case 1:
                   printf("Quanti indirizzi ip vuoi inserire ?");
                   scanf("%d", &dimensione);
                   carica_ip(fileip, address, dimensione);
                   break;
              case 2:
                   printf("***INDIRIZZI IP CARICATI***\n");
                   visualizza_file_ip(fileip, address);
                   break;
              case 3:
                   printf("jk229");
                   break;
         }//fine switch
     }//fine do
     while(risposta != 4);
     system("PAUSE");
     return 0;
}
void carica_ip(FILE *fileip, address_t *address_ip, int dimensione){
      int i;
      fileip = fopen("indirizzi_ip.dat", "w");
      if(fileip == NULL){
          printf("Errore nell'apertura del file in scrittura");
      }
      else
          for(i = 0; i < dimensione; i++){
              fflush(stdin);
              printf("xx: ");
              scanf("%d", &address_ip[i].xx);
              fflush(stdin);
              printf("yy: ");
              scanf("%d", &address_ip[i].yy);
              fflush(stdin);
              printf("zz: ");
              scanf("%d", &address_ip[i].zz);
              fflush(stdin);
              printf("mm: ");
              scanf("%d", &address_ip[i].mm);
              fflush(stdin);
              printf("Nome Utente: ");
              gets(address_ip[i].nick_name);
              fflush(stdin);
              fprintf(fileip, "%d %d %d %d %s\n", address_ip[i].xx,
                                                  address_ip[i].yy,
                                                  address_ip[i].zz,
                                                  address_ip[i].mm,
 
address_ip[i].nick_name);
          }// fine for
          fclose(fileip);
}
void visualizza_file_ip(FILE *fileip, address_t *tmp){
      fileip = fopen("indirizzi_ip.dat", "r");
      if(fileip == NULL){
          printf("Errore nell'apertura del file in lettura.");
      }
      else{
           fscanf(fileip,"%d %d %d %d %s",&(*tmp).xx,
                                          &(*tmp).yy,
                                          &(*tmp).zz,
                                          &(*tmp).mm,
                                          &(*tmp).nick_name);
          printf("Indirizzo Ip,Nome Utente\n");
          while(!feof(fileip)){
              printf("-----------------\n");
              printf("%d.%d.%d.%d,%s\n", (*tmp).xx,
                                         (*tmp).yy,
                                         (*tmp).zz,
                                         (*tmp).mm,
                                         (*tmp).nick_name);
              printf("-----------------\n");
              fscanf(fileip,"%d %d %d %d %s",&(*tmp).xx,
                                             &(*tmp).yy,
                                             &(*tmp).zz,
                                             &(*tmp).mm,
                                             &(*tmp).nick_name);
          }
      }
      fclose(fileip);
      return;
}

 utenti 'matteo' e 'claudio' fanno parte della stessa rete.
e... il programma che deve fare?
Posta almeno il testo "esatto" dell'esercizio (spero che sia piu' preciso).
Ciao
-- 
Cybertoldo
Per rispondermi via email, sostituisci moc.liamg con 
gmail.com

 
Ciao Cybertoldo.
Scusami effettivamente non sono stato chiaro. Ti posto il testo esatto 
dell'esercizio.
Spero che tu possa aiutarmi.
Ciao
Numeric addresses for computers on the international network Internet 
are composed of four parts, separated by periods, of the form
xx.yy.zz.mm
where xx, yy, zz, and mm are positive integers. Locally, computers are 
usually known by a nickname as well. You are designing a program to 
process a list of Internet addresses, identifying all pairs of computers 
from the same locality. Create a structure type called address_t with 
components for the four integers of an Internet address and a fifth 
component in which to store an associated nickname of 10 characters. 
Your program should read a list of up to 100 addresses and nicknames 
terminated by a sentinel address of all zeros and a sentinel nickname.
Sample Data
111.22.3.44	platte
555.66.7.88	wabash
111.22.5.66	green
0.0.0.0	        none
The program should display a list of messages identifying each pair of 
computers from the same località — that is, each pair of computers with 
matching values in the first two components of the address. In the 
messages, the computers should be identified by their nicknames.
Example Message
Machines platte and green are on the same local network.
Follow the messages by a display of the full hst of addresses and 
nicknames. Include in your program a scanaddress function, a print 
address function, and a local_address function. Function local_address 
should take two address structures as input parameters and return 1 (for 
true) if the addresses are on the same local network, and 0 (for false) 
otherwise.

 otherwise.
Qui mi vengono i dubbi.
Perche' "each pair of computers"? Nel file potremmo trovare piu' di 2 
macchine appartenenti alla stessa localita' (vedi esempi sotto). Nel 
testo ho invece inteso che vanno trattati e visualizzati "per coppia" 
(ovvero, la cosa piu' logica forse sarebbe stata quella di scrivere, per 
esempio, nel caso di 3: "Machines pippo, pluto and paperino are on the 
same local network.").
Ma fosse cosi' (per coppia), mettiamo il caso che il file contenga 
questi host di esempio:
222.66.0.1 pippo
222.66.0.2 pluto
222.66.1.1 paperino
111.22.3.44 platte
111.22.5.66 green
1.0.0.1 sola
0.0.0.0 none
...il programma dovrebbe stampare questo?
=== ESEMPIO 1 =============================
Machines pippo and pluto are on the same local network.
Machines pippo and paperino are on the same local network.
Machines pluto and pippo are on the same local network.
Machines pluto and paperino are on the same local network.
Machines paperino and pippo are on the same local network.
Machines paperino and pluto are on the same local network.
Machines platte and green are on the same local network.
Machines green and platte are on the same local network.
222.66.0.1 pippo
222.66.0.2 pluto
222.66.1.1 paperino
111.22.3.44 platte
111.22.5.66 green
1.0.0.1 sola
================================
...oppure dovrebbe stampare questo? (evitando di ripetere le coppie gia' 
scritte)
=== ESEMPIO 2 =============================
Machines pippo and pluto are on the same local network.
Machines pippo and paperino are on the same local network.
Machines pluto and paperino are on the same local network.
Machines platte and green are on the same local network.
222.66.0.1 pippo
222.66.0.2 pluto
222.66.1.1 paperino
111.22.3.44 platte
111.22.5.66 green
1.0.0.1 sola
================================
Risolvimi i dubbi - o dimmi cosa vuoi che il programma stampi. Poi, se 
trovo un po' tempo, guardo cosa posso fare...
PS: ma l'hai tradotto tu in inglese? :)


 
Si hai perfettamente ragione la logica sarebbe stata quella di scrivere 
Machines pippo, pluto and paperino are on the same local network.
credo cmq sia meglio evitare i duplicati. Mi sembra piu' pulito

No nn l'ho tradotto io, il libro che usiamo e' in inglese.
Ciao e grazie ancora. :)

 credo cmq sia meglio evitare i duplicati. Mi sembra piu' pulito
ok
non mi sembra difficile: vedo se riesco a trovare un'oretta di tempo 
libero (sempre + raro)
ciao


 1.0.0.1 sola 
Allora, questo e' il formato del file d'input (un esempio):
-- file: indirizzi_ip.dat ----
222.66.0.1  pippo
222.66.0.2  pluto
222.66.1.1  paperino
111.22.3.44 platte
111.22.5.66 green
1.0.0.1     sola
0.0.0.0     none
-----------------------------
...e piu' sotto c'e' il programmino.
Ho trovato un po' di tempo, come al solito, solo dopo messa a letto la 
famiglia (e riempita la calza al bimbo :) )... ma ho dovuto stenderlo 
giu' abbastanza velocemente. Spero che non abbia grossi errori - e cmq 
ci affidiamo al controllo del ng ;) (quindi continua a seguire il 
thread). Mi auguro che ti possa servire almeno come esempio.
PS: I commenti sono quasi inesistenti. Tu esaminalo ed eventualmente 
chiedi quello che non hai capito.
(l'indentazione - tab a 8 - probabilmente verra' persa con l'invio del post)
Ciao
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NICK_LEN 10        /* Lunghezza max. stringa nickname */
#define MAX_ADDRESS 100    /* Numero massimo di indirizzi ip */
#define SENTINEL_NICKNAME  "none" /* nick-name sentinella */
/* range min/max singolo ottetto di un ip-address */
#define VALID_IP_OCTET(n) ((n) >= 0 && (n) <= 0xff)
/* vedi C-FAQ: 
http://c-faq.com/stdio/scanfvwid.html
 */
#define Str(x) #x
#define Xstr(x) Str(x)
typedef struct tag_address {
	int xx, yy, zz, mm;
	char nick_name[NICK_LEN+1];
}	
	address_t,
	*paddress_t;
int is_empty_string(const char *pString)
{
	while (isspace(*pString))
		++pString;
	return (!*pString);
}
int local_address(paddress_t pAddr1, paddress_t pAddr2)
{	
	int bRes = 0;
	if(pAddr1 && pAddr2)
		bRes = (pAddr1->xx == pAddr2->xx) && (pAddr1->yy == pAddr2->yy);
	return bRes;
}
void empty_addresses(paddress_t *apAddresses)
{	
	int i;
	for(i = 0; apAddresses[i]; i++)
	{	free(apAddresses[i]);
		apAddresses[i] = NULL;
	}
}
int scanaddress(paddress_t *apAddresses, FILE *fp, int nMaxNumAddr)
{	
	char bfLine[1024];
	long lLineNum;
	int  nAddresses = 0;
	int  nRet = -1;
	clearerr(fp);
	/* trova il primo libero (append degli indirizzi) */
	for(nAddresses = 0; nAddresses < nMaxNumAddr && 
apAddresses[nAddresses]; nAddresses++)
		;
	for(lLineNum = 1L; nAddresses < nMaxNumAddr && fgets(bfLine, 
sizeof(bfLine), fp); lLineNum++)
	{	address_t Addr;
		int n, bValidLine = 0;
		if(is_empty_string(bfLine))
			continue; /* linea vuota: ignora/non da' errore */
		memset(&Addr, 0, sizeof(Addr));
		/* qui potrebbe essere implementato un miglior controllo, cmq.: */
		/* si limita la lung. nick_name a NICK_LEN car. (ma tronca se + lungo); */
		/* in nick_name si accetta solo il set di caratteri A...Z, a...z, '_' 
e '-' */
		n = sscanf(bfLine, "%d.%d.%d.%d %" Xstr(NICK_LEN) "[a-zA-Z_-]", 
&Addr.xx, &Addr.yy, &Addr.zz, &Addr.mm, Addr.nick_name);
		if(n == 5 && VALID_IP_OCTET(Addr.xx) && VALID_IP_OCTET(Addr.yy) && 
VALID_IP_OCTET(Addr.zz) && VALID_IP_OCTET(Addr.mm))
			bValidLine = 1;
		/* verificato che i singoli ottetti non possano essere < 0 o > 255, */
		/* si puo' usare la loro somma come controllo == 0 */
		if(bValidLine && (Addr.xx + Addr.yy + Addr.zz + Addr.mm) == 0 && 
strcmp(Addr.nick_name, SENTINEL_NICKNAME) == 0)
			break;  /* trovate le sentinel richieste dal testo */
		if(bValidLine)
		{	paddress_t pNewAddr;
			if(!(pNewAddr = malloc(sizeof(*pNewAddr))))
				return nRet;
			memcpy(pNewAddr, &Addr, sizeof(*pNewAddr));
			apAddresses[nAddresses] = pNewAddr;
			nAddresses++;
		}
		/* semplifico, ma una printf direttamente qui non dovrebbe esserci: */
		/* non si separa questa funzione dall'interfaccia utente */
		else	printf("** Invalid address line (%ld)\n", lLineNum);
	}
	if(ferror(fp))
		nRet = -2;
	else	nRet = nAddresses;
	return nRet;
}
void load_addresses(paddress_t *apAddresses, const char * const 
pFileIndirizzi, int nMaxNumAddr)
{	
	FILE *fp;
	printf("Reading addresses from file %s...\n", pFileIndirizzi);
	if((fp = fopen(pFileIndirizzi, "rt")))
	{	int nRes;
		if((nRes = scanaddress(apAddresses, fp, nMaxNumAddr)) < 0)
			printf("** Error: function scanaddress().\n");
		else	printf("Loaded %d address(es)\n", nRes);
		fclose(fp);
	}
	else	printf("** Error: cannot open file %s\n", pFileIndirizzi);
}
void manual_append_addresses(paddress_t *apAddresses, int nMaxNumAddr)
{	
	const char * const pPrompt = ""
		">> Input one or more line with: ip-address<space>nick-name<enter>\n"
		">> (eg.: 1.2.3.4 hostname).\n"
		">> End the input list with: 0.0.0.0 %s\n"
		">> or with EOF char\n"; /* crtl-d su unix, ctrl-z su dos/win */
	int nRes;
	printf(pPrompt, SENTINEL_NICKNAME);
	if((nRes = scanaddress(apAddresses, stdin, nMaxNumAddr)) < 0)
		printf("** Error: function scanaddress().\n");
	else	printf("Now, the list has %d addresses.\n", nRes);
}
void print_address(paddress_t pAddr)
{	
	if(pAddr)
		printf("%d.%d.%d.%d %s\n", pAddr->xx, pAddr->yy, pAddr->zz, pAddr->mm, 
pAddr->nick_name);
}
void print_list(paddress_t *apAddresses)
{	
	int i;
	puts("--- Machines ---");
	for(i = 0; (apAddresses[i]); i++)
		print_address(apAddresses[i]);
	if(i <= 0)
		puts("(empty list)");
}
int print_local_addresses(paddress_t *apAddresses)
{	paddress_t pAddr1, pAddr2;
	int n, i, nFound = 0;
	puts("--- Matches ---");
	for(n = 0; (pAddr1 = apAddresses[n]); n++)
	{	for(i = n+1; (pAddr2 = apAddresses[i]); i++)
			if(local_address(pAddr1, pAddr2))
			{	printf("- Machines '%s' and '%s' are on the same local network.\n",
					pAddr1->nick_name,
					pAddr2->nick_name
				);
				nFound++;
			}
	}
	if(nFound <= 0)
		printf("(no machines found on the same local network)\n");
	puts("");
	return nFound;
}
int prompt_menu(const char * const pPrompt)
{	
	char bf[128];
	int  nRes = 0;
	if(pPrompt)
		printf("\n%s\n", pPrompt);
	while(fgets(bf, sizeof(bf), stdin))
	{	nRes = 0;
		if(1 == sscanf(bf, "%d", &nRes))
			break;
	}
	return nRes; /* restituisce 0 anche su EOF */
}
int main(void)
{
	enum { MNU_EXIT, MNU_MANUALINS, MNU_LOAD, MNU_PRINT, MNU_EMPTYLIST=9 };
	const char * const pFileIndirizzi = "indirizzi_ip.dat";
	const char * const pPromptMenu = ""
		"Main menu:\n"
		"\t1) manual insert/append\n"
		"\t2) load from file\n"
		"\t3) print\n"
		"\t9) empty list\n"
		"\t0) exit";
	/* array di puntatori, elenco terminato da NULL: */
	paddress_t apAddresses[MAX_ADDRESS+1];
	int nChoice;
	memset(apAddresses, 0, sizeof(apAddresses)); /* inizializza array */
	while((nChoice = prompt_menu(pPromptMenu)) != MNU_EXIT)
	{	
		switch(nChoice)
		{	
			case MNU_MANUALINS:
				manual_append_addresses(apAddresses, MAX_ADDRESS);
				break;
			case MNU_LOAD:	
				empty_addresses(apAddresses); /* svuota la lista */
				load_addresses(apAddresses, pFileIndirizzi, MAX_ADDRESS);
				break;
			case MNU_PRINT:
				print_local_addresses(apAddresses);
				print_list(apAddresses);
				break;
			case MNU_EMPTYLIST:
				empty_addresses(apAddresses); /* svuota la lista */
				break;
			default:
				puts("** invalid choice - please retry");
				break;
		}
	}
	puts("Bye!");
	empty_addresses(apAddresses); /* svuota e libera la memoria */
	return 0;



[...]
Piccola nota: un "0-filling" della memoria non garantisce che il
puntatore sia impostato al "null-pointer".
In passato mi č capitato di inizializzare i puntatori in
questo modo, ma non č portabile al 100%.
--
Giorgio Silvestri
DSP/Embedded/Real Time OS   Software Engineer

 questo modo, ma non è portabile al 100%.
A me e' successo l'esatto contrario. In passato inizializzavo sempre, 
con la costante NULL, tutti i puntatori (anche dopo una eventuale memset 
o una calloc). Poi ho perso questa buona pratica man mano negli anni: 
sui "normali" sistemi dove portavo il mio codice, trovarsi ad avere a 
che fare con puntatori NULL con valore diverso da 0, era il piu' 
improbabile tra i rischi...
Il problema e' che, una volta avvezzi ad alcune liceita', poi rimane 
istintivo scriverle di getto: brutte abitudini! :)
Ciao
