PDA

View Full Version : esercizio C


nicod83
16-03-2007, 10:43
ciao ragazzi!
ho un problema con il seguente esercizio
qualcuno può darmi una mano? grazie!

TESTO
Si inizializzi la variabie intera 'a' in modo che il ciclo while esegua un
numero
finito di iterazioni e venga prodotta la stampa a video della stringa "X11"
(doppi apici esclusi).
Si commenti la soluzione. Alternativamente si sarebbe potuto stampare con
lo
stessa metodo la stringa "X-11"?

int main()
{
int a=...;
char* p=&a;
while(*p)
{
printf("%c",*p);
p++;
}
printf("\nFatto!");
}

andbin
16-03-2007, 11:15
TESTO
Si inizializzi la variabie intera 'a' in modo che il ciclo while esegua un
numero
finito di iterazioni e venga prodotta la stampa a video della stringa "X11"
(doppi apici esclusi).
Si commenti la soluzione. Alternativamente si sarebbe potuto stampare con
lo
stessa metodo la stringa "X-11"?Uhm ... non è affatto chiaro! (almeno per me).
La stringa "X11" deve essere stampata in virtù di che cosa?? Cioè in che modo deve essere prodotta??


int main()
{
int a=...;
char* p=&a;
while(*p)
{
printf("%c",*p);
p++;
}
printf("\nFatto!");
}Questo codice non ha molto senso. Poi comunque quando fai p++ incrementi il puntatore 'p', che quindi va a puntare non più ad 'a' ma a ... qualcos'altro dopo.
E tra l'altro 'p' è un puntatore a char mentre tu assegni a 'p' l'indirizzo di un int ...

nicod83
16-03-2007, 12:14
è un esempio di esercizio d'esame...

lo so.. è quello il problema... p??
qualcuno ha qualche idea?

RaouL_BennetH
16-03-2007, 12:33
è un esempio di esercizio d'esame...

lo so.. è quello il problema... p??
qualcuno ha qualche idea?

Oltre al codice che se è un esempio credo di poter affermare che è un pessimo esempio, la domanda rimane la stessa, ovvero, la stringa in che modo dev'essere prodotta?

Mi spiego:

Hai una serie di stringhe e devi scegliere "X11";
Devi scorrere tutti i caratteri dell'alfabeto sino a raggiungere prima 'X', poi '1' e poi '1' (oppure '11') e metterli insieme per formare la stringa;
Devi estrapolarla da una stringa già esistente (ed eventualmente aggiungerci il carattere '-' in modo da farla diventare 'X-11').

etc..

Cioè, se ti hanno posto questo problema, te lo hanno posto in un modo tutt'altro che chiaro :)

andbin
16-03-2007, 12:34
qualcuno ha qualche idea?Ripeto: dovresti spiegare meglio in che modo deve essere prodotta in output la stringa.

nicod83
16-03-2007, 12:45
questo esercizio era sul file di esercizio proposti per l'esame...

non ci sono altre istruzioni..
bisogna inizializzare la variabile "a" e produrre in output 3 caratteri formando "X11"

andbin
16-03-2007, 13:01
questo esercizio era sul file di esercizio proposti per l'esame...

non ci sono altre istruzioni..
bisogna inizializzare la variabile "a" e produrre in output 3 caratteri formando "X11"Sì ma ... 'a' di che tipo deve essere?? char? int? E devi basarti solo su questa variabile per il test del while e per mandare in output i caratteri??

repne scasb
16-03-2007, 13:09
Come gia' fatto notare l'esercizio e' tutt'altro che chiaro e merita una risposta "sciocca":


#include <stdio.h>

void main(void)

{
int a=10;

while (a--);

printf("X11");
}

mfonz85
16-03-2007, 13:28
Boh! Esercizio stranissimo :eek:


int main()
{
int a=88;
char* p= &a;
while(*p) {
printf("%c",*p);
if( *p == 49 ) { printf("%c",*p); *p = 0; }
if( *p == 88 ) *p = 49;
}
printf("\nFatto!");
system("pause");
}


Ho inizializzato a ad 88, ma dentro il while ho dovuto fare 2 if :mbe:

