首页 > 解决方案 > C字符串字符串比较总是导致错误

问题描述

我正在尝试在文件中查找字符串。我通过修改getline.

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

int main(void)
{
    FILE * fp;
    char * line = NULL;
    char *fixed_str = "testline4";
    size_t len = 0;
    ssize_t read;

    fp = fopen("test.txt", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);

    while ((read = getline(&line, &len, fp)) != -1) {
        printf("Retrieved line of length %zu:\n", read);
        printf("%s", line);

        if (strcmp(fixed_str,line)==0)
            printf("the match is found\n");
    }
    //printf("the len of string is %zu\n", strlen(fixed_str));

    fclose(fp);
    if (line)
        free(line);
    exit(EXIT_SUCCESS);
} 

问题是尽管 getline 成功且正确地遍历了文件中的所有行,但 strcmp 的结果始终为假。由于换行符,fixed_str 的长度为 9,文件中相等字符串的长度为 10(我对吗?)。但是在 的帮助下比较 9 个字符strncmp仍然会产生错误的结果。我还排除了大写和空格的可能性,所以我认为我做错了什么

test.txt 如下

test line1
test line2
test line3
testline4
string1
string2
string3
first name

我尝试了所有条目但没有成功

注意:在我的实际程序中,我必须fixed_str从另一个文件中读取

标签: clinuxstringfile

解决方案


getline()手册页(我的重点):

getline() 从流中读取整行,将包含文本的缓冲区的地址存储到 *lineptr 中。缓冲区以空值结尾并包括换行符(如果找到)。

fixed_str没有换行符。

因此剥离任何换行符(例如):

char* nl = strrchr( line, '\n' ) ;
if(nl != NULL) *nl = `\0` ;

或者更有效,因为getline()返回行长度(read在你的情况下):

if(line[read - 1] == '\n' ) line[read - 1] = `\0` ;

添加'\n'tofixed_str可能看起来更简单,但这不是一个好主意,因为文件中的最后(或唯一)行没有,但可能是匹配的。

按照您的问题中所述使用strncmp()应该有效,但没有看到尝试很难评论,但无论如何它都是有缺陷的解决方案,因为它会匹配以下所有内容,例如:

testline4
testline4 and some more
testline4 12345.

wherefixed_str取自控制台或文件输入而不是常量,输入方法和数据源可能会导致问题,以及替代行尾约定的可能性。为了使它更健壮,你可以这样做:

// Strip any LF or CR+LF line end from fixed_str
char* line_end = strpbrk( fixed_str, "\r\n" ) ;
if( line_end != NULL ) *line_end = '\0' ;  

// Strip any LF or CR+LF line end from line
line_end = strpbrk( line, "\r\n" ) ;
if( line_end != NULL ) *line_end = '\0' ;  

或者@AndrewHenle 指出的更简单(即更好)的解决方案:

// Strip any LF or CR+LF line end from fixed_str
fixed_str[strcspn(line, "\r\n")] = '\0';

// Strip any LF or CR+LF line end from line
line[strcspn(line, "\r\n")] = '\0';

这样,无论行以什么结尾,CR 或 CR+LF 都可以比较任一输入,并且行结束甚至可能在两个输入之间有所不同。


推荐阅读