Why does program terminate without taking input? - arrays

This is sample of my program:
#include <stdio.h>
void sum();
int main()
{
char choice[4];
do
{
sum();
printf("\nDo You want to restart the program: yes or no:\n");
fgets(choice, 4, stdin); //error point
} while (choice[0] == 'y' || choice[0] == 'Y');
printf("\nThanking You");
return 0;
}
void sum()
{
int a = 3, b = 4;
printf("sum of two number is %d", a + b);
}
In this program, only in the 1st iteration of while does it ask for input in choice and, on the next iteration the program auto terminates by taking any value in choice.
Following is the result after execution of code:
sum of two number is 7
Do You want to restart the program: yes or no:
yes
sum of two number is 7
Do You want to restart the program: yes or no:
Thanking You
[Program finished]
I am unable to understand that it takes input in choice while I haven't used scanf() (which leaves the new line character in the buffer). It may be it takes input from buffer that may be whitespace or other characters, but I don't know from where it came?

Your program is leaving a newline in the input buffer after the first prompt because there's not enough room for it in the buffer.
On the first call to fgets you give the string "yes" followed by a newline. The buffer has size 4 and you pass that size to fgets so it reads at most that many characters-1 to account for the terminating null byte. So there is still a newline left in the buffer.
That newline gets read immediately the next time fgets is called.
You should enlarge your buffer to handle more characters.

Your choice array is not large enough to hold all the input from the first loop. The second argument to the fgets function (4) tells it to read at most 3 characters (and it then appends a nul-terminator to the input). So, it leaves the newline character in the input stream, and that is read in the second loop (by itself).
Just increase your choice array size and the input limit to 5 (or more):
#include <stdio.h>
void sum();
int main()
{
char choice[5]; // Increase space for newline and nul
do {
sum();
printf("\nDo You want to restart the program: yes or no:\n");
fgets(choice, 5, stdin); // Inputs 'y', 'e', 's' and newline (4 chars) and appends a nul.
} while (choice[0] == 'y' || choice[0] == 'Y');
printf("\nThanking You");
return 0;
}
void sum()
{
int a = 3, b = 4;
printf("sum of two number is %d", a + b);
}
From fgets - cppreference (bolding mine):
Reads at most count - 1 characters from the given file stream and
stores them in the character array pointed to by str. Parsing stops if
a newline character is found, in which case str will contain that
newline character, or if end-of-file occurs. If bytes are read and no
errors occur, writes a null character at the position immediately
after the last character written to str.

Related

Program seems to be ignoring one instance of 'gets()' and show an error message when the user hasn't interacted with the program [duplicate]

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
int n=1,i,cont;
char string[50];
scanf("%d",&n);
while(n!=0){
gets(string);
cont=0;
for(i=0;i<strlen(string);i++){
if(string[i]=='.'){
cont++;
}
}
if(cont%2==0){
printf("S\n");
}else{
printf("N\n");
}
scanf("%d",&n);
}
return 0;
}
My problem is quite simple but troublesome, I want to read an integer value n, and then read a string, after that read n again, but whenever I run the program, it only reads the string value... but if I digit 0 the program ends... it's like my scanf is within the gets function.
Mixing scanf with gets or fgets is troublesome because they each handle newlines differently.
Get rid of the gets call (which is unsafe anyway) and replace it with the following scanf call:
scanf("%49s", string);
This will read at most 49 characters into string (i.e. one less that its size).
From OP's comments, it sounds like the goal is to be able to read strings containing spaces. While there are ways to accomplish this using scanf(), it would be better to use fgets(), which is at the least less error-prone.
The fgets() function can be used to read input for the number into a buffer, and this buffer can then be processed by sscanf() to extract the number. Since fgets() keeps the newline character, it is not left behind to interfere with the next I/O operation.
But, when fgets() is used to get the string, since the newline is retained, it may be desirable to remove it. This can be accomplished in a number of ways, but here strcspn() is used to provide the index of the first \r or \n character encountered; a \0 character is then written to this location, removing the terminating newline from the string.
The code below illustrates these suggestions. Note that both buffer[] and string[] are generously allocated to accommodate reasonably large inputs. If a user enters a large number of characters (more than 999 in this case), the extra characters are left behind in the input stream for the next I/O function call. Also note that the main loop has been streamlined a bit; now there is a for(;;) loop that never terminates, broken out of when the user enters 0 for the number. And, there is a nested loop within the main loop that prompts the user to enter a number until a valid number is entered. Since the #include <stdlib.h> was unnecessary, it was removed. Better code would check the values returned from the calls to fgets() for possible errors.
#include<stdio.h>
#include<string.h>
int main(void)
{
int n = 1, cont;
char buffer[1000];
char string[1000];
for (;;) {
/* Loop until user enters a number */
do {
printf("Please enter a number: ");
fgets(buffer, sizeof buffer, stdin);
} while (sscanf(buffer, "%d", &n) != 1);
/* Break on 0 */
if (n == 0) break;
/* Get a string, and remove trailing newline */
printf("Please enter a string\n");
fgets(string, sizeof string, stdin);
string[strcspn(string, "\r\n")] = '\0';
cont = 0;
for (size_t i = 0; i < strlen(string); i++) {
if (string[i] == '.') {
cont++;
}
}
if (cont % 2 == 0){
printf("S\n");
} else {
printf("N\n");
}
}
return 0;
}
When you enter 5 for an example, you hit a new line character afterwards.
So you are entering 2 characters: 5 and a new line character.
That new line character is causing your headache.
The new line character is also considered an input.
In order to ignore this new line char, simply add a new line that acts as a garbage collection:
char garbage[50];
scanf( "%d", &n);
fgets(garbage, sizeof(garbage), stdin);