P.S ah, e il gcc ovviamente da buon compilatore mi dice
Warning: inizialization from incompatible pointer type @line char* p= &a;
Non si possono fare giochetti del genere con puntatori a int e char, questo funziona solo per coincidenza...perchè lavoriamo su interi sempre minori di 255 (quindi rappresentabili su carattere ASCII)

andbin
16-03-2007, 13:39
Sorgente meno "banale"???
Questo:
#include <stdio.h>

int main (void)
{
int a = 88;

while (a) {
printf ("%c", (char) a);
a = a == 88 ? 49 : a == 49 ? 305 : 0;
}

printf ("\n");
return 0;
}Però mi sembra quasi più roba da IOCCC (http://www.ioccc.org) che un esercizio! :D :p

pierosa
16-03-2007, 13:40
int main()
{
int a= 3223896;
char* p=&a;
while(*p)
{
printf("%c",*p);
p++;
}
printf("\nFatto!");
}


prova così

EDIT: ho corretto prima stampava W11 ora stampa X11 come avevi chiesto

mfonz85
16-03-2007, 14:32
int main()
{
int a= 3223896;
char* p=&a;
while(*p)
{
printf("%c",*p);
p++;
}
printf("\nFatto!");
}



Ok, spiegaci :eek:
Hai sfruttato gli overflow??



a = a == 88 ? 49 : a == 49 ? 305 : 0;



Cos'è sta roba?? :eek:

pierosa
16-03-2007, 15:07
Ok, spiegaci :eek:
Hai sfruttato gli overflow??

in c un char è composto da un byte dunque 8 bit.
il codice ascii di X è 88 che in binario è 1011000 (01011000 aggiungiamo uno 0 all'inizio per ottenere 8 bit)
il codice ascii di 1 è 49 che in binario è 110001 (00110001 come sopra)
un intero a 32 bit può dunque contenere 4 caratteri, che sono necessari per contenere la string "X11\0", il carattere \0 è necessario per delimitare la fine della stringa.
ora dobbiamo trovare un intero che sia rappresentato in memoria nello stesso modo della stringa "X11\0", siccome i byte degli interi in memoria vengono invertiti l'intero che stiamo cercando è questo
00000000 00110001 00110001 01011000 (in binario, ho separato i byte con uno spazio)
3223896 (in decimale)
assegnando l'indirizzo di questo numero ad un puntatore a carattere (p nel nostro esercizio) questo conterrà l'indirizzo del primo byte di a che rappresenta la W. Per l'aritmetica dei puntatori in c, p++ passa al prossimo byte (perchè p è dichiarato come puntatore a char, se fosse stato dichiarato come puntatore ad int non avrebbe funzionato).

mfonz85
16-03-2007, 15:09
in c un char è composto da un byte dunque 8 bit.
il codice ascii di X è 88 che in binario è 1011000 (01011000 aggiungiamo uno 0 all'inizio per ottenere 8 bit)
il codice ascii di 1 è 49 che in binario è 110001 (00110001 come sopra)
un intero a 32 bit può dunque contenere 4 caratteri, che sono necessari per contenere la string "X11\0", il carattere \0 è necessario per delimitare la fine della stringa.
ora dobbiamo trovare un intero che sia rappresentato in memoria nello stesso modo della stringa "X11\0", siccome i byte degli interi in memoria vengono invertiti l'intero che stiamo cercando è questo
00000000 00110001 00110001 01011000 (in binario, ho separato i byte con uno spazio)
3223896 (in decimale)
assegnando l'indirizzo di questo numero ad un puntatore a carattere (p nel nostro esercizio) questo conterrà l'indirizzo del primo byte di a che rappresenta la W. Per l'aritmetica dei puntatori in c, p++ passa al prossimo byte (perchè p è dichiarato come puntatore a char, se fosse stato dichiarato come puntatore ad int non avrebbe funzionato).

grande, che pensata :eek:

RaouL_BennetH
16-03-2007, 15:10
Ok, spiegaci :eek:

Cos'è sta roba?? :eek:

E' l'utilizzo degli operatori ternari in C.

per esempio:





if( a > b)
{
c = a;
}
else
{
c = b;
}

//si può anche scrivere:

c = (a > b) ? a : b;

andbin
16-03-2007, 15:10
Ok, spiegaci :eek:
Hai sfruttato gli overflow??overflow?? No no.
pierosa ha sfruttato il fatto che il numero decimale 3223896 in esadecimale è 313158h e siccome sulle architetture Intel che sono "little-endian" i byte sono memorizzati dal meno significativo al più significativo, in memoria il valore intero è memorizzato come:

58h 31h 31h 00h
dove i 3 valori sono appunto i codici ASCII dei caratteri X 1 1
Con 'p' punta ai singoli byte che compongono l'intero. L'ultimo è appunto nullo quindi fa da terminatore

Cos'è sta roba?? :eek:Io invece ho usato una strada diversa. ?: è un operatore ternario. La mia espressione è equivalente a:
if (a == 89)
a = 49;
else if (a == 49)
a = 305;
else
a = 0;Anche qui uso i codici ASCII dei caratteri ma dal momento che si devono stampare due '1', devo differenziarli. 305 in hex è 131h, castato a (char) vale solo 31h ma così il valore intero è diverso dall'altro (49).

pierosa
16-03-2007, 15:25
overflow?? No no.
pierosa ha sfruttato il fatto che il numero decimale 3223896 in esadecimale è 313158h e siccome sulle architetture Intel che sono "little-endian" i byte sono memorizzati dal meno significativo al più significativo

infatti la mia soluzione funziona con questo tipo di architettura, non è detto che in altre funzioni.
L'esercizio come è stato proposto è ambiguo perchè non specifica appunto l'architettura che si sta considerando.
anche la seconda domanda non è del tutto corretta, infatti se si sta lavorando su un sistema in cui gli int sono a 32 bit, la stringa "X-11" non può essere contenuta in un int, ma se stiamo lavorando su un sistema con int a 64 bit (credo che esistano) allora un intero può contenere stringhe di 7 caratteri più il terminatore.

nicod83
16-03-2007, 17:23
grazie 1000 pierosa!!!

..chiaramente non era un esercizio banale!!:D

andbin
16-03-2007, 19:34
grazie 1000 pierosa!!!E a me grazie ... no? Che ho fatto tutto con 1 sola variabile???

Scherzo ... non c'è problema. :p :p

71104
16-03-2007, 20:14
Uhm ... non è affatto chiaro! (almeno per me).
La stringa "X11" deve essere stampata in virtù di che cosa?? Cioè in che modo deve essere prodotta??

Questo codice non ha molto senso. Poi comunque quando fai p++ incrementi il puntatore 'p', che quindi va a puntare non più ad 'a' ma a ... qualcos'altro dopo.
E tra l'altro 'p' è un puntatore a char mentre tu assegni a 'p' l'indirizzo di un int ... esattamente è proprio questo il punto: l'esercizio (assolutamente schifoso a mio parere :Puke: ) vuole che tu definisca un valore di a percui quella printf finisce per stampare "X11". e probabilmente il testo è stato riportato in maniera errata perché non è possibile stampare anche gli apici (un int è da 4 bytes, quindi ci puoi stampare al massimo 4 caratteri di cui uno deve essere il terminatore nullo per uscire dal while, quindi 3; ecco perché la risposta all'ultima domanda è no).


EDIT - ehm, scusate, avevo letto solo i primi due post... :fagiano: :fagiano: :fagiano: :fagiano:

comunque vorrei farvi notare che è assolutamente errato definirlo un esercizio di C, in quanto il valore di a è diverso a seconda che la macchina sia big-endian o little-endian :Prrr: :Prrr: :Prrr:

71104
16-03-2007, 20:20
Come gia' fatto notare l'esercizio e' tutt'altro che chiaro e merita una risposta "sciocca":


#include <stdio.h>

void main(void)

{
int a=10;

while (a--);

printf("X11");
}
sciocca nel senso di ignorante? :Prrr: no perché AFAIK il main in C non si dovrebbe mai dichiarare come void (e per questo mi aspetto almeno una cinquantina di :blah: )

repne scasb
16-03-2007, 20:31
sciocca nel senso di ignorante? :Prrr: no perché AFAIK il main in C non si dovrebbe mai dichiarare come void (e per questo mi aspetto almeno una cinquantina di :blah: )

Come al solito dormi sempre.

Senza il problema per little-endian:


#include <stdio.h>

void main(void)

{
long a=3223896;

while (a)
{
printf("%c",a%256);
a/=256;
}
printf("\nFatto!");
}


Valido anche per X-11:


#include <stdio.h>

void main(void)

{
long a=825306456;

while (a)
{
printf("%c",a%256);
a/=256;
}
printf("\nFatto!");
}

71104
16-03-2007, 23:03
1) impara la coerenza nel quoting :O
2) mi sa che non hai ancora capito che il sorgente faceva parte del testo dell'esercizio... :read:

