I'm using Eclipse IDE for C/C .
I wrote simple C program to find string length. After scan I'm pressing Enter in console screen but it takes as input and adding one more extra byte in string. It happens only in eclipse IDE in other compiler like online gdb i got accepted output.
Example:
#include <stdio.h>
#include <string.h>
#define MAX_LIMIT 127
int main()
{
char str[MAX_LIMIT];
int length;
printf("Enter the string\n");
fflush(stdout); // flush the output buffer
scanf("%[^\n]",str);
length = strlen(str);
printf("Length of the string is = %d\n",length);
return 0;
}
Output in Eclipse console screen:
Enter the string
hello
Length of the string is = 6
Output in other compiler:
Enter the string
hello
Length of the string is = 5
I tried to solve my self but not getting output
EDIT:
In the comments, I was told to print the individual character codes of the string, by adding the line
printf("x x x x x x x x\n", str[0], str[1], str[2], str[3], str[4], str[5], str[6], str[7]);
at the end of my program. When I do this, I get the following output:
Enter the string
hello
Length of the string is = 6
68 65 6c 6c 6f 0d 00 00
CodePudding user response:
It appears that your Eclipse IDE is not behaving in a way that complies with the ISO C standard.
According to §7.21.3 ¶7 of the ISO C11 standard, standard input must be a text stream, which, according to §7.21.2 ¶2, must have \n
line endings. However, according to the information that you provided, it is behaving as a binary stream with \r\n
line endings.
Therefore, if you want to compensate for this non-compliant behavior of Eclipse, you will have to change the line
scanf("%[^\n]",str);
to:
scanf("%[^\r\n]",str);
CodePudding user response:
'\r'
in the stream
This is an eclipse interface, compiler and keyboard issue. The keyboard Enter injects both Ctrl R and Ctrl N and gcc's stdin
blindly takes this in as a common character the Ctrl R followed by an end-of-line. If you cut/paste sequence like "123\n"
from some other source into the console window (or pipe data in from the command line), code will work as expected.
This is not a case of text vs. binary stream issue. Note: stdout
prints without a '\r'
.
Issue: buffer overrun
Do not code scanf("%[^\n]",str);
(or scanf("%[^\r\n]",str);
(to ignore the'\r'
) without a width.
Do not use str
afterword without checking the return value.
if (scanf("6[^\r\n]",str) != 1) {
Handle_error();
}
Alternate
Read a line of input with fgets()
.
if (fgets(str, sizeof str, stdin) == NULL) {
Handle_error();
}
// Lop off line endings
str[strcspn(str, "\r\n")] = '\0';
Note that this 2nd version nicely reads a line of only "\n"
, whereas the scanf("%[^\n]", ...)
does not.
Also scanf("%[^\r\n]",str)
still leaves those pesky "\r\n"
to be read by something.
Deeper
In a way the incoming of "\r\n"
or "\n"
on stdin
allows one to consider how to make an executable resilient to being run is various environments. I have found that a set of re-directed input from a file may have originated in with the "\r\n"
or "\n"
land and strive to make code handle either. Steps include :
Do not use a simplistic
scanf()
to read a line of input. It is not the right tool.fgets()
is better.Use
str[strcspn(str, "\r\n")] = '\0';
to end the line of text either way.Increase the size of
str[]
by 1.