PDA

View Full Version : Problema con C


Gino+89+
02-12-2005, 18:25
Ciao a tutti... :D
Dovrei fare un programma che legga da tastiera un carattere, e se questultimo corrisponde a back space (praticamente quello di cancellatura in poche parole) "torna indietro", per capirci meglio ecco il sorgente cannato:


#include <stdio.h>

int main()
char car;
int num;
printf(">>inserire un carattere:");
scanf("%c",&car);

num=car-'0';

if(num==10)
return 6;
else{
printf("\n>>Carattere accettato");
while(getchar()!='\n');
}

getchar();
return 0;
}

Praticamente in questo programma se si preme backspace (che in codice ASCII vale 10) il programma torna dietro e ti richiede il carattere..su num ho messo "car-'0' " in modo che mi trasforma il carattere in numero e si possa fare il confronto con 10...sicuramente il pgm sarà pieno di errori...mi potete ridare la forma corretta del codice??..grazie mille!!!

VegetaSSJ5
02-12-2005, 20:51
guarda forse non ho capito bene io cmq il controllo che dovresti fare è

if (car==10)...

andbin
02-12-2005, 21:11
Praticamente in questo programma se si preme backspace (che in codice ASCII vale 10) il programma torna dietro e ti richiede il carattere..su num ho messo "car-'0' " in modo che mi trasforma il carattere in numero e si possa fare il confronto con 10...sicuramente il pgm sarà pieno di errori...mi potete ridare la forma corretta del codice??..grazie mille!!!
Ma il backspace è il codice ASCII 8 (0x08)!

VegetaSSJ5
02-12-2005, 22:23
Ma il backspace è il codice ASCII 8 (0x08)!
:asd:

Netskate
03-12-2005, 08:34
Premesso che non ho guardato il suo sorgente, per fare quello che serve a te bastano queste poche righe di codice:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
int insCharASCII;
do{
printf("\nInserisci un carattere: ");
insCharASCII=getchar();
}
while(insCharASCII==8);
system("PAUSE");
return 0;
}

Non ho messo i commenti perchè è banalissimo. Teoricamente dovrebbe funzionare :D ma in pratica non funziona a causa del dos, mi spiego meglio.

Se al posto di voler fare ripetere il programma quando premi backspace (ASCII=8) lo vuoi fare ripetere con un qualunque altro tasto, ad esempio lo spazio (ASCII=20), funziona benissimo. Qual'è allora il problema? Il dos non riconosce backspace come un carattere inserito (o meglio lo riconosce, ma in qualche modo lo bypassa identificandolo come un "cancella il carattere precedente al cursore"). Spero di essere stato abbastanza chiaro...in ogni caso il programma che devi fare tu, si può fare benissimo in assembler:

cseg segment para public 'code'
assume cs:cseg, ds:dati,es:dati,ss:stack
init proc far
mov ax,dati
mov ds,ax
mov es,ax
;***************************************
inizioPr: mov bx,offset stringa
printText: mov dl,[bx]
cmp dl,00h
je insCaract
call stampaVideo
inc bx
jmp printText
insCaract: call insChar
call insRiga
cmp al,8h
je inizioPr
;*****************************************
fine_programma:
ret_cd equ 0
ret_fn equ 4ch
mov ax,ret_fn*256+ret_cd
int 21h
init endp
;*****************************************
;* PROCEDURA "insRiga"
;* Questa procedura stampa una riga vuota
;* in modo da poter andare a capo.
;*****************************************
insRiga proc near
push ax
push dx
mov ah,2
mov dl,0dh
int 21h
mov dl,0ah
int 21h
pop dx
pop ax
ret
insRiga endp
;*****************************************
;* FINE PROCEDURA "insRiga"
;*****************************************
;*****************************************
;* PROCEDURA "stampaVideo"
;* Questa procedura stampa a video il
;* simbolo del codice ascii contenuto in DL
;*****************************************
stampaVideo proc near
push ax
mov ah,2
int 21h
pop ax
ret
stampaVideo endp
;*****************************************
;* FINE PROCEDURA "stampaVideo"
;*****************************************
;*****************************************
;* PROCEDURA "insChar"
;* Questa procedura legge un carattere da
;* tastiera e lo memorizza nel registro AL
;*****************************************
insChar proc near
mov ah,1
int 21h
ret
insChar endp
;*****************************************
;* FINE PROCEDURA "insChar"
;*****************************************
cseg ends
;*****************************************
dati segment para public 'dati'
stringa db 1 dup ("Inserisci un carattere: ")
dati ends
;*****************************************
stack segment para stack 'stack'
db 64 dup ("stack ")
stack ends

