Program terminating abnormally if input is very large - c

#include<stdio.h>
#include<stdlib.h>
#define n ((sizeof(char)) * 100 )
int stringlength(char * str)
{
int count=0;
while(*str)
{
if(*str == '\n')
{
*str=0;
}
else
count++, str++;
}
return count;
}
int palin1(char *str, int k)
{
char * pend = str + k - 1;
if(*pend != *str)
return 0;
else
palin1(str+1, k-1);
return 1;
}
int palin(char *str)
{
int length = stringlength(str), f=0;
char *pend = str + length - 1;
while(str <= pend)
{
if(*str == *pend) f=1;
else
return (f = 0);
str++, pend--;
}
return 1;
}
main()
{
char * ps = (char *)malloc(n);
int flag;
if(ps == NULL) printf("Malloc Fail\n");
else
{
printf("Malloc Succeeded, you have memory of %d bytes\n", n);
printf("This program checks if String is Palindrome or not\n\
\nEnter your String: ");
fgets(ps, 100, stdin);
printf("You entered: %s of length %d", ps, stringlength(ps));
int i = 0;
printf("\n\nEnter:\n1.Using iteration\n2.Using Recursion ");
scanf("%d", &i);
switch(i)
{
case 1:
flag=palin(ps);
break;
case 2:
flag=palin1(ps,stringlength(ps));
break;
default:
printf("Invalid input");
}
if(flag) printf("\nYou entered a Palindrome");
else printf("\nNot a Palindrome");
}
free (ps);
return 0;
}
Why does the above program http://www.ideone.com/qpGxi does not give any output on putting the input:
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
I know fgets(ps,100,stdin) will take only 100 characters and not more than that, but why does the program halt execution?

You should check for fgets failure, as recommended by the fgets spec.
if ( fgets(ps,100,stdin) == NULL ) {
printf("Input failed.");
//check for 'feof' or 'ferror' here
return -1;
}
printf("You entered: %s of length %d",ps,stringlength(ps));
I don't see why fgets would be failing, but you would get an uninitialized character buffer back, which would crash printf.
EDIT: You should really pay attention to your compiler warnings, too.
prog.c:49: warning: return type defaults to ‘int’
prog.c: In function ‘main’:
prog.c:59: warning: ignoring return value of ‘fgets’, declared with attribute warn_unused_result
prog.c:63: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result
prog.c: In function ‘palin’:
prog.c:46: warning: control reaches end of non-void function
prog.c: In function ‘main’:
prog.c:52: warning: ‘flag’ may be used uninitialized in this function
You can see that even your compiler recommends checking fgets for null. Also, flag should be set to 0 in the default case, otherwise you will get undefined behavior if the user enters something other than 1 or 2.
EDIT 2: Oh for Christ's sake! your program works fine! You forgot to check "run program" in Ideone!!!
http://www.ideone.com/7ecZd

