[题集]指针与结构体

调试题:

#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)

我们先来找找程序错误的地方:

img

  • score是一个int类型的变量,若要通过scanf函数进行输入,需要取到变量的地址,传给scanf函数,才能进行键盘输入赋值
  • 解决方案:增加取地址符号,改为:&st1.score

img

  • st2为一个结构体类型指针,这儿运算符是->没用错,但是这个指针未定义,它未指向任何一片内存,按照程序思路来说,不能将他指向st1,因为需要输入两个类型的信息
  • 解决方案:利用malloc函数对st2进行动态内存分配
  • st2=(struct student*)malloc(sizeof(struct studen));

img

  • st2虽然为指针变量,但是成员score也是普通的int变量,也需要取到它的地址才能进行键盘输入
  • 解决方案:增加取地址符,改为&st2->score

编译器报错:

img

解决后:

img

运行结果:

img

第二题:

#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类型的成员

又定义了两个结构体变量

我们先来找找错误的地方:

img

  • 在结构体声明的时候,是不会分配内存的,只有在定义了时候会分配,在程序中定义st1,st2的时候,分配了相对应的内存给两结构体变量
  • 但结构体内拥有一个指针类型的成员,这个成员未初始化,没指向任何一片内存,由于没有指向任何一片内存,则不能通过scanf函数输入值
  • 解决方案:给name指针分配相对应类型(char*)的空间:
  • (char*)malloc(50);

img

  • score成员是一个int类型,如果要使用scanf输入,必须将成员的地址传入scanf函数内
  • 解决方案:增加取地址符,改为:&st1.score

编译器报错:

img

解决后:

img

运行结果:

img

第三题:

#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普通类型);

又定义了一个结构体类型的变量和指针变量

我们来找下问题:

img

st2是结构体指针类型,但它未指向任何一个变量,没有内存让它管理,按照程序思路来说,需要输入两个学生信息,所以不能让他指向st1的地址,则需要手动为它分配内存

解决方案:(struct student*)malloc(sizeof(struct student));

img

  • 在结构体变量已定义的情况下,不能再进行重定义,而name是一数组,指针常量,是不可以在已定义后赋值给它的
  • 解决方案:
  • 可通过调用string库使用strcpy函数将字符复制进入数组

img

  • 在定义结构体是初始化成员

img

编译器报错:

img

解决后:

img

注意:使用malloc后需要free释放所指向的内存

运行结果:

img

第四题:

#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类型成员

我们来找下错误

img

  • 由于score是一个int类型的数据,它需要传入地址到scanf函数内,才能完成输入
  • 解决方案:改为&stu[i].score或,(stu+i).score

img

  • 将stu的地址传入passOrdown函数内,实参为stu的地址,拷贝进形参p
  • 则p->passdown为数组类型(指针常量),不可使用赋值号给它赋值
  • 解决方案:
  • 将passdown成员改为指针变量
  • 使用stecpy函数将字符串复制进passdown数组内

img

  • 根据程序思维,循环需要遍历数组,但是这儿只输出了形参q(为实参stu的地址)
  • 解决方案:
  • 将q->name改为q[i].name
  • 加上q++语句

编译器报错:

img

解决后:

#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++;
    }
}

运行结果:

img

第五题:

#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,指向结构体数组

我们先来找找问题:

img

前半段没问题,那么问题就出在了表达式上,我们来剖析所有的表达式

img

  • 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,还是没错

img

  • --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改为数组类型!

img

好了第一个问题找到了,咱们看看接下来的语句

img

三个表达式中都有p,那么,我们需要注意:

img

在这之前,p做过一次自增,这时p已经指向了st[1]

而且!

img

在这段循环中,自增自减依次作用于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;
}

程序声明了一个结构体,同时定义了两个结构体变量,一个指针类型, 一个普通变量

这题挺有意思的,我第一遍看的时候没发现错误所在,看了第二遍才找到,我们来看看

img

  • st2为指针类型的结构体变量,那么它引用成员的时候不能使用普通的(.)应该使用->成员运算符
  • 解决方案:引用st2时候,将运算符改为->

编译器报错:

img

修改后:

img

运行结果:

img

第七题:

#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指针类型成员!

我们来找找错误所在:

img

  • 在输入姓名的功能里,使用的都是scanf函数输出,总所周知的是,指针未分配内存的时候是不可以用scanf的!
  • 解决方案:将指针变量改为指针常量,fristname和lastname都改为数组类型
  • 为两个指针变量动态分配内存

编译器报错:

img这玩意没啥用

修改后:

img

运行结果:

img

第八题:

#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数组类型成员!

这儿我们一看就能发现错误所在:

img

  • 结构体内的firstname和lastname均为数组类型,在定义的时候未赋值就不可以进行赋值了
  • 解决方案:在定义时赋值
  • 使用strcpy函数将字符串复制进去

编译器报错:

img

修改后:

img

运行结果:

img

第九题:

#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;
}

这几题代码近乎相同,我就不多剖析代码作用了,一眼能看出错误所在:

img

  • 在为成员lastname分配内存的时候,它为加变量名,系统不知道作用于那儿,而且lastname是属于student结构体的成员,不加变量名是访问不到成员的
  • 解决方案:加上变量名

编译器报错:

img

解决后:

img

运行结果:

img

第十题:

#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;
}

程序声明了一个结构体,里面内嵌了一个结构体类型指针

同时定义了三个结构体指针变量

我们来找找问题所在:

img

  • 结构体成员name为数组类型,不可使用指定运算符为它赋值
  • 解决方案:使用strcpy函数将字符串复制进去

img

  • 这个地方没得错,但是最好让r指向NULL,完成完整的链表结构

img

  • 按照程序思想,需要输出完整的链表数据,但这儿输出了三次p指向内存的值
  • 解决方案:第二句第三句使用next引用q,r中的数据

编译器报错:

img

修改后:

img

运行结果:

img

第十一题

#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循环遍历链表数据

我们来找找问题:

img

  • 循环判断条件是不为空,但是当遍历到r的时候,r中的next指针未指向任何区域
  • 将造成循环无法完成
  • 解决方案:将r->next指向NULL

img

循环的判断条件是取到current中的next,next不为空则继续循环

每一循环后,将会把此次循环中next的值赋给current,那么到了第三次,则不能输出r中的数据:

img

解决方案:将表达式改为current!=NULL,判断此节点内是否为空,而不是判断此节点中next是否指向空

编译器未报错,解决后:

img

img

运行结果:

img

剖析代码:一

#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

输出结果:

img

第三题

#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;

}

语句较多我们一段一段来看:

img

  • 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

img

  • 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

img

  • ++(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,

输出结果:

img

总结:

结构体与指针的关系算是学完了,但只是基础,在往后的学习当中还会碰到很多的困难,共勉

指针可做结构体变量,结构体成员,结构体做函数时的参数,也可用于结构体自引用

指针为指针变量,指针做结构体变量的时候,访问指向内存的成员时需要用到->成员运算符等等!总结不到位的希望各位大佬补充

咱们进入心系很久的链表学习!

本文链接:

https://nullcode.fun/112.html
1 + 4 =
快来做第一个评论的人吧~