PDA

Visualizza la versione completa : [C] Problema con struttura di controllo if else


viridovix
11-08-2005, 15:21
IL codice in C gira sotto Linux 9.2, compilatore gcc.
Si tratta sempre di un client e server connessi tra loro tramite socket, con protocollo tcp.

qui riporto la parte del server con la struttura if:




char x[1024],y[1024];
unsigned char z,w;
char buf[1024];
char buf2[1024];
do
{
send(ds_sock_acc,"\nInserisci fila :",20,0);
recv(ds_sock_acc,&x,2,0);
printf("%s",&x);
if ((strcmp(x,"A")!=0)||(strcmp(x,"B")!=0)||(strcmp(x,"C")!=0))
{
send(ds_sock_acc,"\nfila inesistente\n",30,0);
}
else (strcpy(buf,"fatto"));
}
while (strcmp(buf,"fatto")!=0);


purtroppo nn so perchè questo nn funziona :
if ((strcmp(x,"A")!=0)||(strcmp(x,"B")!=0)||(strcmp(x,"C")!=0))

se inserisco dal client il carattere A o B o C comunque sia il sever spedisce il messaggio fila inesistente.

modificando cosi' riconosce invece ol carattere A:

if ((strcmp(x,"A")!=0)
{
send(ds_sock_acc,"\nfila inesistente\n",30,0);
}

ma ovviamente nn mi fa gli altri confronti
se modifico ulteriormente cosi

if ((strcmp(x,"A")!=0)
{
send(ds_sock_acc,"\nfila inesistente\n",30,0);
}

else if (strcmp(x,"B")!=0)
{
send(ds_sock_acc,"\nfila inesistente\n",30,0);
}

ritorno al problema iniziale qualsiasi carattrere invio da client poi il server spedisce il messaggio fila inesistente.

nn riesco a capire dove sia la magagna :(

DydBoy
11-08-2005, 15:44
Sintassi del recv :


int recv(int s, void *buf, size_t len, int flags);

La tua chiamata dovrebbe essere :



recv(ds_sock_acc,x,2,0);


x e' un puntatore a char, cosi' invece con il &x gli passi l'indirizzo del puntatore (andrebbe bene se la funzione riceveva un **buf).

Una volta presi i due caratteri il controllo nell'if provalo cosi :



if (x[0] =='A' ||x[0] == 'B' || x[0] == 'C')
strcpy(buf,"fatto")
else
send(ds_sock_acc,"\nfila inesistente\n",30,0);



Spero vada bene...

Ciau
:ciauz:

tia86
11-08-2005, 15:55
Originariamente inviato da DydBoy


x e' un puntatore a char, cosi' invece con il &x gli passi l'indirizzo del puntatore (andrebbe bene se la funzione riceveva un **buf).



x è un array di char, quindi se metti x senza parentesi quadre passi alla funzione l'indirizzo di x.
In pratica mettere x o &x in questo caso è la stessa cosa.

DydBoy
11-08-2005, 16:11
x e' un puntatore al primo char dell'array.

Il valore quindi di "x" e' l'indirizzo di memoria del primo char del buffer.

Il valore invece di "&x" e' l'indirizzo del puntatore al primo char del buffer.

Dato che la recv prende come parametro un indirizzo ci va "x" e non "&x".

Non capisco perche' tu dica che sono la stessa cosa.

Se cosi' fosse perdonami ma sono curioso di sapere il perche'.

Ciau! :)

tia86
11-08-2005, 16:22
Allora, x non è un puntatore, ma un array.
x quindi è un indirizzo di memoria in cui dentro c'è il primo carattere del buffer.

Quindi &x[0] è uguale a &x anchesso uguale a x

Fa una prova:



char a[] = "ciao";

printf("%p \n",a);
printf("%p \n",&a);
printf("%p \n",&a[0]);




0022FF60
0022FF60
0022FF60
Premere un tasto per continuare . . .


cvd

DydBoy
11-08-2005, 17:00
Non si finisce mai di imparare, ho sempre considerato un'array come un puntatore costante al primo elemento di un buffer.



Quindi &x[0] è uguale a &x anchesso uguale a x


D'accordissimo. Però sapevo solo la parte &x[0] = x e non del &x.

Bè, che dire, grazie della dritta!

DydBoy
11-08-2005, 17:27
Uhm...è tutto esattamente come dici tu però non mi spiego ancora molto il perchè!

Tratto dal Deitel & Deitel "Fondamenti di programmazione C++" :



Array e puntatori sono strettamente correlati in C++ e possono essere utilizzati in modo equivalente.
Il nome di un array è in realtà un puntatore costante.
Supponiamo di dichiarare l'array di interi b[5] e la variabile puntatore bptr.Il nome dell'array b senza indici è un puntatore al primo elemento dell'array.
.

Questo riporta il Deitel e questo sapevo, solo che non mi spiego perchè &b = b !!!

tia86
11-08-2005, 18:03
La spiegazione è un pò complicata e va a toccare come gestisce il compilatore le varibili gli indirizzi ecc... ma cercherò di essere chiaro.

Quando tu dichiari

char a[5];

il compilatore riserva 5 byte nella ram. Ora tu ti aspetteresti che l'indirizzo del primo byte vada a finire in un'altra cella di memoria (il cosidetto puntatore ad 'a'). In realtà non è cosi.
Il compilatore si ricorda qual'è l'indirizzo di &a[0] ed ogni volta che incontra ad es.

a[2] = 'd';

lui somma l'indirizzo che ha in memoria (&a[0]) con 2 (l'offset) e crea il codice asm che il computer dovrà eseguire



In molto pseudo ASM

metti &a[2] in 0x0c
metti 'd' nell'accumulatore
mouvi il contenuto dell'accumulatore all'indirizzo *puntato* da 0x0c


Come vedi viene creato un puntatore (all'indirizzo 0x0c) ma che muore subito dopo.

Stessa cosa (ma non te la sto a scrivere in preudo asm perchè non ho voglia :P) se hai

while(i){
a[i]= i;
i--;
}

In pratica quando lui vede la variabile a sostituisce ad essa il suo indirizzo per poi sommarlo all'eventuale offset.
Quindi se a diventa (ad es.) 0x0A

fare &a vuol dire fare &0x0A e l'indirizzo di 0x0A è 0x0A! :)

DydBoy
11-08-2005, 18:23
Grazie mille tia, giuro che da solo non ci sarei mai arrivato anche perchè nelle varie manualistiche non ho mai trovato questa descrizione dell'argomento.

Molto interessante.

Ciao e grazie

:)

tia86
11-08-2005, 21:13
Originariamente inviato da DydBoy
Grazie mille tia, giuro che da solo non ci sarei mai arrivato anche perchè nelle varie manualistiche non ho mai trovato questa descrizione dell'argomento.

Molto interessante.

Ciao e grazie

:)

Prego.
Purtroppo nessun manuale va fino in fondo, perchè risulterebbe troppo complesso e lungo.

:ciauz:

Loading