鱼C论坛

 找回密码
 立即注册
查看: 1357|回复: 16

[已解决]大佬们看一下为毛addstu函数里的ptr指针的地址是0x0

[复制链接]
发表于 2019-3-28 16:31:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct students{
        char name[10];
        int num;
        float score;
        struct students *next;        
};


int count=0;
int *p = &count;

void getInfo(struct students *);
int addStu(struct students **);
int delStu(struct students **,int );
int searchStu(struct students *,int );
void showList(struct students **);

int main(){
        struct students *S = NULL;//生成一个头节点
        int op,i;
        do{
        printf("welcome to students' information manage system!\n");
        printf("please chose your operation:\n");
        printf("1 add a student to specified location\n");
        printf("2 delete a student from the specified location\n");
        printf("3 find a student through his number\n");
        printf("4 show the list:\n");
        printf("0 exit\n");
        scanf("%d",&op);
                switch(op){
                        case 1:printf("input the num you want to insert:");addStu(&S);break;
                        case 2:printf("input the num you want to delete:");scanf("%d",&i);delStu(&S,i);break;
                        case 3:printf("input his num:");scanf("%d",&i);searchStu(S,i);break;
                        case 4:showList(&S);break;
                }
        }while(op != 0);
        
        return 0;
}
void getInfo(struct students *s){
        printf("input students's name :\n");
        scanf("%s",s->name);
        printf("input students's num and score:\n");
        scanf("%d%f",&s->num,&s->score);
}
int addStu(struct students **S1){ //问题出在这个函数里
        struct students *ns,*temp,*ptr = *S1;
        ns = (struct students *)malloc(sizeof(struct students));
        if(ns == NULL){
                printf("menory allocation error!");
                exit(1);
        }
        getInfo(ns);
        if(ptr == NULL){
                *S1 = ns;
                ns->next = NULL;
                (*p)++;
        }
        while(ptr->next != NULL && ptr->num < ns->num){
                temp = ptr;
                ptr = ptr->next;
        }
        if(ptr == *S1){
                temp = *S1;
                *S1 = ns;
                ns->next = temp;
        }
        else if(ptr->next == NULL){
                ptr->next = ns;
                ns->next = NULL;
                
        }
        else{
                temp->next = ns;
                ns->next = ptr;
        }
        printf("name\tnum\tscore\t\n",(*S1)->name,(*S1)->num,(*S1)->score);
        return 0;
}
int delStu(struct students **S1,int n){
        struct students *temp,*ptr = *S1; //用来接收旧的结构体节点,并准备释放内存 
        if(ptr->next == NULL){
                printf("can't delete student from an empty list\n");
        }
        while(ptr->num < n){
                ptr=ptr->next;
        }
        if(ptr == NULL){
                printf("can't find this student!\n");
        }
        if(ptr->num == n){
                temp = ptr;
                ptr = temp->next;
                free(temp);
                printf("delete complete\n");
        }
        return 0;
}
int searchStu(struct students *S1,int n){
        int i;
        while(S1 != NULL){
                if(S1->num == n){
                        printf("he/she is the %d student");
                        return i+1;
                }
                S1 = S1->next;
        }
        if(S1->next == NULL && S1->num != n){
                        printf("can't find this student");
                        return 0;
                }
}
void showList(struct students **S1){
        if(*S1 == NULL){
                printf("no student in this list!\n");
        }
        else{
                printf("name\tnum\tscore\t\n");
        }
        while(*S1 != NULL){
                printf("%s\t%d\t%d\t\n",(*S1)->name,(*S1)->num,(*S1)->score);
                *S1 = (*S1)->next;
        }
        
}
最佳答案
2019-3-31 14:27:19
本帖最后由 Croper 于 2019-3-31 22:49 编辑

知道你的意思,你是想move改变的时候(*S1)同时改变是么,


C语言里,仍然只能使用二重指针
struct student **move=S1;
然后使用(*move)代替你原代码里的move

//=================这里是分析环节==================
你前面这一段程序,相当于
int main(){
        int S=0;
        int *S1=&S;
        int move=*S1;
}
S1指向S,你认为,改变move的值能够改变S的值么,
他们分别属于两个不同的内存,这当然是不可能的

