我正在用元素周期表项目练习C语言.我有这个.txt文件,其中包含以下顺序的所有元素: atomic_number name symbol mass_number.

我的程序应该用数据填充一个 struct 数组(为了便于搜索). 问题是我的程序不会一直打印到最后一个元素(ATOM_NUMBER=118),它只在54结束,不会继续打印.它也不会填充超过54的array.

以下是我试图解决这个问题的方法

file: populate.c

#include "periodic_table.h"

int populate(void)
{
    struct element
    {
        int atomic_num;
        char name[15];
        char symbol[5];
        float mass_num;
    };

    // Array to hold the elements
    struct element e[118];

    // checks that the file exists
    FILE *ptr = fopen("periodic_table.txt", "r");
    if (ptr == NULL)
    {
        printf("No file to read from.\nExiting...\n");
        return 1;
    }

    int line;   // first line of the txt file
    for (line = 1; line <= 118; line++)
    {
        if (fscanf(ptr, "%d %s %s %f", &e[line].atomic_num, &e[line].name, &e[line].symbol, &e[line].mass_num))
        {
            //print is just for debugging purpose
            printf("%d record: %d %s %s %.2f\n", line, e[line].atomic_num, e[line].name, e[line].symbol, e[line].mass_num);
        }
        fflush(stdin);
    }

    fclose(ptr);
    return (0);
}

我的文本文件如下所示

1 Hydrogen H 1.01
2 Helium He 4.00
3 Lithium Li 6.94
.
.
.
116 Livermorium Lv 293.00
117 Tennesine Ts 294.00
118 Oganesson Og 294.00

推荐答案

您的程序中存在多个问题:

  • struct element和数组e的定义是populate函数的本地定义,因此一旦该函数返回,数据将不可用.

  • 索引变量line应该在0117之间运行,因为它用于索引e[118]array.访问e[118]具有未定义的行为.

  • 您应该一次读取一行,并使用sscanf()来解析该行,并报告转换错误以及行内容,以便于调试.

  • 测试if (fscanf(...))不正确:如果所有4次转换都成功,则返回值应为4.任何其他结果都应被视为错误.

  • %s是一个危险的转换说明符,因为如果文件内容包含的单词比预期的更长,则fscanf()可能会导致缓冲区溢出.

  • 对于数组形式的目标变量,不应使用&.

  • fflush(stdin);是无用的,实际上具有未定义的行为.

以下是修改后的版本:

#include "periodic_table.h"

// these definitions should be moved to "periodic_table.h"
struct element {
    int atomic_num;
    char name[15];
    char symbol[5];
    float mass_num;
};

// Array to hold the elements
struct element e[118];

int populate(void) {
    // checks that the file exists
    FILE *ptr = fopen("periodic_table.txt", "r");
    if (ptr == NULL) {
        fprintf(stderr, "No file to read from.\nExiting...\n");
        return 1;
    }

    int line;   // first line of the txt file
    for (line = 0; line < 118; line++) {
        char buffer[128];
        int pos;
        if (!fgets(buffer, sizeof buffer, ptr)) {
            fprintf(stderr, "cannot read element %d\n", line + 1);
            break;
        }
        if (sscanf(buffer, "%d%14s%4s%f%n", &e[line].atomic_num, e[line].name,
                   e[line].symbol, &e[line].mass_num, &pos) == 4) {
            //print is just for debugging purpose
            printf("%d record: %d %s %s %.2f\n",
                   line + 1, e[line].atomic_num, e[line].name,
                   e[line].symbol, e[line].mass_num);
            if (buffer[pos] != '\n') {
                fprintf(stderr, "line %d: extra data: %s\n", line + 1, buffer + pos);
            }
        } else {
            fprintf(stderr, "line %d: invalid data: %s\n", line + 1, buffer);
        }
    }

    fclose(ptr);
    return 0;
}

C++相关问答推荐

MISRA C:2012 11.3违规强制转换(FLOAT*)到(uint32_t*)

在C中使用JMP_buf数组进行线程化(在xv6中测试)

显式地将值转换为它从函数返回的类型的含义是什么?

GDB输出ARM助记符

如何在CANbus RX/TX FIFO起始地址寄存器(ATSAME 51)的特定地址初始化数组?

S将C语言宏定义为自身的目的是什么?(在glibc标题中看到)

在WSL关闭/重新启动后,是什么原因导致共享对象依赖关系发生更改?

从C文件中删除注释

将字符串数组传递给C中的函数:`str[dim1][str_size]`vs`*str[dim1]`

我在C中运行和调试时得到了不同的输出

为四维数组中的Dim-1和Dim-3重新分配空间

使用正则表达式获取字符串中标记的开始和结束

用于计算位数和的递归C函数

某些EAX值的不同调用方的CPUID结果不一致

C中的空指针是什么(_N)?

为什么GCC不能在 struct 初始值设定项中以sizeof作为条件的三进制中处理复合文字的编译时求值?

如何在C中计算包含递增和递减运算符的逻辑表达式?

struct 中的qsort,但排序后的 struct 很乱

如何为avr atmega32微控制器构建C代码,通过光电二极管捕获光强度并通过串行通信传输数据

如何转义包含指令中的字符?