Prompt User to press enter to continue - c

I'm having trouble getting my program to accept hitting the enter key to continue... I tried getchar() two ways (as condition for while loop and just calling the routine) but one doesn't pause the program and await input it just goes through it all and the other pauses but wont let me enter anything or continue when i hit enter...
void RestOfGame(int r, int c, int mG, int **cGen,int **nGen) {
int i = 0, q = 0;
for (i = 2; i <= mG; i++) {
printf("\n(press enter to continue)\n\n");
getchar();
printf("Generation %d:\n", i);
ExamineReplace(r, c, cGen, nGen);
NewToOld(r, c, cGen, nGen);
DrawGrid(r, c, cGen);
}
}
I read in a few other threads something about having previously scanned in something and the buffer keeping the \n... tried some variations but I dont think i did it right.
Working on a windows platform, C language.
Any suggestions?
UPDATE: Thought I might add that this code is being run with a data file as input in redirection at command line. Would confuse my getchar() even though I've read through the entire file?

Use of the GetAsyncKeyState() function from the Windows.h header file allows us to check if a key has been pressed or currently being pressed.
So create a loop that checks the key state until it detects that it has been pressed.
which I have done in the wait_key() function
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#define UNUSED(x)((void)(x))
// Function that waits for key press
static inline void wait_key(const int vKey, const char* const phrase) {
// Display user message
puts(phrase);
// Wait until key is pressed
while (!GetAsyncKeyState(vKey))
Sleep(100);
}
int main(const int argc, const char** argv) {
UNUSED(argc); UNUSED(argv);
// VK_RETURN = enter key : https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
// Wait until enter key is pressed
wait_key(VK_RETURN, "Press enter to continue...");
return (int)EXIT_SUCCESS;
}

If you simply want to wait and have the user to press Enter to continue, then use fgets() and a short buffer. fgets() will block until input is received and will read and include the '\n' (generated by pressing Enter) in the buffer it fills.
You must be mindful of the state of stdin before you call fgets() (e.g. if a prior read with scanf and "%d" has left a '\n' in stdin unread, then it will appear that fgets() was skipped)
Your function above and be re-written as follows to wait until the user presses Enter
void RestOfGame (int r, int c, int mG, int **cGen,int **nGen)
{
int i = 0, q = 0;
for (i = 2; i <= mG; i++) {
char buf[128]; /* short buffer for fgets */
printf("\n(press enter to continue)\n\n");
fgets (buf, sizeof buf, stdin); /* fgets for input */
printf("Generation %d:\n", i);
ExamineReplace(r, c, cGen, nGen);
NewToOld(r, c, cGen, nGen);
DrawGrid(r, c, cGen);
}
}
Above, buf is a short 128-char buffer that will handle the Enter as well as 126 other slips of the finger before Enter and continue working fine.

Related

Accepting a single character in C?

