我在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
仍应创建已定义的字段,但不应在控制台中显示空字段/地址
答案 0 :(得分:0)
您的代码有一些问题。
entrys
成员是指向char
的指针,该指针永远不会初始化或接收动态分配的内存。您已经静态声明了其他3个成员,并使用strcpy
初始化了它们的值。但是,strcpy
不应在未分配的指针上使用,因为您可能正在写入分配给程序运行的内存之外的任意内存空间。 内存访问冲突#1。
您根据用户输入分配Periodictable
。因此,如果用户输入的数字小于89,则当您引用Periodictable[88]
时,您将尝试访问程序可能无法访问的另一个内存空间。从一开始就知道元素的数量,您可以使用一个简单的固定数组,该数组将容纳所有118个元素(如果要按元素编号保留数组索引而忽略元素0,则大小为119)。 内存访问冲突#2。
分配Periodictable
数组时,您忘记了对其进行初始化。请记住,C默认情况下不会初始化数组,因此您必须自己进行初始化。在整个数组上调用memset()
即可。
if (Periodictable[i].entrys)
将不起作用,因为您没有从原始实现中取消引用entrys
指针。如果决定保留entrys
作为指针,则可以改写if (*Periodictable[i].entrys)
。但是,似乎并不一定需要使用指针,而是可以使用简单的char
来解决问题(实际上,bool
甚至更合适,更清晰)。
您必须使用else i++
语句跳过一个元素,因为该数组中没有足够的元素注册,所以它尚未显示。您不必再增加i
,因为for循环已经做到了。
您的代码中有两种初始化样式,两种都可以使用。一种是直接将值写入数组,另一种是在堆栈上声明元素,然后将其写入并复制到数组中。在下面的代码中,两个元素作为示例进行了不同的初始化。
所以,这就是代码的样子。
#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
最后,这些更改将使当前的设计工作正常进行,但是可能有更简单的方法来设计同一程序,具体取决于您要寻找的内容。尽管如此,我希望答案能解释发生了什么事。