C, čtení z klávesnice – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

C, čtení z klávesnice – C / C++ – Fórum – Programujte.comC, čtení z klávesnice – C / C++ – Fórum – Programujte.com

 

Venombrain
~ Anonymní uživatel
11 příspěvků
3. 2. 2012   #1
-
0
-

Zdravím,

jsem začátečník a mám problém se čtením z klávesnice. Potřebuji, aby program přečetl první zadaný znak a ostatní nechal být(včetně ENTERU). Pokusím se nastínit problém.

V příkazu "switch" naskenuji z klávesnice znak, vše jde bez problému do té doby, než dojde k části programu "default", kde upozorňuji na zadání špatného znaku, ale upozornění se vytiskne 2x, protože se mi naskenuje i ENTER.

Asi se s tím setkala většina z vás. Zkouším hledat řešení už dlouho leč marně. Pro čtení z klávesnice používám příkaz "getchar".

Předem děkuji za odpovědi. Prosil bych bez urážek. Zeptáš-li se, budeš 5 minut vypadat jako blbec. Nezeptáš-li se, budeš blbcem po celý život.

Nahlásit jako SPAM
IP: 77.237.136.–
crazy
~ Moderátor
+10
Grafoman
3. 2. 2012   #2
-
0
-

#1 Venombrain
nějak nechápu, getchar ti přece načte pouze jeden znak... kdyžtak sem hoď kousek kódu...

Nahlásit jako SPAM
IP: 89.190.90.–
All you need is vision and time.
KIIV
~ Moderátor
+43
God of flame
3. 2. 2012   #3
-
0
-

on spis asi mysli ze aby to nacetlo znak, tak musi hodit taky enter... a pokud nacita v cyklu tak se nacte vsechno co je v bufferu

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Venombrain
~ Anonymní uživatel
11 příspěvků
3. 2. 2012   #4
-
0
-

   

switch (getchar()){ //Zde to načte i ENTER, kterým musím potvrdit zadaný znak.

case 'A' : bla bla bla...

default : printf("Upozorneni"); //Toto upozornění to vytiskne 2x.
Nahlásit jako SPAM
IP: 77.237.136.–
Venombrain
~ Anonymní uživatel
11 příspěvků
3. 2. 2012   #5
-
0
-

Koukám, že nikdo neví. Ani můj kámoš, se kterým jsem to teď probíral. Nakonec jsem to udělal, tak že jsem vynechal "default" a před "switch" jsem dal cyklus ve kterém pomocí "if" porovnávám vstupní hodnotu se znaky mnou nadefinované v použitých "case".

Nahlásit jako SPAM
IP: 77.237.136.–
zlz
~ Anonymní uživatel
634 příspěvků
3. 2. 2012   #6
-
0
-

Když neukážeš kód, ze kterého by se dalo něco vyčíst, tak samozřejmě nikdo neví.

Nahlásit jako SPAM
IP: 213.211.51.–
devilfish0
Stálý člen
3. 2. 2012   #7
-
0
-

Asi nechapem kde je problem......vsak ked pouzijes getchar() len raz tak nacita len prvy znak ziadne ine ani enter....

Nahlásit jako SPAM
IP: 188.121.172.–
KIIV
~ Moderátor
+43
God of flame
3. 2. 2012   #8
-
0
-

#7 devilfish
on to bude mit s vysokou pravdepodobnosti obaleny cyklem

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
devilfish0
Stálý člen
3. 2. 2012   #9
-
0
-

V tom pripade nechapem tu logiku....chce precitat len prvy znak tak preco cita v cykle? A keby aj chcel citat napr prvy znak na x riadkoch tak proste si vzdy len prvy znak ulozi do premennej a ostane len prebehne getcharom a nevsima si ich....stale nechapem kde je problem....

Nahlásit jako SPAM
IP: 188.121.172.–
crazy
~ Moderátor
+10
Grafoman
4. 2. 2012   #10
-
0
-

#9 devilfish
no rozhodně z toho, co nám napsal mu nemůžeme pomoci, protože nevíme co od toho chce a co vlastně napsal...

Nahlásit jako SPAM
IP: 89.190.90.–
All you need is vision and time.
vitamin+8
Grafoman
4. 2. 2012   #11
-
0
-

Po spracovani prveho znaku moze pouzit fflush(stdin) .

Nahlásit jako SPAM
IP: 178.143.60.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Pudni tvor+2
Stálý člen
5. 2. 2012   #12
-
0
-

Možná budu offtopic :

Pod Windows existuje možnost vypnout čekani na Enter a vypnout echo vstupu na obrazovku :

#include <stdio.h>
#include <windows.h>

int main(int argc, char* argv[])
{
#if 1
  // Vypne navraceni z getchar teprve po Enter, 
  // getchar se bude vracet ihned po precteni nejakeho znaku, 
  // bez jeho echa na obrazovku
  HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); 
  DWORD mode;
  GetConsoleMode(handle, &mode);
  mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT); 
  SetConsoleMode(handle, mode);