What is the difference between scanf("%s", &str) and scanf("%s\n", &str)?

Input
There will be several lines in the input terminated with a line containing a single *. This last line
should not be processed. Each of the lines will contain either Hajj or Umrah.
Output
For each line of the input, output either Hajj-e-Akbar or Hajj-e-Asghar in separate lines without
quotations. For the exact format refer to the sample.
Here's my code for this problem.
#include <stdio.h>
int main()
{
char str[100];
int i = 1;
while (scanf("%s", &str))
{
if (str[0] == '*')
break;
else if (str[0] == 'H')
printf("Case %d: Hajj-e-Akbar\n", i);
else
printf("Case %d: Hajj-e-Asghar\n", i);
i++;
}
}
For the input
Hajj
Umrah
*
When I gave this input at a time, the program provides the expected output by printing
Hajj
Case 1: Hajj-e-Akbar
Umrah
Case 2: Hajj-e-Asghar
*
But after getting * as input, the program is waiting for an Enter. After hitting Enter, the program terminates. But I want my program to terminate, whenever it gets * as input, not by pressing Enter. Please help me here. But this is not my question. My question is for the same input-
Hajj
Umrah
*
When I take input by scanf("%s\n", &str). The program does not print the output Case 1: Hajj-e-Akbar after the first input Hajj but it prints the output for first input after taking the second input Umrah. Then the program is waiting for an Enter for the input *.
The output is like this
Hajj
Umrah
Case 1: Hajj-e-Akbar
*
Then I press Enter, it prints the output Case 2: Hajj-e-Asghar for the second input Umrah
and then waits for another input. This the output looks like after pressing Enter.
Hajj
Umrah
Case 1: Hajj-e-Akbar
*
Case 2: Hajj-e-Asghar
I don't understand how \n is making a difference in scanf.
Thank you.
I'm sorry if I can't explain my question correctly. I am new to programming.
scanf reads formated input, so when you use %s\n”, &str the string will consumed and stored in str as will the newline character , which will be present in the buffer when you press enter, the string will be stored and the newline character will be discarded.
Note that the correct usage is “%s\n”, str, str is already a pointer you shouldn't use &.
When you use “%s”, &str the newline character will be left in the buffer and will be consumed in the next loop, so str will be stored in the first iteration, and "\n" will be stored in str in the next iteration, only then you will be asked for input again, in the third iteration.
For completion, as stated in the comments bellow, as per the definition of scanf:
...any single whitespace character in the format string consumes all available consecutive whitespace characters from the input (determined as if by calling isspace in a loop). Note that there is no difference between "\n", " ", "\t\t", or other whitespace in the format string.
I would also advise you to limit the size of the string expected by scanf to avoid container overflow, something like %99s for a 100 charaters container like you have, and also check scanf return, in this case, it must be = 1 for each cycle.
To do what you want, which I gather is to get a character from stdin without pressing return you will need a SO specific method, here is a small example for Windows using <conio.h> library, and getch():
#include <stdio.h>
#include <conio.h>
int main()
{
int i = 1, c;
while (1)
{
if ((c = getch()) == '*')
return 0;
else if (c == 'H')
printf("Case %d: Hajj-e-Akbar\n", i);
else
printf("Case %d: Hajj-e-Asghar\n", i);
i++;
}
}
For Linux one option is to use also getch() from <ncurses.h> library, which you might need to install.
PS: Don't worry, your question is well built, specially being only the second in the site.
The trailing \n in the scanf is a bad idea: any whitespace character in the format string causes any sequence of whitespace characters to be discarded from the input stream. If reading from a file, you will not necessary have a problem but if you read from the terminal, scanf() will not return until you have typed the next item, and this will create major confusion as you experience, because the program's output will correspond to the previous item, not the one that was just typed... Never add trailing spaces or newlines in a scanf() format string.
You should test if scanf() returns 1 to avoid an infinite loop when it returns EOF at the end of file.
Note also that it is incorrect to pass &str: str is an array, passing it as str will effectively pass a pointer to its first element, which is correct.
Furthermore, you should tell scanf() the maximum number of characters that can be stored into the destination array to avoid undefined behavior on overlong input. Since the array is defined with a size of 100, the format string should be "%99s" to leave space for the null terminator.
Finally, you need to hit Enter after the final * for 3 combined reasons, each of which would force this behavior:
the terminal device driver is line buffered by default, so the input is not made available to the program until you type Enter.
the standard input stream (stdin) is line buffered by default, so it will read data from the system handle until it gets a newline, and only then does scanf() get a chance to see the first character of the entered line.
scanf("%s", str) will keep its input stream until it gets the end of the word, a whitespace character or the end of file, so it does not return when you type just *.
Here is a modified version:
#include <stdio.h>
int main() {
char str[100];
int i = 1;
while (scanf("%99s", str) == 1 && str[0] != '*') {
if (str[0] == 'H') {
printf("Case %d: Hajj-e-Akbar\n", i);
} else {
printf("Case %d: Hajj-e-Asghar\n", i);
}
i++;
}
return 0;
}

