fgets() keeps getting skipped before entering loop [duplicate] - c

This question already has an answer here:
fgets is getting skipped
(1 answer)
Closed 4 years ago.
Been trying to remove a character but the call to fgets gets skipped/jumped over. On different computers it runs like it should but for some reason, it skips and basically jumps to the end of the program. Any ideas?

Several problems in your code but I do not see any reason of fgets() skipped or jumped over. The getchar() function reads the next character from stdin. Generally when we give input to the getchar() function, we enter the character and press ENTER key. This left the \n character in input stream which can be consumed by next input function called. But in your case you are not calling any other input function after getchar().
[Try calling getchar() above fgets() and give input as - enter a character followed by ENTER key. You will see the fgets() is skipped because it consumes the leftover \n character from input stream stdin.]
Problem 1:
Look at this statement:
str[j] = str + 1;
Since, the str is a char array, str[j] represents a character at location j and str + 1 is pointer. So, this assignment is incompatible because you are trying to assign a char * type to a char. It should be:
str[j] = str[j + 1];
Problem 2:
Your code is having a logical problem. It is unable to handle the scenario where the character to be removed occurs consecutively in the input string. Test your code for input like "Hello World" [character l is occurring consecutively]. Your program output will be [after fixing problem 1]:
Enter a sentence:
Hello World
This is the sentence: Hello World
Enter character to remove:
l
Sentence after removal: Helo Word <==== character l not removed
Your program is unable to handle this particular scenario because once it removes a character, in the next iteration it starts with next character.
Problem 3:
The strlen() return type is size_t and you are using char type to receive its return value. Instead, you should use size_t type.
The getchar() return type is int [because it returns the special value EOF when the end of the input stream is reached]. You are using char type variable to receive getchar() return value.
One more point (it is not a problem but you should be aware of it and take the precautionary measures):
From fgets() [emphasis 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 end-of-file occurs or a newline character is found, in which case str will contain that newline character. If no errors occur, writes a null character at the position immediately after the last character written to str.
So, it is possible that your input buffer passed to fgets() can have new line character ('\n') in it. For e.g., if you give input Hello World followed by ENTER key than the input buffer str will have "Hello World\n" in it. In your case this will not cause any problem but few extra iteration of loop. You can remove the \n from str buffer like this:
fgets(str, 100, stdin);
str[strcspn(str, "\n")] = 0; // This will remove the trailing newline character from input buffer
Also, you should check the fgets() return. In case of failure, fgets() returns NULL.
Putting these altogether, you can do:
#include <stdio.h>
#include <string.h>
int main() {
char str[100];
size_t i, j, len;
int r;
printf("Enter a sentence: \n");
if (fgets(str, 100, stdin) == NULL) {
fprintf (stderr, ("fgets failed"));
return -1;
}
str[strcspn(str, "\n")] = 0;
printf("This is the sentence: %s\n", str);
printf("Enter character to remove: \n");
r = getchar();
/*If getchar returns EOF, no need to go through character removal logic*/
if (r != EOF) {
len = strlen(str);
i = 0;
while (str[i] != '\0') {
if (str[i] == (char)r) {
for (j = i; j < len; j++) {
str[j] = str[j+1];
}
len--;
}
else
i++;
}
}
printf("Sentence after removal: %s\n", str);
return 0;
}
Output:
# ./a.out
Enter a sentence:
Hello World
This is the sentence: Hello World
Enter character to remove:
l
Sentence after removal: Heo Word
# ./a.out
Enter a sentence:
zzzzz
This is the sentence: zzzzz
Enter character to remove:
z
Sentence after removal:
# ./a.out
Enter a sentence:
aazz
This is the sentence: aazz
Enter character to remove:
a
Sentence after removal: zz

Try changing r = getchar(); with scanf("%c\n", &r);.
Also, your loop has some bugs or inconsistencies:
You're assigning to str[j] the value of a pointer. Should be assigning to str[j] the value of str[j+1].
The end of the inner loop should be len-1 then.
j-- has no effect at all.
You should end your string with \0 after you're done, otherwise you'll print garbage (in my case it was a bunch of \ns).
Putting everything together:
for (i = 0; i < len; i++) {
if (str[i] == r) {
for (j = i; j < len-1; j++) {
str[j] = str[j+1];
}
len--;
}
}
str[len] = '\0';
printf("Sentence after removal: %s\n", str);
If you want to remove the \n at the end of the string after you read it, you can do
str[len] = '\0';
len--;
before the loop.

Related

C programming - issues with printing string with backspace characters stored

I am writing a basic C program which takes a word from the user as input and prints that word twice on the same row. The issue that I am facing in printing the word twice is mentioned after the code that I have written below to do this job
void print_word()
{
char ch;
char str[15];
int i = 0; /* i will be used as index to access the elements of str */
printf ("\n Enter a word of your choice : ") ;
ch = getch() ; /* Dont echo character */
while ( !isspace(ch) && i < 14) /* while loop executes till user doesn't input a space or until the str array is full */
/* isspace() is defined in header file <ctype.h> */
{
putchar(ch); /* Now echo character */
str[i] = ch ;
i++ ;
ch = getch();
} //while loop ends
str[i] = '\0' ;
printf("\t") ; //print a gap
printf ("%s ", str) ;
printf ("%s", str) ;
}
This function works properly if user directly enters a word (without using backspace to edit the word).
Suppose user enters 'HELLO' then 5 characters viz.'H' 'E' 'L' 'L' 'O' gets stored in array str. But then user presses backspace three times and the word on the console appears 'HE' while str now contains eight characters H-E-L-L-O and 3 backspace characters. But when the printf function in the last two statements of this code is executed and prints str, the first statement correctly prints the 8 character and displays 'HE' on the console, but second statement prints 'HELLO', leaving the 3 backspace characters that are also there in the array str.
Why the last printf() statement is not printing the string str properly i.e., why is it not printing the backspace characters?
The problem remains even if I print str with puts() function or even if the str is printed with a for loop -- character by character. And I want to know what is actually happening in the backend process?
Use printf("%s\n", str); both times and you'll see that the first printf does not print 'HE'. It prints 'HELLO' just like the second one, just after that it moves the cursor back 3 times, so if you print both strings on the same line then the second string overwrites the last 3 characters of the first 'HELLO'. After printing HELLO and 3 backspaces you have output HELLO and cursor at the mark:
HELLO
^
After printing the space you have:
HE LO
^
After printing another HELLO and 3 backspaces:
HE HELLO
^
You might want to check this question if you want more information about printing strings with a backspace: Function printf() to print backspace problem.
As an alternative to printf("%s\n",str); solution you could process char by char your user's input.
Usually getch() is used whenever the programs require a full control of the input characters, so take advantage of it.
In your while loop just do this, instead:
while ( !isspace(ch) && i < 14)
{
putchar(ch); /* Now echo character */
if( ch == 0x08 && i > 0)
{
i--;
}
else
{
str[i] = ch ;
i++ ;
}
ch = getch();
}
Basically you need to check if the current input character is a backspace (ASCII value 0x08). If it is, decrease the current index of the input array in order to perform the character deletion. Of course don't do it if the current index is 0.
This approach is common in applications such as AT parsers.
This function works properly if user directly enters a word (without using backspace to edit the word).
See this,
#include<stdio.h>
#include<conio.h>
void print_word()
{
char ch;
char str[15];
int i = 0,flag=0;
printf ("\n Enter a word of your choice : ") ;
for(i=0; i<15&&flag==0; ++i)
{
ch = getch();
switch(ch)
{
case 13:
str[i] = '\0';
flag=1;
break;
case '\b':
if(i>0) i--;
str[i--]='\0';
printf("\b \b");
break;
default:
str[i] = ch;
printf("%c",ch);
}
}
str[15]='\0';
printf("\t") ;
printf ("%s ", str) ;
printf ("%s", str) ;
}
int main()
{
print_word();
}
You are responsible for removing backspace from str.
Why the last printf() statement is not printing the string str properly i.e., why is it not printing the backspace characters??
your input: HELLO+(3 backspace)
so the str contains {'H','E','L','L','O','\b','\b','\b'}
and the intersection point in console is
"HE^LLO"
After one tab (nearly 7 spaces), so console appears
"HE "
after one print of str
"HE HE^LLO"
after print of space and str
"HE HE HELLO"

Request for an explanation of a program which uses the getchar() in a while statement

Will it be too much to ask if I pray for an elucidation of the following codes from Line 7 onward? I have difficulty in comprehending how getchar() may differ from gets() or scanf() for the most parts. Why is it important to add an escape sequence, \n with it, when in my belief, the value inputting would be done in a horizontal form(as it is a 1D string)? The increment and then the immediate usage of decrement operator bewilder me too. Also, require help with the strcpy(). :|
If somebody has the time, I implore guidance. Thank you!
main()
{
char st[80], ch, word[15], lngst[15];
int i, l, j;
printf("\n Enter a sentence \n ");
i = 0;
while((st[i++] = getchar()) != '\n');
i--;
st[i] = '\0';
l = strlen(st);
i = 0; j = 0;
strcpy(word," ");
strcpy(lngst," ");
while(i <= l)
{
ch = st[i];
if(ch == ' ' || ch == '\0')
{
word[j] = '\0';
if(strlen(word) > strlen(lngst))
strcpy(lngst, word);
strcpy(word," ");
j = 0;
}
else
{
word[j] = ch;
j++;
}
i++;
}
printf("\n Longest word is %s", lngst);
printf("\n Press any key to continue...");
getch();
}
I can't say why the code is written as it is (there are other input options) but I can address some of your concerns:
Why is it important to add an escape sequence, \n?
This "newline" character is returned by getchar() when you hit the return/enter key (the typical 'signal' used to indicate you've done entering your line of text). Without checking for this, the getchar function would just keep (trying to) read in more characters.
How getchar() may differ from gets() or scanf()?
It is notoriously tricky to read in text that includes spaces using the scanf function (this SO Q/A may help), and the gets function has been declared obsolete (because it's dangerous). One could use fgets(st, 80, stdin) but, like I said, I can't comment on why the code is written exactly like it is.
The increment and then the immediate usage of decrement operator
bewilder me too.
The expression (st[i++] = getchar()) transfers the character read into the st array element indexed by i and afterwards increments the value of i, so the next call to getchar will put its result in the next array element. But, when the \n (newline) character has been read, i will have been incremented, ready for the next character - but there won't be one, so we then reduce it by one after we have finished our while loop.
Also, require help with the strcpy().
The call strcpy(dst, src) will copy all characters in the string src (up to and including the required nul terminator, '\0') into the dst string, replacing anything that is already there.
Feel free to ask for further clarification and/or explanation.
while((st[i++] = getchar()) != '\n');
has the same effect as
while (1) { // "infinite" loop
int tmp = getchar(); // get keypress
st[i] = tmp; // copy to string
i++; // update index
if (tmp == '\n') break; // exit the infinite loop after enter is processed
}

C: Trying to remove newline character from end of string

I'm trying to write a program that deletes the last newline from user input, ie the one generated when the user hits enter after having typed in a string.
void func4()
{
char *string = malloc(sizeof(*string)*256); //Declare size of the string
printf("please enter a long string: ");
fgets(string, 256, stdin); //Get user input for string (Sahand)
printf("You entered: %s", string); //Prints the string
for(int i=0; i<256; i++) //In this loop I attempt to remove the newline generated when clicking enter
//when inputting the string earlier.
{
if((string[i] = '\n')) //If the current element is a newline character.
{
printf("Entered if statement. string[i] = %c and i = %d\n",string[i], i);
string[i] = 0;
break;
}
}
printf("%c",string[0]); //Printing to see what we have as the first position. This generates no output...
for(int i=0;i<sizeof(string);i++) //Printing the whole string. This generates the whole string except the first char...
{
printf("%c",string[i]);
}
printf("The string without newline character: %s", string); //And this generates nothing!
}
But it doesn't behave as I thought it would. Here's the output:
please enter a long string: Sahand
You entered: Sahand
Entered if statement. string[i] =
and i = 0
ahand
The string without newline character:
Program ended with exit code: 0
Questions:
Why does the program seem to match the '\n' with the first character 'S'?
Why does the last line printf("The string without newline character: %s", string); generate no output at all when I haven't deleted anything from the string?
How can I make this program do what I intend it to do?
The condition (string[i] = '\n') will always return true. It should be (string[i] == '\n').
if((string[i] = '\n'))
this line may be wrong, you are assign value to string[i], not compare it.
if((string[i] == '\n'))

Getchar() function logic in the following codes

I would like to know about the getchar() logic in the following codes...
printf("Type up to 25 characters and then press Enter. . . \n") ;
for (i = 0; i < 25; i++)
{
msg[ i] = getchar() ;
if (msg[ i] == ' \n' )
{
i--;
break;
}
}
putchar(' \n' ) ;
for (; i >= 0; i--)
{
putchar(msg[ i] ) ;
}
In the above code if i input a name,say "STACKEXCHANGE" and then hit enter it will display the word properly..but the below code works differently..
printf("What are your two initials?\n") ;
firstInit = getchar() ;
lastInit = getchar() ;
In this example, if i type "ST" and then hit enter, 'S' will be stored in firstinit, while "\n" will be stored in lastInit instead of 'T'.
How does this happen? Isn't 'T' the second character input into the buffer. Infact \n is the third character in the buffer. so why does \n get stored. correct me if iam wrong, but the buffer is released when \n is pressed or entered, then why is it again being stored in the next getchar() function.
Why is the first code executed differently then? I mean if i input "stackexchange" and hit enter "t" is stored as the second character as is wanted, but it in the second example if the same "st" is typed and "enter' is input, the "t" is not stored as the second input, but instead "enter' is taken as the second input.
I am sorry if my typing is confusing... basically i want to know the logical flow in both codes, how it happens behind the scene..
the only reason for storing \n is when you are entering S the pressing enter and not flushing out the carriage return so it will store \n in your second string.
firstInit = getchar() ;
will read and store S
lastInit = getchar() ;
will read and store carriage return
getchar() is a standard library function which will read a character from the console.
Check the below code which takes your input ST and stores it in 2 char's a and b.
int main(void){
char a;
char b;
a = getchar();
b= getchar();
printf("a = %c b = %c\n",a,b);
return 0;
}
Input
ST<enter>
Output
a = S b = T
If you are seeing a newline char being saved into b here then the input is like S<enter> not ST<enter>

Length of a char array in C

I want to calculate the length of an char array in C with a while loop.
But If I insert otto it returns the length of 5. Shouldn't be 4 the right answer?
char eingabe[255];
printf("geben Sie eine Zeile ein:");
fgets(eingabe, 255, stdin);
int i = 0;
while (eingabe[i] != '\0')
{
++i;
}
printf("Laenge: %d\n", i);
It's very likely that eingabe contains:
{ 'o', 't', 't', 'o', '\n', '\0', junk ... }
Check the man page of fgets().
Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer.
As you are reading from stdin, it stores the trailing newline [\n] character also in the supplied buffer.
Change your check to while ((eingabe[i] != '\0') && (eingabe[i] != '\n')). Hope this will solve your issue.
A newline character '\n' makes fgets stop reading, but it is considered a valid character by the function, and included in the string copied to the result. If you would like to avoid this, use fscanf like this:
fscanf(stdin, "%254[^\n]", eingabe);
Note the limit in the format: it is less than the actual length of the buffer to accommodate the null terminator.
Note: You can use strlen to compute the length of the string. It does the same thing as your for loop:
int i = strlen(eingabe);
The size of eingabe is 255. Now, if you want the number of initialized characters in it you should use strlen. But first, insert this code:
int n;
for(n = 0; n < 255; n++){
if(eingabe[n] == '\n'){
eingabe[n] = '\0';
}
}
eingabe[254] = '\0';
This code replaces the '\n' character with a NULL character. Without this, strlen will return wrong values. I also include eingabe[254] = '\0'; so that if the string read in is long enough that the newline character does not fit in the buffer, there is still a NULL character so that strlen can function properly

Resources