#endif

  int c;
  while ((c = getchar()) != 'Q' && c != 'q') {
    printf("stiskl si %c\n", (unsigned char) c);
  }

  printf("Konec\n");

  return 0;
}

viz dokumentace SetConsoleMode a GetConsoleMode

Nahlásit jako SPAM
IP: 90.180.213.–
Venombrain
~ Anonymní uživatel
11 příspěvků
11. 2. 2012   #13
-
0
-

Omlouvám se, že jsem se zde už neukázal, ale jsem intrák a tam nemám přístup k netu. Po několika marných pokusech a kompletním překopáním programu. Když jsem to nemohl najít nikde na netu, mne to už začalo štvát a zeptal jsem se učitele.   

Poradil mi ať tam dám tohle.  

scanf("%c", &c);
if (c=='\n'){
scanf("%c",&c);
}

A zde vám dávám celí program, aby jste viděli k čemu jsem to potřeboval (Vytvořil jsem si projekt Console Application)

 "main.c"

#include <stdio.h>
#include <ctype.h>

float PI=3.14159;
extern int zacatek();
extern void kruh();
extern void valec();

int main(){

    switch (zacatek()) {

        case 'K' : {
        kruh();
        return 1;
        }

        case 'V' : {
        valec();
        return 2;
        }

        case 'Q' :{
        return 0;
        }
    }
}

pomocny_soubor.c 

#include <stdio.h>
#include <ctype.h>

extern float PI;
static float r, h, s;
int zacatek();
void kruh();
void valec();

int zacatek(){

    int w=0;
    char c;

    while(w==0){
        printf("Stisknete:\n\"K\" pro vypocet obsahu kruhu.\n\"V\" pro vypocet obsahu valce.\n\"Q\" pro ukonceni programu.\n(Potvrdte ENTERem)\n");
        scanf("%c", &c);
        if (c=='\n'){
        scanf("%c",&c);
        }
        c = toupper(c);
        
        printf("Zadali jste \"%c\"\n", c);

        if( c == 'K' || c == 'V' || c == 'Q' ){
            w=1;
        }
    }
return c;
}

void kruh(){

    printf("\nProsim zadejte polomer kruhu.\n");
    scanf("%f", &r);

    s = PI*r*r;

    printf("\nPlocha kruhu je: %.2fcm^2\n", s);

}

void valec(){

    printf("\nProsim zadejte polomer valce.\n");
    scanf("%f", &r);
    printf("Nyni zadejte vysku valce.\n");
    scanf("%f", &h);

    s = 2*PI*r*(r+h);

    printf("\nPlocha valce je: %.2fcm^2\n", s);

}

Snad je to dostatečně přehledný a pochopitelný. Jedná se pouze o výpočet plochy kruhu a válce.

Nahlásit jako SPAM
IP: 77.237.136.–
m->29+6
Super člen
11. 2. 2012   #14
-
0
-

Ak sa nemýlim tak toto ti je tam na nič a môžeš to vynechať.

if (c=='\n'){
  scanf("%c",&c);
}

Pretože scanf biele znaky preskakuje a teda v c nebude nikdy znak '\n'.

Nahlásit jako SPAM
IP: 178.143.81.–
KIIV
~ Moderátor
+43
God of flame
11. 2. 2012   #15
-
+1
-
Zajímavé

#14 m->29
scanf("%c",...)  bere i bile znaky... (musel sem si to pro jistotu overit, abych nahodou nekecal kraviny)

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Samot10
~ Anonymní uživatel
26 příspěvků
11. 2. 2012   #16
-
0
-

neviem ako je to windowse, ja programujem v linuxe, ale tam ked v terminaly stlacim ENTER('\n'), tak sa mi ukonci vstup, takze ak ma toto byt len nejake osetrenie, ze co ak sa nahodou uzivatelovi najskor podari odriadkovat a az potom napise pismeno, tak mi v tvojom programe chybaju aj osetrenia pre vstup "floating pointov" pri zadavani rozmerov telies...

ale ak sa mam vyjadrit k teme, tak ked testujes len prvy znak, tak by som to riesil cez getchar();