scanf not reading properly because of gets function

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
int n=1,i,cont;
char string[50];
scanf("%d",&n);
while(n!=0){
gets(string);
cont=0;
for(i=0;i<strlen(string);i++){
if(string[i]=='.'){
cont++;
}
}
if(cont%2==0){
printf("S\n");
}else{
printf("N\n");
}
scanf("%d",&n);
}
return 0;
}
My problem is quite simple but troublesome, I want to read an integer value n, and then read a string, after that read n again, but whenever I run the program, it only reads the string value... but if I digit 0 the program ends... it's like my scanf is within the gets function.
Mixing scanf with gets or fgets is troublesome because they each handle newlines differently.
Get rid of the gets call (which is unsafe anyway) and replace it with the following scanf call:
scanf("%49s", string);
This will read at most 49 characters into string (i.e. one less that its size).
From OP's comments, it sounds like the goal is to be able to read strings containing spaces. While there are ways to accomplish this using scanf(), it would be better to use fgets(), which is at the least less error-prone.
The fgets() function can be used to read input for the number into a buffer, and this buffer can then be processed by sscanf() to extract the number. Since fgets() keeps the newline character, it is not left behind to interfere with the next I/O operation.
But, when fgets() is used to get the string, since the newline is retained, it may be desirable to remove it. This can be accomplished in a number of ways, but here strcspn() is used to provide the index of the first \r or \n character encountered; a \0 character is then written to this location, removing the terminating newline from the string.
The code below illustrates these suggestions. Note that both buffer[] and string[] are generously allocated to accommodate reasonably large inputs. If a user enters a large number of characters (more than 999 in this case), the extra characters are left behind in the input stream for the next I/O function call. Also note that the main loop has been streamlined a bit; now there is a for(;;) loop that never terminates, broken out of when the user enters 0 for the number. And, there is a nested loop within the main loop that prompts the user to enter a number until a valid number is entered. Since the #include <stdlib.h> was unnecessary, it was removed. Better code would check the values returned from the calls to fgets() for possible errors.
#include<stdio.h>
#include<string.h>
int main(void)
{
int n = 1, cont;
char buffer[1000];
char string[1000];
for (;;) {
/* Loop until user enters a number */
do {
printf("Please enter a number: ");
fgets(buffer, sizeof buffer, stdin);
} while (sscanf(buffer, "%d", &n) != 1);
/* Break on 0 */
if (n == 0) break;
/* Get a string, and remove trailing newline */
printf("Please enter a string\n");
fgets(string, sizeof string, stdin);
string[strcspn(string, "\r\n")] = '\0';
cont = 0;
for (size_t i = 0; i < strlen(string); i++) {
if (string[i] == '.') {
cont++;
}
}
if (cont % 2 == 0){
printf("S\n");
} else {
printf("N\n");
}
}
return 0;
}
When you enter 5 for an example, you hit a new line character afterwards.
So you are entering 2 characters: 5 and a new line character.
That new line character is causing your headache.
The new line character is also considered an input.
In order to ignore this new line char, simply add a new line that acts as a garbage collection:
char garbage[50];
scanf( "%d", &n);
fgets(garbage, sizeof(garbage), stdin);

