How Does Char Variable Work in C - c

What I am trying to accomplish is prompting the user with the question of do they want to run the program again. They either type y or n. If y, it reruns the program. If no, it stops the program. Anything other than those two will prompt an error and ask the question again. I'm used to C# where strings are not complicated, but in C, I guess there technically isn't strings, so we have to use either char arrays or char pointers. I've tried both, none that work that way I want, but I'm probably the problem. This is what I have.
char answer[1] = "a";
while (strcmp(answer, "y") != 0 || strcmp(answer, "n") != 0)
{
printf ("\n\nWould you like to run the program again? Type y or n. Then, hit Enter.");
scanf ("%c", answer);
if (strcmp(answer, "y") == 0)
{
main();
}
else if (strcmp(answer, "n") == 0)
{
continue;
}
else
{
printf ("\nERROR: Invalid input was provided. Your answer must be either y or n. Hit Enter to continue.");
F = getchar();
while ((getchar()) != F && EOF != '\n');
}
}
I have other while loops similar to this that work as expected, but use a float. So I'm assuming the problem is me using char here. What happens right now is that it doesn't even prompt the user for the question. It just asks the question and shows the error right afterwards. I'm sure there are other things wrong with this code, but since I can't get the prompt to work, I cannot test the rest of it yet.

I suggest using a light weight getchar() instead of the heavy scanf.
#include <stdio.h>
int c; /* Note getchar returns int because it must handle EOF as well. */
for (;;) {
printf ("Enter y or n\n");
c = getchar();
switch (c) {
case 'y': ...
break;
case 'n': ...
break:
case EOF:
exit(0);
}
}

"a" is a string literal == char id[2]={'a','\0'} //Strings are
char arrays terminated by zero, in C
'a' is a char literal
strcmp is just "compare each char in two strings, until you hit '\0'"
scanf ("%c", ___); expect an address to write to as the second
argument. Functions in C cannot modify their arguments (they don't
have access to them--they get their own local copy) unless they have
a memory address. You need to put &answer in there.
Jens has already basically answered the question, you most likely want to use getchar so that you can detect EOF easily. Unlike scanf("%c",...), getchar will not skip spaces, and I believe both versions will leave you with the unprocessed rest of the input line (a newline character ('\n') at least) after each getchar. You might want to something like
int dump;
while((dump=getchar())!='\n' && dump!=EOF) {};
So that you discard the rest of the line once you've read your first character of it.
Otherwise, the next getchar will get the next unprocessed character of the same line. ('\n' if the line was a single letter).

Here is one way to do it. It is by no means the only way to do it, but I think it accomplishes what you want. You should not call the main function recursively.
#include <stdio.h>
#include <stdlib.h>
void run_program()
{
printf("program was run.");
}
int main() {
char answer[2] = "y\0";
int dump;
do {
if (answer[0] == 'y')
{
run_program(); /* Not main, don't call main recursively. */
}
printf ("\n\nWould you like to run the program again? Type y or n. Then, hit Enter.\n");
scanf ("%1s", answer);
/* Dump all other characters on the input buffer to
prevent continuous reading old characters if a user
types more than one, as suggested by ThorX89. */
while((dump=getchar())!='\n' && dump!=EOF);
if (answer[0] != 'n' && answer[0] != 'y')
{
printf ("Please enter either y or n\n");
}
} while (answer[0] != 'n');
return 0;
}
Using %s instead of %c, reads in the new line so that the new line character is not in the stdin buffer which would become answer then next time scanf was called.
The run_program function is just a function where you would put your program's logic. You can call it whatever you want. I did this to separate out the menu logic from the logic of the actual program.

Well, you are comparing two strings instead of characters.
If you want to compare two character you have to follow this syntax:
char c;
scanf("%c",&c);
if(c == 'y')
//do something
else
//do nothing

Related

Loop back to question instead of printing out "Try again"? (C)

