1

我试图研究这个问题,但找不到任何可以帮助我的东西。我一直在尝试使用 进行调试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(),它没有正确比较并且返回 a-1或 a 1。我也尝试过打印出这些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 语言上做得更好。

4

2 回答 2

3

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

所以当用户输入的值“Anchor Porter”用gets读取时,你的字符串看起来像这样"Anchor Porter\0",但是当你用fgets从文件中读取它时,它最终会变成这样"Anchor Porter\n\0",比较不相等。

于 2012-03-27T01:15:44.693 回答
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*对象。

现在,把你带到这里的错误:罗伯特指出了这一点,fgets(3)gets(3)以不同的方式处理输入的终止换行符。(还有一个尽快摆脱的理由gets(3)。)

于 2012-03-27T01:21:44.017 回答