1

I'm trying to write a minishell with this code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_LEN  50
#define MAX_PARTS  50

int main ()
{
char* token;
char str[LINE_LEN];
char* arr[MAX_PARTS];
int i,j;

printf("Write a line: \n $:");
fgets(str, LINE_LEN, stdin);

while (str != "quit") {
    i=0;
    token = strtok(str, " \t\r\n");
    while( token != NULL ) 
    {
        arr[i] = token;
        printf("'%s'\n", arr[i]);
        i++;
        token = strtok(NULL," \t\r\n");
    }
    fflush(stdin);

    printf("Write a line: \n $:");
    fgets(str, LINE_LEN, stdin);
}   
return 0; 
}

It works correctly, but for the fact that when I type "quit", the program doesn't end. I guess it must be related with fgets and the fact that it incorporates EOF as another character at the end of string str, so when I compare it with "quit" it's not the same string. I don't know which is the correct way to extract the \n character from the string I read from standard input. ¿Could anyone help me, please?

Another question I would like to ask is if it's a good idea to use fflush in this code or not. Thank you

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
Trouble-lling
  • 333
  • 5
  • 15
  • 1
    `while(strcmp(str, "quit\n") != 0) {` – BLUEPIXY Feb 09 '14 at 16:16
  • Thanks, I had thought about adding \n to quit, but I'd rather like to know an efficient way of erasing \n of the string I read with fgets. – Trouble-lling Feb 09 '14 at 16:17
  • I think it's more effective than erase perhaps. – BLUEPIXY Feb 09 '14 at 16:19
  • 1
    `char *p = strchr(str, '\n'); if(p) *p = 0;` Read it all the way through the string, but there is no need to read it twice because he is cut out eventually in strtok this. – BLUEPIXY Feb 09 '14 at 16:20
  • @BLUEPIXY When "quit" without a following `\n` appears in the last line of a text file, and we feed it into his shell by redirection, then it will not be recognized by your `strcmp` – nodakai Feb 09 '14 at 16:23
  • @nodakai I think it's certainly true, but this program and is assumed to be input from the user it. – BLUEPIXY Feb 09 '14 at 16:24

4 Answers4

2

I guess it must be related with fgets and the fact that it incorporates EOF as another character at the end of string str, so when I compare it with "quit" it's not the same string.

Nope.

First of all, EOF doesn't exist as a character, it's just a flag returned by some IO functions to tell you that the file finished while trying to read it.

What fgets leaves in the string is the newline character (if it stopped because of it and not because of EOF or of an error). You can easily remove it - if it's present - after acquiring the string:

size_t l=strlen(str);
if(l && str[l-1]=='\n')
    str[l-1]=0;

But most importantly, you are getting the comparison with "quit" wrong.

If you write str != "quit" you are performing a pointer comparison between str and "quit", which will always fail since str and "quit" are distinct character arrays, and thus refer to different locations in memory. What you want is to compare the content of the two strings; in C, that is done with strcmp:

while(strcmp(str, "quit")!=0)
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
2

fgets will read newline character as well from statement below..

fgets(str, LINE_LEN, stdin);

So you have two option

  1. use condition as below to compare 'quit':

    while (strcmp(str, "quit\n"))  
    
  2. Remove newline from input. Detail here

Community
  • 1
  • 1
Digital_Reality
  • 4,488
  • 1
  • 29
  • 31
0

You cannot compare strings by pointer like you do str != "quit"

Use 0 != strcmp(str,"quit") instead.

LiMar
  • 2,822
  • 3
  • 22
  • 28
0
if(str[4] == '\n')
    str[4] = '\0';
while (strcmp(str, "quit")!=0) {
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70