this is my first day coding and I'm trying to see how the code work, how can I change Y/N to Yes/No and loop back questions if the answer is not Yes instead of printing out "Try again?" or make it better?
int main(void)
{
char answer;
int name;
printf("Enter Username: \n");
scanf("%s",&name);
printf("Is your username \"%s\"? Enter Y or N\n", &name);
while (scanf(" %c", &answer) == 1 && answer == 'Y')
{
char answer2;
Sleep(1000);
printf("Username confirmed\n");
Sleep(2000);
int pass;
printf("Enter your password: \n");
scanf("%s",&pass);
printf("Is your password \"%s\"? Enter Y or N\n", &pass);
while (scanf(" %c", &answer2) == 1 && answer2 == 'Y')
{
printf("Success!");
Sleep(1000);
exit;
}
printf("Try again..\n");
Sleep(1000);
exit;
}
Sleep(1000);
printf("Try again..\n");
Sleep(1000);
exit;
return 0;
}
My best advice, as Weather Vane told you in the comment section, is to try to compile your code, before making changes: you'll find out that it won't even compile, since there are some errors (https://godbolt.org/z/MdahM4sT8).
You should debug and try to figure out why it doesn't work, fix it, then move to the new "features".
You probably want to change the while() condition and read a sequence of characters (array of char) instead of a single char.
char answer[4];
while (scanf("%3s", answer) > 0 && strcmp(answer, "Yes") == 0)
char answer[4]; creates an array of characters (which can be called a string, even though C doesn't have that abstraction) of size 4.
You might want to know why we need a size of 4, since the longer answer we can get is "Yes". Well, a string in C is a sequence of characters (char), ending with a special character, called terminating character '\0'.
Therefore, when you read a string with scanf(), you need to reserve some space for the terminating character aswell, and scanf() will add it when reading a space or carriage return after your input string. So if you enter "Yes" and then press the Return key, your answer[4] buffer will look like: {'Y', 'e', 's', '\0'}.
%3s tells scanf() to read only the first 3 characters of the string (prevents security issues like buffer overflow).
int scanf(const char *format, ...)
Description
Reads formatted input from stdin.
Return Value
On success, the function returns the number of items of the argument list successfully read. If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror) and, if either happens before any data could be successfully read, EOF is returned.
Once you've read that string, you can use strcmp(), a function defined in `<string.h> header, that takes in 2 string parameters, and returns:
a negative value if the first precedes alphabetically the second;
0 if they're equal;
a positive integer if the second precedes alphabetically the second;
Therefore you can check if strcmp(answer, "Yes") == 0 to know if you've read Yes, and

Do-While loop in C - error at printing

I am making a little program that takes as input the answer to the question "Are you an adult?" as a character like that:
bool adult() {
char answer;
do {
printf("Are you an adult? [y/n]\n");
answer = getchar();
} while (!(answer == 'y' || answer == 'n'));
return (answer == 'y');
}
My aim was that the question should repeat itself if the answer is neither y or n. But this seems to have a bug:
When I answer something else (neither y or n), the question gets printed twice:
Are you an adult?
u
Are you an adult?
Are you an adult?
...
Why is this happening?
Also, I've tried the same method with scanf instead of getchar but there is the same bug. For this kind of program, should I use scanf or getchar and why?
Thanks!
Actually the extra '\n' in the answer with (yes) y or (no) n gets counted and it's printed twice. You just remember to get that dummy '\n'. Use another extra getchar(). The dummy getchar() is a solution to this problem.
bool adult() {
char answer;
do {
printf("Are you an adult? [y/n]\n");
answer = getchar();
getchar(); //~~~~~~~~~~~~~~~~~~~~> this is what gets the extra '\n'
} while (!(answer == 'y' || answer == 'n'));
return (answer == 'y');
}
You can check my other answer here.You will get a clear idea.
the input buffer in getchar() and scanf
EDIT: As pointed out by Random832 in case of yes\n the ye is consumed but not the s\n. so a better solution is to store the first character and consume every other character until \n using a do..while or while loop. Then check the first character. Or you can store the whole string as per your need and use the first character to get the answer.
EDIT 2: flushing is not a solution to this problem. Previously I mentioned it. iharob pointed out to me that. You can check this two answers to get a clear idea.
Flushing buffers in C
How to clear input buffer in C?
To make the code robuts, i.e. for it to work with any input, you might need to read all the characters that you are not going to consider as valid, including the '\n' that is sent when you press enter and flush the input buffer, which you can't do by using fflush(), because it's only defined for output buffers, you should also consider the case of an empty line, i.e. when the user presses Enter immediately, the following code does all what I describe
#include <stdio.h>
#include <stdbool.h>
bool
adult()
{
char answer;
do {
int chr;
printf("Are you an adult? [y/n] ");
answer = getchar();
if (answer == '\n')
continue;
while (((chr = getchar()) != EOF) && (chr != '\n'));
} while (!(answer == 'y' || answer == 'n'));
return (answer == 'y');
}

scan a variable and use it in do while loop

#include <stdio.h>
void main()
{
char ans='n';
do
{
printf("\n Enter yes or no:");
scanf("%c",ans);
printf("\n entered %c",ans);
}while(ans == 'y');
}
As do while the loop is getting exccuted and that scanf is working and prnting my answer (say my answer is y) , its coming for 2nd time but not doing the scan and getting exited . May i know the reason for this ? why it is happening and what is the correct way to handle the infinite loop.
First up, you're missing a & in the scanf:
scanf("%c", &ans);
^
Second, you're not handling the newline, and the %c format specifier doesn't ignore blanks. So you read a character, press return, and the next scanf is immediately satisfied by that \n. To ignore blanks in scanf try:
scanf(" %c", &ans);
^
Not only are you missing the &address-of operator as indicated in other answers, but you're also missing the return value checks. Consider if a user presses CTRL+Z in Windows, or CTRL+d in Linux, to close stdin. Your loop would run infinitely and freeze your app ;)
if (scanf("%c", &ans) != 1) {
break;
}
Alternatively, I would suggest using getchar because it's far cleaner:
int main(void) { /* NOTE: There is no "void main()" entrance point in C. main should always return 'int'. */
int c;
do {
c = getchar();
} while (c == 'y');
return 0;
}
Use fflush(stdin) to flush those return feeds.
But when you are inputting a single character, then why not use getchar()?
EDIT:
As correctly pointed out by cnicutar here, fflush(stdin) has undefined behaviour. There doesn't seem to be any inbuilt function to take care of that and hence must be taken care of in the code itself.
One example could be:
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
Thanks for pointing that out there!

Why does this if condition not work even if I enter the correct data?

#include < stdio.h >
#include < process.h >
rec();
main() {
int a, fact;
char question, n, y;
do {
printf("\nEnter any number ");
scanf("%d", & a);
fact = rec(a);
printf("Factorial value = %d\n", fact);
printf("do you want to exit.....(y/n):");
scanf("%s", & question);
}
while (question == n);
exit(0);
}
rec(int x) {
int f;
if (x == 1) return 1;
else f = x * rec(x - 1);
return f;
}
In this program I want to get factorial of the entered number, which I get. But I also want the user to say whether to exit or get the factorial of another number, which I can't do. It asks user but when I enter "n" it exits.
Where is the error?
You want
while (question == 'n');
Or
char question, n = 'n', y = 'y';
Though I find the 2nd version a little redundant.
Either way you need to change
scanf("%s"
to
scanf("%c"
To correctly read in a single char and not a string. Thanks RageD
One problem is the combination of:
char question, n, y;
scanf("%s", &question);
You are using %s to read a null-terminated string into a single character. Even if you hit 'y' and return, you'll be overwriting beyond the end of the variable. This is not good. (The good news is that "%s" skips over white space, including the newline after the number).
You either need to use "%c" in the format:
char question;
scanf(" %c", &question); // NB: The leading space is important!
or you need to use a string format and a string variable (and no &):
char question[10];
scanf("%9s", question);
If you use an array, you need to consider whether to use strcmp(), or whether to compare the first character from the input:
while (strcmp(question, "n") == 0);
while (question[0] == 'n');
You probably got told by the compiler that you'd not declared variable n so you added it. You probably need the loop to end with while (question == 'n');and then get rid of the (now) unused variablen(and the currently unused variabley`).
Note that if you use omit the space in the " %c" format string:
scanf("%c", &question);
then it will normally get the newline after the number, which won't be 'n', so your loop will exit every time, apparently without waiting for you to enter anything. You can finesse that with scanf(" %c", &question); which skips white space before reading a character.
You should test that scanf() received the input you expected each time you use it. The correct test for single item inputs is:
if (scanf(" %c", &question) != 1)
...input failed...
If you need to distinguish between EOF and conversion failure, you can capture the return from scanf():
int rc;
if ((rc = scanf(" %c", &question)) != 1)
...rc == EOF on EOF; rc == 0 on 'conversion failure'...
...a single character input can't easily fail...
...but if someone types 'a' instead of '9' when you're looking for a number...
Getting I/O right using scanf() is distressingly hard. Many experienced programmers simply don't use it; it is too hard to get right. Instead, we use fgets() or POSIX getline() to read a line of data, and then use sscanf() to parse it. There are many advantages to this, but a primary one is that the newline has been eaten so you don't run into problems with the variable question not containing the answer you expect.

C code for ignoring the enter key after input

I am having a problem with the Enter key or character in the stdin stream messing up following input calls.
let's say I have one input call, so I enter in the stuff.
but then takes the Enter key as input for the next input call.
I think in c++ there is cin.ignore() to do the trick.
I just can't find the C version.
The input methods are getchar() and gets().
Sorry if this is a duplicate. I couldn't find the question that matches mine.
thanks for any help!
printf("Do you want to view the lines? ");
int choice = getchar();
while (choice == 'y')
{
char line[80];
printf("What line do you want to see? ");
gets(line);
if (line != "all")
{
n = atoi(line);
printf("Line %d: %s\n",n,list[n]);
}
else
for (int i = 0; i<size; i++)
printf("%s \n",list[i]);
printf("Any more lines? ");
choice = getchar();
}
I admit that this is extremely basic, but still learning .
You simply need to keep calling getchar to consume the characters you don't want from the stream. If you know there's always a single additional character then it is as simple as making one additional call to getchar.
If you want to remove multiple characters from the stream or deal with situations where the input may actually contain something you really need you can do something like the code below instead of your choice = getchar().
do
{
choice = getchar();
} while(choice=='\n'); // Add any other characters you may want to skip
This will keep removing characters (in this case only if they are newline) but leave choice set to the first non-removed character.
By the way, you can't compare strings like that (!= "all") use the C string compare functions, e.g. strcmp().
More generically the C++ istream ignore can be roughly written in C as something like the code below; call with stdin to skip characters from the standard input:
int ignore(FILE *stream, int n, int delim)
{
int c;
while(n>0)
{
c = getc(stream);
if(c==EOF || c==delim)
{
return c;
}
n--;
}
return(c);
}

Resources