将文件中的字符串与用户在C中输入的字符串数组进行比较时遇到问题

时间:2012-03-27 01:06:04

标签: c arrays string compare strcmp

我试图研究这个问题,但却无法找到任何可以帮助我的东西。我一直在尝试使用fprint进行调试,但我仍然无法弄明白。

我是一名中级程序员,如果能在这里得到一些帮助,我会很高兴。这是我的代码:

int i = 0;
const int arraySize = 10;
char buf[256];
char str[256];
char buffer[256];
char *beerNames[arraySize] = { };

FILE *names;
FILE *percent;
i = 0;
int numBeers = 0;
printf("Please enter a name or (nothing to stop): ");
gets(buf);
while (strcmp(buf, "") != 0) {
    beerNames[i] = strdup(buf);
    i++;
    numBeers++;

    if (numBeers == arraySize)
        break;

    printf("Please enter a name or (nothing to stop): ");
    gets(buf);
}

// now open files and look for matches of names:        //      
names = fopen("Beer_Names.txt", "r");
percent = fopen("Beer_Percentage.txt", "r");

while (fgets(str, sizeof(str) / sizeof(str[0]), names) != NULL) {
    fgets(buffer, sizeof(buffer) / sizeof(buffer[0]), percent);
    for (i = 0; i < numBeers; i++) {
        if (strcmp(str, beerNames[i]) == 0) {
            printf("Beer: %s Percentage: %s\n", str, beerNames[i]);
            break;
        }
    }
}

fclose(names);
fclose(percent);

所以,我遇到的问题是当我尝试strcmp()时,它没有正确比较并返回-11。我已经尝试打印出strcmp()值,当它等于0时,它最终会跳过匹配。

我的Beer_Names.txt(缩写)看起来像这样:

Anchor Porter
Anchor Steam
Anheuser Busch Natural Light 
Anheuser Busch Natural Ice
Aspen Edge
Big Sky I.P.A. 
Big Sky Moose Drool Brown Ale 
Big Sky Powder Hound (seasonal) 
Big Sky Scape Goat Pale Ale 
Big Sky Summer Honey Ale (seasonal) 
Blatz Beer 
Blatz Light
Blue Moon

我的Beer_Percentage.txt(缩写)看起来像这样:

5.6
4.9
4.2
5.9
4.1
6.2
5.1
6.2
4.7
14.7
4.8
0
5.4

这不是作业作业,我只是在做一个个人项目,我想在C做得更好。

2 个答案:

答案 0 :(得分:3)

你的问题是,gets()不会将换行符作为字符串的一部分返回,而fgets()会这样做。

因此,当用户输入值时,使用gets读取“Anchor Porter”,您的字符串看起来像"Anchor Porter\0",但是当您从带有fgets的文件中读取它时,它最终会像"Anchor Porter\n\0"一样,这不会比较平等。

答案 1 :(得分:2)

gets(buf);

我知道gets(3)很方便,我知道这是一个玩具,但请不要使用gets(3) 。使用gets(3)编写安全代码是不可能的,并且未来的C库可能甚至不包含此函数。 (是的,我知道它是标准化的,但我们希望未来的版本将省略它; POSIX.1-2008已经删除它。)合理的编译器将警告您使用它。请改用fgets(3)

while (fgets(str, sizeof(str) / sizeof(str[0]), names) != NULL) {

sizeof(char)定义为1。这不太可能改变,你不太可能改变阵列的类型。这通常不是什么大问题,但你不能像你可能怀疑的那样经常使用这样的结构 - 在这种情况下你可以使用它只是因为在这一行的封闭范围内声明了str[]。如果str作为参数传递,sizeof(str)运算符将返回数据指针的大小,数组的大小。不要太习惯这种结构 - 它并不总是像你期望的那样工作。

names = fopen("Beer_Names.txt", "r");
percent = fopen("Beer_Percentage.txt", "r");

while (fgets(str, sizeof(str) / sizeof(str[0]), names) != NULL) {
    fgets(buffer, sizeof(buffer) / sizeof(buffer[0]), percent);

请花点时间检查fopen(3)是否成功。这是一个很好的习惯,如果你提供一个好的错误信息,它也可以节省你将来的时间。用以下内容替换fopen()行:

names = fopen("Beer_Names.txt", "r");
percent = fopen("Beer_Percentage.txt", "r");

if (!names) {
    perror("failed to open Beer_Names.txt");
    exit(1);
}
if (!percent) {
    perror("failed to open Beer_Percentage.txt");
    exit(1);
}

您可以将其包装到执行fopen()的函数中,检查返回值,然后打印错误消息并退出或返回FILE*对象。

现在,将您带到此处的错误:Robert已指出fgets(3)gets(3)以不同方式处理输入的终止换行符。 (另一个理由是尽快摆脱gets(3)。)