You cannot break a string literal just like that
printf("%s\n", "string literal **WRONGLY**\n
broken right after the line break.");
What you can do is use the preprocessor feature of joining successive string literals to make just one
printf("%s\n", "string literal **CORRECTLY**\n"
"broken because the preprocessor joins these 2 parts.");

It's terminating because there are characters left in the input stream if the input is too large. For example, if you wish to take only 5 characters using fgets but have given the input as -
StackOverflow
Overflow are left in the input stream. They need to be removed from the stream for further input operations to succeed. So, remove those extra characters from the stream using -
fgets(ps,100,stdin);
while (getchar() != '\n');
Since the input stream is struck with offending characters, the scanf statement that actually takes the user input is not working and jumping to subsequent operations.
Also initialize the flag variable to 0 other wise it has garbage values.

Related

Does scanf need to be checked for number of conversions if using a default switch statement?

I have a scanf function that takes an integer 1,2, or 0. My default statement will return to a loop if there is not an input of these integers. If a character is entered, the default case still works, displays an error and returns to main. My question is if I should be using another while loop to check the scanf function for an integer, or if it is okay to keep the default statement which will return for any invalid input.
int main(int argc, char* argv[]) {
int value;
value = length_orWeight();
while (value != 0) {
value = length_orWeight();
}
return 0;
}
int length_orWeight(void) {
int choice;
printf("\nWhat would you like to convert?\n0.End Program 1.Lengths 2.Weights: ");
scanf("%d", &choice);
clear_keyboard_buffer();
switch (choice) {
case 1:
convert_lengths();
return 1;
case 2:
convert_weights();
return 2;
case 0:
return 0;
default:
printf("\nError: You must enter 0, 1, or 2.\n");
return 3;
}
}
Not checking the return value of scanf is inadequate.
The C standard does not specify what happens to objects that are not assigned values because input terminated early (as when a non-matching character was found, an end-of-file was encountered, or an input error occurred). A common behavior may be for scanf to leave the object (choice) unchanged. If this occurs in your first execution of scanf, it will remain uninitialized. However, as the standard does not define what scanf does in this regard, other behaviors are possible. For example, a rudimentary scanf implementation could, upon starting to work on %d, initialize choice to zero, in anticipation of building a number in it digit-by-digit. When it then reads a character and finds some non-digit the user entered, it could terminate with a return value indicating no conversion was performed, with choice still set to zero.
If scanf does not return a value that indicates the a conversion was completed that assigned a value to an object you passed it, you do not know what value is in that object, even if you initialized the object prior to calling scanf. Therefore, before using the object at all, you must check the return value of scanf.
Eric Postpischil clearly stated that checking scanf's return value is necessary, but didn't point to the fact that it is a very bad function for reading input from the user. Better use fgets and sscanf:
// Reads one line
char *scanline(char *line, size_t size, FILE *istream)
{
if (!fgets(line, size, istream)) // Input failed
return NULL;
// Replace newline with null-terminator
size_t nl = strcspn(line, "\n");
line[nl] = '\0';
return line;
}
// Reads an int
bool scanint(int *i, FILE* istream)
{
char buffer[255];
if (!scanline(buffer, sizeof buffer, istream))
return false;
if (sscanf(buffer, "%d", i) != 1)
return false;
return true;
}
Also, make sure that clear_keyboard_buffer() is not fflush(stdin):
void clear_keyboard_buffer(void)
{
scanf("%*[^\n]"); // Read and discard everything until hitting a newline.
}
Here is how your code would look like:
int length_orWeight(void)
{
int choice;
printf("\nWhat would you like to convert?\n0.End Program 1.Lengths 2.Weights: ");
while (!scanint(&choice, stdin)) {
printf("Please enter a valid number: ");
};
// clear_keyboard_buffer(); // No longer necessary
switch (choice) {
case 1:
//convert_lengths();
return 1;
case 2:
//convert_weights();
return 2;
case 0:
return 0;
default:
printf("\nError: You must enter 0, 1, or 2.\n");
return 3;
}
}
int main(int argc, char* argv[])
{
int value;
value = length_orWeight();
while (value != 0) {
value = length_orWeight();
}
}

Using a user-inputted string from one function to another in C

So... the main question is how I can use the string that the user entered in another function? I know it would be a lot easier to do it all in the main function but we are forced to use as many separate ones as possible. Thanks in advance.
Following on from the comment, you most likely want to declare the str in a scope available to both functions:
int enterWord (char *str) {
...
scanf("%24s", str);
...
return str[0];
}
int menuScan (char *str) {
...
}
int main (void) {
char str[25] = {0};
int someint;
...
someint = menuScan (enterWord (str));
return 0;
}
or
int main (void) {
char str[25] = {0};
int someint, someotherint;
...
someint = enterWord (str);
...
someotherint = menuScan (str);
return 0;
}
You may want to employ a bit of additional error checking on the user input as well, e.g.:
int enterWord (char *str) {
printf ("Please enter a single word that is no more than 25 characters: ");
if (scanf ("%24s", str))
printf ("\nThanks! You entered: %s", str);
else
return -1;
return str[0];
}
...
int main (void) {
char str[25] = {0};
int someint, someotherint;
...
if ((someint = enterWord (str)) = -1) {
fprintf (stderr, "enterWord() error: input failure.\n");
return 1;
}
...
someotherint = menuScan (str);
return 0;
}
Remaining Issue With '\n' Left In Input Buffer
Your remaining problems come from the fact that after you call scanf, you are leaving the '\n' (cause by pressing [Enter]) in the input buffer stdin. The next time your program calls scanf it takes the '\n' left in the input buffer as the user input. (if you check, you will find it is using the value 0xa (or 10) which is the value for newline)
You have two options. You can use a loop to empty stdin:
int c;
while ((c = getchar()) != '\n' && c != EOF) {}
You can also use the assignment suppression operator of scanf to read and discard the newline, e.g.:
scanf ("%24[^\n]%*c", str)
Where %24[^\n] read upto 24 chars (not including the '\n' into str) and %*c which reads and discards a single character (the newline). That way your input buffer is empty before the next user input.
Here is a short working example:
#include <stdio.h>
int enterWord (char *str);
void menuOptions ();
int menuScan (char *str);
int main (void) {
char str[25] = {0};
if (enterWord (str) == -1) {
fprintf (stderr, "enterWord() error: input failure.\n");
return 1;
}
do {
menuOptions();
} while (!menuScan (str));
return 0;
}
int enterWord (char *str)
{
printf ("Please enter a single word that is no more than 25 characters: ");
if (scanf ("%24[^\n]%*c", str))
printf ("\nThanks! You entered: %s", str);
else
return -1;
return str[0];
}
void menuOptions ()
{
printf("\n\n========= MENU =========\n\n");
printf("Key Function\n");
printf("=== ========\n");
printf(" C Count the letters\n");
printf(" V Count the vowels\n");
printf(" R Reverse the word\n");
printf(" P Check if the word is a palindrome\n");
printf(" W Enter a new word\n");
printf(" Z Exit\n\n");
}
int menuScan (char *str)
{
/* always initialize variables */
char *p = str;
char menuChoice = 0;
int c = 0;
int charcnt = 0;
printf ("Please enter a character from the options above: ");
if (!scanf ("%c%*c", &menuChoice)) {
fprintf (stderr, "menuScan() error: input failure.\n");
return -1;
}
printf ("\nYou entered: %c\n", menuChoice);
c = menuChoice; /* I don't like to type */
/* validate input */
if (c < 'A' || ('Z' < c && c < 'a') || 'z' < c) {
fprintf (stderr, "menuChoice() error: input is not [a-z] or [A-Z]\n");
return -1;
}
/* convert to lowercase */
if ('A' <= c && c <= 'Z') c += 32;
switch (c) {
case 'c':
for (; *p; p++) charcnt++;
printf ("\n\nThere are '%d' letters in '%s'\n", charcnt, str);
break;
case 'z':
return -1;
default : printf ("(%c) invalid choice -> try again.\n", c);
}
return 0;
}
Compile
gcc -Wall -Wextra -finline-functions -O3 -o bin/menuscan menuscan.c
Example/Use
$ ./bin/menuscan
Please enter a single word that is no more than 25 characters: 0123456789
Thanks! You entered: 0123456789
========= MENU =========
Key Function
=== ========
C Count the letters
V Count the vowels
R Reverse the word
P Check if the word is a palindrome
W Enter a new word
Z Exit
Please enter a character from the options above: c
You entered: c
There are '10' letters in '0123456789'
========= MENU =========
Key Function
=== ========
C Count the letters
V Count the vowels
R Reverse the word
P Check if the word is a palindrome
W Enter a new word
Z Exit
Please enter a character from the options above: z
You entered: z
There are a lot of problems with your code, but I will address only the actual question you posed.
When you have a function which creates a result value to be used somewhere else, you need to return that value when the function ends. The 'return' keyword will do this, but you must bear in mind that the thing being returned must continue to exist after the function has ended (as noted by #David C. Rankin in the comments).
Locally declared variables will cease to exist when the function ends, so the solution is to declare them in a wider scope.
// declare the string in a wider scope
// provide one extra character space for the string terminator \0 character
char inputStr[25 + 1];
// pass the string to the function which will fill it with the entered string
// NOTE: to avoid risk of someone entering too many letters in the string, we
// also pass in the length of the string buffer
enterWord(inputStr, 25);
The changes to the enterWord function would be:
void enterWord(char* str, int length){
printf("Please enter a single word that is no more than %d characters: ", length);
// this should verify the length of the entered text to make sure it isn't too long... but that's not your question
scanf("%s", str);
printf("\nThanks! You entered: %s", str);
}
In the scope where you declared inputStr, the string will now contain the data entered by the user.
In this case we are returning the string from the function by a different mechanism than the 'return' keyword. Here we are passing a pointer to the first letter of the buffer space, so that the function will fill the original inputStr buffer from inside the function.
If you must use a more 'functional' coding paradigm, you might want to consider allocating space for the buffer on the heap using 'malloc', you would then need to remember to use 'free' at a later point in the code to release that allocated memory and avoid a memory leak, which is why that would not be my preferred solution in this case.

scanf validation sits and waits for another input. Why?

I was working on this sample exercise, and everything works as I would like it to, but there is one behavior I don't understand.
When providing input: if I make consecutive invalid entries everything seems to work great. But if I enter a number different from 1,2,3 in the case of the first question, or 1,2 in the case of the second question, the program just sits there until a new input is given. If another invalid entry is made, it goes back to the error "invalid entry" message, and if an appropriate number is entered, everything moves along fine.
I do not understand why it stops to wait for a second input...anyone?
Thanks guys.
#include <stdio.h>
static int getInt(const char *prompt)
{
int value;
printf("%s",prompt);
while (scanf("%d", &value) !=1)
{
printf("Your entry is invalid.\nGive it another try: %s", prompt);
getchar();
scanf("%d", &value);
}
return value;
}
int main() {
int wood_type, table_size, table_price;
printf("Please enter " );
wood_type = getInt("1 for Pine, 2 for Oak, and 3 for Mahogany: ");
printf("Please enter ");
table_size = getInt("1 for large, 2 for small: ");
printf("\n");
switch (wood_type) {
case 1:
table_price = (table_size == 1)? 135:100;
printf("The cost of for your new table is: $%i", table_price);
break;
case 2:
table_price = (table_size == 1)? 260:225;
printf("The cost of for your new table is: $%i", table_price);
break;
case 3:
table_price = (table_size == 1)? 345:310;
printf("The cost of for your new table is: $%i", table_price);
break;
default:
table_price = 0;
printf("The cost of for your new table is: $%i", table_price);
break;
}
}
You most likely need to flush your input buffer (especially with multiple scanf calls in a function). After scanf, a newline '\n' remains in the input buffer. fflush does NOT do this, so you need to do it manually. A simple do...while loop works. Give it a try:
edit:
static int getInt(const char *prompt)
{
int value;
int c;
while (printf (prompt) && scanf("%d", &value) != 1)
{
do { c = getchar(); } while ( c != '\n' && c != EOF ); // flush input
printf ("Invalid Entry, Try Again...");
}
return value;
}
The blank line you get if you enter nothing is the normal behavior of scanf. It is waiting for input (some input). If you want your routine to immediately prompt again in the case the [Enter] key is pressed, then you need to use another routine to read stdin like (getline or fgets). getline is preferred as it returns the number of characters read (which you can test). You can then use atoi (in <stdlib.h>) to convert the string value to an integer. This will give you the flexibility you need.
example:
int newgetInt (char *prompt)
{
char *line = NULL; /* pointer to use with getline () */
ssize_t read = 0; /* number of characters read */
size_t n = 0; /* numer of chars to read, 0 no limit */
static int num = 0; /* number result */
while (printf ("\n %s ", prompt) && (read = getline (&line, &n, stdin)) != -1)
{
if ((num = atoi (line)))
break;
else
printf ("Invalid Input, Try Again...\n");
}
return num;
}
If some invalid input is entered, it stays in the input buffer.
The invalid input must be extracted before the scanf function is completed.
A better method is to get the whole line of input then work on that line.
First, put that input line into a temporary array using fgets(),
then use sscanf() (safer than scanf because it guards against overflow).
#include <stdio.h>
int main(int argc, const char * argv[]) {
char tempbuff[50];
int result, d , value;
do
{
printf("Give me a number: ");
fgets( tempbuff, sizeof(tempbuff), stdin ); //gets string, puts it into tempbuff via stdin
result = sscanf(tempbuff, "%d", &value); //result of taking buffer scanning it into value
if (result < 1){ //scanf can return 0, # of matched conversions,
//(1 in this case), or EOF.
printf("You didn't type a number!\n");
}
}while (result < 1);
//some code
return 0;
}
Knowledge from: http://www.giannistsakiris.com/2008/02/07/scanf-and-why-you-should-avoid-using-it/

How to check if the user input an integer using scanf

I created a program to make a diamond out of *'s. I am looking for a way to check if the type of input is an integer in the C language. If the input is not an integer I would like it to print a message.
This is what I have thus far:
if(scanf("%i", &n) != 1)
printf("must enter integer");
However it does not display the message if it's not an integer. Any help/guidance with this issue would be greatly appreciated!
you can scan your input in a string then check its characters one by one, this example displays result :
0 if it's not digit
1 if it is digit
you can play with it to make your desired output
char n[10];
int i=0;
scanf("%s", n);
while(n[i] != '\0')
{
printf("%d", isdigit(n[i]));
i++;
}
Example:
#include <stdio.h>
#include <string.h>
main()
{
char n[10];
int i=0, flag=1;
scanf("%s", n);
while(n[i] != '\0'){
flag = isdigit(n[i]);
if (!flag) break;
i++;
}
if(flag)
{
i=atoi(n);
printf("%d", i);
}
else
{
printf("it's not integer");
}
}
Use fgets() followed by strtol() or sscanf(..."%d"...).
Robust code needs to handle IO and parsing issues. IMO, these are best done separately.
char buf[50];
fgets(buf, sizeof buf, stdin);
int n;
int end = 0; // use to note end of scanning and catch trailing junk
if (sscanf(buf, "%d %n", &n, &end) != 1 || buf[end] != '\0') {
printf("must enter integer");
}
else {
good_input(n);
}
Note:
strtol() is a better approach, but a few more steps are needed. Example
Additional error checks include testing the result of fgets() and insuring the range of n is reasonable for the code.
Note:
Avoid mixing fgets() and scanf() in the same code.
{ I said scanf() here and not sscanf(). }
Recommend not to use scanf() at all.
strtol
The returned endPtr will point past the last character used in the conversion.
Though this does require using something like fgets to retrieve the input string.
Personal preference is that scanf is for machine generated input not human generated.
Try adding
fflush(stdout);
after the printf. Alternatively, have the printf output a string ending in \n.
Assuming this has been done, the code you've posted actually would display the message if and only if an integer was not entered. You don't need to replace this line with fgets or anything.
If it really seems to be not working as you expect, the problem must be elsewhere. For example, perhaps there are characters left in the buffer from input prior to this line. Please post a complete program that shows the problem, along with the input you gave.
Try:
#include <stdio.h>
#define MAX_LEN 64
int main(void)
{ bool act = true;
char input_string[MAX_LEN]; /* character array to store the string */
int i;
printf("Enter a string:\n");
fgets(input_string,sizeof(input_string),stdin); /* read the string */
/* print the string by printing each element of the array */
for(i=0; input_string[i] != 10; i++) // \0 = 10 = new line feed
{ //the number in each digits can be only 0-9.[ASCII 48-57]
if (input_string[i] >= 48 and input_string[i] <= 57)
continue;
else //must include newline feed
{ act = false; //0
break;
}
}
if (act == false)
printf("\nTHIS IS NOT INTEGER!");
else
printf("\nTHIS IS INTEGER");
return 0;
}
[===>] First we received input using fgets.Then it's will start pulling each digits out from input(starting from digits 0) to check whether it's number 0-9 or not[ASCII 48-57],if it successful looping and non is characters -- boolean variable 'act' still remain true.Thus returning it's integer.

Unusual Behaviour while passing an array to a function

#include <stdio.h>
#define SIZE 5
void func(int*);
int main(void)
{
int i, arr[SIZE];
for(i=0; i<SIZE; i++)
{
printf("Enter the element arr[%d]: ", i);
scanf("%d", &arr[i]);
}//End of for loop
func(arr);
printf("The modified array is : ");
for(i=0; i<SIZE; i++)
printf("%d ", arr[i]);
return 0;
}
void func(int a[])
{
int i;
for(i=0; i<SIZE; i++)
a[i] = a[i]*a[i];
}
Output :::
While I'm entering integer elements the output is OK.But as I entered a float value like 1.5, it didn't ask for other elements and the O/P is as shown in the figure.I think it should implicitly typecast 1.5 to 1 but it didn't happen..can u plz tell why this happened ? All the info about the compiler is shown in the figure.
When you scanf("%d") a value like 1.5 the scanning will stop at the decimal point and return 1.
The next time you call scanf, the pointer will still point to the decimal point and your scan will return immediately because there are no digits there to scan.
You should be checking the return value from scanf - it gives you the number of items successfully scanned which will be 1 initially for the 1 before the decimal point, and 0 from then on.
As an aside, scanf stands for "scan formatted" and I'll guarantee you won't find anything more unformatted than user input.
Investigate looking into fgets for line input. Here's a copy of a function I often use for such purposes:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
Once you get a line in with that function, you can sscanf it to your heart's content, handling errors much easier.
What's happening is that scanf stops reading an integer when it sees the '.' character, and leaves it in the input buffer. Then subsequent calls to scanf fail because the next character is '.' and not something parseable as an integer.
How do you fix this? The first step is to forget you ever heard of scanf and always use fgets to read whole lines of input, then process them after you read them into a string buffer. You can use sscanf for this purpose, but a robust function like strtol would be a lot better.
Problem with buffer - I think the remaining part (.5) remains on the buffer.
use flushall(); after your scanf("%d..

Resources