C 语言指针问题,急!

题目是这样的,在主函数里输入 5 个考生的 3 门课考试成绩,然后找出有两门以上不及格的学生,并输出其学号和不及格课程的成绩。我定义了一个指针函数。

int *failed(int num,int *(*score)){/*定义找出不及格学生的函数,
参数 num 为总学生人数,
指针 score 指向一个二维数组,
即存储所有学生的各科成绩(并非单科)。
*/
int i,j,t,p;/*i,j 为双重循环变量,
t 临时记录某个学生不及格科目的数量,
p 记录满足不过关条件的人数,以便在结果中释放相应大小的空间。
*/
int *c=NULL;//c 指针为最终返回结果,先初始化为空。
p=0;//初始化总不及格人数为 0
for(i=0;i<num;i++){//现在开始逐个核对
t=0;//在没有核对之前,先将这个人的不及格科目数初始化为 0
for(j=0;j<3;j++){//核对第 i 个人的每个科目成绩
if(score[j][i]<60){//如果第 i 个人的第 j 门课的成绩为不及格
t++;//那么不及格数量加 1
}
}
if(t>=2){//统计完成后,如果发现第 i 名学生的不及格科目数在 2 门以上
c=(int *)malloc(4*sizeof(int));/*那么就给 c 指针释放 4 个整型数据的空间,
这 4 块内容分别存放学号和所有不及格的考试成绩
(如果有哪门课及格了,那么就存入 -1)
*/
c[4*p]=i;//在刚才释放的四块区域的首位存入该学生的学号
for(j=0;j<3;j++){/*后三块区域依次存入三门课的成绩,
如果有已经及格的科目,那么存入 -1,在主程序中不予考虑。
*/
if(score[j][i]<60){
c[4*p+j+1]=score[j][i];
}
else{
c[4*p+j+1]=-1;
}
}
p++;//存储完一个学生的信息后,不及格人数要加 1。
}
}
return c;//当所有不及格学生的信息都存储完毕后,返回整个指针。
}

但是,每次当程序执行到 c[4*p]=i; 这一句的时候就说指针引用错误。就是在给 c 指针释放 4 个整数型空间的下面一句。到底是为什么呢?
附一下主程序:
void main(){
int score[3][5];
char name[5][32];
int *c=NULL;
int i,j,*p;
for(i=0;i<5;i++){
printf("Input the name of Student %d:",i+1);
scanf("%s",name[i]);
for(j=0;j<3;j++){
printf("Input the score of Student %d in Course %d:",i+1,j+1);
scanf("%d",&score[j][i]);
}
}
c=failed(5,score);
p=&c;
if(p){
printf("The following student(s) are failed in this exam.\n");
do{
printf("Student %d",(*p)+1);
printf("(%s)\n",name[*p]);
for(j=0;j<3;j++){
p++;
if(*p!=-1){
printf("Course %d:%d\n",j+1,*p);
}
}
p++;
}while(p);
}
free(c);
}

你的c每次遇到一个不及格考生时就新建了一个长度为4的int数组,那么请问,碰到第二个不及格考生时,第一个不及格考生的数据去哪里了???本来是c指向它的,现在你c又指向新的内存空间了,第一个不及格考生的数据就成内存碎片了。。。。。。
错误也是由此而来,碰到第二个不及格考生时,你的p就是1了,这时候你的c是新建的长度为4的数组,又哪来的c[4]呢???要知道,c已经指向新申请的内存空间了,不再指向碰到第一个不及格考生时你申请的内存了,而且两次申请的内存是不连续的。。。

正确做法有两种:
一是先统计不及格人数p,再c=(int *)malloc(p*4*sizeof(int));
然后再重新来一次循环,把不及格人的信息存入c。
二是一上来就c=(int *)malloc(num*4*sizeof(int));,然后在查找不及格人的同时,就可以向c写数据了。

另外,你还需要设一个变量来保存不及格人数,而且这个变量最好是做为failed函数的参数,并且使用引用传递

/在你代码基础上小改了一下,已通过测试。我在所有有修改的行的末尾都添加了注释

#include "stdio.h"
#include "stdlib.h"

int *failed(int num,int (*score)[5], int &cnt){//cnt变量用来保存不及格人数
int i,j,t,p;
int *c=NULL;
c=(int *)malloc(num*4*sizeof(int)); //一上来就申请足够大的内存空间
p=0;
for(i=0;i<num;i++){
t=0;
for(j=0;j<3;j++){
if(score[j][i]<60){
t++;
}
}
if(t>=2){
c[4*p]=i;
for(j=0;j<3;j++){
if(score[j][i]<60){
c[4*p+j+1]=score[j][i];
}
else{
c[4*p+j+1]=-1;
}
}
p++;
}
}
cnt=p; //注意要记录不及格人数
return c;
}

void main(){
int score[3][5];
char name[5][32];
int *c=NULL;
int i,j,*p;
int cnt; //添加一个变量,记录不及格人数
for(i=0;i<5;i++){
printf("Input the name of Student %d:",i+1);
scanf("%s",name[i]);
for(j=0;j<3;j++){
printf("Input the score of Student %d in Course %d:",i+1,j+1);
scanf("%d",&score[j][i]);
}
}
c=failed(5,score,cnt); //注意,调用时要加第3个参数了
p=c;
if(p){
printf("The following student(s) are failed in this exam.\n");
i=0; //注意,循环控制方式要改变了,不能以p是否为空作判断
//如果用p来判断的话,即使显示完了所有不及格考生,p仍然不是NULL
do{
printf("Student %d",(*p)+1);
printf("(%s)\n",name[*p]);
for(j=0;j<3;j++){
p++;
if(*p!=-1){
printf("Course %d:%d\n",j+1,*p);
}
}
p++;
i++; //i增加1
}while(i<cnt); //用i作循环控制变量
}
free(c);
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2012-01-19
c[4*p]=i; 这样写有问题

p = 0时,c[0]下标引用没问题
p = 1时,c[4] 下标越界,因为你给 c 指针分配的空间是 4个 int 型长度,有效下标只能 c[0]~c[3],超过3则越界。
我觉得是不是只需要c[p] = xxx既可?当然,没仔细看你说明,只看了下代码

你说的“释放”我一直没看明白,看了代码才知道应该是“分配”
第2个回答  2012-01-19
1. int x=1,*p; *p=&x *p=&x表达式错误的,*p代表指针变量p的C语言书上有的。。 都有问题第一个应该是 int x=1,*p;p=&x;
第3个回答  2012-01-19
玷占用
相似回答