Need of getchar? - c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
char* get_input_text() {
int paragraph_count;
scanf("%d", &paragraph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
memset(doc, 0, sizeof(doc));
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
char* returnDoc = (char*)malloc((strlen (doc)+1) * (sizeof(char)));
strcpy(returnDoc, doc);
return returnDoc;
}
int main()
{
char* text = get_input_text();
printf("%s",text);
return 0;
}
Input
2
Learning C is fun.
Learning pointers is more fun.It is good to have pointers.
If I remove getchar();. Program doesn't work, Why is that?
Other wise code works fine and prints the the exact input as output.

when you try to give input to this scanf("%d", &paragraph_count); you will enter an integer and then press enter key ,scanf will take the exact input you said, which means the integer , but leaves \n produced by enter key in buffer so if you don't use getchar(); the next scanf (scanf("%[^\n]%*c", p[i]);) will take \n as the input character. but when you use getchar() this function will take that \n from buffer and
next scanf will work fine.

scanf("%[^\n]%*c", p[i]); Means read a line and then ignore a char ('\n').
In scanf("%d", &paragraph_count) you read a int but left a '\n' in buffer.
So you need getchar() to ignore a '\n', or you next scanf will meet a '\n' at the begining and read nothing.

Related

Using scanf for character input, but the do-while loop wont stop at the null character

I'm completely new to programming (1st term in uni) and I can't keep up with my lecturer. At the moment I'm stuck on this exercise (for much more time than I'm willing to admit). I've tried to find help on the internet (in this site and others as well), but I can't, since our lecturer has us use a very simple form of c. I'm not asking necessarily for a complete answer. I'd really appreaciate even some hints about where I'm on the wrong. I understand that it might be really simple for some, that the question might seem ignorant or stupid and I feel bad for not getting what's wrong, but I need to try to understand.
So, what I'm trying to do is use scanf and a do while loop so the user can input characters in an array. But I don't understand why the loop won't stop when the user presses ENTER. There's more to the code, but I'm trying to take it slowly, step by step. (I'm not allowed to use pointers and getchar etc).
#include <stdio.h>
main()
{
char a[50];
int i;
printf("Give max 50 characters\n");
i=0;
do
{
scanf("%c", &a[i]);
i=i+1;
}
while((i<=50) && (a[i-1]!='\0'));
for(i=0; i<50; i++)
printf("%c", a[i]);
}
There aren't any nul-terminated strings here, but only string arrays.
So, when pressing enter, a[i-1] is \n not \0 (scanf with %c as parameter doesn't nul-terminate the strings, and ENTER is just a non-nul character with code 10 AKA \n)
Then don't print the rest of the string because you'll get junk, just reuse i when printing the string back:
#include <stdio.h>
main()
{
char a[50];
int i;
printf("Give max 50 characters\n");
i=0;
do
{
scanf("%c", &a[i]);
i=i+1;
}
while((i<sizeof(a)) && (a[i-1]!='\n')); // \n not \0
int j;
for(j=0; j<i; j++) // stop at i
printf("%c", a[j]); // output is flushed when \n is printed
}
Also test with i<50 not i<=50 because a[50] is outside the array bounds (I've generalized to sizeof(a))
Here is another way you can do this.
#include <stdio.h>
// define Start
#define ARRAY_SIZE 50
// define End
// Function Prototypes Start
void array_reader(char array[]);
void array_printer(char array[]);
// Function Prototypes End
int main(void) {
char user_input[ARRAY_SIZE];
printf("Please enter some characters (50 max)!\n");
array_reader(user_input);
printf("Here is what you said:\n");
array_printer(user_input);
return 0;
}
// Scans in characters into an array. Stops scanning if
// 50 characters have been scanned in or if it reads a
// new line.
void array_reader(char array[]) {
scanf("%c", &array[0]);
int i = 0;
while (
(array[i] != '\n') &&
(i < ARRAY_SIZE)
) {
i++;
scanf("%c", &array[i]);
}
array[i + 1] = '\0';
}
// Prints out an array of characters until it reaches
// the null terminator
void array_printer(char array[]) {
int i = 0;
while (array[i] != '\0') {
printf("%c", array[i]);
i++;
}
}
You may try with this code:
#include <stdio.h>
main()
{
char a[50];
int i;
printf("Give max 50 characters\n");
i=0;
do {
scanf("%c", &a[i]);
i=i+1;
} while(i<50 && a[i-1] != '\n');
a[i] = 0;
for(i=0; a[i] != 0; i++)
printf("%c", a[i]);
}
The function scanf("%c", pointer) will read one character at a time and place it at the pointer location. You are looking for '\0', which is a valid string terminator, but the newline character you get when you press ENTER and that you should be looking for is '\n'.
Also, it is a good idea to terminate the string you have read by adding a '\0' at the end (really a zero). Then use it to stop printing or you may print the "rest" of the contents of an uninitialized char array.

Frequency function in C

I wrote a program that should take a string and a letter, then call a function which have two parameters (the string, the letter) and then count frequency of letter in the string.
The problem with my code is that it always returns num with value zero for any letter.
#include <stdio.h>
#include <stdlib.h>
int Occur(char [], char);
int main()
{
char s[100], l;
printf("Enter A String:\n");
scanf("%s",s);
printf("Enter A Letter:\n");
scanf("%c",&l);
getchar();
printf("Num Of Occurance is %d ",Occur(s,l));
return 0;
}
int Occur(char S[100], char L)
{
int i;
int num=0;
for(i=0; S[i]!='\0'; i++)
{
if(S[i]==L)
num++;
}
return num;
}
First, you should have tried debugging your code. If you would have done it, you would have seen that the letter you thought L holds is not what L actually holds.
Second, your problem is simple, L is not getting the letter you enter because of the enter from the string before is stuck in the scanf buffer... use scanf (" %c") [with preceeding whitespace] to resolve.
As mentioned in other answers, there are other solutions like the unrecommended fflush(). An alternative that is not considered harmful is getchar() between the scanf("%s") and the scanf("%c"). That will give you the same effect as using scanf(" %c");
The reason that all of these methods work is because they all consume the last char (which is, in your case the \n) stuck in the buffer, and thus allowing the %c to consume the char you actually intend to read
Reason of problem :
scanf("%c",&l) //Here %c takes enter key of scanf("%s",s);;
So, there are mainly 2 solution to your problem:
Sol. 1 => scanf(" %c",&l) //use whitespace before %c
Sol. 2 => Use fflush(stdin) that flushes the output buffer of a stream.
int main()
{
char s[100],l;
printf("Enter A String:\n");
scanf("%s",s);
printf("Enter A Letter:\n");
fflush(stdin); //here fflush(stdin) used to flushes the output buffer.
scanf("%c",&l);
l = getchar();
......
......
}
NOte: Since fflush(stdin) has undefined behavior so, always use priority to Solution 1 , instead of fflush(). :)
It's an input buffer problem. The char is read by getchar instead of scanf.
Doing l = getchar() solves the problem (the call of scanf just before clears the input buffer).
#include <stdio.h>
#include <stdlib.h>
int Occur(char [],char);
int main()
{
char s[100],l;
printf("Enter A String:\n");
scanf("%s",s);
printf("Enter A Letter:\n");
scanf("%c",&l);
l = getchar();
printf("Num Of Occurance is %d ",Occur(s,l));
return 0;
}
int Occur(char S[100],char L){
int i;
int num=0;
for(i=0;S[i]!='\0';i++){
if(S[i]==L)
num++;
}
return num;
}
Your function definition is wrong in terms of good code practices.
Instead of
int Occur(char S[100], char L)
You should write it as
int Occur(char S[] , char L)
because otherwise your code would specifically look to accept strings of size not more than 100 chars.
Apart from that as Ilario Pierbattista said its a input buffer problem.
The stdin needs to get cleared before taking further input, hence the juggad of putting scanf before a getchar() call would work.

Read strings in c in if instruction

I have a problem with reading strings in c. When I add the gets() function in an if-instruction, the program stops.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n,i = 0;
char sir[2000],ch;
printf("Press you option: "); scanf("%d",&n);
if(n == 1)
{
printf("text: "); gets(sir);
printf("\nINPUT: ");
for(i = 0;i < strlen(sir);i++)
printf("%c",sir[i]);
}
return 0;
}
Any solution?
When I add the gets() function in an if-instruction, the program stops.
Look at the preceding code. Maybe you entered 1 Enter
printf("Press you option: ");
scanf("%d",&n);
scanf("%d",&n); consume the '1', but not the '\n'.
Later code does
printf("text: ");
gets(sir);
And then gets() reads that '\n' and returns with sir[0] == '\0', an empty string. This causes for(i = 0;i < strlen(sir);i++) to not iterate the body of the for() loop.
What to do?
Read a line of user input fgets() and then process that string. Note that invalid input, EOF and buffer overflow handling not addressed in this simple code example. That would be step 2.
char buf[80];
printf("Press you option: ");
fgets(buf, sizeof buf, stdin);
sscanf(buf, "%d",&n);
printf("text: ");
fgets(buf, sizeof buf, stdin);
buf[strcspn(buf, "\n")] = '\0'; // lop off potential \n
strcpy(sir, buf);
This is due to the C input buffer problem, just add one getchar() as shown, it will work, let me know for any other help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n,i = 0;
char sir[2000],ch;
printf("Press you option: "); scanf("%d",&n);
if(n == 1)
{
printf("text: ");
getchar();
gets(sir);
printf("\nINPUT: ");
for(i = 0;i < strlen(sir);i++)
printf("%c",sir[i]);
}
return 0;
}
gets() is not preferred way to get the input from the user these days. As mentioned above please use fgets to read the input.
Coming back to your problem. Please fflush(stdin) in order to resolve your issue. Trying running the below code. i have just added fflush(stdin) and now the user input is taken by fgets() and no program stopping happens.
Code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int n, i = 0;
char sir[2000], ch;
printf("Press you option: "); scanf("%d", &n);
if (n == 1)
{
printf("text: ");
fflush(stdin);
gets(sir);
printf("\nINPUT: ");
for (i = 0; i < strlen(sir); i++)
printf("%c", sir[i]);
}
return 0;
}
Also please read and understand why we are using fflush and why we need to avoid gets() function going forward. Hope i have helped you. Thank you :)

