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
玷占用

C语言指针问题
一、如有定义char y[4]= "321"则表达式 *y+2的值是'5' 。分析:y是字符串数组首元素'3'的地址,*y的值就是字符'3',再加上2,就是字符'5'(也可以说是字符'5'的ASC码值)。二、 如有定义char z[2][4]={"MAT", "LAB"};,则表达式*(*z+2)的值是 'T'。分析:z是二维字符...

c语言指针问题,求解答
首先 函数指针的定义 A、D定义为:A 定义指向函数的指针pf,所指向的函数参数为空,无返回值 D 定义指向函数的指针pf,函数参数为int,char型(不符题意,题目为int,char*),无返回值 B、D的定义为:定义函数pf,函数参数为空,返回类型为void *(void 型指针)单从函数指针的定义可排除BCD。其次...

C语言指针问题。
(1) ++(*pointer)是先取值,再自增,当前pointer指向的是位置arr[3],取值后是2,*pointer的结果是2,2再自增,当然会得出3。值得说明的是,这个括号是可以省略的,此处括号只起到增加程序可读性的作用。(2)*(pointer-2)是先移动指针,再取值。pointer-2是把指针从当前位置arr[3]回退两...

c语言指针问题
就是 char *p=*s; 或 等价于: 声明 char *p; 语句 p=*s; 让 p 指向 char s[3][8];的始地址 &s[0][0]。 目的是 让 p 有了字符\/字符串存放空间。你也可以理解: p=*s; 即 p= *(s+0); 即 p=s[0]; p=&s[0][0];p 有了字符\/字符串存放空间。

C语言指针问题
1.概念问题:指针是指存放地址值的变量或常量;指针与一般变量或常量的区别,在于它不直接存储数值,而是存放被存储数值的地址,属于间接存放,所以不少初学者感觉学习困难。 比如:int a=2,b,c,*ptr; ptr=&a;表示将指针ptr指向变量a,存放a的地址,假设是2000H,而指针变量ptr本身也要有地址,...

c语言 指针问题 有点看不懂 能帮忙解答一下正确答案中的 每一步运算...
,’x’,4}, 把t中的字符a,字符b,字符x 赋给结构体中char a[3]; 4赋给结构体 int num,然后定义了一个指针变量 int *p=&t ,指针p指向结构体变量t,要调用结构体中的成员变量,有三种方法;t.成员名(如 t.num)(*p).成员名(如(*p).num)p->成员名(如 p->num)答案为B ...

c语言这几道题 关于指针的 望大神解答
1、D选项,*x本身就错误,因为x是int类型,没法使用*操作符。2、A之所以错是因为代码中有一句q=NULL,也就是说q是一个空指针了,你再向里面写东西就错了,而且你在vc6.0中可以试一下,马上会出现一条0xc000 0005的写异常。。3、是的,你不管给它赋值多少都是4的。。就好比一个4平方米的房子...

c语言指针问题?
99)赋值给指针p指向的变量。因为p指向的是变量a,所以这一句相当于:a=b;运行后,abc的值分别是:99、99、222。③c=*p;,这又是一个赋值语句,它是把p指向的变量的值赋值给c。所以,这一句相当于:c=a;运行后,a=99、b=99,c=99。故最后打印出来的四个值都是99。有什么问题请留言。

c语言指针问题
(2),对于*P1=*P2 操作之前,一定要先将P1和p2先指向变量。还有*p=3之前,也要先把p指向一个变量。指针就是一个指向地址的变量,使用之前需要先给它赋值,也就是先将将一个变量的地址赋值给它,这个时候指针里面存的就是这个变量的地址。理解了指针的概念,上面这些问题就好理解了~...

C语言指针问题
int *p;这里,定义的是一个指向int变量的指针。它同时也可以用来指向一个int数组。因为在C中,数组的表示是通过元素的首地址来表示的。作为指针,它和int变量指针没区别,编译器无法区分。int (*p)[4],如果你的这里符合语义的话,应该有类似这样的一个声明:int p[3][4]int (*p)[4]其实指向的...

相似回答
大家正在搜