3

I can't figure out why my string compare isn't comparing correctly. This is for C.

It's reading from a file that is set up like this:

1 - ls              
2 - cd                   
3 - history               

If I type !c it's suppose to grab the last used string that started with 'c' and run the command. Yet it never goes into the if(strcmp(())=0) line.

Part of my code is here:

  char currLine[MAXINPUTLINE];

    else if (isalpha(input[1])){
        int count = 1;
        fileRead = fopen(".simpleshell_history", "r");
        while(fscanf(fileRead, "%s\n", currLine) != EOF){
            printf(input+1);
            printf(currLine);
            if(strcmp((input+1), currLine) == 0){
                printf("%s\n", currLine);
                parse(currLine);
            }
        }
    }

This is what the printf in the while loop prints, I can't figure out how to fix this and I've been stuck on it for a while. This is when I enter '!c'

 c
 1c
 -c
 lsc
 2c
 -c
 cdc
 3c
 -c
 historyc
 4c
 -c
 !c!c
9
  • 1
    What do you have at the output? Commented Dec 18, 2013 at 1:40
  • 1
    you have printf-s there. What do they print? Commented Dec 18, 2013 at 1:43
  • 1
    Do you check that your input[...] has appropriate lenghth? (at least 2). Commented Dec 18, 2013 at 1:44
  • 1
    Do you really need to check input[1]? may be you meant input[0]? Commented Dec 18, 2013 at 1:44
  • 1
    Your problem is with the manner in which you get input. It likely has a trailing \n. Show how you get input. Commented Dec 18, 2013 at 1:51

4 Answers 4

2

This loop:

while(fscanf(fileRead, "%s\n", currLine) != EOF) {

will read whitespace delimeted tokens into currLine rather than lines. So the first iteration will be 1, the second -, the 3rd ls, etc as you are seeing with your printfs. The name currLine suggests you want to read lines rather than tokens.

You then compare the read tokens with the rest of your input line which is apparently "c\n". Since you never get a token with a newline, it never matches. Even if you got rid of the newline, it would never match, as your file does not contain the token c

edit

You say you want to compare the rest of the input line against a prefix of the command on the line. To do that you want to first figure out how long the prefix is, then use strncmp. You also want to parse the line from the file to separate the command from the index. So you could do something like:

else if (isalpha(input[1])){
    int count = 1;
    int pfxlen = 1;
    while (!isspace(input[pfxlen+1])) pfxlen++;
    fileRead = fopen(".simpleshell_history", "r");
    while(fscanf(fileRead, "%d - %[^\n]", &index, currLine) == 2) {
        if(strncmp((input+1), currLine, pfxlen) == 0) {
            printf("%s\n", currLine);
            parse(currLine);
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

You're right it does do that, trying to figure the best way to do this but I'm somewhat clueless.
What is that you're trying to figure out how to do? You just say "it isn't working correctly" but don't say what it should do.
So I'd have to get the "\n" out from the input and also somehow compare only the first char instead of the whole token?
When I type "!c" into the program it's suppose to pull up the last command used that started with 'c' so if I input "!c" it'll run line #2 which is "cd". If I type "!l" it'll run "ls" which is the first line. It should work if I type "!ls" also but i'll worry about that later. Pretty much it's suppose to function like what's incorporated into C currently with the 'history' and "!string" functions.
1

If input is the string !c and you are looking to match that against the line 2 - cd, you will have to be careful. strcmp will definitely not work, as it will only return success if the two strings it is comparing are exact matches.

In order to test whether one string (cd) starts with another string (c), you want to use strncmp(), which will take a limit on the number of characters to compare.

Also: you will need to be careful to start comparing from the second character of input (skipping the !) and from the fifth character of currLine (skipping the 2 - characters).

This should get you there:

    while (fgets(currLine, sizeof currLine, fileRead) != NULL) {
        printf(input+1);
        printf(currLine);
        if (strncmp(input + 1, currLine + 4, strlen(input)-1) == 0) {
            printf("%s\n", currLine);
            parse(currLine);
        }
    }

4 Comments

Tried your solution, however it still isn't going into the if statement. I showed the output of the while loop down below in my answers.
Does input have a trailing newline character, as suggested elsewhere? If so, try strlen(input)-2 instead to prevent it from trying to compare the newline from input with the d in currLine.
Yes you're right, now when I printf however it prints the whole line including the number which I don't need it to but I think that's a simple fix. At least I hope so, for example it prints out "3 - history" instead of just "history"
Yes, I expect that will be a straightforward fix.
1

One possibility is that input may contain a trailing newline, while curline definitely will not because of the scanf specification.

3 Comments

You're right input does have the trailing '\n' at the end of the string but isn't this only comparing the first letter? So that wouldn't matter would it?
No, strcmp will compare the entire string. if you want to compare the first letter then do (input[1] == curline[1])
Hmm that doesn't seem to work either, will the "1 -" interfere with the string comparison at all?
1

Your problem is with the manner in which you get input. (notice when you print, it has a line feed). It has a trailing \n and your currLine does not. Hence the compare fails.

Suggest OP uses fgets() for both user and file input.

Something like

char buf[MAXINPUTLINE];
while(fgets(buf, sizeof buf, fileRead) != NULL) {
  int LineNo;
  if (sscanf(buf, "%d - %s", &LineNo, currLine) != 2) Handle_UnexpectedInput();
  ...
}

Note: "%s\n" does the same as "%s " does the same as "%s\t": %s skips optional leading whitespace, then scans non-whitespace. The whitespace after s in "%s\n" scans for optional whitespace.

5 Comments

Maybe I should've included this, I also have a " while(fgets(input, sizeof(input), stdin)){" before all of that code. So it does fgets() "input"
@user2318083 Yes, it gets "!c\n".
So i just either need to get the '\n' out of the input or add it to the currLine?
@user2318083 Yes. I suggest removing the \n. various ways exist.
Example size_t len = strlen(input); if (len && input[len-1] == '\n') input[--len] = '\0';

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.