The scanf function is accepting values infinately - c

int n;
int a[maxsize];
int b[maxsize];
int c[maxsize];
int i;
printf("enter number of elements(disks)\n");
scanf("%d",&n);
printf("enter the elements in ascending order\n");
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
This works fine at times, but most of the times this piece of code is going into infinite loop,the 'scanf' in the loop is accepting values infinitely,i tried using the function (fflush) to clear the buffer contents,but still its not working, someone please help me out!! and please explain why !!

The code posted cannot enter an infinite loop, it's probable that the scanf() function is blocking until you input something like a Ctrl+D to end the input stream or maybe another integer, the problem is that you are handling the input in a very dangerous way because you are not checking for errors at all, what might do what you exactly want is this
#include <stdio.h>
#include <stdlib.h>
#define clearstdin() do {int chr; while (((chr = getchar()) != EOF) && (chr != '\n')); } while (0)
#define SOMELARGESIZE 1024
int main(void)
{
unsigned int index;
unsigned int size;
int result;
fprintf(stderr, "input the desired array size: ");
while (((result = scanf("%u", &size)) != 1) && (result != EOF))
{
fprintf(stderr, "invalid input, try again\n");
clearstdin();
}
if (result == EOF)
{
fprintf(stderr, "EOF recieved, ending the program\n");
return -1;
}
if (size < SOMELARGESIZE)
{
int array[size];
for (index = 0 ; index < size ; index++)
{
fprintf(stderr, "input an integer: ");
if (((result = scanf("%d", &array[index])) == 1) && (result != EOF))
fprintf(stdout, "\tarray[%d] = %d\n", index, array[index]);
else if (result == EOF)
{
fprintf(stderr, "EOF recieved, ending the program\n");
return -1;
}
else
{
fprintf(stderr, "invalid input, try again\n");
index -= 1;
}
clearstdin();
}
}
else
{
fprintf(stderr, "sorry, you requested a very large array\n");
return -1;
}
return 0;
}
the only problem with the program above, is that if you input any white space character while scanf() is wating for input it will do nothing, until valid or invalid input but specifically non-white-space input is entered.

scanf will return the number of items successfully scanned.
If scanf does not return 1, a character is read and scanf tries again.
scanf ( "%*[^0-9\n]"); will read and discard any characters that are NOT numbers or a newline.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 10
int main()
{
int i;
int n;
int a[SIZE];
printf("enter number of elements(disks) 0-%d\n", SIZE - 1);
while ( scanf("%d",&n) != 1 || n >= SIZE) {
scanf ( "%*[^0-9\n]");
printf ( "problem with input, try again\n");
}
printf("number was %d\n", n);
printf("enter the elements in ascending order\n");
for(i=0;i<n;i++)
{
while ( scanf("%d",&a[i]) != 1) {
scanf ( "%*[^-0-9\n]");//[^-0-9\n] characters NOT digit, newline or minus
printf ( "problem with input, try again\n");
}
printf("number for a[%d] was %d\n", i, a[i]);
}
return 0;
}

Related

User Input of Integers Infinite Loop Until User Inputs a Character (C)

i'm new to C - I have intended to make a program that shows whether the user input int is odd or even, until the user decides to quit by inputing a char 'x'. The loop kind of works by detecting odd numbers and terminating the program with 'x', however glitches with even numbers - why is that so? Would appreciate it if you could point out the flaws in the code. Thank you
#include <stdio.h>
int main(void)
{
int i=0;
char x = "x";
printf("Enter an integer to check whether your number is odd or even\n");
printf("Enter an ´x´ at any time to quit the program\n");
do
{
scanf("%d", &i);
if (i % 2 == 0)
{
printf("The number is even\n");
}
else if (i % 2 != 0)
{
printf("The number is odd\n");
}
else("%c ", &x);
{
scanf(" %c", &x);
getchar();
printf("The program will now terminate\n");
return 0;
}
}
while (i > 0);
i++;
return 0;
}
Very close but I've marked a couple of changes:
#include <stdio.h>
int main(void)
{
int i=0;
char x = 'x'; // Note: single quotes for char, double for string
printf("Enter an integer to check whether your number is odd or even\n");
printf("Enter an ´x´ at any time to quit the program\n");
do
{
int n = scanf("%d", &i); // Check if number was read
if (n == 1) {
if (i % 2 == 0)
{
printf("The number is even\n");
}
else // Only other possibility
{
printf("The number is odd\n");
}
} else // No number, see if there's an 'x'
{
scanf(" %c", &x);
if (x == 'x')
{
printf("The program will now terminate\n");
return 0;
} else
{
printf("Unknown input %c\n", x);
}
}
}
while (i > 0); // Will also end if user enters <= 0
return 0;
}

