Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Getchar
Forum - C/C++ - Getchar

Avatar
gforce (Normal User)
Rookie


Messaggi: 33
Iscritto: 21/01/2010

Segnala al moderatore
Postato alle 17:49
Sabato, 03/04/2010
Utilizzando getchar e putchar su una variabile di tipo char da me definita il valore di ritorno è sempre il primo carattere. Come faccio a gestire per esempio il 4^ carattere ? E come faccio a gestire tutta la parola ?

Inoltre ho scritto 2 frammenti di codici
  
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.         char ch;
  6.         while (getchar() != '\n') {
  7.                 ch = getchar();
  8.                 putchar(ch);
  9.         }
  10.         return 0;
  11. }

Con questo codice se io inserisco la parola ciao mi stampa io. Perchè non ciao ?

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.         char ch;
  6.         while (1) {
  7.                 ch = getchar();
  8.                 putchar(ch);
  9.         }
  10.         return 0;
  11. }

Con questo codice mi stampa tutta la parola.

Ultima modifica effettuata da gforce il 03/04/2010 alle 18:08


www.sys14.it <--- portale dedicato al linguaggio C / C++
PM Quote
Avatar
Poggi Marco (Member)
Guru


Messaggi: 950
Iscritto: 05/01/2010

Segnala al moderatore
Postato alle 18:39
Sabato, 03/04/2010
Ho letto il tuo programma, e ho notato che usi getchar() come condizione del ciclo
while, di conseguenza, putchar() non stamperà tutte le lettere.

Ultima modifica effettuata da Poggi Marco il 03/04/2010 alle 18:42


Nulla va più veloce della luce, quindi rilassati.
PM Quote
Avatar
TheWorm (Member)
Rookie


Messaggi: 24
Iscritto: 13/09/2009

Segnala al moderatore
Postato alle 18:47
Sabato, 03/04/2010
Non mi ricordo molto del C, ma nel primo codice usi due volte getchar, uno nella condizione e uno nelle istruzioni! Quindi il primo getchar nelle condizioni prende il primo carattere, ma poi nelle istruzioni prendi il secondo e stampi quello. Poi rifai da capo e prendi il terzo, poi il quarto e stampi il quarto.
Quindi potresti togliere il getchar nelle istruzioni e lasciare quello nelle condizioni così:

Codice sorgente - presumibilmente C/C++

  1. while ( (ch = getchar()) != '\n') {



E invece di usare un MALEFICO while(1), il tutto diventa:

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.     char ch;
  6.     while( (ch = getchar()) != '\n' ) {
  7.         putchar( ch );
  8.     }
  9.     putchar( ch );
  10.     return 0;
  11. }



Se ti serve leggere e stampare stringhe inserite in input al programma continuamente evitando che si chiuda tutto, cioè non una volta sola (tipo col comando "cat"), puoi fare così:

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.         char ch;
  6.         for( ;; ) {
  7.                 while( (ch = getchar()) != '\n' ) {
  8.                         putchar( ch );
  9.                 }
  10.                 putchar( ch );
  11.         }
  12.         return 0;
  13. }



Anche se ti conviene così:

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.         char ch;
  6.         for( ;; ) {
  7.                 ch = getchar();
  8.                 putchar( ch );
  9.         }
  10.         return 0;
  11. }



Se ti serve qualcosa di ancora più corto, ecco un'altra (pessima) alternativa:

Codice sorgente - presumibilmente Plain Text

  1. main(){for(;;)putchar(getchar());}



oppure

Codice sorgente - presumibilmente Plain Text

  1. main(){putchar(getchar());main();}



Inutile far notare la bruttura delle ultime due...

Sicuramente non sono stato chiaro, ma il codice parla da solo, quasi sempre. Cosa buona e giusta potrebbe anche essere un libro/manuale sul C: non mangiano mica! Al massimo ti mangia il portafoglio se il manuale è buono.

Poi se vuoi fare qualcosa di leggero e veloce, puoi semplificare tutto in assembly (32 bit). Questo funziona per me:

Codice sorgente - presumibilmente C/C++

  1. void _start()
  2. {
  3. //  asm("pusha");                      // Salva i valori dei registri
  4.         asm("movl $3, %eax");          // 3 = Leggi
  5.         asm("movl $1, %edx");          // 1 = Lunghezza input: 1 byte
  6.         asm("movl %esp, %ecx");      // %esp = Registro dove salvare momentaneamente l'input
  7.         asm("movl $1, %ebx");          // 1 = STDIN
  8.         asm("int  $0x80");                 // Chiama il kernel, esegue il tutto
  9.         asm("movl $4, %eax");          // 4 = Scrivi
  10.         asm("movl %esp, %ecx");      // %esp = Registro con l'input da scrivere
  11.         asm("movl $1, %ebx");          // 1 = STDOUT (Terminal)
  12.         asm("movl $1, %edx");          // 1 = Lunghezza output: 1 byte
  13.         asm("int  $0x80");                 // Chiama il kernel, esegue il tutto
  14. //  asm("popa");                         // Reimposta i registri
  15.         asm("call _start");                  // Chiama _start ye ricomincia il ciclo dall'inizio
  16. }



E lo compili senza includere headers o librerie standard: senza "#include <stdio.h>" e con l'opzione -nostdlib per il compilatore (io uso gcc). La differenza si vede: da 4649 bytes a 1037 bytes... un po' meglio eh?

...Oppuuuure, lo scrivi direttamente in asm visto che ci sei. In my_cat.S:

Codice sorgente - presumibilmente C/C++

  1. .global _start
  2.  
  3. _start:
  4. movl $3, %eax
  5. movl $1, %edx
  6. movl %esp, %ecx
  7. movl $1, %ebx
  8. int  $0x80
  9. movl $4, %eax
  10. movl %esp, %ecx
  11. movl $1, %ebx
  12. movl $1, %edx
  13. int  $0x80
  14. jmp _start



E poi: as -o my_cat.o my_cat.S && ld -o my_cat my_cat.o && rm my_cat.o
L'eseguibile adesso mi si è ridotto a 708 bytes!
Se poi hai tempo da perdere, puoi accorciarlo ancora un pochino, ottenendo 692 bytes (sulla mia macchina):

Codice sorgente - presumibilmente C/C++

  1. .global _start
  2.  
  3. _start:
  4. xorl %eax, %eax
  5. xorl %ebx, %ebx
  6. xorl %edx, %edx
  7. movb $3, %al
  8. inc  %edx
  9. movl %esp, %ecx
  10. inc  %ebx
  11. int  $0x80
  12. movb $4, %al
  13. movl %esp, %ecx
  14. //movb $1, %bl
  15. //movb $1, %dl
  16. int  $0x80
  17. jmp _start



Probabilmente potresti renderlo ancora più corto, non sono un guru. Per esempio "jmp _start" viene tradotto "e9 e7 ff ff ff" mentre credo si possa accorciare a "eb f9". Ah comunque il codice non è perfetto, potrebbe non funzionare in alcuni casi perchè ho badato solo alla lunghezza, non alla correttezza... in pratica funziona.

Morale della favola: Ridurre un programma al 15%, sicuramente è *cool* e ne aumenta la velocità di esecuzione.
PS: Si, ok, ovviamente non ce ne frega un cazzo se scriviamo due righe di codice (tipo queste) e se abbiamo un 8 core sotto il culo xD

Ultima modifica effettuata da TheWorm il 22/04/2010 alle 19:33
PM Quote