Автор Тема: getchar() не работи от пъривя път.  (Прочетена 3577 пъти)

completer

  • Напреднали
  • *****
  • Публикации: 347
  • Distribution: Debian 6.0
  • Window Manager: Gnome
    • Профил
    • WWW
Ето какво става!Първо мислех, че ще мога да използвам gethce(); но се оказа, че тя била само за бъгиндоулс(whatever  :P). Та реших, че getchar() ще свърши работата,но възникна проблем.В прогрмата която съм написал съм го поставил в цикъл while за проверка дали вкарва верен знак. Там е работата че при първото изпълнение на цикъла пропуска ch=getchar(); а чак при второто изпълнение се изпълнява getchar().Реших да направя пробна програма със същият цикъл да видя какво ще стане, интересното тук беше че се изпълни както трябва но само първия път ! Ето вижте сорса на пробната програма за да ме разберете по-добре.
Код
GeSHi (C):
  1. #include<stdio.h>
  2. int multiply_second_line(void);
  3. int main (void)
  4. {
  5. printf("HELLO\n");
  6. multiply_second_line();
  7. return 0;
  8. }
  9.  
  10. int multiply_second_line(void)
  11. {
  12. char ch;
  13. printf("ENTER\n");
  14. while(ch!='n' || ch!='y'){
  15.  printf("Go back to main menu? (y/n)");
  16.  ch=getchar();
  17.  if(ch=='y') main(); /*ако "да" се връща в главната функция*/
  18.  else if(ch=='n'){
  19.  printf("Exitting..\n");
  20. break;
  21. }
  22. }
  23.  
  24. return 0;
  25. }
  26.  

Ето какво става при пускането на пробната програма


Код:
completer@debian:~/C Programing/Matrux$ ./a.out
HELLO
ENTER
Go back to main menu? (y/n)y
HELLO
ENTER
Go back to main menu? (y/n)Go back to main menu? (y/n)   /*изглежда тук се повтаря два пъти*/     

Ето пък какво става при въпросната ми прогрма

Код:
Please enter the values of the first matrix in the following order:
Please enter the values of a11 and a12(with interval): 1 1
Please enter the values of a21 and a22(with interval): 1 1
Please enter the values of the second matrix in the following order:
Please enter the values of b11 and b12(with interval): 1 1
Please enter the values of b21 and b22(with interval): 1 1
The new matrix looks like this:
2.000000;   2.000000;
2.000000;   2.000000;
Go back to main menu? (y/n)Go back to main menu? (y/n)^C

P.S. Моля не ме критикувайте като програмист все още се уча от една книга и реших да изпробвам натрупаните досега знания.
« Последна редакция: Aug 31, 2009, 14:40 от completer »
Активен

I'm using Linux and i'm proud of it!!!
I hate Windows and i'm also proud of it!!! :)

romeo_ninov

  • Напреднали
  • *****
  • Публикации: 2155
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #1 -: Aug 31, 2009, 15:01 »
1. преди използване инициализирай променливата ch
2. while сравнението (мисля) трябва да е от вида while(ch!='n' && ch!='y')....
Активен

0x2B|~0x2B

bop_bop_mara

  • Напреднали
  • *****
  • Публикации: 2433
  • Distribution: Debian Testing
  • Window Manager: LXDE
  • Cute and cuddly
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #2 -: Aug 31, 2009, 15:05 »
Извинявай, ама няма как да се мине без критика... Прочети много внимателно за функциите, как се извикват, за стека на извикванията и рекурсията... Връщането във функцията, от която си извикал дадена функция, не става с нейно извикване или с goto, става с изход от извиканата функция. Ти имаш функция А, която вика функция Б, която вика А и т.н. - на това му се вика косвена рекурсия.

