C语言中字符串比较不正确

3

我不明白为什么我的字符串比较结果不正确。这是关于C语言的。

它从一个文件中读取数据,文件的格式如下:

1 - ls              
2 - cd                   
3 - history               

如果我输入!c,它应该获取最后一个以“c”开头的使用过的字符串并运行命令。但它从未执行if(strcmp())=0)语句。

这是我的代码的一部分:

  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);
            }
        }
    }

这是while循环中printf语句打印的内容,我无法弄清如何修复它,并且已经陷入困境一段时间。这是当我输入'!c'时发生的。

 c
 1c
 -c
 lsc
 2c
 -c
 cdc
 3c
 -c
 historyc
 4c
 -c
 !c!c

1
你有printf语句。它们打印什么? - klm123
1
你是否检查过输入的长度是否合适(至少为2)? - klm123
1
你真的需要检查input[1]吗?也许你想要的是input[0]吧? - klm123
1
你的问题在于获取“input”的方式。它很可能有一个尾随的\n。请展示一下你是如何获取“input”的。 - chux - Reinstate Monica
1
我在解读输出方面遇到了麻烦。第一行输出是“c”,它是(输入+1)的结果。第二行是“1c”,表示currLine。那么你的历史文件是按编号排序的?剩下的呢? - Duck
显示剩余4条评论
4个回答

2
这个循环:
while(fscanf(fileRead, "%s\n", currLine) != EOF) {

将空格分隔的令牌读入currLine,而不是行。因此,第一次迭代将是1,第二个为-,第三个为ls,等等,正如您在printfs中看到的那样。名称currLine表明您想要读取行而不是令牌。

然后,您将读取的令牌与其余输入行进行比较,该行显然为"c\n"。由于您从未获得带有换行符的标记,因此它永远不会匹配。即使您去掉换行符,它也永远不会匹配,因为您的文件不包含标记c

编辑

您说您想将输入行的其余部分与行上的命令前缀进行比较。要做到这一点,您需要首先确定前缀的长度,然后使用strncmp。您还需要解析来自文件的行以将命令与索引分开。因此,您可以执行以下操作:

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);
        }
    }
}

你说得对,它确实会这样做,但我正在尝试找出最佳方法,但我有些不知所措。 - user2318083
你在尝试弄清楚要做什么?你只是说“它不能正常工作”,但没有说明它应该做什么。 - Chris Dodd
所以我需要从输入中去掉"\n",并且以某种方式仅比较第一个字符而不是整个标记? - user2318083
当我在程序中输入“!c”时,它应该调用最后一条以“c”开头的命令,因此如果我输入“!c”,它将运行第2行,即“cd”。如果我输入“!l”,它将运行第一行的“ls”。如果我输入“!ls”,它也应该起作用,但我稍后再担心这个问题。基本上,它应该像当前在C中使用的“history”和“!string”函数一样运行。 - user2318083

1
你的问题在于获取的方式。(请注意,当你打印时,它有一个换行符)。它有一个尾随的\n,而你的currLine没有。因此比较失败了。
建议使用fgets()获取用户和文件输入。
像这样:
char buf[MAXINPUTLINE];
while(fgets(buf, sizeof buf, fileRead) != NULL) {
  int LineNo;
  if (sscanf(buf, "%d - %s", &LineNo, currLine) != 2) Handle_UnexpectedInput();
  ...
}

注意:"%s\n""%s "以及"%s\t"的效果相同: %s跳过可选的前导空格,然后扫描非空白字符。在"%s\n"中,s后面的空格会扫描可选的空格。

也许我应该包括这一点,那段代码之前我还有一个 "while(fgets(input, sizeof(input), stdin)){"。所以它会执行fgets()函数的 "input" 参数。 - user2318083
1
@user2318083 是的,它会得到“!c\n”。 - chux - Reinstate Monica
那么我只需要将输入中的 '\n' 去掉或者添加到 currLine 中吗? - user2318083
1
@user2318083 是的。我建议删除\n。有多种方法可供选择。 - chux - Reinstate Monica
1
如果(len && input[len-1] == '\n')则 size_t len = strlen(input); input[--len] = '\0'; - chux - Reinstate Monica

1
如果input是字符串!c,并且您要将其与行2 - cd匹配,那么您必须小心。 strcmp肯定不起作用,因为它只会在比较的两个字符串完全匹配时返回成功。
为了测试一个字符串(cd)是否以另一个字符串(c)开头,您需要使用strncmp(),它将对要比较的字符数进行限制。
此外:您需要小心,从input的第二个字符(跳过!)和currLine的第五个字符(跳过2-字符)开始比较。
这应该可以帮助您完成任务:
    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);
        }
    }

尝试了你的解决方案,但它仍然没有进入if语句。我在我的回答中展示了while循环的输出。 - user2318083
1
input是否有尾随的换行符,如其他地方所建议的那样?如果是这样,请尝试使用strlen(input)-2来防止它尝试将input中的换行符与currLine中的d进行比较。 - Tim Pierce
是的,你说得对。现在当我printf时,它会打印整行,包括我不需要的数字,但我认为这是一个简单的修复。至少我希望如此,例如它会打印出“3 - 历史”,而不仅仅是“历史”。 - user2318083
1
是的,我预计这将是一个简单的修复。 - Tim Pierce
是的,已经修好了。谢谢你的帮助,我很感激! :) - user2318083

1

可能的一种情况是输入可能包含一个尾随的换行符,而由于scanf规范,curline绝对不会包含换行符。


你说得对,输入字符串末尾确实有'\n',但这个代码只比较了第一个字符,所以这个'\n'并不会影响结果,是吧? - user2318083
1
不,strcmp会比较整个字符串。如果你想比较第一个字母,那么可以这样写:(input[1] == curline[1])。 - Sam Hartman
这好像也行不通,"1 -" 会干扰字符串比较吗? - user2318083

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接