Возникают проблемы при сравнении строк в файле с массивом строк, введенных пользователем в C - PullRequest
1 голос
/ 27 марта 2012

Я пытался исследовать этот вопрос, но не смог найти ничего, что могло бы мне помочь.Я постоянно пытался отлаживать, используя 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(), он не сравнивается должным образом и возвращает либо -1, либо 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.

Ответы [ 2 ]

3 голосов
/ 27 марта 2012

Ваша проблема в том, что gets () не возвращает символ новой строки как часть строки, в то время как fgets () делает.

Таким образом, когда введенное пользователем значение «Anchor Porter» читается с помощью get, ваша строка выглядит следующим образом "Anchor Porter\0", но когда вы читаете ее из файла с fgets, она заканчивается следующим образом "Anchor Porter\n\0", который не будет сравниваться равны.

2 голосов
/ 27 марта 2012
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) как можно скорее.)

...