Usage of fgets function in C
One of my assignments in to write my own UNIX Shell. To receive input from the user, I am using fgets to capture the input as a string but I'm not really sure how it works. When I run:
char command[50];
fgets(command, sizeof(command), stdin);
printf("Your Command: %s", &command);
int length = strlen(command);
printf("Length of String: %d\n", length);
Lets say my the input was "exit". strlen says that the string is 5 characters long, instead of four. I want to do this:
if( (strcmp(command, "exit")) == 0 ){
doSomething();
}
but command is never equaling the string that I want it to; its like it has a开发者_开发知识库n unknown character that Im not sure of. Is it the null character at the end? How do I change the if statement to check that the user input caught with fgets equals "exit"? Thanks!
fgets
considers the line terminator as a valid character. That's the extra character you are receiving.
Just do something like command[strlen(command) - 1] = '\0';
to remove the line terminator. Then you are free to do all your strcmp
's.
From the fgets
manual page:
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A '\0' is stored after the last character in the buffer.
Bottom-line: you have an extra newline at the end of your string when comparing.
fgets
will always include the line termination character in the input string. You can remove any space, including the newline characters, from the end of your "command" by doing:
char command[50];
fgets(command, sizeof(command), stdin);
size_t length = strlen(command);
// Trim off trailing "spaces" including newline characters
while ((length > 0) && isspace(command[length-1]))
command[--length] = '\0';
printf("Your Command: %s\n", &command); // Include newline now...
// This is computed above...
// int length = strlen(command);
// Continue as before
fgets
is capturing the line break, too.
Note that you can overcome this in a few ways, one might be using strncmp
:
if((strncmp(command, "exit", 4)) == 0)
which checks if only the first 4 characters of command match (though this might not be the right option for you here).
Another tactic is to check with the line break in place:
if((strcmp(command, "exit\n")) == 0)
Probably the easiest way to handle this is to switch to using scanf
to read the input:
char command[51];
scanf("%50[^\n]", command);
if (0 == strcmp(command, "exit"))
do_something();
Your string still has the newline at the end. You could compare with "exit\n"
or use something like strncmp(command, "exit", 4)
. Note that that would accept anything that started with "exit" and ignore the rest.
As noted, fgets
(3) gives you the trailing '\n'. If you use gets
(3), you don't gets the trailing newline. Nothing like consistency, sez I.
Perl has a hand chomp() function that trims the trailing newline if its present — you could do worse than to roll your own:
#define NUL ((char)0)
void chomp( char *s )
{
if ( s != null )
{
int len = strlen(s) ;
if ( len >= 1 && s[len-1] == "\n" )
{
s[len-1] = NUL ;
}
}
return ;
}
精彩评论