首先,我会解释为什么我这样做是这样的。我正在上一门计算机编程课程,我的教授给了我们一个作业,我们必须制作一系列记录(每个记录包含名字,姓氏和分数),然后允许用户操作记录使用菜单选项。所有这些必须仅使用指针数组来完成,并且不允许使用结构。我知道这是一件令人头痛的事。我知道这可能是实现这一目标的最困难的方法之一,但它是教授想要的。
有了这个,下面就是我到目前为止我的主要功能。大多数长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;
}
在我将 SECOND TIME ,&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
函数内的输出线。具体来说,指向第一条记录record[0]
的指针在addRecord
函数的第二次传递中变为垃圾值,就在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多个进行评分。
欢迎任何帮助。
答案 0 :(得分:1)
这个问题似乎更好地实现为
#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
以上是输入记录的伪代码
并且应该足以使输入正确。
此后打印信息应该很容易。
答案 1 :(得分:0)
对多维数组使用realloc的示例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int size_initial = 10;
int **ptr;
int i, j;
ptr = (int**) malloc(sizeof (int*) * size_initial);
for (i = 0; i < size_initial; i++) {
ptr[i] = (int*) malloc(sizeof (int) * 10);
for (j = 0; j < 10; j++)
ptr[i][j] = i+j;
}
/* realloc +10 */
ptr = (int**) realloc(ptr, sizeof (int*) * (size_initial * 2));
for (i = size_initial; i < size_initial * 2; i++) {
ptr[i] = (int*) malloc(sizeof (int) * 10);
for (j = 0; j < 10; j++) {
ptr[i][j] = i+j;
}
}
/* print values */
for (i = 0; i < 20; i++) {
for (j = 0; j < 10; j++) {
printf("ptr[%d][%d] = %d\n", i, j, ptr[i][j]);
}
}
return 0;
}