What I intend to do is to get the character entered and used it as a pattern. I've tried using getchar() but it won't work. I've hear of using scanf but it skips and stops whenever I press "shift" for the special characters on my keyboard.
int i, j, n;
char c;
c = getchar();
printf("Enter value of n: ");
scanf("%d", &n);
printf("Enter a Character: ");
getchar();
for(i=1; i<=n; i++)
{
for(j=1; j<=i; j++)
{
printf("%c", c);
}
printf("\n");
}
You need to assign the value returned by getchar to the variable c, and you had a redundent call to getchar that's why it skips reading the desired input:
int i, j, n;
char c;
printf("Enter value of n: ");
scanf("%d", &n);
printf("Enter a Character: ");
scanf(" %c", &c);
for(i=1; i<=n; i++)
{
for(j=1; j<=i; j++)
{
printf("%c", c);
}
printf("\n");
}
You can use %c with scanf:
scanf("%d %c", &n, %c);
This eliminates the need for the two getchar calls.
The space is required; it tells scanf to skip whitespace.
The problem you have is that your assumptions on getchar(3) are incorrect. You think getchar() is going to return the next key pressed in the input stream, but you are incorrectly assuming that it will be done without buffering or system processing (the terminal driver gives the program complete lines, or even worse, if you are reading from a file, complete buffer blocks, that have to be buffered so you miss no characters from the input stream)
You are assuming incorrectly that the end of line you need to press for the input to be feeded to the program does not count in the input stream.
What actually happens is:
you feed a complete line (because the kernel driver works that way) so you press your character, and then you see nothing, not after you have pressed the return key.
once you press it, you have more than one character (depending on how many you pressed before hitting the return key) that will stay in the buffer, until they are so consumed by the program. Normally this happens when you have executed more getchar() or scanf() statements.
The idea of this buffering mechanism is to allow a programmer to process character by charcacter large amounts of text, without the overhead of making a system call per character reading (this is a costly operation) so think of getchar() not as a sample function to get new users introduced to the world of programming, but as a hint to experienced programmers to use efficiently without having to think on buffering large amounts of text.
With stdio package, every character counts, so you have to think slowly and minuciously when you feed input to getchar(3).
The next question is: Right, then how can I solve and stop my program until I press some key? The first answer, with the set of tools you have exposed here is, be careful on what you input, instead of asking for any key, ask the user to press the return key, and then, do something like:
printf("Hit <ENTER> to continue"); fflush(stdout); /* so we get the line out, bypassing the buffering mechanism */
int c;
while ((c = getchar()) != EOF && c != '\n') {
/* just ignore the character we have received */
}
/* c == '\n' || c == EOF, so we can continue */
or, if you prefer, you can write a function just to do this (as there can be so many criteria to implement it, nobody included such a function in the standard C library, my apologies for that. ;) )
void wait_for_enter()
{
/* I use stderr, for two reasons:
* o stderr is normally unbuffered, so there's no need to fflush()
* o stdout can be redirected, so the prompt will not be visible in
* case you want to save the output of your program.
*/
fprintf(stderr, "Hit <ENTER> to continue");
int c;
while ((c = getchar()) != EOF && c != '\n') {
/* just ignore the character we have received
* until we get the end of file (ctrl-d at the terminal)
* or a new line */
}
/* c == '\n' || c == EOF, so we can continue */
/* it's assumed that the user pressed the enter key, so the echoed
* enter already did a newline, no need to do it here */
} /* wait_for_enter */
In order to wait for any character and in raw mode, you need first to ensure your input comes from a terminal (you cannot do the following on a normal file), then you have to switch the terminal driver to raw mode, so each character is given immediately to the program and no line editing processing is done, and then set the stdin descriptor to no buffering at all. Only then, you can receive individual characters with getchar(3), one by one, as they are keyed in. I think this is far out of the scope of this question, as the code to do that is far more complex than the above.
EDIT
Following is a complete sample of a program that uses raw input to process characters as they are keyed in.
/* pru.c -- program to show raw input from the terminal.
* Author: Luis Colorado <luiscoloradourcola#gmail.com>
* Date: Fri Sep 20 08:46:06 EEST 2019
* Copyright: (C) 2019 Luis Colorado. All rights reserved.
* License: BSD.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h> /* see termios(3) for a description on terminal conf */
#define F(_fmt) __FILE__":%d:%s: " _fmt, __LINE__, __func__
/* this function switches the terminal into raw mode and returns a malloc(3)ed
* terminal configuration, so it can be later restored. BEWARE that the returned
* configuration info must be deallocated by free(3) once it's not needed anymore.
* In case of failure of any system call, the function returns NULL, and errno is
* set to the failing cause. */
struct termios *set_raw(int fd)
{
struct termios *ret = malloc(sizeof *ret), cfg;
if (!ret) return NULL;
int res = tcgetattr(fd, &cfg);
if (res < 0) goto error;
*ret = cfg; /* save it for return */
cfmakeraw(&cfg);
/* set it after all buffered characters in the driver have drained out */
res = tcsetattr(fd, TCSADRAIN, &cfg);
if (res < 0) goto error;
return ret;
error:
free(ret);
return NULL;
} /* set_raw */
/* restores the configuration back to the associated file descriptor */
int restore_cfg(int fd, struct termios *cf)
{
/* set it after all buffered characters in the driver have drained out */
return tcsetattr(fd, TCSADRAIN, cf);
} /* restore_cfg */
int main()
{
struct termios *cfg = set_raw(fileno(stdin));
if (!cfg) {
fprintf(stderr, F("stdin: %s\n"),
strerror(errno));
}
setbuf(stdin, NULL); /* stdin unbuffered */
setbuf(stdout, NULL); /* stdout unbuffered */
/* BEWARE that raw mode doesn't process any characters, so no Ctrl-C(interrupt), Ctrl-D(EOF), etc.
* will be available, only if you read from a file, you'll get EOF, but you'll not be able to produce
* that on the terminal, you'll need to swith to another console and kill the process. */
int c;
while ((c = getchar()) != EOF && c != '\033') { /* ESCAPE key('\033') is a safeguard to end input */
/* print the input char as an hex number */
printf("[%02x]", c);
}
if (cfg) { /* if we were able to set the terminal to raw mode */
/* restore config */
restore_cfg(fileno(stdin), cfg);
/* and free it */
free(cfg);
}
exit(EXIT_SUCCESS);
} /* main */
The full source code can be also downloaded from here.
You can use this program to see how input keys get mapped into characters, as you'll note that when you press the enter key, the raw input is [0d] (ascii char 13, CARRY RETURN) while in normal line mode you get '\n' which is [0a] or ASCII LINE FEED, instead (you can check this if you redirect input from the pru.c text file). Also you'll see that you are unable to specify EOF from the terminal driver with Ctrl-D and that Ctrl-C does not come to help. Well, I have included a safeguard, by ending the program in case you press the ESC key, which generates an ASCII ESCAPE character (\033). This is also commented in the source code.
All of this processing is done by the kernel driver, so all unix implementations get the same line end characters or interpret the control characters the same way.

