2

I am writing a simple shell program in C where the program accepts commands from user in the command line, tokenizes the input into the array and then uses execvp() function to execute user commands. To read the user input I am using fgets() function:

char command[MAX];
fgets(command, MAX, stdin);

Now here where's my problem is (and I am very new to C programming). If the user types, for example, ls -af and I check the length of the typed string like

strlen(command)

the result is 7 even though there are only 6 characters typed. I understand that this is because fgets() always adds a \0 at the end of a string. This, however, causes problems for my program later. I tokenize the input using strtok() function like so:

char* token;
int i = 0;
char* args[10];
token = strtok(command, " ");
while(token != NULL)
  {   
      args[index] = token;
      token = strtok(NULL, " ");
      index ++ ;
   }
  args[index] = NULL;

After this, the last element in the args array before NULL (-af in this case) retains that trailing \0 produced by fgets(). This, in turn, causes a problem for my execvp() call since it does not recognize the last element in the array. I assume it reads it as -af\0 whereas it should be just -af. Is there a way to trim that last \0 produced by fgets() function or is there an easier way to read an input from the user? Thank you in advance!

  • 11
    `strlen` is *not* counting the `\0` terminator. What you see is probably the newline `\n` character. – Eugene Sh. Sep 13 '18 at 17:13
  • Ok, so how can I trim it so it does not appear in the tokenized array? – Alexander Nenartovich Sep 13 '18 at 17:14
  • Right there, in the second comment... – Eugene Sh. Sep 13 '18 at 17:15
  • After adding the above statement, I'm getting a compile error "command could not be resolved". Do I need to #include something? Sorry, guys, and thank you again for your help. – Alexander Nenartovich Sep 13 '18 at 17:21
  • 1
    `command` is already used in your code, so if you're getting *command could not be resolved* you've put it in the wrong place. It's hard to tell you where you went wrong *After adding the above statement*, because we can't see your screen from here to see what you did when you added the above statement . – Ken White Sep 13 '18 at 17:24
  • the function: `strcspn()` is found in the header file: `string.h` – user3629249 Sep 13 '18 at 17:33
  • 1
    Thank you all so much, guys, it works now! I wish some of you would have posted the answer so I could have up voted you. Thank you again! – Alexander Nenartovich Sep 13 '18 at 17:36

1 Answers1

2

As stated in the comments above, you're probably seeing the newline being stored in the string.

Reading the MAN (3) page for fgets (emphasis mine):

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 terminating null byte ('\0') is stored after the last character in the buffer.

If you want to strip newlines, you can see this post which has an answer suggesting that you use something like this:

buffer[strcspn(buffer, "\n")] = 0;
Addison
  • 7,322
  • 2
  • 39
  • 55
  • @AlexanderNenartovich - Good to hear! If my answer helped out, remember to upvote and accept :) – Addison Sep 19 '18 at 06:51