0

我已经用 C 语言创建了一个带有动态字段的元素周期表程序,或者至少我尝试过。

稍后我将使用其他 116 个元素扩展程序,但现在,它将是这样的。

编译器什么也没说,但我得到一个运行时错误:'内存访问冲突'

我忽略/错过了什么?

输出应该只显示保存的元素(铝/镭)。

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


  typedef struct
  {
    char Name[20];
    char Symbol[3];
    char Atomicnumber[5];
    char* entrys;
  } Element;


int main(void)
{
    //Define the two entrys/elements

    Element Aluminium;
    strcpy(Aluminium.Name, "Aluminium");
    strcpy(Aluminium.Symbol, "Al");
    strcpy(Aluminium.Atomicnumber, "13");

    Element Radium;
    strcpy(Radium.Name, "Radium");
    strcpy(Radium.Symbol, "Ra");
    strcpy(Radium.Atomicnumber, "88");

    int size=0;
    //Define field
    printf ("size of field:");
    scanf( "%d" , &size);
    //Gives the saved Elements an Adress in Array/Field  

    Element Periodictable [size];

    strcpy(Periodictable[13].Name, "Aluminium");
    strcpy(Periodictable[13].Symbol, "Al");
    strcpy(Periodictable[13].Atomicnumber, "13");
    strcpy(Periodictable[13].entrys, "1");

    strcpy(Periodictable[88].Name, "Radium");
    strcpy(Periodictable[88].Symbol, "Ra");
    strcpy(Periodictable[88].Atomicnumber, "88");
    strcpy(Periodictable[88].entrys, "1");

    void output(Element* Periodictable, int*entry);

    printf("Recorded elements:\n");
    printf("\n");
    for (int i=1; i<= size; i++)
    {
        if (Periodictable[i].entrys)
        {
            printf("Name: %s \n",Periodictable[i].Name);
            printf("Symbol: %s \n",Periodictable[i].Symbol);
            printf("Atomic number: %s \n",Periodictable[i].Atomicnumber);
            printf("\n");
        }
        else i++;
    }

    return (0);
}

输出应该是这样的:

Recorded elements:
Name: Aluminium
Symbol: Al
Atomic number: 13
Name: Radium
Symbol: Ra
Atomic number: 88

仍应创建定义的字段,但不应在控制台中显示空字段/地址

4

1 回答 1

0

您的代码存在一些问题。

  1. entrys成员是一个指针,char它永远不会被初始化或接收动态分配的内存。您已静态声明其他 3 个成员并使用strcpy. 但是,strcpy不应在未分配的指针上使用,因为您可能正在写入分配给程序运行的内存之外的任意内存空间。内存访问冲突#1。

  2. Periodictable您根据用户输入进行分配。因此,如果用户输入小于 89 的数字,您将尝试访问另一个内存空间,当您引用Periodictable[88]. 正如您从一开始就知道元素的数量一样,您可以使用一个简单的固定数组来保存所有 118 个元素(如果您想按元素编号保持数组索引并忽略元素 0,则大小为 119)。内存访问冲突#2。

  3. 当你分配Periodictable数组时,你忘记了初始化它。请记住,C 默认情况下不会初始化数组,因此您必须自己进行。调用memset()整个数组就可以了。

  4. if (Periodictable[i].entrys)将不起作用,因为您没有entrys从原始实现中取消引用指针。如果您决定保留entrys为指针,则可以if (*Periodictable[i].entrys)改为编写。但是,似乎没有必要使用指针,而是一个简单的方法char可以解决问题(实际上 abool甚至更合适,更清晰)。

  5. 您必须使用该else i++语句跳过一个元素,它只是尚未显示,因为数组中注册的元素不足。您不必i再次增加,因为 for 循环已经这样做了。

  6. 您的代码中有两种初始化方式,都可以使用。一种是直接向数组写入值,另一种是在栈上声明元素,写入,复制到数组中。在下面的代码中,作为示例,两个元素的初始化方式不同。

所以,这就是代码的样子。

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

#define MAXSIZE 119

typedef struct
  {
    char Name[20];
    char Symbol[3];
    char Atomicnumber[5];
    char entrys;
  } Element;


int main(void)
{
    Element Periodictable [MAXSIZE];
    memset(&Periodictable, 0, sizeof(Element) * MAXSIZE);

    Element Aluminium;
    strcpy(Aluminium.Name, "Aluminium");
    strcpy(Aluminium.Symbol, "Al");
    strcpy(Aluminium.Atomicnumber, "13");
    Aluminium.entrys = 1;
    memcpy(&Periodictable[13], &Aluminium, sizeof(Element));

    strcpy(Periodictable[88].Name, "Radium");
    strcpy(Periodictable[88].Symbol, "Ra");
    strcpy(Periodictable[88].Atomicnumber, "88");
    Periodictable[88].entrys = 1;

    printf("Recorded elements:\n");
    printf("\n");
    for (int i=1; i<= MAXSIZE; i++)
    {
        if (Periodictable[i].entrys)
        {
            printf("Name: %s \n",Periodictable[i].Name);
            printf("Symbol: %s \n",Periodictable[i].Symbol);
            printf("Atomic number: %s \n",Periodictable[i].Atomicnumber);
            printf("\n");
        }
    }

    return (0);
}

它输出:

Recorded elements:

Name: Aluminium
Symbol: Al
Atomic number: 13

Name: Radium
Symbol: Ra
Atomic number: 88

最后,这些更改将使当前的设计工作,但可能有更简单的方法来设计相同的程序,具体取决于您正在寻找的内容。尽管如此,我希望答案有助于解释发生了什么。

于 2019-04-25T00:13:21.303 回答