就算加上你的常指针
int main(){
        int S=0;
        int *S1=&S;
        int move=*(int* const )S1;
}
你认为这有区别么


唯一的方法只能
int main(){
        int S=0;
        int *S1=&S;
        int *move=S1;
}
这样才能做到改变(*move)就是改变S
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2019-3-28 16:32:46 | 显示全部楼层
第51行,ptr已经赋值了,但是却不是*S1的地址
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-28 16:41:15 | 显示全部楼层
本帖最后由 Croper 于 2019-3-28 16:50 编辑
if(ptr == NULL){
                *S1 = ns;   //这里,*S1指向的地址已经被改变了,但ptr仍然指向*S1原来的地址,也就是nullptr
                ns->next = NULL;
                (*p)++;
        }
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-30 14:36:05 | 显示全部楼层

请问大佬这个是不是可以用常指针来解决问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-30 14:42:39 | 显示全部楼层
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct students{
        char name[10];
        int num;
        float score;
        struct students *next;        
};


int count=0;
int *p = &count;

void getInfo(struct students *);
void addStu(struct students **);
int delStu(struct students **,int );
int searchStu(struct students *,int );
void showList(struct students **);

int main(){
        struct students *S = NULL;//生成一个头节点
        int op,i;
        do{
        printf("welcome to students' information manage system!\n");
        printf("please chose your operation:\n");
        printf("1 add a student to specified location\n");
        printf("2 delete a student from the specified location\n");
        printf("3 find a student through his number\n");
        printf("4 show the list:\n");
        printf("0 exit\n");
        scanf("%d",&op);
                switch(op){
                        case 1:printf("input the student information:");addStu(&S);break;
                        case 2:printf("input the num you want to delete:");scanf("%d",&i);delStu(&S,i);break;
                        case 3:printf("input his num:");scanf("%d",&i);searchStu(S,i);break;
                        case 4:showList(&S);break;
                }
        }while(op != 0);
        
        return 0;
}
void getInfo(struct students *s){
        printf("input students's name :\n");
        scanf("%s",s->name);
        printf("input students's num and score:\n");
        scanf("%d%f",&s->num,&s->score);
}
void addStu(struct students **S1){
        struct students *ns,*temp,*move = (struct students * const)S1;
        ns = (struct students *)malloc(sizeof(struct students));
        if(ns == NULL){
                printf("menory allocation error!");
                exit(1);
        }
        getInfo(ns);
        if(*S1 == NULL){ //空链表的操作; 
                move=ns;
                ns->next=NULL;
//                move = move->next;
        }
        else{
                while(move->num<ns->num && move->next != NULL){//通过新学生的学号来移动move与temp指针, 
                        temp = move;
                        move = move->next;
                }
                if(move == *S1){ //如果新来的学生的学号是最小的,那么move指针并不会移动,所以move指针指向头节点 
                        ns->next = move->next;
                        move = ns;
                }
                else if(move->next == NULL && move->num<ns->num){ //新学生的学号是最大的 
                        move->next = ns;
                        ns->next = NULL;
                }
                else{ //学生学号刚好在中间 
                        temp->next = ns;
                        ns->next = move;        
                }
        
        }
        printf("%s\t%d\t%d\t\n",move->name,move->num,move->score);
//        printf("%s\t%d\t%d\t\n",(*S1)->name,(*S1)->num,(*S1)->score);
}
int delStu(struct students **S1,int n){
        struct students *temp,*ptr = *S1; //用来接收旧的结构体节点,并准备释放内存 
        if(ptr->next == NULL){
                printf("can't delete student from an empty list\n");
        }
        while(ptr->num < n){
                ptr=ptr->next;
        }
        if(ptr == NULL){
                printf("can't find this student!\n");
        }
        if(ptr->num == n){
                temp = ptr;
                ptr = temp->next;
                free(temp);
                printf("delete complete\n");
        }
        return 0;
}
int searchStu(struct students *S1,int n){
        int i = 0;
        while(S1 != NULL){
                if(S1->num == n){
                        printf("he/she is the %d student",i);
                        return i+1;
                }
                S1 = S1->next;
                i++;
        }
        if(S1->next == NULL && S1->num != n){
                        printf("can't find this student");
                        return 0;
                }
        return 0;
}
void showList(struct students **S1){
        struct students *s;
        s = *S1;
        if(*S1 == NULL){
                printf("no student in this list!\n");
        }
        else{
                printf("name\tnum\tscore\t\n");
        }
        while(s != NULL){
                printf("%s\t%d\t%d\t\n",s->name,s->num,s->score);
                s = s->next;
        }
        
}
使用常指针的代码,但是不知道为什么,*S1就是一直是空的,求大佬们看看思路哪里有错吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-30 14:50:51 | 显示全部楼层
cookies945 发表于 2019-3-30 14:36
请问大佬这个是不是可以用常指针来解决问题