Returning -1 to a user defined function is resulting to termination of program with exit code 0

In this factorial program when entered any non numeric or negative number then the program should ask to renter the value but in the output the program is getting terminated.
Is it because I am returning -1 in display() function? If so then is it compulsory to return a variable (or other function) value to a function if the function is meant to return a value?
#include <stdio.h>
int display();
void fact_fun(int num_fact);
int main() {
int num = 0;
char next;
next = display();
if (next == -1) { //WHEN ANY CHARACTER OR NEGATIVE NUMBER IS ENTERED IT WILL ASK TO RENTER
printf("\nOnly positive number is allowed");
display();
}
while (next >= 0) { //WHEN NEGATIVE NUMBER IS ENTERED IT WILL END THE LOOP
num = next;
fact_fun(num);
next = display();
}
return 0;
}
int display() {
char inp[10] = { 0 };
int input;
int index = 0;
printf("\nEnter number to find factorial or press ENTER KEY to exit: ");
while (((input = getchar()) != EOF) & (index < 10)) {
if ((input >= '0') && (input <= '9')) {
inp[index++] = input;
} else
if (input == '\n')
break;
else
return -1;
}
input = atoi(inp);
return input;
}
void fact_fun(int num_fact) {
int fact = 1;
if (num_fact == 0) {
printf("\nFactorial of %d is 1", num_fact);
return;
} else {
for (int i = 1; i <= num_fact; i++) {
fact = fact * i;
}
printf("\nFactorial of %d is %d", num_fact, fact);
}
}
Also when I press ENTER KEY I am getting output as below:
Factorial of %d is 1
Enter number to find factorial or press ENTER KEY to exit:
And when enter \n the program gets terminate. As per my understanding it should treat the Enter key and \n same. If not then what is the difference and how should I check for ENTER KEY value?
User input is line buffered by default. It is much simpler for your purpose to read input one line at a time from the user, parse it to assert input validity and compute the factorial only for valid input.
Note also that you can simplify the computation as the special case for 0 is redundant with the code for the general case. You should also check for potential arithmetic overflow as the computation may easily exceed the range of type int and produce undefined behavior.
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int display();
void fact_fun(int num_fact);
int main() {
int num;
while ((num = display()) >= 0) {
fact_fun(num);
}
return 0;
}
int display() {
char buf[256];
char *p;
long value;
for (;;) {
printf("Enter number to find factorial or press ENTER KEY to exit: ");
if (fgets(buf, sizeof buf, stdin) == NULL || *buf == '\n')
return -1;
errno = 0;
value = strtol(buf, &p, 0);
if (p == buf) {
printf("Invalid input: not a number\n");
} else {
if (value < 0) {
printf("Invalid input: negative values not allowed\n");
} else
if (errno != 0 || value > INT_MAX) {
printf("Invalid input: value too large for type int\n");
} else {
return (int)value;
}
}
}
void fact_fun(int num_fact) {
int fact = 1;
for (int i = 1; i <= num_fact; i++) {
if (fact > INT_MAX / i) {
printf("Invalid input: arithmetic overflow\n");
return;
}
fact = fact * i;
}
printf("Factorial of %d is %d\n", num_fact, fact);
}
Here is your code with some corrections. There were two problems.
The first is that you have to finish reading the input until you reach an end of the line or EOF.
The second is that you need two error codes, one for invalid input, and a second for no-input. (Your comment in the code indicates that you want to exit on no-input).
#include <stdio.h>
#include <stdlib.h>
int display();
void fact_fun(int num_fact);
int main() {
//int num = 0;
char next;
while( 1 ) {
next = display();
if (next == -2) {
break;
}
if (next == -1) {
//WHEN ANY CHARACTER OR NEGATIVE NUMBER IS ENTERED IT WILL ASK TO RENTER
printf("\nOnly positive number is allowed");
}
else {
fact_fun(next);
}
}
return 0;
}
int display() {
char inp[10] = { 0 };
char c;
int input = 0;
int index = 0;
printf("\nEnter number to find factorial or press ENTER KEY to exit: ");
while ( ((c = getchar()) != EOF) && (c != '\n') && (index < 10)) {
if ( (c >= '0') && (c <= '9') ) {
inp[index++] = c;
} else {
input = -1;
break;
}
}
// Finish inputting the line
while ( (c != EOF) && (c != '\n') ) {
c = getchar();
}
if ( !input ) {
if ( index )
input = atoi(inp);
else
input = -2;
}
return input;
}
void fact_fun(int num_fact) {
int fact = 1;
if (num_fact == 0) {
printf("\nFactorial of %d is 1", num_fact);
return;
} else {
for (int i = 1; i <= num_fact; i++) {
fact = fact * i;
}
printf("\nFactorial of %d is %d", num_fact, fact);
}
}
In this factorial program when entered any non numeric or negative number then the program should ask to renter the value
The while loop in your main() function only loops to ask for new numbers until input() returns a negative number. You have even documented it:
while(next>=0) //WHEN NEGATIVE NUMBER IS ENTERED IT WILL END THE LOOP
...
When you do return -1 in input(), the function returns -1, which will set next to -1 and end the loop. The program then exists shortly after that.
There is nothing inherently wrong with using a return statement to return -1 from a user defined function. It's quite normal and common to do things like that.

*pointer_variable != '\0' is not working for the check of unsuccessful conversion in strtol() function

The program was not working for input 5r i.e in input when first character is number and remaining next character is any alphabet or negative number. For example when I am giving input as 5r in the output I am getting factorial of 5.
So I tried putting check for strtol unsuccessful conversion :-
if (p == buf || *p != '\0'){ printf("\nInvalid input: not a number\n");}
but I am getting output as Invalid input: not a number for all the input.
I found many similar questions in Stack Overflow. However, they don't resolve my issue. I am not understanding what is wrong with this simple check? How can I successfully detect errors from strtol?
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
int display();
void fact_fun(int num_fact);
int main()
{
int num;
while ((num = display()) >= 0)
{
fact_fun(num);
}
return 0;
}
int display()
{
char buf[256];
char *p;
long value;
for (;;)
{
printf("\nEnter number to find factorial or press ENTER KEY to exit: ");
if (fgets(buf, sizeof buf, stdin) == NULL || *buf == '\n')
return -1;
errno = 0;
value = strtol(buf, &p, 0);
if (p == buf || *p != '\0')
{
printf("\nInvalid input: not a number\n");
}
else
{
if (value < 0)
{
printf("\nInvalid input: negative values not allowed\n");
}
else if (errno != 0 || value > INT_MAX)
{
printf("\nInvalid input: value too large for type int\n");
}
else
{
return (int)value;
}
}
}
}
void fact_fun(int num_fact)
{
int fact = 1;
for (int i = 1; i <= num_fact; i++)
{
if (fact > INT_MAX / i)
{
printf("\nInvalid input: arithmetic overflow\n");
return;
}
fact = fact * i;
}
printf("\nFactorial of %d is %d\n", num_fact, fact);
}
The string you get from fgets contains '\n' as last char because you hit enter, so replace it with '\0'. That is a common error we C coders sometimes make.
Edit:
So I have tested it myself, and you're right, the reason is that strtoI does not mess with line terminator, so now it works fine with the following check:
*p != '\n'
The full working code is this:
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
int display();
void fact_fun(int num_fact);
int main()
{
int num;
while ((num = display()) >= 0)
{
fact_fun(num);
}
return 0;
}
int display()
{
char buf[256];
char *p;
long value;
for (;;)
{
printf("\nEnter number to find factorial or press ENTER KEY to exit: ");
if (fgets(buf, sizeof buf, stdin) == NULL || *buf == '\n')
return -1;
errno = 0;
value = strtol(buf, &p, 0);
if (p == buf || *p != '\n')
{
printf("\nInvalid input: not a number\n");
}
else
{
if (value < 0)
{
printf("\nInvalid input: negative values not allowed\n");
}
else if (errno != 0 || value > INT_MAX)
{
printf("\nInvalid input: value too large for type int\n");
}
else
{
return (int)value;
}
}
}
}
void fact_fun(int num_fact)
{
int fact = 1;
for (int i = 1; i <= num_fact; i++)
{
if (fact > INT_MAX / i)
{
printf("\nInvalid input: arithmetic overflow\n");
return;
}
fact = fact * i;
}
printf("\nFactorial of %d is %d\n", num_fact, fact);
}

dealing with string input in C

I am trying to input string into fixed size char array.
I have a questions:
when I input a string which is bigger than the char array, the array become bigger without any additional declaration. I want to make the code only take the string that 'equal or smaller than the char array'.
Thank You.
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
/***************************Function****************************/
int string_length(char s[]) {
int c = 0;
while (s[c] != '\0')
c++;
return c;
}
/**************************************************************/
char *str;
int arrSize;
void opt1()
{
printf("Enter array size: ");
scanf("%d", &arrSize);
arrSize=arrSize+1;
str = malloc(arrSize);
return;
}
void opt2()
{
printf("Enter characters: ");
scanf("%s", str);
length = string_length(str);
printf("your input is '%s'\n", str);
printf("your input length is '%d'\n", length);
return;
}
int main()
{
int input = 0;
while(input != 3) {
printf("\n NAME \n");
printf("\n");
printf("--------------------------------------\n");
printf("1) Making Array \n");
printf("2) Check Array \n");
printf("3) Quit\n");
printf("\nEnter selection: ");
scanf("%d", &input);
if( input == 1 ) {
/* */
opt1();
}
else if(input == 2) {
opt2();
}
}
return 1;
}
OP wants to read data, yet if larger that the target array, then do not change the target array.
// 1: success
// -1 EOF
// 0: Input too long
int read_array(char *buffer, size_t size) {
char tmp[size];
size_t i = 0;
int ch;
while ((ch = fgetc(stdin)) != EOF && ch != '\n') {
if (i < size) {
tmp[i++] = ch;
}
}
if (ch == EOF && i == 0) return EOF;
if (i >= size) return 0; // too many
memcpy(buffer, tmp, i);
buffer[i] = '\0';
return 1;
}
Normally code could use fgets(), but there are corner cases that fail to meet OP goals.
To read in a whole line, you can use fgets:
char line[80];
if (fgets(line, sizeof line, stdin) != NULL) {
// use the input
}
Now you won't need to check if the user entered more than the limit, since fgets will only get the first 79 (-1 for null terminator) characters; the remainder, if any, will be ignored.

int array doesnt get char values

I am absolutely brand new at programming and im not sure how to explain what im doing here.
The whole purpose of this piece is to enter values and then print them out in the same order. Now I wanna quit from entering values when pressing 'q' and so I have to scanf for chars but when I assign them back to the int array the values are not the same.
Hope that makes any sense to you but in any case heres my code:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5000
define flush fflush(stdin)
main() {
int input[SIZE] = {0},i = 0;
int counter = 0;
char inputs, quit;
do {
system("cls");
printf("Input number ('q' to quit and display numbers entered): ");
flush;
scanf("%c",&inputs);
flush;
if (inputs == 'q')
quit = 'q';
else {
input[i] = inputs;
counter++;
i++;
}
} while (i < SIZE && quit != 'q');
for(i = 0; i < counter; i++){
printf("%i.%i\n", i + 1, input[i]);
}
system("pause");
}
Ive been trying to do this on my own btw and also researched some information online regarding chars but couldnt find anything that would help me. Thanks a lot in advance.
You should nor be getting integer through %c neither assign char values to integers variables when that is not the intention, rather you should approach something like this
i = 0;
do {
printf("Enter a number: ");
scanf("%d", &input[i]);
i++; counter++;
printf("Do you want to continue? (y/n) : ");
scanf("%c", &inputs);
} while(inputs == 'y');
or u can get the number of integer inputs upfront and loop to get that much integers.
try instead (using your original code as much as possible):
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define SIZE 5000
int main()
{
int input[SIZE] = {0},i = 0;
int counter = 0;
char inputs[32];
bool quite = false;
do
{
system("cls");
printf("Input number ('q' to quit and display numbers entered): ");
// read a string from user, then convert when appropr
fgets(stdin, sizeof(inputs), inputs);
if (inputs[0] == 'q')
{
quit = true;
}
else if ( isdigit(inputs[0]) )
{
input[i] = atoi(inputs); // this will disregard any ending \n
counter++;
i++;
}
}
while (i < SIZE && !quit);
for(i = 0; i < counter; i++)
{
printf("%i.%i\n", i + 1, input[i]);
}
system("pause");
}
Another variant. This one will read in characters regardless of the use of whitespaces, since it uses getchar() rather than scanf(). I'm not sure if this is what you want. It seems as though you want integers but are reading characters. So this solution may be completely off base.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5000
int main()
{
char input[SIZE] = {0};
int i = 0;
int counter = 0;
char inputs;
printf("Input number ('q' to quit and display numbers entered): ");
while (((inputs = getchar()) != EOF) && (counter < SIZE))
{
if (inputs == 'q')
break;
input[counter] = inputs;
counter++;
}
for(i = 0; i < counter; i++)
{
printf("%c\n", input[i]);
}
system("pause");
return 0;
}
If you do really want ints, this one should work.
Notice that the atoi() function can be used to convert a C-string to an int.
The fgets() function is used to read the C-string from STDIN. However, scanf("%s", input); would also work here, as opposed to the scanf("%c", &inputs); that you used.
#include <stdio.h>
#include <stdlib.h>
#define INPUT_SIZE 1000
#define SIZE 5000
int main()
{
char input[INPUT_SIZE] = {0};
int numbers[SIZE] = {0};
int i = 0;
int counter = 0;
while ((fgets(input, sizeof(input), stdin) != NULL) && (counter < SIZE))
{
system("cls");
printf("Input number ('q' to quit and display numbers entered): ");
if (input[0] == 'q')
break;
numbers[counter] = atoi(input);
counter++;
}
for(i = 0; i < counter; i++)
{
printf("%i\n", numbers[i]);
}
system("pause");
return 0;
}

Resources