3) ti sei giocata la possibilità di fare i :blah:

:Prrr:

il che significa che se li fai ti segnalo per spam :O

pierosa
16-03-2007, 23:13
grazie 1000 pierosa!!!

..chiaramente non era un esercizio banale!!:D

non farti ingannare da tutti i numeri binari che ho usato.
L'esercizio si può risolvere usando i numeri esadecimali senza fare neanche una conversione, dato che le tabelle con i codici ascii riportano anche i valori esadecimali.
essendo
X = 58h
1 = 31h

si poteva anche risolvere così


int main()
{
int a = 0x313158;
char* p=&a;
while(*p)
{
printf("%c",*p);
p++;
}
printf("\nFatto!");
}

sottovento
17-03-2007, 06:20
non farti ingannare da tutti i numeri binari che ho usato.


Infatti non serviva usarli.
Potevi scrivere

int a = 'X11\0';

su una macchina BIG ENDIAN, oppure


int a = '\00011X';

su una macchina LITTLE ENDIAN.

In ogni caso, puoi risolvere il problema INDIPENDENTEMENTE dal fatto che la macchina sia LITTLE o BIG, purche' abbia gli interi ad almeno 4 bytes:


int main()
{
int a = (int)ntohl('X11\0');
char* p=&a;
while(*p)
{
printf("%c",*p);
p++;
}
printf("\nFatto!");
}