所以我推荐链表在初始化时就申请一个空置的头节点,然后把这个头节点作为唯一参照物,
然后所有过程都不需要讨论头结点为空的情况了

你这个ptr再重新指定一下就好啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-31 10:59:05 | 显示全部楼层
Croper 发表于 2019-3-30 14:50
所以我推荐链表在初始化时就申请一个空置的头节点,然后把这个头节点作为唯一参照物,
然后所有过程都不 ...

还是没有怎么听懂,我在main函数中初始化的头指针就是空,然后再将其传入addStu的函数的时候把它作为常指针了,是哪里思路有问题么,还是我们讨论的不是同一个指针
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-31 14:27:19 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Croper 于 2019-3-31 22:49 编辑

知道你的意思,你是想move改变的时候(*S1)同时改变是么,


C语言里,仍然只能使用二重指针
struct student **move=S1;
然后使用(*move)代替你原代码里的move

//=================这里是分析环节==================
你前面这一段程序,相当于
int main(){
        int S=0;
        int *S1=&S;
        int move=*S1;
}
S1指向S,你认为,改变move的值能够改变S的值么,
他们分别属于两个不同的内存,这当然是不可能的

就算加上你的常指针
int main(){
        int S=0;
        int *S1=&S;
        int move=*(int* const )S1;
}
你认为这有区别么


唯一的方法只能
int main(){
        int S=0;
        int *S1=&S;
        int *move=S1;
}
这样才能做到改变(*move)就是改变S
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-31 16:23:16 | 显示全部楼层
本帖最后由 Croper 于 2019-3-31 16:38 编辑

我按你的风格重写了一个,自己对照着改改吧
#include <stdio.h>

struct students{
        char name[10];
        int num;
        float score;
        struct students *next;        
};

struct students* CreateStudent();
void addStu(struct students *,struct students *);
int delStu(struct students *,int );
struct students* searchStu(struct students *,int );
void showList(struct students *);
void PrintStudentInfo(struct students *);

struct students* prehead;

void flushstdin(){
        char c;
        while ((c=getchar())!=EOF && c!='\n');
}

void PrintStartInterface(){
            printf("**********************************************************************\n"); 
        printf("*        welcome to students' information manage system!             *\n");
        printf("*          please chose your operation:                              *\n");
        printf("*                                                                    *\n");
        printf("*          1 add a student to specified location                     *\n");
        printf("*          2 delete a student from the specified location            *\n");
        printf("*          3 find a student through his number                       *\n");
        printf("*          4 show the list:                                          *\n");
        printf("*          0 exit                                                    *\n");
        printf("**********************************************************************\n\n"); 
}

void InitAll(){
        prehead=(struct students*)malloc(sizeof(struct students));
        prehead->next=NULL;
}

int PostOperation(){
        int op;
        scanf("%c",&op);
        flushstdin();
        
        switch (op){
                case '1':{
                        struct students *p=CreateStudent();
                        addStu(prehead,p);
                        printf("Add student success!\n");
                        PrintStudentInfo(p);
                        printf("\nPress Anykey to return..");
                        getch();
                        break;
                }
                case '2':{
                        int id;
                        printf("input the num you want to delete:");
                        scanf("%d",&id);
                        flushstdin();
                        if (!delStu(prehead,id)){
                printf("can't find this student!\n");
                        }
                        else{
                            printf("delete success!\n");        
                        }
                        
                        printf("\nPress Anykey to return..");
                        getch();
                        break;
                }
                case '3':{
                        int id;
                        printf("input the num you want to find:");
                        scanf("%d",&id);
                        flushstdin();
                         struct students *p=searchStu(prehead,id);
                         if (p){
                                 PrintStudentInfo(p);
                        }
                        else{
                                printf("Can't find this student!");
                        }
                        printf("\nPress Anykey to return..");
                        getch();
                        break;
                }
                case '4':
                        showList(prehead);
                        printf("\nPress Anykey to return..");
                        getch();
                        break;
                case '0':
                        break;
                default:
                        printf("Unrecognized operation!");
                        getch();
                        return -1;
        }
        return op;
} 