Why this program is generating wrong answer?

This program is not giving the correct output; and it is taking input once instead of 't' times, while entering for the first time in the for-loop.
This problem is HEADBOB (https://www.codechef.com/problems/HEADBOB)
#include <stdio.h>
int main()
{
int t;
scanf("%d", &t);
for(t; t>0; t--)
{
int J=0, Y=0, N=0, I=0, len=0;
if(len==0)
scanf("%d", &len);
char ar[len];
for(J=0; J<len; J++)
{
scanf("%c",&ar[J]);
if(ar[J]=='Y')
Y++;
else if(ar[J]=='N')
N++;
else if(ar[J]=='I')
I++;
}
if(I>0)
printf("INDIAN\n");
else
{
if((Y&&!N)||(N&&!Y))
printf("NOT SURE\n");
else if(Y&&N) printf("NOT INDIAN\n");
}
}
}
INPUT:
NUMBER OF TEST CASES
NUMBER OF CHARACTERS
N NUMBER OF CHARACTERS
SAMPLE INPUT & OUTPUT OF ABOVE CODE:
INPUT:
5
5
NNYNN
OUTPUT:
NOT INDIAN
Check, if scanf("%c", &ar[j]) is reading whitespace characters! Think about
scanf(" %c", &ar[j]);
That means to skip all whitespace characters (space, tabs, \ns, etc).
Or even better:
scanf("%d", &len);
char ar[len + 1]; // + 1 for 0-termination
scanf(" %s", ar); // skip all whitespace characters, then read a string
Reading full string in one shot is a lot faster.
The problem is that the second scanf (scanf("%d", &len);) leaves a newline character in the standard input stream (stdin). This character is then consumed by the third scanf (scanf("%c",&ar[J]);) in the first iteration of the loop.
Changing
scanf("%d", &len);
to
scanf("%d%*c", &len);
will fix the problem. %*c tells scanf to read and discard a character.

Program Runs before accepting second string in input in C

I am trying to run the following code but the program accepts only one string and displays the output immediately without waiting for the second string to be entered. The program is for 2 string concatenation. Here is the code :-
#include <stdio.h>
main()
{
int i, j, len=0;
char name[100], abc[100];
printf("\nPlease Enter String 1 =\t");
scanf("%[^\n]c",&name);
printf("\nPlease Enter String 2 =\t");
scanf("%[^\n]c",&abc);
for(i=0; name[i]!='\0'; i++)
len++;
for(j=0; abc[j]!='\0'; j++)
{
len++;
name[len]=abc[j];
}
printf("\nThe Concatenated String Is =\t");
puts(name);
}
Use fgets instead of scanf, also you were incrementing len at the wrong place:
#include <stdio.h>
#include <string.h>
int main() {
int len = 0;
char name[100], abc[100];
printf("\nPlease Enter String 1 =\t");
fgets(name, 100, stdin);
len = strlen(name) - 1;
name[len] = 0;
printf("\nPlease Enter String 2 =\t");
fgets(abc, 100, stdin);
abc[strlen(abc) - 1] = 0;
strcpy(name+len, abc);
printf("\nThe Concatenated String Is =\t");
puts(name);
return 0;
}
Use the following scanf instead:
scanf("%[^\n]",name);
.....
scanf(" %[^\n]",abc);
Please refer to this scanf() manual page for more detail of how to use scanf().
You have to throw away the newline character ('\n').
Try:
while(getchar() != '\n')
continue;
after each scanf
I would like to suggest you not to use scanf. Better to use fgets instead.
By the way the reason that your program accepts only one string and displays the output immediately without waiting for the second string to be entered is the \n character left behind by the first scanf after pressing the Enter key. To eat up this newline character you may use gatchar() after first scanf.
printf("\nPlease Enter String 1 =\t");
scanf("%[^\n]c",name);
getchar();
printf("\nPlease Enter String 2 =\t");
scanf("%[^\n]c",abc);
Other two mistakes are:
1. Wrong increment of len
for(i=0; name[i]!='\0'; i++)
len++;
for(j=0; abc[j]!='\0'; j++)
{
name[len++]=abc[j];
}
2. Reason for weird output is the string is not NUL terminated. Add this line after second for loop.
name[len] = '\0'; // add this to null terminate your string.
Here is your working Code
should be
scanf("%[^\n]%*c", name);
printf("\nPlease Enter String 2 =\t");
scanf("%[^\n]%*c", abc);
for(i=0;name[i]!='\0';i++)
len++;
for(j=0;abc[j]!='\0';j++){
name[len]=abc[j];
len++;
}
name[len]='\0';

Resources