gpt4 book ai didi

c - 多维指针数组重新分配导致段错误

转载 作者:行者123 更新时间:2023-11-30 15:21:11 24 4
gpt4 key购买 nike

首先,我将解释为什么我要这样做。我正在学习计算机编程类(class),我的教授给我们布置了一项作业,我们必须制作一组记录(每个记录都包含名字、姓氏和分数),然后允许用户使用以下命令操作记录菜单选项。所有这些都必须仅使用指针数组来完成,并且不允许使用结构。我知道这很令人头痛。我知道这可能是实现这一目标的最困难的方法之一,但这正是教授想要的。

除此之外,下面是到目前为止我的主要功能。大多数长 printf 函数只是我打印调试信息。请注意 char*** 变量的声明。它旨在充当 3D 数组,其中 nameRecords[0] 为第一条记录,nameRecords[0][0] 为第一条记录的名字,nameRecords[0][1] 是第一条记录的姓氏。第三个维度是 nameRecords[0][0][21],因为字符串的长度仅为 20 个字符加上空字符。

int main(void)
{
char ***nameRecords = NULL;
float *scores = NULL;
int size = 0; // total number of records
int usrInt = 0;
while(usrInt < 1)
{
printf("\nEnter the number of records to record(min 1): ");
scanf("%d", &usrInt);
inpurge();

if(usrInt < 1) printf("\nMust be integer greater than 1.\n");
}

nameRecords = (char***)calloc((size), sizeof(char**));
scores = (float*)calloc(size, sizeof(float));

int i;
for(i = 0; i < usrInt; i++)
{
addRecord(&nameRecords, &scores, &size);
printf("\nnameRecords@%p :: nameRecords[%d]@%p :: nameRecords[%d][0]=%s :: nameRecords[%d][1]=%s\n", nameRecords, size - 1, nameRecords[size - 1], size - 1, nameRecords[size - 1][0], size - 1, nameRecords[size - 1][1]);
}

printf("\nnameRecords[0]@%p\n", nameRecords[0]);

prntRecords(nameRecords, scores, size);

printf("\n\n\n");
return 0;
}

在我第二次&nameRecords传递到addRecord函数(定义如下)之后,麻烦就来了。澄清一下,如果用户选择在主函数开头仅输入 1 个条目,则不会收到段错误,并且程序实际上按预期运行和终止。

void addRecord(char ****records, float **scores, int *size)
{
printf("\t(*records)[0]%p\n", (*records)[0]);
++*size; // increment total number of records by 1
int index = (*size) - 1;

char ***tempNames = (char***)realloc(*records, (*size) * sizeof(char**)); // reallocate larger space.
if(tempNames != *records)
*records = tempNames; // set original pointer to new value.

printf("\n\tsize - 1 = %d\n", index);

float *tempScores = (float*)realloc(*scores, (*size) * sizeof(float)); // reallocate larger space.
if(tempScores != *scores)
*scores = tempScores; // set original pointer to new value.

printf("\ttempNames[0]@%p\n", tempNames[0]);

tempNames[index] = (char**)calloc(tempNames[index], 2 * sizeof(char*));
enterRecord(tempNames[index], scores[index]);

printf("\n\ttempNames@%p :: tempNames[0]@%p :: tempNames[%d][0]=%s :: tempNames[%d][1]=%s\n", tempNames, tempNames[0], index, tempNames[index][0], index, tempNames[index][1]);
printf("\n\t*records@%p :: *records[0]@%p :: *records[%d][0]=%s :: *records[%d][1]=%s\n", *records, (*records)[0], index, (*records)[index][0], index, (*records)[index][1]);

return;
}

下面是该程序的示例输出。不用花太多时间来解释发生了什么,选项卡式行是 addRecord 函数内的输出行。具体来说,在第二次通过 addRecord 函数时,指向第一条记录 record[0] 的指针已变成垃圾值,就在 EnterRecord 函数。

Enter the number of records to record(min 5):  2
(*records)[0](nil)

size - 1 = 0
tempNames[0]@(nil)

Enter first name: 1

Enter last name: 1

Enter score: 1

COMPLETE enterRecord

tempNames@0x6387010 :: tempNames[0]@0x6387050 :: tempNames[0][0]=1 :: tempNames[0][1]=1

*records@0x6387010 :: *records[0]@0x6387050 :: *records[0][0]=1 :: *records[0][1]=1

