当前位置:学习生活->会员解答->程序执行异常中断,编译没错,执行一半走不下去跳出了。

原创版权标志程序执行异常中断,编译没错,执行一半走不下去跳出了。

作者:lhw1  发表时间:2016/12/12 15:57:06  阅读:
[摘要] C++技术网已经用心解答了用户提出的问题【程序执行异常中断,编译没错,执行一半走不下去跳出了。】,如还有问题,请继续在文章底部留言交流,直到完全懂了为止。
文章来源:C++技术网原创文章版权所有,会员文章禁止转载。非会员文章转载做好本文超链接即表示授权转载。通过文章下面的分享按钮可以自由分享所有文章。
#include<stdio.h>#include<stdlib.h>#include<string.h>struct student{    char name[30]; int age; int num;};//filename数组存放文件名char filename[25];FILE *fp;//主要函数原型声明void creat();void output();void append();main(){    int m;char k;    printf("\n请输入你要打开的文件名:");    gets(filename);    if((fp=fopen(filename,"r"))==NULL)        {        printf("\n当前没有此文件,现在是否执行创建(Y/N)?:");        scanf("%c",&k);getchar();//用于接收输入后的回车键,下边的delete函数同理        while(k!=''Y''&&k!=''N''&&k!=''y''&&k!=''n'')            {printf("\n输入有误,请再次输入一个值:");scanf("%c",&k);getchar();}        if(k==''Y''||k==''y'') {creat();}//当选择了Y或y时执行创建函数            else if(k==''N''||k==''n'')                    {printf("\n由于你选择了退出,现在程序即将关闭!\n");}        }    else    //当文件存在时把通讯录信息输出,并且提示操作        {            printf("\n你要打开的文件%s已存在,现在可直接对其操作\n",filename);            printf("\n文件%s现已有的信息:\n",filename);output();            printf("\n请根据提示选择1或2对文件进行操作\n");        }    while(1)    {        printf("\n添加,请按1");        printf("\n输出,请按2");        printf("请输入数字1或2:");        scanf("%d",&m);getchar();        while(m<0||m>5)            {printf("\n抱歉,您输入的值不是1或2的数字,请再次输入:");scanf("%d",&m);getchar();}        if(m>=0&&m<=5)        {            switch(m)            {            case 1: append();break;            case 2: output();break;            }            printf("\n操作完毕,请再次选择!\n");        }    }}/*建立通信录函数creat():功能:建立通信录文件,并连续输入记录,以0结束输入*/void creat(){    struct student one; if((fp=fopen(filename,"w"))==NULL) {        printf("\n不能建立文件!");        return; }    printf("\n成功创建%s文件,请按提示进行操作*^_^*\n",filename); fprintf(fp,"%-30s%-20d%-25d%\n","姓名","学号","年龄"); printf("\n请输入每个成员的姓名、学号、年龄(当成员名是0时结束输入):\n"); scanf("%s",one.name); while(strcmp(one.name,"0"))        //当输入的名字不为"0"的时候,执行循环,当名字为"0"时,退出循环 {        scanf("%d%d",one.num,one.age);        fprintf(fp,"%%-30s%-20d%-25d%\n\n",one.name,one.num,one.age);            //把输入的信息按指定格式写入文件当中        scanf("%s",one.name); } fclose(fp);}/*输出函数output();通信录中所有通信记录,每行输出一条记录*/void output(){    struct student one; if((fp=fopen(filename,"r"))==NULL) {        printf("\n不能打开文件!");        return; } printf("\n\n%40s\n","< 文 件 >"); while(!feof(fp))//当文件未结束时,逐条读取文件信息并输出 {        fscanf(fp,"%s%d%d\n",one.name,one.num,one.age);        printf("%-30s%-20d%-25d%",one.name,one.num,one.age); } fclose(fp);}/*通讯录添加函数*/void append(){    struct student one; if((fp=fopen(filename,"a"))==NULL) {        printf("\n不能文件!");        return; }    printf("\n请输入添加的姓名:");    scanf("%s",one.name);    printf("请输入学号");    scanf("%d",one.num);    printf("请输入年龄");    scanf("%d",one.age); fprintf(fp,"%-30s%-20d%-25d%\n",one.name,one.num,one.age);    printf("\n你添加的信息:\n");    printf("%-30s%-20d%-25d%\n","姓名","学号","年龄");    printf("%-30s%-20d%-25d%\n",one.name,one.num,one.age); fclose(fp);}

C++技术网会员解答:

    处理之后的效果图:

    

    运行的崩溃图:

    

    

    

        看出来问题了吗?问题出在最基本的语法上。然而编译时却检查不出来,为什么呢?我们来分析一下。

        出问题的是scanf和fscanf,函数的后面几个参数都是变量的地址,是将输入的值赋值给变量。在处理名字的时候,因为one.name本来就是字符数组,所以one.name就代表了地址。而变量one.num和one.age则是两个变量,不折不扣的变量哦。所以,语法错误了。应该传递变量的地址,使用&操作符取地址。如下所示:

&one.num,&one.age
     这样一改,程序就如第一张图一样,正常运行了。当然错误都是在所难免的,栽在基本错误上也都是常有的事。关键是,这些错误要能够识别出来。如果基础不扎实,很容易近在咫尺却远在天涯!你就是这样,我相信你在程序崩溃之后,怎么也看不出来这个错误。小样,还是自己嫩了点,没有火眼金睛呀。

        那么问题解决了,我们再进一步分析一下,既然都摔了一跤,那么就要摔的值得,不要起身就跑了,那样还会摔跤的。解决问题要抓住本质,如何抓,仔细研究一番。

        为什么编译没有错而运行有错呢?很多人认为,编译通过了,程序就不会有问题了。那就错的太离谱了。亲,这是C/C++的世界,变化莫测,随心所欲。编译器乃一介凡人,对于众多不可预测的变数,也只是叹命运的无奈。

        我们这个问题编译不崩溃的原因在于,scanf和fscanf后面的参数需要的是地址,地址又是什么?地址实际也是一个整数而已。那么变量的值不就是整数吗?那么这样不就隐含了将整型变量的值转为地址值嘛。这样的转换行不行呢?行的。否则编译就报错了。整数到整数的转换为什么不行呢?是吧。所以编译通过了。

        那么地址又是什么呢?地址可不是随便一个数值哦。地址的值代表了一块内存的位置。因为函数会通过地址去操作内存,如果地址错误,也就要崩溃了。虽然整型数值转为了地址,然而数值不对,在运行的时候去操作内存就会出问题。我们这两个变量初始的时候并没有赋值,变量存储的是随机的垃圾值。所以,这个值有可能对应到一个可以用的内存,也可能不对应一个可用的内存或者说对应一个被别人占用了的内存。不管是哪种,都不是幸运的。你以为对应到一个可用的内存会是幸运的,恰恰相反,如果果真对应到了可用的内存,你还发现不了错误,结果有时崩溃有时不崩溃,我想你会崩溃的。对应的是不可用内存或者被占用的内存,直接崩溃,这样还可以很快发现错误,及早解决。

文章来源:C++技术网原创文章版权所有,会员文章禁止转载。非会员文章转载做好本文超链接即表示授权转载。通过文章下面的分享按钮可以自由分享所有文章。


返回顶部

在线提问
问题标题:
问题描述:(简陋的描述会导致问题被最后回答、没有针对性回答甚至无法解答。请确保问题描述的足够清楚。)

C++技术网群聊

弹聊