Chiaramente per poter scrivere 'X-11' la tua macchina deve avere gli interi con piu' di 4 byte

repne scasb
17-03-2007, 10:08
1) impara la coerenza nel quoting

Tu impara ad imparare.

2) mi sa che non hai ancora capito che il sorgente faceva parte del testo dell'esercizio...

Non accetto critiche da uno che di un intera discussione legge i primi due post. Impara anche a leggere, e se non capisci cosa leggi allora non rispondere.

3) ti sei giocata la possibilità di fare i :blah:

:blah::blah::blah::blah::blah::blah::blah::blah::blah::blah::blah:

cionci
18-03-2007, 09:24
Per favore smettetela di beccarvi, alla prossima vi sospendo entrambi.

sirus
18-03-2007, 14:45
In ogni caso, puoi risolvere il problema INDIPENDENTEMENTE dal fatto che la macchina sia LITTLE o BIG, purche' abbia gli interi ad almeno 4 bytes:


int main()
{
int a = (int)ntohl('X11\0');
char* p=&a;
while(*p)
{
printf("%c",*p);
p++;
}
printf("\nFatto!");
}


Chiaramente per poter scrivere 'X-11' la tua macchina deve avere gli interi con piu' di 4 byte

Si ma almeno su Windows per usare la funzione ntohl dovrebbe includere gli headers dei winsock. :D Sarebbe più veloce usare un paio di direttive al precompilatore facendo controllare il CPU type. ;)

sottovento
19-03-2007, 02:33
Si ma almeno su Windows per usare la funzione ntohl dovrebbe includere gli headers dei winsock. :D Sarebbe più veloce usare un paio di direttive al precompilatore facendo controllare il CPU type. ;)

Beh si, ma anche la printf() avrebbe bisogno dei suoi header. Si poteva quindi dedurre che l'esercizio non richiedeva di modificare quella parte (non la riportava nemmeno).

Utilizzando le direttive del precompilatore avresti una soluzione parziale: primo perche' non sono direttive standard (potresti averle e non averle) e secondo perche' la soluzione cosi' generata girerebbe solo sui processori a te noti, quando ntohl e' piu' generale.

Cmq e' sicuramente un'altra strada percorribile, e tutto sommato e' sempre bene prendere in considerazioni soluzioni diverse

cionci
19-03-2007, 09:15
A me sembrava chiaro che andasse modificata SOLO l'inizializzazione dell'int. E' chiaro che chi ha fatto l'esercizio aveva preso un'architettura di riferimento durante le esercitazioni.