;*****************************************
end init

;*****************************************

Questo fa esattamente quello che chiedevi ;)

VegetaSSJ5
03-12-2005, 09:18
è possibile inserire quel programma come blocco asm in un programma C? purtroppo sono totalmente ignorante in materia per cui se ho detto una minchiata non subissatemi di lattuga, pomodori e uova marce... :(

Ziosilvio
03-12-2005, 09:52
Dovrei fare un programma che legga da tastiera un carattere, e se questultimo corrisponde a back space (praticamente quello di cancellatura in poche parole) "torna indietro"
Se ho capito bene, questo programma richiede input non bufferizzato, ossia l'operazione di lettura deve essere effettuata immediatamente dopo la pressione del tasto.
Invece, le varie scanf, getchar (che ti consiglio di usare: a proposito, getchar deve poter restituire EOF che è un valore diverso da ogni altro carattere, quindi il tipo restituito è int e non char) e famiglia, sono funzioni di input bufferizzato, ossia vengono eseguite quando le operazioni di riempimento di una zona di memoria dedicata allo scopo (il buffer, appunto) sono terminate, evento quest'ultimo normalmente corrispondente (nell'input da tastiera) alla pressione del tasto Invio.
E in effetti, nel tuo listato tu aggiri il problema leggendo solo il primo carattere di ogni sequenza che inserisci.

Ora, la libreria standard del C contiene solo funzioni per l'I-O bufferizzato, per il semplice fatto che questo è portabile e l'altro no.
Perciò, se vuoi fare una cosa pulita, devi ricorrere a librerie apposite per il compilatore e il sistema operativo con cui lavori, ad esempio conio sotto DOS o ncurses sotto Linux.
se si preme backspace (che in codice ASCII vale 10)
10 è il codice ASCII del newline.
Per il backspace, devi usare o il codice ASCII 127, oppure la costante '\b'.
su num ho messo "car-'0' " in modo che mi trasforma il carattere in numero e si possa fare il confronto con 10
Se dài per scontato che il testo sia ASCII, e vuoi sapere se la variabile car contiene un carattere corrispondente a una cifra decimale puoi semplicemente fare il confronto:
if (car>='0' && car<='9')
Attento a non confondere la cifra 0 '0' con il carattere nullo '\0', mi raccomando!

P.S.: comunque è tutto scritto nel K&R.

Netskate
03-12-2005, 11:16
ecco..ziosilvio ti ha spiegato meglio perchè non funziona con backspace :D

Gino+89+
03-12-2005, 12:51
Grazie a tutti..allora..
1)Quello stronzo del mio prof mi ha detto che backspace corrispondea 10 :mad: ..bè la sciamo stare
2)Mi ha anche spiegato che :
int num=carattere(char)-'0';
..ti restituisce il valore numerico del carattere...
3)Poi non ho capito:
if (car>='0' && car<='9')
..come faccio a fare questo confronto se in codice ASCII backspace vale 127???
4)Quindi se uso la conio.h e uso getchar() e putchar() potrebbe funzionare??..(infatti il programma partiva ma prima di andare avanti dovevo premere invio :mad:..il mio prof mi ha spiegato che dopo ogni scanf(); ci va while(getchar()!='\n'); in modo da blocca senò il pgm va avanti, allora io ho dedotto che se non metto quel codice il programma sarebbe andato avanti come volevo io senza interruzioni..bè fa lo stesso..)..

Gino+89+
03-12-2005, 13:46
Ok avevi ragione :D...con getch (della conio.h appunto) mi fa tutto diretto...ora il problema è solo come tornare indietro nel programma...con return mi parte tutto e quindi non và..

andbin
03-12-2005, 13:47
1)Quello stronzo del mio prof mi ha detto che backspace corrispondea 10 :mad: ..bè la sciamo stare :D

2)Mi ha anche spiegato che :
int num=carattere(char)-'0';
..ti restituisce il valore numerico del carattere...int num = carattere - '0';
ti fornisce il valore numerico, a patto che il carattere sia compreso tra '0' (0x30) e '9' (0x39), altrimenti non ha senso.

3)Poi non ho capito:
if (car>='0' && car<='9')
..come faccio a fare questo confronto se in codice ASCII backspace vale 127???Attenzione, lo standard ASCII definisce che il codice 8 è il backspace e il codice 127 è il "delete" (a volte chiamato anche "rubout").
Sono due cose leggermente diverse: il backspace (8) porta indietro solo il cursore (quindi non cancella il carattere precedente) mentre il delete (127) cancella a tutti gli effetti il carattere precedente (proprio come se tu premessi il tasto di cancella che c'è nelle tastiere sopra l'enter).
Tiene presente anche che, da quello che ho potuto sempre constatare io, su linux il 127 si comporta effettivamente come delete mentre sulla console di Windows, il 127 stampa un carattere grafico.