a neviem ci to tu bolo uz povedane, ale to upozornenie sa ti vypisalo 2x pretoze getchar() precita jeden znak, porovna ho, prevedie sa prislusny prikaz a ked to cyklis, tak getchar() zoberie dalsi znak, cize '\n' pokial ukoncujes vstup stalecim klavesy enter, ten sa znovu porovna a prevedie sa prislusni prikaz...mozes sa pohrat aj s funkciou isspace a pod.

Nahlásit jako SPAM
IP: 147.229.206.–
Venombrain
~ Anonymní uživatel
11 příspěvků
11. 2. 2012   #17
-
0
-

V cyklu to mám proto, abych ošetřil to, když uživatel zadá jinou hodnotu než má, tak se to vrátí a opět ho vyzve, aby zadal hodnotu, kterou má zadat. Problém je, když zadá více znaků, tak tak se cyklus proběhne několikrát.

Tímto jsem ošetřil alespoň to, že když zadá jeden špatný znak, tak mu to vypíše jen jednou.

if (c=='\n'){
  scanf("%c",&c);
}

Abych ošetřil i ostatní znaky, bych musel to použít několikrát a možná by to v tom programu dělalo bordel. Zkusím to udělat a pak sem napíši jak to dopadlo.

Nahlásit jako SPAM
IP: 77.237.136.–
Samot10
~ Anonymní uživatel
26 příspěvků
11. 2. 2012   #18
-
0
-

#17 Venombrain
viem preco je to v cykle :)
 

btw. mne sa osvedcilo pri citani zo stdin urcit si najskor vstupne podmienky...aky vstup je korektny a aky vstup uz korektny nie je...potom vies osetrit vsetko tak ako potrebujes a nestane sa ti, ze uzivatel to nejako pokasle :D

Nahlásit jako SPAM
IP: 147.229.206.–
Venombrain
~ Anonymní uživatel
11 příspěvků
11. 2. 2012   #19
-
0
-

Tak se mi to nepodařilo zprovoznit, asi to byla blbost.

#18 Samot10
Není mi jasné, jak se dají nastavit vstupní podmínky pro stdin. Rozhodně to zní zajímavě a určitě bych našel využití i v jiných případech. Mohl bys mi vytvořit nějakou ukázku?

Nahlásit jako SPAM
IP: 77.237.136.–
Samot10
~ Anonymní uživatel
26 příspěvků
11. 2. 2012   #20
-
0
-

asi si ma zle pochopil...myslim rozdelit vstupy na vstupy dobre a zle...
napr.:

"K" = dobry vstup

"Ahoj" = zly vstup

ale co napriklad "Kq"? alebo " K"?

najskor si ujasni taketo veci...ake vstupy su pre teba prijatelne a ktore nie...

Nahlásit jako SPAM
IP: 147.229.206.–
Venombrain
~ Anonymní uživatel
11 příspěvků
13. 2. 2012   #21
-
0
-

Jo takhle jsi to myslel. No uživatel má zadat jeden ze tří znaků (K, V a Q). Ostatní znaky jsou nepřijatelné. Toto mám ošetřené, ale pouze pokud uživatel zadá jen jeden znak. Problém nastane, když uživatel zadá v¨znaků více což nevím jak ošetřit.

Nahlásit jako SPAM
IP: 195.113.213.–
KIIV
~ Moderátor
+43
God of flame
13. 2. 2012   #22
-
0
-

#21 Venombrain
to tady uz taky padlo pokud se nemylim

Nahlásit jako SPAM
IP: 62.168.56.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Samot10
~ Anonymní uživatel
26 příspěvků
13. 2. 2012   #23
-
0
-

ale zase je rozdiel ci tie ostatne znaky tvoria medzery alebo nejake "viditelne znaky"
priklad:

"K          "
"Kaaaaaa"

oba vstupy su neprijatelne?

Nahlásit jako SPAM
IP: 147.229.206.–
vitamin+8
Grafoman
13. 2. 2012   #24
-
0
-

Podla mna je zbitocne robit programi uplne blbovzdorne, ked chce uzivatel zadat hovadinu netreba mu v tom branit.

Nahlásit jako SPAM
IP: 178.143.60.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Samot10
~ Anonymní uživatel
26 příspěvků
13. 2. 2012   #25
-
0
-

samozrejme vsetky pripady sa nemusia riesit...ale treba si stanovit ktore su korektne a ktore nie...
ked si poviem, ze jediny spravny prijatelny vstup bude "K", tak nemam co riesit, jeden getchar a hotovo...ale ked chceme aby boli spravne aj vstupy ako "K     ", "           K" alebo "\nK", tak potom to uz musime osetrovat...
preto vravim, ze si treba najskor stanovit jasne vstupne podmienky