How backspace can actually delete the string in getchar() loop

#include <stdio.h>
#include <conio.h>
#define ENTER_KEY '\n'
#define NULL_TERMINATOR '\0'
int main()
{
char name[100], input;
int counter = 0;
while(input != ENTER_KEY)
{
input = getchar();
name[counter] = input;
counter++;
}
counter--;
name[counter] = NULL_TERMINATOR;
printf("%s", name);
return 0;
}
If I write something, it should continuously saved in the name Array. And the counter should go up on every character I enter. But if I press Backspace, it looks like it makes the counter decreased. Because for example if I write "abcdef" and press backspace 3 times and change that to "abcxyz", and then press Enter. It prints "abcxyz".
It depends on the console driver. On most systems (at least Unix-like in line mode and in Windows console), the program does not receive the characters at the moment they are typed but the system prepares a line (up to the newline character) and sends the full line to the program.
In that case, the backspace if often used to edit that console buffer, meaning that the characters erased are actually removed before being handed to the program. So if you type abcdef<backspace><backspace><backspace>xyz<Return> the program will receive the following string: "abcxyz\n".
Beware, in a GUI program or in fullscreen text mode program like emacs or vi, the system is in raw mode (Unix language) and each character is received when it is typed. In that case, the program has to manage the input and erase its own character array when it receives a <backspace>.

Read each line in a text file when I press a key? C programming

I know how to use fgets inside a while loop to read an entire text file, but how can I press a key inside that loop, so it will read another line, one at a time?
I tried with a simple printf("Press any key\n") getchar() but nothing happens, I run the programm and it just doesn't do anything, not even show the first line. I'm assuming this may be a stupid question but I can't find how to do this :(
Here is what I've tried:
/* gcc readline.c -Wall -o read */
#include <stdio.h>
//#include <stdlib.h>
int main (int argc, char *argv[]) {
char url[]="dbus.log";
FILE *arq;
char info[1000];
arq = fopen(url, "r");
while (fgets(info, sizeof(info), arq) != NULL) {
printf("%s", info);
printf("Press Any Key to Continue\n");
getchar();
}
fclose(arq);
return 0;
}
The program isn't showing the prompts because stdio is buffered and you're not flushing. Use fflush(stdout); to ensure that buffered output is produced.
Like this:
fflush(stdout);
getchar();
Also note that by default stdin is in "cooked" IO mode. Pressing enter will produce a character, but other characters will be buffered until enter is pressed.

Non-Blocking i/o in c? (windows)