Gino+89+
03-12-2005, 13:57
Ora mi è tutto chiaro....manca solo una cosa per completare quel maledetto codice:COME SI FA A TORNARE INDIETRO NEL PROGRAMMA??...con return non và..nessuna sa come si fa??...

andbin
03-12-2005, 14:22
Ora mi è tutto chiaro....manca solo una cosa per completare quel maledetto codice:COME SI FA A TORNARE INDIETRO NEL PROGRAMMA??...con return non và..nessuna sa come si fa??...
"Tornare indietro nel programma" in che senso??

Gino+89+
03-12-2005, 14:30
Nel senso che se si digita backspace il programma "torna alla riga 6" dove viene chiesto di nuovo di iserire il carattere...non so se sia possibile ma però mi sembra di aver letto in un codice una cosa simile..

andbin
03-12-2005, 19:16
Nel senso che se si digita backspace il programma "torna alla riga 6" dove viene chiesto di nuovo di iserire il carattere...non so se sia possibile ma però mi sembra di aver letto in un codice una cosa simile..
Ho visto solo adesso (non ci avevo fatto caso prima) che nel codice del tuo post iniziale c'è un "return 6;", che sinceramente non so a cosa ti serva o se ha qualche attinenza con quello che hai appena detto.
Comunque se vuoi che ci sia un ciclo, cioè che una parte del codice venga rieseguita in base ad una determinata condizione, devi usare il costrutto while o il do-while (nel tuo caso penso sia meglio quest'ultimo).

VegetaSSJ5
03-12-2005, 20:17
Nel senso che se si digita backspace il programma "torna alla riga 6" dove viene chiesto di nuovo di iserire il carattere...non so se sia possibile ma però mi sembra di aver letto in un codice una cosa simile..
Ho visto solo adesso (non ci avevo fatto caso prima) che nel codice del tuo post iniziale c'è un "return 6;", che sinceramente non so a cosa ti serva o se ha qualche attinenza con quello che hai appena detto.
:eek:

andbin
03-12-2005, 22:45
:eek:
:confused: Ho detto forse qualcosa di strano o sbagliato?

Ziosilvio
04-12-2005, 08:46
Attenzione, lo standard ASCII definisce che il codice 8 è il backspace e il codice 127 è il "delete" (a volte chiamato anche "rubout").
Acc... è vero! (http://www.lookuptables.com/)
Chiedo scusa per l'imprecisione.

A proposito: backspace ha il codice ASCII decimale 8, quindi il suo valore numerico ottale è 010: per cui, è possibile che il prof di Gino+89+ abbia letto la colonna sbagliata...

Ziosilvio
04-12-2005, 08:54
Nel senso che se si digita backspace il programma "torna alla riga 6" dove viene chiesto di nuovo di iserire il carattere...non so se sia possibile ma però mi sembra di aver letto in un codice una cosa simile..
Non return, che provoca la terminazione della funzione con la restituzione di un valore; ma goto, che porta il flusso dell'esecuzione al punto contrassegnato da un'etichetta.
Per cui, nel tuo caso doversti sostituire:
printf(">>inserire un carattere:");
scanf("%c",&car);

if(car=='\b')
return 6;
con:
insert_char:
printf(">>inserire un carattere:");
scanf("%c",&car);

if(car=='\b')
goto insert_char;
In realtà, l'uso del goto è considerato indice di programmazione non elegante; inoltre, il Teorema di Bohm-Jacopini ti assicura che puoi sostituire ogni istanza di goto con una combinazione di istruzioni condizionali, cicli, e chiamate a procedura o a funzione.
Studia bene, sul tuo libro, la parte relativa ai cicli (while, do-while, e for), incluse le istruzioni break e continue.

Gino+89+
04-12-2005, 11:10
Mitico Ziosilvio!!..proprio goto..ora ricordo...infatti mi sembrava di averla gia vista sta cosa...mi serve questo perchè devo fare un programma che funge come una specie di prompt dei comandi e inserire ogni volta cicli non finisco più..ok..grazie a tutti!!!!

DanieleC88
04-12-2005, 11:29
è possibile inserire quel programma come blocco asm in un programma C?
Volendo, si, ma dipende dal compilatore. Ad esempio, con gcc puoi, ma dev'essere scritto nella sintassi Unix (AT&T). Se vuoi, puoi anche compilare il file assembly esternamente e poi linkarlo soltanto all'oggetto del file C. ;)