for loop runs twice in C

I am new to C programming. And I was doing a practice, and the question goes like this: Use the ?: operator and the for statement to write a program that keeps taking the characters entered by the user until the character q is accounted.
And here is the program I wrote:
#include <stdio.h>
main()
{
int x, i=0;
for (x = 0; x == 'q'? 0 : 1; printf("Loop %d is finished\n",i))
{
printf("Enter q to exit!!!\n");
printf("Please enter a character:\n");
x=getc(stdin);
putc(x,stdout);
++i;
}
printf("\nThe for loop is ended. Bye!");
return 0;
}
The problem is: every time I enter a "non-q" character, the loop seems to run twice.
I don't know what is wrong with my program.
Please help!
When you enter a non-q letter, you also hit Enter, which is read in the second loop.
To make the loop only run once per input, use fgets() to read an entire line of input at once, and check if the input string matches your expectations.
When you type a and then press Enter, the newline character becomes part of the stdin stream. After a is read, the next time you execute x=getc(stdin), the value of x is set to \n. That's why two iterations of the loop get executed.
The loop runs twice because when you enter a non-q character, you actually enter two characters - the non-q character and the newline '\n' character. x = getc(stdin); reads the non-q character from the stdin stream but the newline is still lying in the buffer of stdin which is read in the next getc call.
You should use fgets to read a line from the stream as others have suggested and then you can process the line. Also, you should specify the return type of main as int. I suggest the following changes -
#include <stdio.h>
int main(void)
{
int x, i = 0;
// array to store the input line
// assuming that the max length of
// the line is 10. +1 is for the
// terminating null added by fscanf to
// mark the end of the string
char line[10 + 1];
for (x = 0; x == 'q'? 0 : 1; printf("Loop %d is finished\n", i))
{
printf("Enter q to exit!!!\n");
printf("Please enter a character:\n");
// fgets reads an input line of at most
// one less than sizeof line, i.e.,
// 10 characters from stdin and saves it
// in the array line and then adds a
// terminating null byte
fgets(line, sizeof line, stdin);
// assign the first character of line to x
x = line[0];
putc(x, stdout);
++i;
}
printf("\nThe for loop is ended. Bye!");
return 0;
}
When you enter a character, say 'x' and press enter, you actually input two characters, which are 'x' and '\n' also known as newline(when you hit enter). The '\n' becomes part of the input stream and the loop is executed for it as well.
Also, try inputting "xyz" and hit enter, the loop will be executed 4 times. For each 'x', 'y', 'z', and '\n'.
If you want the code to work one time for every input, use the function gets.
#include <stdio.h>
main()
{
int i=0;
char x[10];
for ( ; x[0]!='q'; printf("Loop %d is finished\n",i) )
{
printf("Enter q to exit!!!\n");
printf("Please enter a character:\n");
gets(x);
i++;
}
printf("\nThe for loop is ended. Bye!");
return 0;
}
In this code we declared x as an string, the gets() function reads the whole line we entered, then in the condition part of the for loop, we check whether the first character of the string is 'q' or not.

