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
Tim Pierce
  • 5,514
  • 1
  • 15
  • 31
user2318083
  • 567
  • 1
  • 8
  • 27
  • 1
    What do you have at the output? – klm123 Dec 18 '13 at 01:40
  • What do you mean? Right now it's suppose to go into the if statement and output the currLine but it's only looping through the while loop and not going into the if statement. – user2318083 Dec 18 '13 at 01:42
  • 1
    you have printf-s there. What do they print? – klm123 Dec 18 '13 at 01:43
  • 1
    Do you check that your input[...] has appropriate lenghth? (at least 2). – klm123 Dec 18 '13 at 01:44
  • 1
    Do you really need to check input[1]? may be you meant input[0]? – klm123 Dec 18 '13 at 01:44
  • I just updated my OP with what printf prints out. I need input[1] because it checks the second char after '!' to see if it's a alphabet, if I put input[0] it'll always compare with the first char which is '!' – user2318083 Dec 18 '13 at 01:47
  • 1
    Your problem is with the manner in which you get `input`. It likely has a trailing `\n`. Show how you get `input`. – chux - Reinstate Monica Dec 18 '13 at 01:51
  • 1
    I am having trouble deciphering the output. The first output line is 'c' which is (input + 1). The second line is "1c" which is currLine. So your history file is numbered? What's the rest? – Duck Dec 18 '13 at 02:03
  • It's reading from a file which I have an example of up there.. it's listed as "# - string" I'm not sure how I'll be able to skip the numbering and '-' and just read from the string. – user2318083 Dec 18 '13 at 02:08

4 Answers4

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);
        }
    }
}
Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • You're right it does do that, trying to figure the best way to do this but I'm somewhat clueless. – user2318083 Dec 18 '13 at 02:19
  • 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. – Chris Dodd Dec 18 '13 at 02:23
  • 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? – user2318083 Dec 18 '13 at 02:28
  • 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. – user2318083 Dec 18 '13 at 02:29
1

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

Sam Hartman
  • 6,210
  • 3
  • 23
  • 40
  • 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? – user2318083 Dec 18 '13 at 01:48
  • 1
    No, strcmp will compare the entire string. if you want to compare the first letter then do (input[1] == curline[1]) – Sam Hartman Dec 18 '13 at 01:53
  • Hmm that doesn't seem to work either, will the "1 -" interfere with the string comparison at all? – user2318083 Dec 18 '13 at 02:11
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.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
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);
        }
    }
Tim Pierce
  • 5,514
  • 1
  • 15
  • 31
  • 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. – user2318083 Dec 18 '13 at 02:50
  • 1
    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`. – Tim Pierce Dec 18 '13 at 02:55
  • 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" – user2318083 Dec 18 '13 at 03:02
  • 1
    Yes, I expect that will be a straightforward fix. – Tim Pierce Dec 18 '13 at 03:06