I have a do-while loop, and I want if I press ENTER key, the progress will continue, but q will finish the program. It is not working as the program will end straight away and does not wait for the user to enter the key.
Code below is my main code.
void displayGrid() {
bool progress = true;
printf("%s", "input round for round mode, moves for move mode");
scanf("%s", input);
toLowerCase(input);
if (strcmp(input, "round") == 0) {
do {
printf("Enter key ENTER to continue,Q for quit \n");
bool qoc = quitOrContinue();
if (qoc) {
} else if (!qoc) {
progress = false;
}
} while (progress);
}
}
This is my code for checking enter and q key:
bool quitOrContinue() {
if (kbhit()) {
char click = fgetc(stdin);
while (getchar() != '\n');
if (click == 0x0A) {
return true;
} else if (click == 'q') {
return false;
}
}
}
You do not need three functions to read a char from stdin.
Here's some psuedo-code to illustrate how to read one char. (I couldn't test it, so there may be some bugs in it).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
static bool quitOrContinue(void)
{
int click = fgetc(stdin);
if (click == 0x0A) {
return true;
} else if (click == 'q') {
return false;
}
/* Returns false in case of any other character */
return false;
}
int main(void)
{
bool condition = false;
do {
printf("Hello World\n");
printf("Enter q to quit or ENTER to continue.\n");
condition = quitOrContinue();
} while (condition);
return EXIT_SUCCESS;
}
You do not need the progress variable.
while (getchar() != '\n');
serves no purpose in your code, unless you're trying to flush stdin.
regarding:
printf("%s", "input round for round mode, moves for move mode");
You could use:
printf("input round for round mode, moves for move mode");
regarding:
scanf("%s", input);
What happens when one inputs more than size characters?
Limit length:
scanf("%6s", input);
Related
I want so that when the user enters e it will run my function called enter and scan in values but all I get is VECRQ?:, why is this? Did I call upon the function wrong?
I tried having the while loop to 1 also instead of menuoption != 'q' didn't work. I was thinking that with the menuoption is not equal to 'q' it will keep the loop running until the user actually enters 'q' to shut the program off.
#include <stdio.h>
int enter(int measurments[], int nrOfmeasurments)
{
while(nrOfmeasurments<10)
{
printf("Enter measurment #%d (or q to quit): ",nrOfmeasurments+1);
int oneMeasurment;
int readInteger = scanf("%d",&oneMeasurment);
if(readInteger)
{
measurments[nrOfmeasurments] = oneMeasurment;
nrOfmeasurments ++;
//return nrOfmeasurments;
}
else
{
char tmp;
scanf(" %c",&tmp);
break;
}
}
if(nrOfmeasurments==10)
{
printf("Array is full\n");
}
return nrOfmeasurments;
}
int main(void)
{
int measurments[10];
int nrOfmeasurments;
char menuoption;
printf("Measurment tool 2.0\n");
while (menuoption != 'q')
{
printf("VECRQ?:\n");
scanf(" %c",&menuoption);
if (menuoption == 'e')
{
//int MeasurmentData[10];
//int nrOfmeasurments;
//enter(measurments, nrOfmeasurments);
nrOfmeasurments = enter(measurments, nrOfmeasurments);
}
else if(menuoption == 'v')
{
}
else if(menuoption == 'c')
{
}
else if(menuoption == 'q')
{
printf("Exiting Measurment tool 2.0\n");
break;
}
}
}
Don't forget to init your variables with default values. Your problem is that nrOfmeasurments is not initialized and have some trash value. Also, set a default value to menuoption for some non q char to be sure, that your loop will be executed at least one time
I'm facing a problem with my code of a simple login program. The problem I'm facing is when I use a switch case or if statement for the option of logging in as an Admin or a User, the input for username is skipped and goes directly to password, and no matter what I type it gives me my error message. Instead, I want it to receive my username first then the password. It works fine on its own if there is only code for either Admin OR User, only one but not when there are more than one. Please help. Note: I'm using the same functions for both admin and user just to check if it works. The picture shows the output.I'm a C newbie, so minimal jargon perhaps? Code as follows:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
char username[18];
char pass[16];
void arequest()
{
printf("\nPlease Enter username:");
fflush(stdin);
gets(username);
printf("\nPlease Enter Password:");
fflush(stdin);
gets(pass);
}
void averify()
{
if (strcmp(username, "admin") == 0)
{
if (strcmp(pass, "apass") == 0)
{
printf("Successful Login");
_getch();
}
else
{
printf("Invalid Password");
_getch;
}
}
else
{
printf("Invalid Username");
_getch();
}
}
int choice;
int main()
{
printf("Welcome to Railway Reservation System");
printf("\n1.Admin \n2.User");
printf("\nPlease Enter your selection:");
scanf_s("%d", &choice);
if (choice == 1)
{
arequest();
averify();
}
else if (choice == 2)
{
arequest();
averify();
}
else
{
printf("Invalid Choice");
_getch();
return main;
}
return 1;
}
output
You are flushing the input stream with fflush(). fflush(stdin) is undefined behavior in most cases, and is at best implementation-dependent. To clear the extra characters from the input stream, consider writing a little function like this:
void clear_stream(void)
{
int c;
while ((c = _getch()) != '\n' && c != EOF)
continue;
}
Remove the calls to fflush(). You do not need to clear the stream after gets(username) since gets() discards the newline. Add a call to clear_stream() after this line in main():
scanf_s("%d", &choice);
There may be extra characters, including a newline, left in the input stream after the call to scanf_s(), and these need to be removed before trying to read user input again. In some cases scanf()_s (and scanf()) will skip over initial whitespaces in reading input, but _getch() and getchar() will not. This illustrates one of the dangers of using scanf().
printf("\nPlease Enter your selection:");
scanf("%d", &choice);
clear_stream();
Also, gets() is considered so dangerous that there is never a reason to use it for anything at all. Use fgets() instead. fgets() does keep the newline, where gets() discards it, so I often write my own version of gets() using fgets() that is safe:
char * s_gets(char *st, int n)
{
char *ret;
int ch;
ret = fgets(st, n, stdin);
if (ret) {
while (*st != '\n' && *st != '\0')
++st;
if (*st)
*st = '\0';
else {
while ((ch = getchar()) != '\n' && ch != EOF)
continue; // discard extra characters
}
}
return ret;
}
The library conio.h is nonstandard, as are the functions _getch() and scanf_s(). You should use the stdio.h functions getchar() and scanf(). The value returned by scanf() is the number of successful assignments, and you should check this to be sure that the input is as expected. In your program, if the user enters a letter at the selection prompt, no assignment is made, and the value of choice remains uninitialized. The code continues without handling this problem. choice could be initialized to some reasonable value, such as int choice = -1;. Alternatively, you can check the return value from scanf() to see if an assignment was made, and proceed accordingly.
I noticed that you are returning 1 from main(). You should return 0 unless there is an error. And, I see that you return main in the event of an invalid choice. Maybe you meant to return 1 here? And it appears that you have forgotten to #include <string.h> for the strcmp() function.
Finally, I don't understand why username, pass, and choice are global variables. This is a bad practice. These should be declared in main() and passed to functions as needed. It would be a good idea to #define the global constants MAXNAME and MAXPASS instead of hard-coding the array dimensions.
I didn't intend this to be a full-scale code review when I started, but that is what it turned into. Here is a revised version of your program that implements the suggested changes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNAME 18
#define MAXPASS 16
void clear_stream(void)
{
int c;
while ((c = getchar()) != '\n' && c != EOF)
continue;
}
char * s_gets(char *st, int n)
{
char *ret;
int ch;
ret = fgets(st, n, stdin);
if (ret) {
while (*st != '\n' && *st != '\0')
++st;
if (*st)
*st = '\0';
else {
while ((ch = getchar()) != '\n' && ch != EOF)
continue; // discard extra characters
}
}
return ret;
}
void arequest(char username[MAXNAME], char pass[MAXPASS])
{
printf("\nPlease Enter username:");
s_gets(username, MAXNAME);
printf("\nPlease Enter Password:");
s_gets(pass, MAXPASS);
}
void averify(char username[MAXNAME], char pass[MAXPASS])
{
if (strcmp(username, "admin") == 0)
{
if (strcmp(pass, "apass") == 0)
{
printf("Successful Login");
getchar();
}
else
{
printf("Invalid Password");
getchar();
}
}
else
{
printf("Invalid Username");
getchar();
}
}
int main(void)
{
char username[MAXNAME];
char pass[MAXPASS];
int choice;
printf("Welcome to Railway Reservation System");
printf("\n1.Admin \n2.User");
printf("\nPlease Enter your selection: ");
if (scanf("%d", &choice) == 1) {
clear_stream();
if (choice == 1)
{
arequest(username, pass);
averify(username, pass);
}
else if (choice == 2)
{
arequest(username, pass);
averify(username, pass);
}
else
{
printf("Invalid Choice: %d\n", choice);
getchar();
return 1;
}
} else {
clear_stream(); // stream has not yet been cleared
printf("Nonnumeric input");
getchar();
}
return 0;
}
EDIT
The OP mentioned in the comments that scanf() was causing problems in Visual Studio. Apparently Visual Studio tries to force the use of scanf_s(). The issue with this function is not that it is inherently bad, just that it is nonstandard. One solution might be to use the s_gets() function already added to the code to read the user selection into a character buffer, and then to use sscanf() to extract input. This has an advantage in that there is no need to call the clear_stream() function after s_gets(), because s_gets() cleans up after itself, so the clear_stream() function could now be removed altogether from the program. This can be accomplished with only a small change in main():
char choice_buffer[10];
int choice;
...
if (s_gets(choice_buffer, sizeof(choice_buffer)) &&
sscanf(choice_buffer, "%d", &choice) == 1) {
if (choice == 1)
...
} else {
printf("Nonnumeric input");
getchar();
}
s_gets() reads up to the first 9 characters (in this case) of a line of user input into choice_buffer, which is an array that will hold chars (there is more space in choice_buffer than is needed to hold a single digit choice and a '\0'). If there is an error, s_gets() returns a NULL pointer, otherwise a pointer to the first char of choice_buffer is returned. If the return value of s_gets() was non-NULL, then sscanf() assigns the first int stored in the buffer to choice. If no int is found in the string, sscanf() returns a value of 0, failing the conditional test.
I'm using a while loop per below:
do {
scanf("%c", &turnChoice);
if (turnChoice == 'r')
{
invalidSelection = false;
}
else if (turnChoice == 'h')
{
invalidSelection = false;
}
else
{
printf("Invalid input.\n");
}
} while (invalidSelection == true);
However, before stopping for the user input, it runs the full loop once (so it displays "Invalid input" and then asks the user for a letter). What am I doing wrong?
My guess is that you have some input before the code you show, some input that you end with a newline, right?
The problem here is that the newline is still in the input-buffer when you call scanf to read a character, so that newline is what you read and get.
There is a very simple "trick" to tell scanf to read and discard leading white-space (like newlines), and that is to prepend a single space to the format string, so try e.g.
scanf(" %c", &turnChoice);
// ^
// |
// Note space here
After take char input, we need to take '\n' char which is giver by pressing the enter button
char turnChoice;
bool invalidSelection = true;
do {
scanf("%c", &turnChoice);// if you want to give leading space then use scanf(" %c",&turnChoice);
getchar();
if (turnChoice == 'r')
{
invalidSelection = false;
}
else if (turnChoice == 'h')
{
invalidSelection = false;
}
else
{
printf("Invalid input.\n");
}
} while (invalidSelection == true);
This might help, when you scanf put "%*c" after your first character to ignore the enter key that you hit after entering the input. Code is as follows:
do {
scanf("%c%*c", &turnChoice);
if (turnChoice == 'r')
{
invalidSelection = false;
}
else if (turnChoice == 'h')
{
invalidSelection = false;
}
else
{
printf("Invalid input.\n");
}
} while (invalidSelection == true);
I need a help with the following function, it's expecting an integer input; and when I insert something like "F" (non-numerical characters ), the program gets stuck, it doesn't show any output or let me insert more inputs.
how can this be fixed?
int input_legality(int game_board[FIELD_ROWS][FIELD_COLS])
{
int input=0;
while(1)
{
if(scanf("%d", &input)==1)
{
if(input==DOWN || input==LEFT || input==RIGHT || input==UP)
{
return input;
}
else
if(input==EXIT)
{
printf("\n program exited by user \n");
return 1;
}
else
if(input==PRINT)
{
printField(game_board);
continue;
}
else
{
fprintf(stderr,"your step is undefined, please try another one\n");
continue;
}
}
}
return 0;
}
It seems that "F" is left in stdin if scanf() does not read an integer.
One answer would be to scan a string if an integer is not detected...
Try to add something like
char bla[256];
scanf("%s",bla);
At the end of the while loop (or in case scanf("%d) failed)
Here is a basic "main" code :
#include <stdio.h>
#define DOWN 0
#define UP 1
#define LEFT 2
#define RIGHT 3
#define EXIT 4
#define PRINT 5
int input_legality()
{
int input=0;
while(1)
{
if(scanf("%d", &input)==1)
{
if(input==DOWN || input==LEFT || input==RIGHT || input==UP)
{
return input;
}
else{
if(input==EXIT)
{
printf("\n program exited by user \n");
return 1;
}
else{
if(input==PRINT)
{
printf("ble %d \n",input);
continue;
}
else
{
fprintf(stderr,"your step is undefined, please try another one\n");
continue;
}
}
}
}
//while(getchar() != EOF);
//fflush(stdin);
char bla[256];
scanf("%s", bla);
}
return 0;
}
int main ( int argc , char * argv [] )
{
int i;
for(i=0;i<42;i++){
input_legality();
}
return 0;
}
This scanf is the easy way : some other may be better.
Using switch-case may clarify the code.
Bye,
Francis
Always, always, always get (interactive) input a line at a time. That's how the user conceives it, so the program logic should be similar.
The POSIX getline function is very useful. Alternatively, you can use fgets and deal with overlong lines yourself (perhaps implementing getline, since it is pretty easy).
Once you've fetched a line of input, parse it (being sure to error on trailing garbage) using any method: sscanf, strtok_r, strtou?ll?, ...
I'm trying to create a program of a stopwatch using this Standard C-Free 5.0. Here's what I've got so far:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
char button;
int minutes=0, seconds=0, millisec=0;
int main(void)
{
while(1)
{
reset:
button = '\0';
int minutes=0, seconds=0, millisec=0;
printf(" %d : %d : %d ", minutes, seconds, millisec);
system("cls");
if(button == 'a')
{
while(1)
{
cont:
button = '\0';
Sleep(10);
millisec++;
if(millisec == 100)
{
millisec = 0;
seconds++;
if(seconds == 60)
{
seconds = 0;
minutes++;
}
}
printf(" %d : %d : %d ", minutes, seconds, millisec);
system("cls");
if(button == 's')
{
while(1)
{
button = '\0';
printf(" %d : %d : %d ", minutes, seconds, millisec);
system("cls");
if(button == 'a')
{
goto cont;
}
if(button == 'd')
{
goto reset;
}
}
}
}
}
}
}
I'm trying to start the stopwatch with a pressed of button 'a' but it wouldn't work. Using scanf() will pause the whole program. Is there a way to detect a button being pressed and continue the stopwatch program? I mean without pausing the program especially the pressing 's' to stop and pressing 'a' again to continue, while displaying the timer at all times.
This should help _kbhit and it's important to use _getch() after it.
#include <conio.h>
//...
int key;
while (1)
{
if (_kbhit())
{
key = _getch();
if (key == 'a')
printf("You pressed 'a'\n");
else if (key == 'd')
printf("You pressed 'd'\n");
}
}
Since you use system("cls");, this is probably on dos / Windows command prompt. You can try to see if conio.h is supported by your compiler.
If it is, kbhit() or _kbhit() (link to MSDN, you should check docs of your compiler's libraries for most accurate reference) seems to be what you need to use.
This is a system problem not C. In general, your hosting system provide buffering to inputs, so when you press a key, it is not delivered at that time to your program, it is buffered until some condition occurs (basically, an end-of-line is pressed).
Under Windows there is different calls you should make to get a keypress.
Under Unix, you should put your tty in non-canonical mode (there is a set of magic calls to tcgetattr and tcsetattr).
See that one for example
#include<stdio.h>
#include<conio.h>
#include<dos.h>
#include<time.h>
#include<windows.h>
main()
{
int choice, h,m,s; h=0; m=0; s=0; //--variable declaration--//
char p= 'p';
printf("Press 1 to start the timer\nPress 2 to exit\n");
printf("\nEnter your choice\n");
scanf("%d",&choice);
switch(choice) //--switch case --//
{
case 1:
{
while(1) //--while condition is true//
{
if(s>59) //--if seconds(s) is > 59--//
{
m=m+1; //--increment minute by 1--//
s=0;
}
if(m>59) //--if minutes(s) is > 59--//
{
h=h+1; //--increment hour by 1--//
m=0;
}
if(h>11) //--if hour(h) is > 11--//
{
h=0; //-Hour to 0--//
m=0;
s=0;
}
Sleep(1000); //--inbuilt function for 1sec delay--//
s=s+1;
system("cls"); //--Clear screen--//
printf("DIGITAL CLOCK");
printf("\n\nHOUR:MINUTE:SECOND");
printf("\n\n%d:%d:%d",h,m,s); //--Print time--//
printf("\n\nTo pause : press P\n");
if(kbhit()) //--Check if any button is pressed on keyboard--//
{
if(p==getch()) //--Check if P is pressed--//
{
system("pause"); //--Inbuilt function for pause and resume--//
}
}
}
break;
}
case 2:
exit(0); //--Exit --//
default:
{
printf("Wrong Choice");
}
}
getch(); //--Holding the screen--//
return 0;
}