I'm trying to get a non-blocking I/O on a Windows terminal application (windows only, sorry!).
What if I want to have a short input time in wich the user can press a button, but if he doesn't the input stops and the program continues?
For example:
A timer that counts from 1 to whatever that stops when the user presses a certain key:
I should have a while loop, but if I do a getch or a getchar function it will stop the program, right?
I know I could use kbhit(); , but for the "program" I'm trying to make I need to know the input, not just IF THERE IS input!
Are there any simple functions that would allow me to read like the last key in the keyboard buffer?
From the documentation for _kbhit():
The _kbhit function checks the console for a recent keystroke. If the function returns a nonzero value, a keystroke is waiting in the buffer. The program can then call _getch or _getche to get the keystroke.
So, in your loop:
while (true) {
// ...
if (_kbhit()) {
char c = _getch();
// act on character c in whatever way you want
}
}
So, you can still use _getch(), but limit its use to only after _kbhit() says there is something waiting. That way it won't block.
Here is how to make a non blocking call to stdin in windows by using the right API :
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
void ErrorExit(LPSTR);
void KeyEventProc(KEY_EVENT_RECORD ker);
// Global variables are here for example, avoid that.
DWORD fdwSaveOldMode;
HANDLE hStdin;
void printToCoordinates(int x, int y, char* text)
{
printf("\033[%d;%dH%s", y, x, text);
}
int main()
{
printf("\033[H\033[J");
int i = 0;
char* s = "*";
DWORD fdwMode, cNumRead;
INPUT_RECORD irInBuf[128];
DWORD bufferSize = 0;
hStdin = GetStdHandle(STD_INPUT_HANDLE);
// Just a check to ensure everything is fine at this state
if (hStdin==INVALID_HANDLE_VALUE){
printf("Invalid handle value.\n");
exit(EXIT_FAILURE);
}
// Just a check to ensure everything is fine at this state
if (! GetConsoleMode(hStdin, &fdwSaveOldMode) )
ErrorExit("GetConsoleMode");
// Those constants are documented on Microsoft doc
// ENABLE_PROCESSED_INPUT allows you to use CTRL+C
// (so it's not catched by ReadConsoleInput here)
fdwMode = ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT;
if (! SetConsoleMode(hStdin, fdwMode) )
ErrorExit("SetConsoleMode");
while (i < 60) {
// The goal of this program is to print a line of stars
printToCoordinates(i, 5, s);
i++;
GetNumberOfConsoleInputEvents(hStdin, &bufferSize);
// ReadConsoleInput block if the buffer is empty
if (bufferSize > 0) {
if (! ReadConsoleInput(
hStdin, // input buffer handle
irInBuf, // buffer to read into
128, // size of read buffer
&cNumRead) ) // number of records read
ErrorExit("ReadConsoleInput");
// This code is not rock solid, you should iterate over
// irInBuf to get what you want, the last event may not contain what you expect
// Once again you'll find an event constant list on Microsoft documentation
if (irInBuf[cNumRead-1].EventType == KEY_EVENT) {
KeyEventProc(irInBuf[cNumRead-1].Event.KeyEvent);
Sleep(2000);
}
}
Sleep(100);
}
// Setting the console back to normal
SetConsoleMode(hStdin, fdwSaveOldMode);
CloseHandle(hStdin);
printf("\nFIN\n");
return 0;
}
void ErrorExit (LPSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
// Restore input mode on exit.
SetConsoleMode(hStdin, fdwSaveOldMode);
ExitProcess(0);
}
void KeyEventProc(KEY_EVENT_RECORD ker)
{
printf("Key event: \"%c\" ", ker.uChar.AsciiChar);
if(ker.bKeyDown)
printf("key pressed\n");
else printf("key released\n");
}
Please notice this work in brand new Terminal application but not in CMD (due to termcaps used in the code) but it will compile and you can run it anyway.

Clear the input buffer

I am trying to implement the press any key to continue function by using kbhit, however, after the user presses a key for example a, it will appear in the input buffer the next time I ask the user to input a value. How do you clear the input buffer?
my code for press any button to continue is below.
void
press_any_key(void)
{
int b=0;
while (b==0)
{
b=kbhit();
}
}
I'm trying to implement the press any key to continue function by using kbhit taking this statement as a need to wait for user keyboard input to continue the program execution the below code does the job,
void press_any_key(void)
{
while(1)
{
if(kbhit())
ch = getch();
printf("You passed %c\n", ch);
}
}
Note: the above snippet doesn't try to clear the input buffer. However kbhit() is non standard instead the right way is to read a character from stdin is using fgetc.

Resources