【问题标题】:Why is my if statement never evaluated?为什么我的 if 语句从未被评估?
【发布时间】:2014-05-11 05:20:55
【问题描述】:

我正在 GCC Ubuntu 10.04 的 C90 标准中制作一个小程序,它在一行文本中搜索一个单词,如果该单词在该行中,则打印出该行。

我的来源:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
    int bytesSearch;
    size_t n = 400;
    char *sentence, *word;
    FILE *pFile;

    pFile = fopen("The War of The Worlds.txt","r");

    if (pFile != NULL) {
        puts ("Please enter a search word:");
        sentence = (char *) malloc (n + 1);
        word = (char *) malloc (n + 1);
        bytesSearch = getline(&word, &n, stdin);
        while ((getline(&sentence, &n, pFile)) != -1) {
            char* strResult = strstr(sentence, word);
            if (strResult) {
                printf("%s\n", sentence);
            }
        }
    }
    free(sentence);
    free(word);
    fclose(pFile);
    return EXIT_SUCCESS;
}

我的问题是我的内部 if 语句从不为真,我假设这意味着我的 strstr 函数调用有问题。有人可以告诉我为什么 if 语句永远不会执行以及如何解决它吗?谢谢!

【问题讨论】:

  • 这是一个很好的调试器用例。检查您的环境使用了哪个调试器,并了解如何有效地使用它。
  • 请提供最少的输入文件集,并告诉我们您在程序中输入了什么,以便我们重现它。
  • 尝试打印ERRNO 找出问题所在。
  • 请给你的问题一个更好的标题,以某种方式说明你的技术问题是什么,而不是你如何观察它。
  • @BenjaminC.Huskisson-Snider,您可以立即开始并编辑您的问题,永远不会太晚。

标签: c string file loops pointers


【解决方案1】:

这是因为您从标准输入中读取的字符串以未被注意到的\n 结尾。

在这种情况下,搜索位于行尾的单词起作用,而搜索位于行中间的单词将会失败,即使它存在。 p>

您可能希望删除复制到 word 的尾随换行符。

人们通常会使用以下方法来做到这一点:

size_t size = strlen(word);
size_t end = size - 1;
if (size > 0 && word[end] == '\n')
    word[end] = '\0';

【讨论】:

  • size_t end = strlen(word); if (end &gt; 0 &amp;&amp; word[end-1] == '\n') ... 对于 pedantic 的情况,strlen(word) == 0 时更安全。
  • @chux 怎么能strlen(word) == 0?它至少可以包含一个\n 字符。这使得strlen(word) == 1
  • @Rikayan Bandyopadhyay 我至少能想到两种方法:1)stdin 来自一个不以\n 结尾的重定向输入文件。 (因为行不以 \n 结尾,但长度不是 0)2) getline() 读取行,而不是 C 字符串,并且正在读取的文本可能包含嵌入的 \0,例如“\0anc\n”。 3) 可能是 IO 输入错误。 4) bytesSearch 返回 -1 并且代码没有像您的答案那样检查它。 word 可以是任何东西。
  • @chux 你是对的。但是,为了便于阅读,我提出这一点;)另外,您的第一个论点毫无意义。如果stdin 来自重定向/管道输入并且不包含换行符,则输出字符串将包含读取的输入,但是其中没有换行符。否则你是对的。
  • @Halim Qarroum 我没有抱怨你的好解决方案,只是想为小众案例添加更安全的方法。关于重定向的输入,我添加了“(scratch this ...)”,因为我看到它不会导致 strlen(word) 为 0,但在这种情况下,@Rikayan Bandyopadhyay 的 word[strlen(word)-1]='\0' 方法会遭受不正确的截断不应该输入的字符 - 你的输入是正确的。 +1
【解决方案2】:

man page 说:

ssize_t getline(char **lineptr, size_t *n, FILE *stream) 从流中读取整行,存储地址 包含文本的缓冲区到*lineptr。缓冲区为空- 终止并包含换行符(如果找到)。

因此,您需要先从word 的末尾删除\n,然后再在sentence 中搜索它。

if (pFile != NULL) {
    puts ("Please enter a search word:");
    sentence = (char *) malloc (n + 1);
    word = (char *) malloc (n + 1);
    bytesSearch = getline(&word, &n, stdin);

    if (bytesSearch!=-1) {
        word[strlen(word)-1]='\0'; //removes the '\n' from the word

        while ((getline(&sentence, &n, pFile)) != -1) {
            char* strResult = strstr(sentence, word);
            if (strResult) {
                printf("%s\n", sentence);
            }
        }
    }
    else
        printf("Error taking input!\n");

}

【讨论】:

  • 谢谢!完全不知道行尾有一个隐藏的\n
【解决方案3】:

getline读取的末尾需要去掉'\n',可以在读取输入后添加这段代码,

if(word[byteSearch-1]=='\n')
    word[byteSearch-1]='\0';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-07
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-14
    • 2021-05-15
    • 2015-04-16
    相关资源
    最近更新 更多