[题集]指针与结构体
调试题:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main()
{
struct student
{
char name[20];
int score;
};
struct student st1, * st2;
printf("Please input your name:");
scanf("%s", st1.name);
printf("Please input your score:");
scanf("%d", st1.score);
printf("Please input #2 student name:");
scanf("%s", st2->name);
printf("Please input #2 student score:");
scanf("%d", st2->score);
printf("%s的C语言分数为:%d\n", st1.name, st1.score);
printf("%s的C语言分数为:%d\n", st2->name, st2->score);
system("pause");
return 0;
}
程序声明了一个拥有两个成员(char类型数组,int类型变量)的结构体
又定义了两个结构体类型的变量(普通变量st1)和指针(结构体指针变量st2)
我们先来找找程序错误的地方:
- score是一个int类型的变量,若要通过scanf函数进行输入,需要取到变量的地址,传给scanf函数,才能进行键盘输入赋值
- 解决方案:增加取地址符号,改为:&st1.score
- st2为一个结构体类型指针,这儿运算符是->没用错,但是这个指针未定义,它未指向任何一片内存,按照程序思路来说,不能将他指向st1,因为需要输入两个类型的信息
- 解决方案:利用malloc函数对st2进行动态内存分配
- st2=(struct student*)malloc(sizeof(struct studen));
- st2虽然为指针变量,但是成员score也是普通的int变量,也需要取到它的地址才能进行键盘输入
- 解决方案:增加取地址符,改为&st2->score
编译器报错:
解决后:
运行结果:
第二题:
#include<stdio.h>
#include<stdlib.h>
int main()
{
struct student
{
char* name;
int score;
};
struct student st1, st2;
printf("Please input your name:");
scanf("%s", st1.name);
printf("Your score:");
scanf("%s", st1.score);
printf("Please input #2student name:");
scanf("%s", st2.name);
printf("#2student's score:");
scanf("%s", st2.score);
printf("%s的C语言分数为:%d", st1.name, st1.score);
printf("%s的C语言分数为:%d", st2.name, st2.score);
getchar();
return 0;
}
程序定义了一个局部结构体类型,拥有一个指针(char*)类型和int类型的成员
又定义了两个结构体变量
我们先来找找错误的地方:
- 在结构体声明的时候,是不会分配内存的,只有在定义了时候会分配,在程序中定义st1,st2的时候,分配了相对应的内存给两结构体变量
- 但结构体内拥有一个指针类型的成员,这个成员未初始化,没指向任何一片内存,由于没有指向任何一片内存,则不能通过scanf函数输入值
- 解决方案:给name指针分配相对应类型(char*)的空间:
- (char*)malloc(50);
- score成员是一个int类型,如果要使用scanf输入,必须将成员的地址传入scanf函数内
- 解决方案:增加取地址符,改为:&st1.score
编译器报错:
解决后:
运行结果:
第三题:
#include<stdio.h>
#include<stdlib.h>
int main()
{
struct student
{
char name[20];
int score;
};
struct student st1, * st2;
st1.name = "Axuan";
st1.score = 90;
st2->name = "Bxuan";
st2->score = 99;
printf("%s的C语言分数为:%d\n",st1.name,st1.score);
printf("%s的C语言分数为:%d\n", st2->name, st2->score);
system("pause");
return 0;
}
程序定义了一个studen类型的结构体,拥有两个成员:name(char类型数组),score(int普通类型);
又定义了一个结构体类型的变量和指针变量
我们来找下问题:
st2是结构体指针类型,但它未指向任何一个变量,没有内存让它管理,按照程序思路来说,需要输入两个学生信息,所以不能让他指向st1的地址,则需要手动为它分配内存
解决方案:(struct student*)malloc(sizeof(struct student));
- 在结构体变量已定义的情况下,不能再进行重定义,而name是一数组,指针常量,是不可以在已定义后赋值给它的
- 解决方案:
- 可通过调用string库使用strcpy函数将字符复制进入数组
- 在定义结构体是初始化成员
编译器报错:
解决后:
注意:使用malloc后需要free释放所指向的内存
运行结果:
第四题:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void passOrdown(struct student*);
void output(struct student*);
struct student
{
char name[20];
int score;
char passdown[10];
};
int main()
{
struct student stu[3];
int i;
for (i = 0; i < 3; i++)
{
printf("请输入%d的姓名:", i + 1);
scanf("%s", stu[i].name);
printf("请输入%d的学分:", i + 1);
scanf("%d", stu[i].score);
}
passOrdown(stu);
output(stu);
system("pause");
return 0;
}
void passOrdown(struct student* p)
{
int i;
for (i = 0; i < 3; i++)
{
if (p->score >= 60)
{
p->passdown = "PASS";
}
else
{
p->passdown = "DOWN";
}
p++;
}
}
void output(struct student* q)
{
int i;
printf("\n\n%10s %10s %20s", "NAME", "SCORE", "PASS OR DOWN");
for (i = 0; i < 42; i++)
{
printf("=");
}
printf("\n");
for (i = 0; i < 3; i++)
{
printf("%10s %10d %20s\n", q->name, q->score, q->score);
}
}
程序定义了两个函数,参数类型均为结构体指针类型
又定义了一个全局结构体,拥有两个char数组类型,一个int类型成员
我们来找下错误
- 由于score是一个int类型的数据,它需要传入地址到scanf函数内,才能完成输入
- 解决方案:改为&stu[i].score或,(stu+i).score
- 将stu的地址传入passOrdown函数内,实参为stu的地址,拷贝进形参p
- 则p->passdown为数组类型(指针常量),不可使用赋值号给它赋值
- 解决方案:
- 将passdown成员改为指针变量
- 使用stecpy函数将字符串复制进passdown数组内
- 根据程序思维,循环需要遍历数组,但是这儿只输出了形参q(为实参stu的地址)
- 解决方案:
- 将q->name改为q[i].name
- 加上q++语句
编译器报错:
解决后:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void passOrdown(struct student*);
void output(struct student*);
struct student
{
char name[20];
int score;
char passdown[10];
};
int main()
{
struct student stu[3];
int i;
for (i = 0; i < 3; i++)
{
printf("请输入%d的姓名:", i + 1);
scanf("%s", stu[i].name);
printf("请输入%d的学分:", i + 1);
scanf("%d", &stu[i].score);
}
passOrdown(stu);
output(stu);
system("pause");
return 0;
}
void passOrdown(struct student* p)
{
int i;
for (i = 0; i < 3; i++)
{
if (p->score >= 60)
{
strcpy(p->passdown, "PASS");
}
else
{
strcpy(p->passdown, "DOWN");
}
p++;
}
}
void output(struct student* q)
{
int i;
printf("\n\n%10s %10s %20s", "NAME", "SCORE", "PASS OR DOWN");
for (i = 0; i < 42; i++)
{
printf("=");
}
printf("\n");
for (i = 0; i < 3; i++)
{
printf("%10s %10d %20s\n", q->name, q->score, q->passdown);
q++;
}
}
运行结果:
第五题:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int i;
struct student
{
char* name;
int i;
struct student* next;
};
struct student st[] =
{
{"Axuan",1,st + 1},
{"Bxuan",2,st + 2},
{"Cxuan",3,st}
};
struct student* p = st;
printf("%s %s %s\n", st[0].name, (++p)->name, st[1].next->name);
for (i = 0; i <= 2; i++)
{
printf("%d", --st[i].i);
printf("%c\n", ++st[i].name[2]);
}
printf("%s %s %s\n", (p->name), st[p->i].name, st[--(p->next->i)].name);
getchar();
return 0;
}
程序定义了一个结构体数组,拥有三个结构体类型变量,又定义了一个结构体指针p,指向结构体数组
我们先来找找问题:
前半段没问题,那么问题就出在了表达式上,我们来剖析所有的表达式
- st[0].name //访问st[0]取到成员name,输出为Axuan,没错
- (++p)->name//p原指向st,自增后指向了st[1]取到st[1]中的name,为Bxuan,用的->,也没错
- st[1].next->name//访问st[1]取到next,next指向st+2,利用->取到st[2]的name成员,为Cxuan,还是没错
- --st[i].i //--作用于st[i].i,循环从0开始,等价于访问st[0]取到i的值为1再进行自增,为0,下一次循环为1,再下一次为2
- ++st[i].name[2]//++还是作用于st[i].name[2],循环从0开始,访问到st[0]中的成员name,取到name所存储字符串的第二个字符就是u,但是!!!!
- 自增作用于字符上!!!而name为指针变量,它存储的字符串存放于文字常量区!是不可改变的!
- 解决方案:将指针变量改为指针常量name改为数组类型!
好了第一个问题找到了,咱们看看接下来的语句
三个表达式中都有p,那么,我们需要注意:
在这之前,p做过一次自增,这时p已经指向了st[1]
而且!
在这段循环中,自增自减依次作用于st中i的值和st中name[2]的值
这时的st[0].i为0,st[1].i为1,st[2].i为2
st[0].name[2]为v,st[1].name[2]为v,st[2].name[2]为v
(自增会改变自身的值,这时基础应该都明白,提醒下)
- (p->name):p指向st[1]这时p中存储的已经是st[1]的地址,则等价于st[1].name,得到值为Bxvan
- st[p->i].name:先看[ ]内的,p->i等价于st[1].i得到1,那么这段语句就等价于st[1].name,得到值为Bxvan
- st[--(p->next->i)].name:先看括号内,p->next->i取到st[1]中next,指向st+2,取到st[2]中的i为2,自减作用于st[2].i上的得到1,那么这段语句等价于st[1].name,得到值为Bxvan
注意:这时st[2].i中的值为1了!!!
这题还是挺有意思的,我们看下一题
第六题
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
struct student
{
char firstname[20];
char* lastname;
int score;
};
struct student st1, * st2;
printf("请输入第一位同学的姓:");
scanf("%s", st1.firstname);
st1.lastname = "阿轩";
printf("请输入%s %s的C语言分数:",st1.firstname,st1.lastname);
scanf("%d", &st1.score);
st2 = (struct studnet*)malloc(sizeof(struct student));
printf("请输入第二位同学的姓:");
scanf("%s", st2->firstname);
st2->lastname = "小轩";
printf("请输入%s %s的C语言分数:",st2.firstname,st2.lastname);
scanf("%d", &st2->score);
printf("\n\n%s %s的C语言分数是%d\n", st1.firstname, st1.lastname, st1.score);
printf("\n\n%s %s的C语言分数是%d\n", st2.firstname, st2.lastname, st2.score);
system("pause");
return 0;
}
程序声明了一个结构体,同时定义了两个结构体变量,一个指针类型, 一个普通变量
这题挺有意思的,我第一遍看的时候没发现错误所在,看了第二遍才找到,我们来看看
- st2为指针类型的结构体变量,那么它引用成员的时候不能使用普通的(.)应该使用->成员运算符
- 解决方案:引用st2时候,将运算符改为->
编译器报错:
修改后:
运行结果:
第七题:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
struct student
{
char* firstname;
char* lastname;
int score;
};
struct student st1, * st2;
printf("请输入第一位同学的姓(中文):");
scanf("%s", st1.firstname);
printf("请输入第一位同学的名(中文):");
scanf("%s", st1.lastname);
printf("请输入%s %s的C语言分数:",st1.firstname,st1.lastname);
scanf("%d", &st1.score);
st2 = (struct studnet*)malloc(sizeof(struct student));
printf("请输入第二位同学的姓:");
scanf("%s", st2->firstname);
printf("请输入第一位同学的名(中文):");
scanf("%s", st2->lastname);
printf("请输入%s %s的C语言分数:",st2->firstname,st2->lastname);
scanf("%d", &st2->score);
printf("\n\n%s %s的C语言分数是%d\n", st1.firstname, st1.lastname, st1.score);
printf("\n\n%s %s的C语言分数是%d\n", st2->firstname, st2->lastname, st2->score);
system("pause");
return 0;
}
程序声明了一个结构体,同时定义了两个结构体变量,一个指针类型, 一个普通变量
结构体内拥有两个char指针类型成员!
我们来找找错误所在:
- 在输入姓名的功能里,使用的都是scanf函数输出,总所周知的是,指针未分配内存的时候是不可以用scanf的!
- 解决方案:将指针变量改为指针常量,fristname和lastname都改为数组类型
- 为两个指针变量动态分配内存
编译器报错:
这玩意没啥用
修改后:
运行结果:
第八题:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
struct student
{
char firstname[20];
char lastname[20];
int score;
};
struct student st1, * st2;
st1.firstname = "阿";
st1.lastname = "大轩";
printf("请输入%s %s的C语言分数:",st1.firstname,st1.lastname);
scanf("%d", &st1.score);
st2 = (struct studnet*)malloc(sizeof(struct student));
st2->firstname = "二";
st2->lastname = "小轩";
printf("请输入%s %s的C语言分数:",st2->firstname,st2->lastname);
scanf("%d", &st2->score);
printf("\n\n%s%s的C语言分数是%d\n", st1.firstname, st1.lastname, st1.score);
printf("\n\n%s%s的C语言分数是%d\n", st2->firstname, st2->lastname, st2->score);
system("pause");
return 0;
}
程序声明了一个结构体,同时定义了两个结构体变量,一个指针类型, 一个普通变量
结构体内拥有两个char数组类型成员!
这儿我们一看就能发现错误所在:
- 结构体内的firstname和lastname均为数组类型,在定义的时候未赋值就不可以进行赋值了
- 解决方案:在定义时赋值
- 使用strcpy函数将字符串复制进去
编译器报错:
修改后:
运行结果:
第九题:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
struct student
{
char firstname[20];
char* lastname;
int score;
};
struct student st1, * st2;
printf("请输入第一位同学的姓:");
scanf("%s", st1.firstname);
printf("请输入第一位同学的名:");
lastname = (char*)malloc(sizeof(char));
scanf("%s", st1.lastname);
printf("请输入%s %s的C语言分数:", st1.firstname, st1.lastname);
scanf("%d", &st1.score);
st2 = (struct studnet*)malloc(sizeof(struct student));
printf("请输入第二位同学的姓:");
scanf("%s", st2->firstname);
printf("请输入第一位同学的名:");
lastname = (char*)malloc(sizeof(char));
scanf("%s", st2->lastname);
printf("请输入%s %s的C语言分数:", st2->firstname, st2->lastname);
scanf("%d", &st2->score);
printf("\n\n%s %s的C语言分数是%d\n", st1.firstname, st1.lastname, st1.score);
printf("\n\n%s %s的C语言分数是%d\n", st2->firstname, st2->lastname, st2->score);
system("pause");
return 0;
}
这几题代码近乎相同,我就不多剖析代码作用了,一眼能看出错误所在:
- 在为成员lastname分配内存的时候,它为加变量名,系统不知道作用于那儿,而且lastname是属于student结构体的成员,不加变量名是访问不到成员的
- 解决方案:加上变量名
编译器报错:
解决后:
运行结果:
第十题:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
struct student
{
char name[20];
int score;
struct student* next;
};
struct student* p,* q,* r;
p = (struct student*)malloc(sizeof(struct student));
p->name = "Axuan";
p->score = 98;
q = (struct student*)malloc(sizeof(struct student));
q->name = "Bxuan";
q->score = 78;
r = (struct student*)malloc(sizeof(struct student));
r->name = "Cxuan";
r->score = 92;
p->next = q;
q->next = r;
printf("There are three students in my class\n");
printf("%s %d\n", p->name, p->score);
printf("%s %d\n", p->name, p->score);
printf("%s %d\n", p->name, p->score);
system("pause");
return 0;
}
程序声明了一个结构体,里面内嵌了一个结构体类型指针
同时定义了三个结构体指针变量
我们来找找问题所在:
- 结构体成员name为数组类型,不可使用指定运算符为它赋值
- 解决方案:使用strcpy函数将字符串复制进去
- 这个地方没得错,但是最好让r指向NULL,完成完整的链表结构
- 按照程序思想,需要输出完整的链表数据,但这儿输出了三次p指向内存的值
- 解决方案:第二句第三句使用next引用q,r中的数据
编译器报错:
修改后:
运行结果:
第十一题
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
struct student
{
char *name;
int score;
struct student* next;
};
struct student* p, * q, * r, * current;
p = (struct student*)malloc(sizeof(struct student));
p->name = "Axuan";
p->score = 98;
q = (struct student*)malloc(sizeof(struct student));
q->name = "Bxuan";
q->score = 78;
r = (struct student*)malloc(sizeof(struct student));
r->name = "Cxuan";
r->score = 92;
p->next = q;
q->next = r;
printf("There are three students in my class\n");
current = p;
while (current->next != NULL);
{
printf("%10s %10d\n", current->name, current->score);
current = current->next;
}
system("pause");
return 0;
}
与上例代码大致相同,但是程序结尾用了while循环遍历链表数据
我们来找找问题:
- 循环判断条件是不为空,但是当遍历到r的时候,r中的next指针未指向任何区域
- 将造成循环无法完成
- 解决方案:将r->next指向NULL
循环的判断条件是取到current中的next,next不为空则继续循环
每一循环后,将会把此次循环中next的值赋给current,那么到了第三次,则不能输出r中的数据:
解决方案:将表达式改为current!=NULL,判断此节点内是否为空,而不是判断此节点中next是否指向空
编译器未报错,解决后:
运行结果:
剖析代码:一
#include<stdio.h>
#include<conio.h>
int main()
{
struct student
{
char* name;
int score;
};//定义一个局部结构体,拥有两个成员,char*类型和int类型
struct student s = { "Marry",90 };//定义一个结构体类型变量s,并为成员赋值
struct student* p = &s;//结构体指针p指向结构体变量s
printf("s.name=%s\n", s.name);
printf("s.score=%d\n", s.score);
printf("p->name=%s\n", p->name);
printf("p->score=%d\n", p->score);
printf("(*p).name=%s\n", (*p).name);
printf("(*p).score=%d\n", (*p).score);
getchar();
return 0;
}
- s为结构体变量,s.name和s.score,直接访问s结构体内的成员,输出为Marry字符串和90,name指向字符串的首地址
- p为结构体指针指向结构体变量,通过->访问p所指向的结构体,p->name表示访问p所指向的s结构体中name,输出为Marry
- (p).name与上语句相同,p中存储的是s的地址,通过取到该地址内name的值,输出为Marry
第二题:
#include<stdio.h>
#include<conio.h>
int main()
{
struct student
{
char* name;
int score;
};//定义一个局部结构体,拥有两个成员,char*类型和int类型
struct student s[] = { {"Marry",90},{"Joth",85},{"Nancy",77} };//定义一个结构体类型数组s,并为成员赋值
struct student* p = s;//结构体指针p指向结构体数组的首地址
printf("%s\n", p->name);
printf("%d\n", p->score);
printf("%s\n", (++p)->name);
printf("%d\n", p->score);
printf("%s\n", p->name);
printf("%d\n", p->score);
getchar();
return 0;
}
- 结构体指针p指向数组s的首地址,也就是s[0]中name中M的地址
- p->name,访问到s[0]中取到name的值,为Marry
- p->socre,访问到s[0]中取到score的值,为90
- (++p)->name,自增作用于p上,这时p指向s[1],访问s[1]中取到name的值为Joth
- p->score,取到s[1]中score的值为85
- p->name,访问到s[1]中取到name的值,为Joth
- p->socre,访问到s[1]中取到score的值,为85
输出结果:
第三题
#include<stdio.h>
#include<conio.h>
struct s1
{
char* s;
int n;
struct s1* ptr;
};//定义一个全局结构体,拥有两个成员,char*类型和int类型,还有一个结构体类型的指针
struct s1 a[] =
{
{"abcd",1,a + 1},
{"efgh",2,a + 2},
{"ijkl",3,a }
};//定义一个结构体类型数组a,并为成员赋值
struct s1* p = a;//结构体指针p指向结构体数组的首地址
int main()
{
int i;
printf("%s\n", a[0].s);
printf("%s\n", p->s);
printf("%s\n", a[2].ptr->s);
for (i = 0; i < 2; i++)
{
printf("-----------\n");
printf("i=%d\n", i);
printf("%d\n", --a[i].n);
printf("%c\n", a[i].s[3]);
}
printf(".............\n");
printf("%s\n", ++(p->s));
printf("%s\n", a[(++p)->n].s);
printf("%s\n", a[--(p->ptr->n)].s);
getchar();
return 0;
}
语句较多我们一段一段来看:
- a[0].s,结构体数组a[0]中s的值以字符串格式输出为:abcd
- p->s,结构体指针p指向a数组的首地址,访问到a[0]中s的值为:abcd
- a[2].ptr->s,结构体数组a[2]中指针ptr指向a,取到a[0]中s的值为:abcd
- i就是循环变量,第一次输出为0,第二次输出为1
- --a[i].n,--作用于a[i].n上,第一次输出为a[0].n为:1自减后为0,第二次输出为a[1].n:2自减后为1
- a[i].s[3],访问a[i]中s的第三个字符,第一次输出为:a[0].s[3]为:d,第二次输出为a[1].s[3]为h
- ++(p->s),++作用于p->s上,取到p指向的s[0]中s的值为字符abcd的首地址,自增取到b的地址,以字符串格式输出为bcd
- a[(++p)->n].s,先看括号内,++作用p上,p指向a[1]取到a[1].n为1,取到a[1].s的值为efgh
- a[--(p->ptr->n)].s,先看括号内,取到p指向a[1]中ptr指向a[2]中n的值为3,自减为2,输出a[2].s,值为:ijkl,
输出结果:
总结:
结构体与指针的关系算是学完了,但只是基础,在往后的学习当中还会碰到很多的困难,共勉
指针可做结构体变量,结构体成员,结构体做函数时的参数,也可用于结构体自引用
指针为指针变量,指针做结构体变量的时候,访问指向内存的成员时需要用到->成员运算符等等!总结不到位的希望各位大佬补充
咱们进入心系很久的链表学习!