Поиск ключа печати двоичного файла c - PullRequest
0 голосов
/ 07 марта 2019

Я пытаюсь создать программу, которая открывает двоичный файл со списком всех элементов с их атомным номером, именем и символом в указанном порядке. Задача, чтобы программа могла принимать имя элемента (не должно быть чувствительным к регистру) и печатать его атомный номер и символ

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

    #include "elements.h"

#define NUM_ELEMENTS (118)

struct elementTag {
   int AtomicNumber;
   char Name[31];
   char Symbol[4];  // note: the longest Symbol has 3 characters
};

typedef struct elementTag ElementType;
    int
    main()
    {
        struct elementTag elements[NUM_ELEMENTS];

    int ctr;
    char ele[31];

    FILE *fbin;

    fbin = fopen ("ELEMENTS.bin", "rb");

    for ( ctr = 0; ctr < NUM_ELEMENTS; ctr ++)
    {
        fread (&elements[ctr], sizeof(struct elementTag), 1, fbin);
    }

    printf("\nInput element name to search: ");
    scanf("%s", ele);

    for ( ctr = 0; ctr < NUM_ELEMENTS; ctr ++)
    {
        if (strcmp(ele, elements[ctr].Name))
        {
            printf("Atomic Number: %d, Symbol: %s\n\n", elements[ctr].AtomicNumber, elements[ctr].Symbol);
        }
        else
        {
            printf("NOT FOUND!\n\n");
            break;
        }
    }

    fclose (fbin);

    return 0;
}

1 Ответ

0 голосов
/ 07 марта 2019

этот код подозрительный:

for ( ctr = 0; ctr < NUM_ELEMENTS; ctr ++)
{
    fread (&elements[ctr], sizeof(struct elementTag), 1, fbin);
}

Выше в коде вы не проверяете, возвращает ли fopen значение NULL или нет, и здесь вы не проверяете результат fread , поэтому вы предполагаете, что по крайней мере NUM_ELEMENTS записи в файле.

Но в основном вы полагаете, что содержимое файла соответствует последовательности того, как elementTag находится в памяти, поэтому файл предназначен для данного компилятора со связанными параметрами компиляции в данной архитектуре, вы уверены? этого?

Ваш способ чтения неверен, если ваш файл содержит их внешнее представление, например

1 Hydrogen H
2 Helium He
...

char ele[31];
...
scanf("%s", ele);

у вас нет защиты от слишком длинного входа, и вы не проверяете случай EOF

Вы можете сделать

if (scanf("%30s", ele) == 1) {
  for (...

Задача для программы иметь возможность принимать имя элемента (не должно быть чувствительным к регистру)

ваш код использует

if (strcmp(ele, elements[ctr].Name))

strcmp чувствителен к регистру, и вы неверно используете его результат, используйте strcasecmp


В

for ( ctr = 0; ctr < NUM_ELEMENTS; ctr ++)
{
    if (strcmp(ele, elements[ctr].Name))
    {
        printf("Atomic Number: %d, Symbol: %s\n\n", elements[ctr].AtomicNumber, elements[ctr].Symbol);
    }
    else
    {
        printf("NOT FOUND!\n\n");
        break;
    }
}

из-за неправильного использования strcmp вы всегда будете говорить, что нашли первый элемент, кроме случаев, когда элемент input является первым элементом. Используя правильно результат strcmp , вы всегда будете говорить NOT FOUND, за исключением случаев, когда вход является первым элементом, и останавливаться, чтобы посмотреть на другие возможности.

Случай ошибки должен быть вне цикла, или зная, что конец цикла достигнут, например:

 for ( ctr = 0; ; ctr ++)
 {
     if (ctr == NUM_ELEMENTS)
     {
         printf("NOT FOUND!\n\n");
         break;
     }

     if (!strcasecmp(ele, elements[ctr].Name))
     {
         printf("Atomic Number: %d, Symbol: %s\n\n", elements[ctr].AtomicNumber, elements[ctr].Symbol);
          break;
     }
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...