mara@OVNI:~$ ./a.out
HELLO
ENTER
Go back to main menu? (y/n)y
HELLO
ENTER
Go back to main menu? (y/n)Go back to main menu? (y/n)y
HELLO
ENTER
Go back to main menu? (y/n)Go back to main menu? (y/n)y
HELLO
ENTER
Go back to main menu? (y/n)Go back to main menu? (y/n)n
Exitting..
Go back to main menu? (y/n)Go back to main menu? (y/n)n
Exitting..
Go back to main menu? (y/n)Go back to main menu? (y/n)n
Exitting..
Go back to main menu? (y/n)Go back to main menu? (y/n)n
Exitting..
mara@OVNI:~$

Ето ти още един резултат от изпълнението с два пъти "y". Като прочетеш за извикванията на функции и си начертаеш схема на това, което правиш, сам ще си обясниш това, което се получава.
И не забравяй, че програмите винаги работят правилно, просто програмистите им казват да правят грешни неща ;)

ПС. Коя е тая книга, дето четеш от нея? Гледам 2рата функция ти е тип int и завършва с return 0, новите C стандарти не изискват такова нещо, има си тип void за функция..
Активен

ludsic

  • Напреднали
  • *****
  • Публикации: 71
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #3 -: Aug 31, 2009, 15:31 »
Има грешка в кода който написах така че го изтрих ...
Поздрави :)
« Последна редакция: Aug 31, 2009, 15:38 от ludsic »
Активен

B4 02 B2 4C CD 21 B2 61 CD 21 B2 6D CD 21 B2 65 CD 21 B2 72 CD 21 B4 4C B0 00 CD 21 00 00 00 00

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: getchar() не работи от пъривя път.
« Отговор #4 -: Aug 31, 2009, 15:38 »
completer, един съвет от мен - извеждай си съдържанието на променливата "ch" през различните стъпки на кода, и с малко логика ще видиш къде грешиш ;)
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

Iron_steel

  • Напреднали
  • *****
  • Публикации: 28
  • Distribution: Arch Linux
  • Window Manager: Gnome
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #5 -: Aug 31, 2009, 15:45 »
Промених си мнението,не схванах идеята. ;D
« Последна редакция: Aug 31, 2009, 15:50 от Iron_steel »
Активен

ludsic

  • Напреднали
  • *****
  • Публикации: 71
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #6 -: Aug 31, 2009, 15:51 »
точно това бях написал и аз но примерно може да натиснеш "d" и тогава няма да изкара никакво съобщение а чака да натиснеш "y" или "n"

Edit: ХАХАХААХАХ много промени станаха :D
Активен

B4 02 B2 4C CD 21 B2 61 CD 21 B2 6D CD 21 B2 65 CD 21 B2 72 CD 21 B4 4C B0 00 CD 21 00 00 00 00

completer

  • Напреднали
  • *****
  • Публикации: 347
  • Distribution: Debian 6.0
  • Window Manager: Gnome
    • Профил
    • WWW
Re: getchar() не работи от пъривя път.
« Отговор #7 -: Aug 31, 2009, 16:10 »
Извинявай, ама няма как да се мине без критика... Прочети много внимателно за функциите, как се извикват, за стека на извикванията и рекурсията... Връщането във функцията, от която си извикал дадена функция, не става с нейно извикване или с goto, става с изход от извиканата функция. Ти имаш функция А, която вика функция Б, която вика А и т.н. - на това му се вика косвена рекурсия.

mara@OVNI:~$ ./a.out
HELLO
ENTER
Go back to main menu? (y/n)y
HELLO
ENTER
Go back to main menu? (y/n)Go back to main menu? (y/n)y
HELLO
ENTER
Go back to main menu? (y/n)Go back to main menu? (y/n)y
HELLO
ENTER
Go back to main menu? (y/n)Go back to main menu? (y/n)n
Exitting..
Go back to main menu? (y/n)Go back to main menu? (y/n)n
Exitting..
Go back to main menu? (y/n)Go back to main menu? (y/n)n
Exitting..
Go back to main menu? (y/n)Go back to main menu? (y/n)n
Exitting..
mara@OVNI:~$