Nahlásit jako SPAM
IP: 147.229.206.–
Venombrain
~ Anonymní uživatel
11 příspěvků
14. 2. 2012   #26
-
0
-

Kaslu na to hefnu to pres goto a bude to. Overit funkcnost buddu moct o vikendu. Mozna driv, ale asi ne. Dekuji vam zza vsechny rady a nazory.

Zasláno z mobilního telefonu.

Nahlásit jako SPAM
IP: 217.77.165.–
Samot10
~ Anonymní uživatel
26 příspěvků
14. 2. 2012   #27
-
0
-

goto je skaredost...

urob to cez getchar ako tu uz niekto pisal...skratka vezmes len prve pismeno a ak to nie je K, V ani Q, tak prejdes retazec zo vstupu az do konca a vypises nejake upozornenie...a toto budes cyklit pokial nezada potrebne pismeno...

ak s tym budes mat problem, tak mi pisni na mail: strbak.t@gmail.com

Nahlásit jako SPAM
IP: 147.229.206.–
feki+1
Duch
15. 2. 2012   #28
-
0
-

nazdar hadam nieje este offtopic a moja skusenost spracovania vstupu od uzivatela ti pomoze

pri spracovani vstupu typu "Kadsjafihdfa atd.", teda viacznakovych vstupov s tym ze su validne a tak aby to nebralo postupne po jednom znaku, vyuzivam funkciu getline(kukni dokumentaciu man getline), ktora ti ziska vstup aj so znakom konca riadku '\n' z tohto ziskaneho retazca ziskam a spracujem iba prvy znak a ostatne ignorujem

popripade az budes taketo viacznakove vstupy jednoducho porovnas dlzku takto ziskaneho vstupneho retazca a ak je dlhsi ako 2 (znak + znak konca riadku) tak jednoducho ho ignorovat a vypisat nejaku vyzvu na opakovanie vstupu

Nahlásit jako SPAM
IP: 77.234.252.–
Samot10
~ Anonymní uživatel
26 příspěvků
15. 2. 2012   #29
-
0
-

podla mna to nie je dobry napad...kvoli jednemu znaku citas cely riadok a este aj zistujes dlzku toho retazca...trosku neefektivne...tato tema je podla mna vyriesena, je tu uz dost rieseni podla mna...

Nahlásit jako SPAM
IP: 147.229.206.–
Venombrain
~ Anonymní uživatel
11 příspěvků
15. 2. 2012   #30
-
0
-

#27 Samot10
Já vím, že goto je prasárna.

No to právě nevím jak přejít řetězec. Pokud zadám více znaků, tak se mi naskenujou všechny což já nechci.

Nahlásit jako SPAM
IP: 77.237.138.–
KIIV
~ Moderátor
+43
God of flame
15. 2. 2012   #31
-
0
-

a zkusil si uz to  fflush(stdin)  jak tu bylo zminene na zacatku??

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Venombrain
~ Anonymní uživatel
11 příspěvků
15. 2. 2012   #32
-
0
-

#31 KIIV
fflush(stdin)? Jo už ten návrh vidím. Musel jsem ho přehlídnout.    Neznám, ale zjistím si o tom vše a poté se to pokusím zrealizovat. Díky za upozornění.

Nahlásit jako SPAM
IP: 77.237.138.–
feki+1
Duch
16. 2. 2012   #33
-
0
-

#29 Samot10
pre mna to bol najjednoduchsi sposob osetrenia nevalidnych vstupov, teda vstupov majucich viac ako 1 znak tak aby sa ti nespracovaval kazdy znak z jedneho vstupu, co sa tyka zistovania dlzky vstupu to bolo myslene v tom zmysle ze ak nechces akceptovat viac ako 1 znakove vstupy tak to zabezpecis porovnanim dlzky tohoto retazca, getline je v tomto pekny ze ti ulozi do dynamicky vytvoreneho pola cely vstup az do vyskytu konca riadku teda s tym ze stlacil enter na konci a ty nemusis ratat kolko je toho v stdin buffri

while(1)
{
	print_menu();
	printf("\nYour choice: ");

	char* input = NULL;
	size_t len;
	if(getline(&input, &len, stdin) == -1)
	{
		perror("getline");
		continue;
	}

	char choice = input[0];
	
	switch (choice) {
		// spracovanie vstupu
		default:
			break;
	}

	free(input); // uvolnenie dynamicky alokovanej pamate getlineom
	system("clear");
}
Nahlásit jako SPAM
IP: 77.234.252.–
Samot10
~ Anonymní uživatel
26 příspěvků
16. 2. 2012   #34
-
0
-