fgets() Not Ignoring New Line

For my practice assignment I have to use either gets() or fgets().
I chose fgets() as its more secure.
The first input is meant to be able to hold a maximum of 5 characters.
So i gave the char array a size of 6 to accommodate the trailing '\0'.
I found the fgets() issue of it adding a trailing '\n' when you press Enter (using stdin with fgets())
I done a bit of research and found a for loop to try and get rid of it. However, it doesnt seem to be working and i cant for the life of me figure out why.
Its still skipping the next input when i type in 5 characters.
Here is the code:
#include <stdio.h>
#include <string.h>
int main(void)
{
//Declare char arrays
char arcInputString5[6];
char arcInputString10[11];
char arcInputString15[16];
char arcInputString20[21];
int clean1, clean2, clean3, clean4;
// int nStrLen1, nStrLen2, nStrLen3, nStrLen4;
// nStrLen1 = nStrLen2 = nStrLen3 = nStrLen4 = 0;
printf("\nPlease Input String 1 - Max Length 5: ");
//gets(arcInputString5);
fgets(arcInputString5, 6, stdin);
for(clean1 = 0; clean1 < strlen(arcInputString5); clean1++)
{
if(arcInputString5[clean1] == '\n' || arcInputString5[clean1] == '\r')
{
arcInputString5[clean1] = '\0';
break;
}
}
printf("\nPlease Input String 2 - Max Length 10: ");
//gets(arcInputString10);
fgets(arcInputString10, 10, stdin);
printf("\nPlease Input String 3 - Max Length 15: ");
//gets(arcInputString15);
fgets(arcInputString15, 15, stdin);
printf("\nPlease Input String 4 - Max Length 20: ");
//gets(arcInputString20);
fgets(arcInputString20, 20, stdin);
printf("\nThankyou For Your Inputs - They Are Shown Back To You Below\n");
puts(arcInputString5);
puts(arcInputString10);
puts(arcInputString15);
puts(arcInputString20);
printf("\nThe String Lengths For Each Input Are Listed Below");
printf("\n%d", strlen(arcInputString5));
printf("\n%d", strlen(arcInputString10));
printf("\n%d", strlen(arcInputString15));
printf("\n%d", strlen(arcInputString20));
}
Ive tried multiple ways of doing the for loop such as using the number 6 instead of "strlen(arcInputString5)"
Any help would be appreciated.
EDIT:
EXAMPLE INPUT:
asd d
EXAMPLE OUTPUT:
Please Input String 2 - Max Length 10: //skips this
Please Input String 3 - Max Length 15: //this is the next line for input
fgets() reads one character less than the given buffer size from stdin and then
appends a NUL-character. So in your case, with an input buffer of 6 characters,
it reads "asd d" into arcInputString5, and the newline character that terminates the line input is still unread.
The next fgets() then reads (only) this newline character into arcInputString10.
You need a buffer size of (at least) 7 to read the five characters "asd d" including the
newline character from stdin.
The same applies to your other buffers used for fgets().
Added: As Jonathan Leffler correctly commented, a better method is to supply
a "large" input buffer to fgets() and check the actual length of the user input after
reading one line.
You should also note that fgets() returns NULL if no character could be read at all
(end-of-file), so you should check the return value.
Change 6 to 7:
arcInputString5[7];
fgets(arcInputString5, 7, stdin);
You need to give space for the '\n' and '\0' characters.
valter
Call getchar() to retrieve the the newline character from the input stream before asking for the next user input.
I like to use the following simple function for clearing the input stream
void clear() {
while(getchar() != '\n');
}

Resources