Ето ти още един резултат от изпълнението с два пъти "y". Като прочетеш за извикванията на функции и си начертаеш схема на това, което правиш, сам ще си обясниш това, което се получава.
И не забравяй, че програмите винаги работят правилно, просто програмистите им казват да правят грешни неща ;)

ПС. Коя е тая книга, дето четеш от нея? Гледам 2рата функция ти е тип int и завършва с return 0, новите C стандарти не изискват такова нещо, има си тип void за функция..

Първо благодаря на всички за отговорите!!!
Ето я въпросната книга http://www.bulbooks.com/book-1451.html
много съм доволен от нея!
Всъщност още не съм чел за нещата които спомена по-горе, до тук което съм чел за функциите е как се създават такива и как се извикват останалото видято в кода ми е плод на развинтената ми логика  ;D.Просто както казах в началото реших с натрупаните до сега знания да ги инвестирам в някаква програма.Напълно ми е ясно,че няма да стане нещо качествено с това което имам до сега, но предполагам и вие сте минали през този път, просто исках да опитам. :)
Активен

I'm using Linux and i'm proud of it!!!
I hate Windows and i'm also proud of it!!! :)

completer

  • Напреднали
  • *****
  • Публикации: 347
  • Distribution: Debian 6.0
  • Window Manager: Gnome
    • Профил
    • WWW
Re: getchar() не работи от пъривя път.
« Отговор #8 -: Aug 31, 2009, 16:20 »
1. преди използване инициализирай променливата ch
2. while сравнението (мисля) трябва да е от вида while(ch!='n' && ch!='y')....

Интересно дори и с инициализация не проработи(или пак греша здраво)
Код:
char ch;
printf("ENTER\n");
ch='m';
 while(ch!='n' && ch!='y'){
 printf("Go back to main menu? (y/n)");
 ch=getchar();
 if(ch=='y') main();
 else if(ch=='n'){
printf("Exitting..\n");
break;
Активен

I'm using Linux and i'm proud of it!!!
I hate Windows and i'm also proud of it!!! :)

Arvigeus

  • Напреднали
  • *****
  • Публикации: 123
  • Distribution: Arch Linux
  • Window Manager: Whatever
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #9 -: Aug 31, 2009, 16:27 »
Пробвай вместо ch=getchar(); да използваш scanf("%c", &ch);
И изполлзвай do-while, така поне ще се изпълни най-малко веднъж...
Активен

Nikolavp

  • Напреднали
  • *****
  • Публикации: 408
    • Профил
    • WWW
Re: getchar() не работи от пъривя път.
« Отговор #10 -: Aug 31, 2009, 16:54 »
Пробвай вместо ch=getchar(); да използваш scanf("%c", &ch);
И изполлзвай do-while, така поне ще се изпълни най-малко веднъж...
scanf не е хубаво изобщо да се ползва за каквото и да е, което не е тестови код :).
Активен

http://blog-nikolavp.rhcloud.com - простотиите, с които се занимавам в свободното време

Iron_steel

  • Напреднали
  • *****
  • Публикации: 28
  • Distribution: Arch Linux
  • Window Manager: Gnome
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #11 -: Aug 31, 2009, 18:05 »
Хайде някои да реши проблема. ??? ???
Дай да видим сорса на другата програма.
Активен

ludsic

  • Напреднали
  • *****
  • Публикации: 71
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #12 -: Aug 31, 2009, 19:31 »
Ето го и решението ( не е с getchar но все пак ...)

Код
GeSHi (C):
  1. #include<stdio.h>
  2. int multiply_second_line(void);
  3. int main (void)  
  4. {
  5. printf("HELLO\n");
  6. multiply_second_line();
  7. return 0;
  8. }
  9.  
  10. int multiply_second_line(void)
  11. {
  12. char ch;
  13. printf("ENTER\n");
  14. while(ch!='n' || ch!='y'){
  15. printf("Go back to main menu? (y/n)");
  16. scanf("%c", &ch);
  17. if(ch=='y')
  18.  {
  19.   getchar();
  20.   main(); /*ако "да" се връща в главната функция*/
  21.   break;
  22.  }
  23. else if(ch=='n'){
  24. printf("Exitting..\n");
  25. break;
  26.                 }
  27. getchar();
  28.                         }
  29.  
  30. return 0;
  31. }
  32.  


Изход :

Код
GeSHi (Bash):
  1. bash-3.1# ./a.out
  2. HELLO
  3. ENTER
  4. Go back to main menu? (y/n)y
  5. HELLO
  6. ENTER
  7. Go back to main menu? (y/n)y
  8. HELLO
  9. ENTER
  10. Go back to main menu? (y/n)y
  11. HELLO
  12. ENTER
  13. Go back to main menu? (y/n)n
  14. Exitting..
  15. bash-3.1# ./a.out
  16. HELLO
  17. ENTER
  18. Go back to main menu? (y/n)n
  19. Exitting..
  20. bash-3.1#
  21.  

Проблема до колкото разбрах е в това че изпълнява цикала 2 пъти без да пита за вход който се реши със scanf(...); и getchar();

Поздрави

ПС: сега пробвах и видях че няма нужда от замяната със scanf(...); може да се ползва и ch=getchar(); въпрос на избор :)