"getline je v tomto pekny ze ti ulozi do dynamicky vytvoreneho pola cely vstup az do vyskytu konca riadku"

v tomto je getline praveze skaredy, nie pekny...potrebujes spracovat jeden znak a kvoli tomu nacitavas cely riadok? to vobec nie je pekne...ano je to jednoduche...pokial chces urobit program "len aby fungoval", tak v pohode...ale podla mna by malo byt cielom vytvarat efektivne programy...

Nahlásit jako SPAM
IP: 147.229.206.–
feki+1
Duch
16. 2. 2012   #35
-
0
-

tak ci tak spracujes vsetky znaky zo vstupu myslim si ze moc efektivite neublizis ked si to najskor vytiahnes vsetko a potom odstranis ale je to vec vkusu ci to moze vyzerat takto 

while(1)
{
	char choice;
	if((choice = getchar() != '\n')
	{
		while(getchar() != '\n') ;
	}
	else
	{
		continue;
	}

	switch(choice)
	{
		// spracovanie vstupu
	}
}

alebo ako hovoris jednoduchsie a neefektivnejsie

while(1)
{
	char* line = NULL;
	size_t len;
	if(getline(&line, &len, stdin) == -1)
	{
		perror("getline");
		continue;
	}

	char choice = input[0];
	free(line);
	
	switch (choice) {
		// spracovanie vstupu
	}
}

takze nech si kazdy teda hlavne Venombrain vybere podla toho co sa mu bude pacit viac a hadam mu to pomoze
 a otazku efektivnosti nech si kazdy zvazi individualne podla svojich vlastnych potrieb pretoze si myslim ze reziou spojenou s alokaciou pamate moc efektivite neublizis, moj nazor s ktorym nemusis suhlasit

Nahlásit jako SPAM
IP: 77.234.252.–
Samot10
~ Anonymní uživatel
26 příspěvků
16. 2. 2012   #36
-
0
-

   

#include <stdio.h>

//easy: ak je znak v poriadku vrati jeho hodnotu, inak vrati nulu
int isKQV(int znak) {

        if (znak == 'K' || znak == 'Q' || znak == 'V')
                return znak;
        else
                return 0;
}

//easier: zahodi vstup
void zahod_vstup() {
        int c;
        while((c = getchar()) != '\n');
}

//telo programu
int main() {

        int c, x, stav = 0;

        while(stav != 1) {

                printf("Zadaj znak\n");
                c = getchar();

                if((x = isKQV(c)) == 0)
                        zahod_vstup();
                else
                        stav = 1;       //dostali sme potrebny 
                                        //znak => konci cyklus  

        //spracujeme nacitany znak v premennej x
        printf("%c\n", x);

return 0;
}

je to len tak narychlo ale zakladny princip tam je...dalo by sa to este skratit ale takto to bude asi pochopitelnejsie...

a uz ozaj by som navrhoval uzavriet to tu, je tu uz dost rieseni...

Nahlásit jako SPAM
IP: 147.229.206.–
Venombrain
~ Anonymní uživatel
11 příspěvků
17. 2. 2012   #37
-
0
-

#36 Samot10

Skvělá práce.    Jednoduchý a funguje to. 

#35 feki

Děkuji za návrhy určitě je také vyzkouším. 

Problem solved, může se to uzavřít.  

Nahlásit jako SPAM
IP: 77.237.136.–
dssl
~ Anonymní uživatel
1 příspěvek
16. 7. 2012   #38
-
0
-

#37 Venombrain


Pokud chceš použít pouze první znak a ostatní zahodit, tak je nejjednodušší vyprázdnit vstupní buffer po přečtení prvního znaku - funkce fflush(stdin).

char c=getc(stdin); 
  while(c != 'q')
  {
    switch(c)
    {
      case 'a': printf("volba a");break;
              
      case 'b': printf("volba b");break;
    }
    
    fflush(stdin);     // vyprazdneni vstupniho bufferu
    c=getc(stdin);
  }
Nahlásit jako SPAM
IP: 90.178.235.–
hlm
~ Anonymní uživatel
1 příspěvek
20. 7. 2012   #39
-
0
-

a co elegantneji _getch() //conio.h

Zasláno z mobilního telefonu.

Nahlásit jako SPAM
IP: 82.145.217.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 4 hosté

Podobná vlákna

C# klavesnice — založil H12

Klavesnice — založil Turbo1

Klavesnice — založil Ladík

Vstup z klávesnice — založil Hans33

Notebook klavesnice — založil Earl Cash

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý