Beginning C program freezing at scanf - c

I'm having a problem with scanf freezing. I've looked around and while some questions are similar, they haven't helped in solving my problem.
main(int argc, char **argv) {
//FILE *stream = stdin;
if (stdin == NULL) {
printf("Could not open file");
return 0;
}
int exists = 0;
char letter;
char next = 'H';
char word[30];
int frequency = -1;
int sample = -1;
char *channels;
channels=malloc(sizeof(7*sizeof(char)));
int bitres = -1;
int secondE = 0;
while (exists == 0) {
scanf("%c", &letter); //this is the problem, possibly scanf
printf("AFTER");
if (letter == EOF) {
// printf(letter);
printf("HEADER NOT DETECTED");
return 0;
}
I've pinpointed the problem using printf. I'm currently piping in another file through command prompt into this program. When I reach scanf it just hangs. If anyone knows the solution I would be very thankful.
On a side note, is using scanf bad practice? It's just as easy to assign stdin to a file pointer (I actually have this commented out) but scanf seemed just as easy.

what do you mean by freezing. i run this code. when your code reach in scanf it wait for your input. you give some input , then see what happen.
scanf is not a bad practice .
channels=(char*)malloc(sizeof(7*sizeof(char)));
int bitres = -1;
int secondE = 0;
while (exists == 0)
{
scanf("%c", &letter); // ok
printf("AFTER");
printf("\n");
printf("%c", letter);
printf("\n");
if (letter == EOF) {
// printf(letter);
printf("HEADER NOT DETECTED"); }
return 0;
}
scanf never return EOF also.

while (exists == 0)
{
scanf("%c", &letter); // ok
printf("AFTER");
printf("\n");
printf("%c", letter);
printf("\n");
if (letter == EOF) {
// printf(letter);
printf("HEADER NOT DETECTED"); }
return 0;
}
So when using this the
if (letter == E0F)
section above is a bit too literal. Why not just use a char to store your desired answer and use the following to create
if(strcmp(letter, *desired char here*) == 0){
just a guess considering the fact it may be client side if your scanf function is freezing only in debug but with the example above it is a bit more user friendly when reading the code and will not have any errors when dealing with other characters and integers later on in your program. Depending on what you want to accomplish with it.

Related

Is there a way of limiting scanf in C?

I am trying to write a correct console application for linked list usage, so i need to scan a number of a command in a infinite loop and do something due to switch case option. So i am using scanf for this but the problem is when the next line doesnt contain number it loops and starts printing not even default value.
`while(1)
{
printf("Enter a number of a command.\n");
scanf("%d",&command);
switch(command)
{
case -1:
....
default:
printf("Reenter command.\n");
break;
}
}
It seems like when i am reading the infinite amount of data stack gets rewrited. I know i have to limit the amount of symbols reading, but dont understand how to do this in right way.
Using gcc version 5.4.0 (GCC), c99 on Ubuntu 18.04.2 LTS
I don't have enough reputation to comment, but this might be what you are looking for. Also try to be more descriptive. I have pasted your code and the only problem I could find is that when you press enter without inserting a number(i.e. a letter) it skips. This should fix it:
int readInt(const char *message, int min, int max){
int num, control;
do{
printf("%s (%d a %d) :", message, min, max);
control = scanf ("%d", &num);
cleanBufferStdin();
if (control == 0)
{
printf("You should enter a number \n");
}
else{
if(num<min || num>max)
{
printf("Number is invalid.\n");
}
}
}
while(num<min || num>max || control ==0);
return num;
}
void cleanBufferStdin(void)
{
char chr;
do
{
chr = getchar();
}
while (chr != '\n' && chr != EOF);
}
I coded for a bit more, and in another interpretation of your question(this one not only detects if you just pressed enter but if you didnt place an integer i didnt check if negative numbers work) I used this function:
//DONT FORGET TO #DEFINE WRONG_REQUEST_MACRO "SOME MESSAGE"
void readString(const char message*, char arrayChars *, int maxChars){
int stringSize;
unsigned char flag=0;
do{
flag =0;
printf("%s", message);
fgets(arrayChars, maxChars, stdin);
stringSize = strlen(arrayChars);
if (stringSize == 1){
printf("[INFO]Empty request. You just pressed ENTER.\n");
flag=1;
}
if (atoi(arrayChars)==0&&arrayChars[0]!=0){
printf("[INFO]You didn't enter a number.\n");
flag=1;
}
} while (flag == 1);
if (arrayChars[stringSize - 1] != '\n'){
clearBuffer();
}else{
arrayChars[stringSize - 1] = '\0';
}
while (strchr(arrayChars, '\'') != NULL || strchr(arrayChars, '?') != NULL || strchr(arrayChars, '*') != NULL || strchr(arrayChars, '\"') != NULL){
printf("%s ' %s '", WRONG_REQUEST_MACRO, arrayChars);
break;
}
}
this should be used like
int command;
char message[20];//yes this could be used with a char pointer but lets assume op doesnt know how to allocate memory or work with char pointers it wouldn't change that much but if he does know how to do it he will promptly change
readString("something something i suppose\n",message,20);
command=atoi(message);
Welp the last although its filled with debugging "duplicates" should work

Why does my code not rewind and keep the inputs in the buffer?

I made this code while I was practicing C language. But apparently this code does not rewind the input. So when I enter some data type different than int, it is upposed to go back to beginning of the while loop and start the question again. But instead of doing that, it just prints stuff infinitely. Seems like it does not rewind what`s in the buffer. I was wondering why it does that. And I use online compiler because my environment does not allow downloading Visual Studio or any compiler.
void main()
{
char account[64];
char password[64];
int i, rAns;
while (1)
{
printf("1.already a member? Log in\n");
printf("2.register\n");
if (scanf("%d", &rAns) == 0)
{
printf("enter right answer\n");
rewind(stdin);
}
else
{
if (rAns < 1 || rAns > 2)
{
printf("enter one of the options\n");
}
else
{
break;
}
}
}
}
Using rewind() on standard input when standard input is a terminal does nothing useful. You can't seek on a terminal. You shouldn't try using fflush(stdin) either.
When you get 0 returned, the character that caused the failure is still in the input stream. At minimum, you need to read that character; usually, though, it is better to read the rest of the line since the user will be puzzled if you prompt them again and then process the rest of what they typed before.
That means you need something more like:
int main(void)
{
char account[64];
char password[64];
int i, rAns;
while (1)
{
printf("1.already a member? Log in\n");
printf("2.register\n");
if (scanf("%d", &rAns) == 0)
{
printf("enter right answer (1 or 2)\n");
int c;
while ((c = getchar()) != EOF && c != '\n')
;
}
else if (rAns < 1 || rAns > 2)
{
printf("enter one of the options (1 or 2)\n");
}
else
{
break;
}
}
return 0;
}
You should also detect EOF on the main scanf(). That requires:
int main(void)
{
char account[64];
char password[64];
int i, rAns;
while (1)
{
printf("1.already a member? Log in\n");
printf("2.register\n");
int rc;
if ((rc = scanf("%d", &rAns)) == EOF)
break;
else if (rc == 0)
{
printf("enter right answer (1 or 2)\n");
int c;
while ((c = getchar()) != EOF && c != '\n')
;
}
else if (rAns < 1 || rAns > 2)
{
printf("enter one of the options (1 or 2)\n");
}
else
{
break;
}
}
return 0;
}
The extra code assumes a C99 compiler which allows variables to be defined when they are needed, rather than requiring them to be defined at the start of a block. You can move the definitions to just after the preceding { if you're using an antiquated compiler.
Warning: no code was compiled while answering this question.

How do i remove NULL input in C?

My teacher has asked me to "Fool proof" my code from any sort of misuse, So I have come up with an
program that can remove any empty values (by disallowing them entirely)
Here is the Un-foolproofed code
#include <stdio.h>
#include <conio.h>
int main()
{
char text[16];
printf("Type something: ");
fgets(text,16, stdin);
printf("You typed: %s",text);
getch();
}
I have made some simple adjustments to ensure there is no error, however, i cannot get the if filter to work properly, as it still allows the NULL input
#include <stdio.h>
#include <conio.h>
int main()
{
char text[16];
int loop;
do
{
printf("Type something: ");
fgets(text,16, stdin);
if( text[0] == '\0')
{
printf("Try again");
system("cls");
loop=1;
}
else
{
loop = -1;
}
}
while(loop > 0);
printf("You typed: %s",text);
getch();
}
I've tried google and i cannot get a solid answer, this probably is some very simple line of code, but sadly i have no idea what it is.
Edit: it's fixed, the if statement should be:
if (text[0] == '\n')
Using the return value from fgets() is the best first step to fool-proofing user I/O.
char text[16];
printf("Type something: ");
if (fgets(text, sizeof text, stdin) == NULL) {
if (feof(stdin)) Handle_stdin_is_closed(); // no more input
if (ferror(stdin) Handle_IOerror(): // very rare event, more common with files
}
// Test is input is is only a '\n'
if (text[0] == '\n')
printf("Try again");
// Look for long line.
size_t len = strlen(text);
if (len + 1 == sizeof text && text[len - 2] != '\n') HandleLongLine();
The next step is to look for scan errors. Let's assume code is to read a long.
errno = 0;
char *endptr;
long = strtol(text, &endptr, 10);
if (errno) Handle_NumericOverflow();
if (text == endptr) Handle_InputIsNotNumeric();
while (isspace((unsigned char) *endptr)) endptr++;
if (*endptr != '\0') Handle_ExtraTextAfterNumber();
Although this is a lot of code, robust handling of hostle user input is best spun off to a helper function where lots of tests can be had.
char * prompt = "Type something: ";
long number;
int stat = GetLong(stdin, prompt, &number); // put all tests in here.
if (stat > 0) Handle_SomeFailure();
if (stat < 0) Handle_EOF();
printf("%ld\n", number);
fgets reads a whole line including the newline into the buffer and 0-terminates it.
If it reads something and then the stream ends, the read line will not have a newline.
If the line does not fit, it won't contain a newline.
If an error occurs before it successfully reads the first character, it returns NULL.
Please read the man-page for fgets: http://man7.org/linux/man-pages/man3/fgets.3.html
According to the fgets() man page
char *fgets(char *s, int size, FILE *stream);
//fgets() returns s on success, and NULL on error or when end of file
//occurs while no characters have been read.
so, you can check the return value of fgets()
n = fgets(text,16, stdin);
if that value is NULL, then nothing have been read.
you can do this by checking the value of n in a for loop,
if( n == NULL)
{
printf("Try again");
system("cls");
loop=1;
}
else
{
loop = -1;
}

The Loop continues forever

The following code compiles and works as expected, despite one frustrating error in program flow that I don't understand ..
The loop in the middle of the main function works fine if I pass 2 or 5 as input. However, when I pass -3 or anything below zero (such as a character, which return -1), the loop continues forever and the program doesn't even pause for me to provide input for the scanf function ..
#include <stdio.h>
#include <stdlib.h>
void getNum(char * prompt, int*num)
{
printf("%s", prompt);
scanf("%d", num);
}
int main(int argc, char ** argv)
{
int num = -1;
while(num < 0) { // problem here
getNum("Number of times you go to the gym in a week: ", &num);
}
return EXIT_SUCCESS;
}
I wonder were the mistake is ..
I noticed something strange .. When I change the loop to a do-while loop it works just fine ..
int main(int argc, char ** argv)
{
int num;
do {
getNum("Number of times you go to the gym in a week: ", &num);
} while (num < 0); // this works fine ..
return EXIT_SUCCESS;
}
Also, for some reason, I recompiled the code and it worked fine ..
Can anybody explain this ?
After accept answer
scanf("%d", num);, upon reading non-numeric input simple returns 0, leaving *num alone. The offending text is still in stdin and subsequent calls will get the same text and same results. Code should check the scanf() result value.
// weak
scanf("%d", num); // fails to consume offending input.
// good
*num = 0; // default answer
int retval;
do {
printf("%s", prompt);
retval = scanf("%d", num); // returns EOF, 0, or 1
// consume rest of line
int c;
while ((c = fgetc(stdin)) != '\n' && c != EOF);
} while (retval == 0); // repeat is no number read and stdin still open
[Edit]
Avoid using scanf(). Offer How to test input is sane as a solution to well handle reading int.
You could try clearing STDIN data after you tried scanf :
void getNum(char * prompt, int*num)
{
printf("%s", prompt);
scanf("%d", num);
// clean stdin
char c;
scanf("%c",&c);
while (c != '\n' && c != EOF) scanf("%c",&c);
}

Letter guessing game weird output

So here is my code:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#define MAX_GUESSES 4
int PlayGame(char guess);
int WinOrLose(char userguess, char solution);
int main()
{
FILE* infile;
char correctlet;
int games,
igame,
result;
infile = fopen("inputLet.txt", "r");
printf ("Welcome to the letter guessing game!\n");
printf ("Your job is to guess a random letter.\n");
printf("You can guess each letter a maximum of 4 times,\n");
printf ("and you will get a hint after every guess.\n");
printf ("LET'S DO THIS!\n\n>");
printf ("\nHow many games would you like to play (1-3)?\n>");
scanf ("%d",&games);
for(igame=0;igame<games;igame++)
{
fscanf(infile," %c",&correctlet);
printf("This is game %d\n", igame+1);
result = PlayGame (correctlet);
if (result == 0)
{
printf ("\nCongratulations, you guessed the right letter!\n");
}
else
{
printf ("\nUnfortunately, you did not guess the right letter. Better luck next time!\n");
}
}
return 0;
}
int PlayGame(char solution)
{
int guessnumber,
result;
char userguess;
guessnumber = 0;
while(guessnumber < MAX_GUESSES)
{
printf("Please enter your guess\n>");
scanf("%c", &userguess);
if (sizeof userguess == 0)
{
continue;
}
else if (sizeof userguess >=1)
{
printf ("Your guess was %c\n",userguess);
result = WinOrLose (userguess, solution);
if (result == 0)
{
return 0;
break;
}
else if (result == 1)
{
if (solution < userguess)
{
printf("The correct letter comes before %c alphabetically\n", userguess);
}
else if (solution > userguess)
{
printf("The correct letter comes after %c alphabetically\n", userguess);
}
guessnumber ++;
}
}
}
}
int WinOrLose (char userguess, char solution)
{
if(solution==userguess)
{
return 0;
}
else if (solution != userguess)
{
return 1;
}
}
The output asks for the number of games, and then it outputs please enter your guess your guess was (blank) The correct letter comes after (blank) Please enter your guess and THEN it allows for user input. So why is it going through one iteration of PlayGame without asking for user input? I have tried everything I can think of and can't fix the problem. I am compiling on VC++ 2010, if that helps.
Thanks in advance!
The simple answer is to flush your buffers.
The stdin buffer, the buffer that takes instructions from the keyboard (or a pipe) and submits it to the program occasionally gets some characters "stuck" in it. Junk characters that never quite get submitted, extra returns, etc. that will cause scanf() to think it reached the proper end, but actually hasn't.
fflush(stdin);
The function fflush "flushes" a buffer. The effect of this is to consume data from a buffer until the data received is the character '\0' (NULL). This means that it's reached the last of the data that is currently in the buffer.
Calling this before calling scanf() means that when scanf() is called, you reasonably know that the program will block on scanf() until you've submitted, and not just consume some junk from the buffer.

Resources