ПСС: и на ред 17 може да се сложи getchar(); и да се изтрият другите 2 по-долу ... пак работи
« Последна редакция: Aug 31, 2009, 19:35 от ludsic »
Активен

B4 02 B2 4C CD 21 B2 61 CD 21 B2 6D CD 21 B2 65 CD 21 B2 72 CD 21 B4 4C B0 00 CD 21 00 00 00 00

Iron_steel

  • Напреднали
  • *****
  • Публикации: 28
  • Distribution: Arch Linux
  • Window Manager: Gnome
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #13 -: Aug 31, 2009, 20:55 »
Ето още един вариант,обаче е написан с библиотеката ncurses.
Код
GeSHi (C):
  1. #include <ncurses.h>
  2. int main()
  3. {
  4.   initscr();                
  5.  
  6.   printw("\nHello World !!!\n");
  7.  
  8.   refresh();                
  9.   prompt();
  10.  
  11.   endwin();                  /* End curses mode                */
  12.  
  13.   return 0;
  14. }
  15.  
  16.  
  17.  
  18. int prompt(void)
  19. {
  20. char ch;
  21.  
  22.  
  23. do{
  24. printw("\nPrint it again:(y/n):");
  25. refresh();
  26. ch=getch();
  27.  
  28. if(ch=='y'){
  29.  
  30. main();
  31. break;
  32. }
  33.  
  34. else if (ch=='n'){
  35. printw("\nExitting ... Press any key to exit\n");      
  36. getch();
  37. break;
  38. }
  39. }while(ch!='y' || ch!='n');
  40.  
  41. return 0;
  42.  
  43. }
  44.  
Тук не трябва да се натиска Enter за  потвърждаване на избора,тъй като getch() е интерактивна.Проблема при getchar() e че, след като въведеш знака и натиснеш Enter знака за нов ред остава в клавиатурния буфер.Поне Аз така си мисля,поправете ме ако греша.
За да компилирате кода
Код:
gcc foo.c -lncurses
.
Дано не съм объркал някой.
Все още се уча на ncurses.Може да има нещо пропуснато.
« Последна редакция: Aug 31, 2009, 21:01 от Iron_steel »
Активен

romeo_ninov

  • Напреднали
  • *****
  • Публикации: 2155
    • Профил
Re: getchar() не работи от пъривя път.
« Отговор #14 -: Aug 31, 2009, 22:10 »
Iron_steel, много си прав, именно в тази функция е проблема :)
completer, използвай getc() за да получиш един символ от STDIN :) Именно знака за нов ред е причината за изпълнение на   printf("Go back to main menu? (y/n)");
Активен

0x2B|~0x2B