我试图创建一个程序来打开一个二进制文件,该文件包含按顺序排列的所有元素及其原子序号,名称和符号的列表。该程序的任务是能够接受元素名称(不区分大小写)并打印其原子序号和符号
#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;
}
答案 0 :(得分:0)
该代码可疑:
for ( ctr = 0; ctr < NUM_ELEMENTS; ctr ++) { fread (&elements[ctr], sizeof(struct elementTag), 1, fbin); }
在代码上方,您不检查 fopen 是否返回NULL,并且在这里您不检查 fread 的结果,因此您假设至少存在NUM_ELEMENTS
记录在文件中。
但是主要是假设文件的内容与 elementTag 在内存中的顺序相对应,因此该文件专用于给定的编译器,并具有给定体系结构上的相关编译选项。确定吗?
如果文件包含外部表示形式,则您的读取方式为false
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 的错误使用,您总是会说找到第一个元素,除非输入元素是第一个元素。正确使用 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;
}
}