I'm writing a program that adds line numbers to C files. I get the filenames as command line arguments but I wanted the user to have a chance to enter them if they forget to when they run the program. I ask the user to if they want to enter filenames and then they answer 'y' or 'n'. They are given five tries to answer correctly if an invalid character is entered but after five tries the program prints an error message and terminates. If the user enters an invalid character I have it print '[y/n]?' to the screen to prompt the user for those letters. If an invalid character is entered though it goes through the loop twice and prints them out side by side. Why does this happen?
Compiler.c file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lineNumAdderHeader.h"
#include "miscellaneousHeader.h"
#include "errorCheckedFunctionsHeader.h"
int main(int argc, char *argv[]){
int i = 1;
char ch;
int answerTries = 0;
char *seperatedFilenames[argc - 1];
if (argc < 2){
fprintf(stderr, "No files were entered for compiling.\n");
answer: do{
if (answerTries == 0)
printf("Would you like to enter files for compiling [y/n]? ");
else if (!(answerTries < 5))
fatal("in main(). An invalid character was entered too many times.");
else
printf("[y/n]? ");
ch = getchar();
if (ch == 'n' || ch == 'N')
exit(0);
answerTries++;
} while (ch != 'y' && ch != 'Y');
}
else{
while (i < argc){
seperatedFilenames[i - 1] = argv[i];
i++;
}
}
i = 0;
while (i < (argc - 1)){
lineNumAdder(seperatedFilenames[i]);
i++;
}
}
Fatal Funciton:
/*Displays a fatal error*/
void fatal(char *errorMessage){
/*Holds the errorMessage*/
char completedErrorMessage[strlen(errorMessage) + 17];
/*Copies the error message into completedErrorMessage*/
strcpy(completedErrorMessage, "[!!] Fatal Error ");
strcat(completedErrorMessage, errorMessage);
/*Prints the error message to the screen*/
fprintf(stderr, "%s\n", completedErrorMessage);
/*Exit the program in failure*/
exit(-1);
}
Your getchar() call returns one character from the standard input. When a users enters an answer, he then hits an enter/return key which translates to new line character which is part of the line that is then sent to standard input.
What you should probably do is to only check first character returned by getchar and then, in loop, read and discard all characters until you get new line character (\n). Only then, you can proceed to ask the question another time.
You should use this loop because your user may enter several characters at once. For example he may enter "yes" which will count as 4 characters.
Try flushing the stream before completing the loop, with
fflush(stdin);
If you don't want to use this function, you could try this,
do{
if(answerTries!=0) //it should clear your newline char input
getchar();
if (answerTries == 0)
printf("Would you like to enter files for compiling [y/n]? ");
else if (!(answerTries < 5))
fatal("in main(). An invalid character was entered too many times.");
else
printf("[y/n]? ");
ch = getchar();
if (ch == 'n' || ch == 'N')
exit(0);
answerTries++;
} while (ch != 'y' && ch != 'Y');
hope it helped..
Related
I want to break this loop when the user press enters twice. Meaning, if the user does not enter a character the second time, but only presses enter again, the loop must break.
char ch;
while(1) {
scanf("%c",&ch);
if(ch=='') { // I don't know what needs to be in this condition
break;
}
}
It is not possible to detect keypresses directly in C, as the standard I/O functions are meant for use in a terminal, instead of responding to the keyboard directly. Instead, you may use a library such as ncurses.
However, sticking to plain C, we can detect newline characters. If we keep track of the last two read characters, we can achieve similar behavior which may be good enough for your use-case:
#include <stdio.h>
int main(void)
{
int currentChar;
int previousChar = '\0';
while ((currentChar = getchar()) != EOF)
{
if (previousChar == '\n' && currentChar == '\n')
{
printf("Two newlines. Exit.\n");
break;
}
if (currentChar != '\n')
printf("Current char: %c\n", currentChar);
previousChar = currentChar;
}
}
Edit: It appears that the goal is not so much to detect two enters, but to have the user:
enter a value followed by a return, or
enter return without entering a value, after which the program should exit.
A more general solution, which can also e.g. read integers, can be constructed as follows:
#include <stdio.h>
#define BUFFER_SIZE 64U
int main(void)
{
char lineBuffer[BUFFER_SIZE];
while (fgets(lineBuffer, BUFFER_SIZE, stdin) != NULL)
{
if (lineBuffer[0] == '\n')
{
printf("Exit.\n");
break;
}
int n;
if (sscanf(lineBuffer, "%d", &n) == 1)
printf("Read integer: %d\n", n);
else
printf("Did not read an integer\n");
}
}
Note that there is now a maximum line length. This is OK for reading a single integer, but may not work for parsing longer input.
Credits: chux - Reinstate Monica for suggesting the use of int types and checking for EOF in the first code snippet.
You can store the previous character and compare it with the current character and enter, like this:
char ch = 'a', prevch = '\n';
while(1){
scanf("%c",&ch);
if((ch=='\n') && (ch == prevch)){// don't know what needs to be in this condition
break;
}
prevch = c;
}
Note that the previous character by default is enter, because we want the program to stop if the user hits enter at the very start as well.
Working like charm now
char ch[10];
while(1){
fgets(ch, sizeof ch, stdin);
if(ch[0]=='\n'){
break;
}
}
I am trying to use getchar() to remove characters from the input buffer. In the following code, the user is asked to input a choice to select, and then depending on the choice, another input is required, either type int or type char (string).
In the int case, getcar() is not needed and scanf takes in input correctly. But in the char case, scanf fails to get input without using getchar() beforehand. Is there a reason why that is?
printf("Available Ciphers:\n1) Caesar Cipher\n2) Vigenere Cipher\nSelected Cipher: ");
if(scanf("%d", &choice) != 1){
printf("Error: Bad selection!\n");
exit(EXIT_SUCCESS);
} else if (choice != 1 && choice != 2){
printf("Error: Bad Selection!\n");
exit(EXIT_SUCCESS);
//If the choice entered is correct, then run the following.
} else {
if(choice == 1){
printf("Input key as nuumber: ");
if(scanf("%d", &caesarkey) != 1){ //Why is getchar() not needed here?
printf("Error: Bad Key!\n");
exit(EXIT_SUCCESS);
}
//morecode here
} else if (choice == 2){
printf("Input key as string: ");
while(getchar() != '\n'); //Why is this needed here?
/*Uses scanf and not fgets, since we do not want the
key to contain the newline character '\n'. This is
due to the fact that the newline character is not
considered in the function that encrypts and decrypts
plaintext and ciphertext.*/
if(scanf("%[^\n]s", vigencipherkey) != 1){
printf("Error, Cannot read inputted key!\n");
exit(EXIT_SUCCESS);
}
//More code here..
}
}
It seems that you are scanning for a string rather than an int, and as such, you are passing in an int rather than the address of an int.
Change this line
if(scanf("%[^\n]s", vigencipherkey) != 1){
To
if (scanf("%d", &vigencipherkey) != 1) {
In order to read the remainder of the line input by the user, you can use this function:
int flush_line(void) {
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
Notes:
c must be defined as int to accommodate for all values of the type unsigned char and the special negative value EOF.
you should test for '\n' and EOF otherwise you will have an endless loop on premature end of file without a trailing newline, such as would occur if you redirect the input of your program from an empty file.
you can test for end of file by comparing the return value of flush_line() with EOF.
so i have
system("clear");
printf( "Enter a value :");`
int c = getchar();
which results in the terminal asking for a character this way
Enter a value:
What i want is the program to suggest a value as if the user had typed the value but didn't press enter, like this:
Enter a value: 5
Then the user can press enter and getchar() will receive 5 or backspace the 5 and input whatever value they want
Is this possible?
This is one way you can do it
#include <stdio.h>
#include <stdlib.h>
int main(){
char input[100] = "5";
int pos = 1;
int c_read = 0;
printf("Enter a value: 5");
while (1){
c_read = getch();
if (c_read == 13 || c_read == -1){
printf("\n");
break;
}
if (c_read == 8){
if(pos == 0)
continue;
pos--;
input[pos] = '\0';
printf("\b \b");
}else{
if (pos == 99)
continue;
printf("%c", c_read);
input[pos] = c_read;
pos++;
input[pos] = '\0';
}
}
printf("You entered %s\n", input);
}
Ofcourse this uses the god awful getch. You can find that in the ncurses library on Linux and comes with MinGW on windows.
You could replace getch with alternative implementation to read characters from the keyboard.
Also I am leaving it to you to convert the string to number before using.
PS: You might also have to put a fflush(stdout) after every print if it is being buffered for you and changes are not reflecting.
I have just started off with C programming and while I was trying to write a programme to accept only y or n characters I came across that
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ch;
printf("Do you want to continue\n");
for (;;)
{
ch=getchar();
if (ch=='Y' || ch=='y')
{
printf("Sure!\n");
break;
}
else if (ch=='N'||ch=='n')
{
printf("Alright! All the best!\n");
break;
}
else
{
printf("You need to say either Yes/No\n");
fflush(stdin);
}
}
return(0);
}
When I run this code, and type in any other character other than Y/y or N/n, I receive the last printf statement (You need to say either Yes/No) as output twice.
I understand that this is happening because it considers enter, i.e, '\n' as another character.
Using fflush doesn't help as it's an infinite loop.
How else can I modify it so that the last statement is displayed only once?
You can use a loop to read any characters left using getchar():
ch=getchar();
int t;
while ( (t=getchar())!='\n' && t!=EOF );
The type of ch should int as getchar() returns an int. You should also check if ch is EOF.
fflush(stdin) is undefined behaviour per C standard. Though, it's defined for certain platforms/compilers such as Linux and MSVC, you should avoid it in any portable code.
Another option - use scanf ignoring white spaces.
Instead of ch=getchar();, just need scanf( " %c", &ch );
With this you can also get rid of fflush(stdin);
Like is said in my comment you should use int ch instead of char ch because the return type of getchar which is int.
To clean stdin you could do something like the following:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int ch,cleanSTDIN;
printf("Do you want to continue\n");
for (;;)
{
ch = getchar();
while((cleanSTDIN = getchar()) != EOF && cleanSTDIN != '\n');
if (ch=='Y' || ch=='y')
{
printf("Sure!\n");
break;
}
else if (ch=='N'||ch=='n')
{
printf("Alright! All the best!\n");
break;
}
else
{
printf("You need to say either Yes/No\n");
}
}
return(0);
}
Any way a do while will probably do the job for you:
#include <stdio.h>
#include <stdlib.h>
int main(void){
char ch;
int check;
do {
printf("Do you want to continue: ");
if ((scanf("%c",&ch)) == 1){
while((check=getchar()) != EOF && check != '\n');
if ((ch == 'y') || (ch == 'Y')){
printf("Alright! All the best!\n");
break;
} else if((ch == 'n') || (ch == 'N')){
printf("You choosed %c\n",ch);
break;
}else{
printf("You need to say either Yes/No\n");
}
}else{
printf("Error");
exit(1);
}
}while (1);
return 0;
}
Output1:
Do you want to continue: g
You need to say either Yes/No
Do you want to continue: y
Alright! All the best!
Output2:
Do you want to continue: n
You choosed n
Or we can simply use another break; statement after the last printf().
I am trying to add a feature to my C console application calculator that prompts the user to decide whether they want to perform another calculation using: y or n, but in testing, getchar() refuses to wait for input and the program proceeds as though it has received valid input. The following is a minimal example of the feature:
main()
{
char newCalculation;
do{
lengthFormula(); /* main calculation formula */
printf("Would you like to do another calculation? (Y/N)");
newCalculation = getchar();
}while(tolower( newCalculation ) == 'y');
if(tolower(newCalculation) == 'n'){
exitProgram(); /* exit the program */
}
while(tolower(newCalculation) != 'n' && tolower(newCalculation) != 'y'){
printf("This is not a valid response.\n Please enter \"Y\"
if you want to do another calculation,
or enter \"N\" to exit.\n");
newCalculation = getchar();
}
return 0;
}
When I run this, the program does not wait for input after:
Would you like to do another calculation? (Y/N)
, but instead proceeds as though it has received invalid input. The result is that it spits out the prompt and the invalid input notice one after the other without a space:
Would you like to do another calculation? (Y/N)
This is not a valid response.
Please enter \"Y\" if you want to do another calculation, or enter \"N\" to exit.
If I enter a "y" after this, main() returns 0 and the program terminates.
Is someone able to see where I went wrong here?
Why won't the console wait for input at getchar()?
Why does valid input terminate the program after the first invalid response?
P.S.: Please don't tell me to "read a book" or shoo me away to Dennis Ritchie or one of the previous SO discussions on input. I've been poring over Richie's discussion of I/O, as well as similar texts from Lynda.com and Wiley, and none of the previous "it won't wait for input" posts addresses my issue as far as I can tell.
#simplicisveritatis Here is the modification of your code that I tried. Still have the same getchar issues.
int main(void)
{
/* local variable declaration */
char newCalculation = 'y';
/* main function */
/*if(tolower( newCalculation ) == 'y')
{
lengthFormula(newCalculation);
}*/
do
{
lengthFormula();
printf("Would you like to do another calculation? (Y/N)");
newCalculation = getchar();
if( tolower( newCalculation ) == 'n' )
{
exitProgram();
}
while( tolower( newCalculation ) != 'n' && tolower( newCalculation ) != 'y' )
{
printf("This is not a valid response.\n Please enter \"Y\" if you want to do another calculation, or enter \"N\" to exit.\n");
newCalculation = getchar();
}
}while( tolower( newCalculation ) == 'y' );
return 0;
}
Your code has a lot of problems:
main should be:
int main(void){return 0;}
You need to cast getchar (read about getchar) and should be:
newCalculation = (char)getchar();
Your approach on do{}while; + while{} is also wrong used.
Try the following:
#include<stdio.h>
#include<stdlib.h>
int main(void){
int validate;
char menu_choice;
validate = 0;
do{
printf("Would you like another go?(y/n):\t" );
if(scanf(" %c", &menu_choice ) == 1){
if((menu_choice=='y') || (menu_choice=='Y')){
printf("You choosed Yes\n\n\n");
validate = 1;
}else if((menu_choice=='n') || (menu_choice=='N')){
printf("You choosed No\n\n\n");
validate = 2;
}else{
printf("Wrong Input.\n\n\n");
validate = 0;
}
}
}while( validate == 0 || validate == 1);
printf("Goodbye\n");
return 0;
}
Include your three cases: exit condition, wrong input and calculate within the while loop:
main(){
do{
printf("Would you like to do another calculation? (Y/N)");
// get input
char newCalculation;
newCalculation = getchar();
// exit condition
if(tolower(newCalculation) == 'n'){
exitProgram(); /* exit the program */
}
// wrong input condition
else if(tolower(newCalculation) != 'n' && tolower(newCalculation) != 'y'){
printf("This is not a valid response.\n Please enter \"Y\"
if you want to do another calculation,
or enter \"N\" to exit.\n");
// you should clear the input stream from the wrong input
}
else{
// calculate
lengthFormula();
}
}while(tolower(newCalculation) == 'y');
return 0;
}
Why won't the console wait for input at getchar()?
Most probably, your function lengthFormula() reads input (e. g. by using scanf() or whatever), but doesn't read the line ending character \n from the input buffer. Then after returning from lengthFormula(), the getchar() has to read remaining content from the input buffer rather than requesting fresh input.
Why does valid input terminate the program after the first invalid
response?
That's because your
while(tolower(newCalculation) != 'n' && tolower(newCalculation) != 'y')
does the same after a response of y as after a response of n - it leaves the loop and gets to the following
return 0;