nameRecords@0x6387010 :: nameRecords[0]@0x6387050 :: nameRecords[0][0]=1 :: nameRecords[0][1]=1
(*records)[0]0x6387050

size - 1 = 1
tempNames[0]@0x6387050

Enter first name: 2

Enter last name: 2

Enter score: 2

COMPLETE enterRecord

tempNames@0x6387010 :: tempNames[0]@0x40000000 :: tempNames[1][0]=2 :: tempNames[1][1]=2

*records@0x6387010 :: *records[0]@0x40000000 :: *records[1][0]=2 :: *records[1][1]=2

nameRecords@0x6387010 :: nameRecords[1]@0x63870b0 :: nameRecords[1][0]=2 :: nameRecords[1][1]=2

nameRecords[0]@0x40000000

records@0x6387010 :: records[0]@0x40000000
Segmentation fault

所有调试信息都指向 enterRecord 函数是罪魁祸首。这就是邪恶的 enterRecord 函数...

void enterRecord(char **names, float *score)
{
names[0] = (char*)calloc(21, sizeof(char)); // allocate first name string
names[1] = (char*)calloc(21, sizeof(char)); // allocate last name string

printf("\nEnter first name: ");
fgets(names[0], 21, stdin);
if(strlen(names[0]) == 20) // IGNORE. just handles overflow from fgets.
inpurge();
remNewLine(names[0]); // removes '\n' character at end of string

printf("\nEnter last name: ");
fgets(names[1], 21, stdin);
if(strlen(names[1]) == 20) // IGNORE. just handles overflow from fgets.
inpurge();
remNewLine(names[1]); // removes '\n' character at end of string

printf("\nEnter score: ");
scanf("%f", score);
inpurge();

printf("\nCOMPLETE enterRecord\n");
return;
}

只是...没有尝试更改受影响的指针。记录数组第二个元素的指针值(records[1])被传递到函数中,我看不到任何内容正在改变记录数组第一个元素的指针值(records[0]),但 records[0] 的值是导致段错误的原因。

对于代码的长度和所有混淆性的内容,我深表歉意。同样,这似乎是编写该程序的一种糟糕方法,但这正是情况所需要的。我只是为那位可怜的助教感到难过,他必须给其中 30 多份作业评分。

欢迎任何帮助。

最佳答案

这个问题似乎更好地实现为

#define MAX_FIRST_NAME_LEN (21)
#define MAX_LAST_NAME_LEN (21)
#define MAX_SCORES (10)

// in file global memory...
static char **ppFirstNames = NULL;
static char **ppLastName = NULL;
static int **ppScores = NULL;
static int numOfEntries = 0;

// in the record input function, which needs NO parameters
scanf ( "%d", &numOfEntries );
if scanf fails, exit

ppFirstNames = malloc (numOfEntries*sizeof char*);
if malloc fails, exit

memset (ppFirstName, '\0', numOfEntries*sizeof char* );

ppLastName = malloc (numOfEntries*sizeof char*);
if malloc fails, free all, exit

memset (ppLastName, '\0', numOfEntries*sizeof char* );

ppScores = malloc (numOfEntries *sizeof int* );
if malloc fails, free all, exit

for(int i=0; i<numOfEntries; i++ )
ppFirstNames[i] = malloc( MAX_FIRST_NAME_LEN );
if malloc fails free all, exit

memset ( ppFirstNames[i], '\0', MAX_FIRST_NAME_LEN );

ppLastName[i] = malloc (MAX_LAST_NAME_LEN);
if malloc fails free all, exit

memset ( ppLastName[i], '\0', MAX_LAST_NAME_LEN );

ppScores[i] = malloc (MAX_SCORES *sizeof int);-1
if malloc fails, free all, exit

memset (ppScores[i], '\0', MAX_SCORES *sizeof int );
end for

for ( int i=0; i < numOfEntries; i++ )
now read each record
scanf( "%(MAX_FIRST_NAME_LEN-1)s", ppFirstNames[i] );
if scanf fails, free all, exit

scanf( "%(MAX_LAST_NAME_LEN-1)s", ppLastNames[i] );
if scanf fails, free all exit

for( int j=0; j< MAX_SCORES; j++ )
now read this students scores
int tempScore;
scanf( "%d", tempScore );
if scanf fails, free all, exit

if -1 == tempScore ) break;

ppScores[i][j] = tempScore;
end for
end for

以上是输入记录的伪代码

并且应该足以使输入正确。

此后打印信息应该很容易。

关于c - 多维指针数组重新分配导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29641061/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com