int main(){
        int op,i;
        InitAll();
        do{
                system("cls");
                PrintStartInterface();
                }while(PostOperation());
        return 0;
}

struct students* CreateStudent(){
        struct students *s=(struct students*)malloc(sizeof(struct students));
        if (s==NULL) {
                printf("menory allocation error!");
        exit(1);
        }
        printf("input the student information:\n");
    printf("\n   input students's name :");
    scanf("%s",s->name);
    flushstdin();
    printf("\n   input students's num and score:");
    setbuf(stdin,NULL);
    scanf("%d%f",&s->num,&s->score);
    flushstdin();
    
    return s;
}

void addStu(struct students *prehead,struct students* s){
         struct students *p=prehead;
         while (p->next!=NULL && p->next->num<s->num){
                 p=p->next;
        }
        struct students *tmp=p->next;
        p->next=s;
        s->next=tmp;
}

struct students* searchStu(struct students *S1,int id){
    struct students *p=prehead->next;
    while (p!=NULL && p->num<id){
              p=p->next;
        }
        if (p==NULL || p->num>id){
                return NULL;
        }
        return p;
}

int delStu(struct students *prehead,int id){
    struct students *p=prehead;
    while (p->next!=NULL && p->next->num<id){
              p=p->next;
        }
        if (p->next==NULL || p->next->num>id){
                return 0;
        }
        struct students* tmp=p->next;
        p->next=tmp->next;
        free(tmp);
    return id;
}

void showList(struct students *prehead){
    if(prehead->next == NULL){
        printf("no student in this list!\n");
        return;
    }
  
    printf("name\tnum\tscore\t\n");
    struct students *p=prehead->next;
    while(p != NULL){
        PrintStudentInfo(p);
        p = p->next;
    }  
}

void PrintStudentInfo(struct students *p){
        if (p==NULL) {
                printf("null student error!");
                return;
        }
        printf("%s\t%d\t%.1f\t\n",p->name,p->num,p->score);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-31 22:11:21 | 显示全部楼层
Croper 发表于 2019-3-31 14:27
知道你的意思,你是想move改变的时候(*S1)同时改变是么,

原来如此,我纠结了这么久的问题终于解开了,谢谢大佬
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-31 22:53:09 | 显示全部楼层
Croper 发表于 2019-3-31 16:23
我按你的风格重写了一个,自己对照着改改吧

这里还是有一个小bug,当你打印链表的时候,不知道为什么,你的score就是零

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-31 23:13:57 | 显示全部楼层
cookies945 发表于 2019-3-31 22:53
这里还是有一个小bug,当你打印链表的时候,不知道为什么,你的score就是零


                               
登录/注册后可看大图

有问题么,为什么我运行起来正常呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-31 23:15:35 | 显示全部楼层
不过
      case '0':
             break;
应该改成
          case '0':
                 return 0;
不然无法正常退出
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-4-1 21:56:29 | 显示全部楼层
Croper 发表于 2019-3-31 23:15
不过
应该改成
不然无法正常退出

哦好的我知道了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-4-1 21:57:09 | 显示全部楼层
Croper 发表于 2019-3-31 23:13
有问题么,为什么我运行起来正常呢

我说的是我自己写的程序,一开始还没有这个问题的,改着改着就出来了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-4-1 22:09:43 | 显示全部楼层
cookies945 发表于 2019-4-1 21:57
我说的是我自己写的程序,一开始还没有这个问题的,改着改着就出来了
        printf("%s\t%d\t%d\t\n",move->name,move->num,move->score);
你的score是浮点变量,输出却是%d
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-4-3 21:41:18 | 显示全部楼层
Croper 发表于 2019-4-1 22:09
你的score是浮点变量,输出却是%d

好的吧,我的小错误还是那么多,谢谢叫你那么耐心一一解答
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-3 14:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表