这是问题

下面的程序1.c是自己编写的,运行结果如下:

输入:

24 susan's birthday
5 6:00 - Dinner with Marge and RUSS
25 Movie - "Chinatown"
7 10:30 - Dental appointment
5 Saturday
0

输出:

 24 Saturday

问题:程序1.c错在哪里了?

//程序1.c
#include <stdio.h>
#include <string.h>#define MAX_REMINDERS 50
#define MSG_LEN 60int read(char (*p)[MSG_LEN + 3],int n);
int readline(char *,int n);
void print(char (*p)[MSG_LEN + 3]);
int main()
{
char reminders[MAX_REMINDERS + 1][MSG_LEN+ 3];//2 seat for date,others for reminders
read(reminders,MAX_REMINDERS + 1);
print(reminders);return 0;
}int read(char (*p)[MSG_LEN + 3],int n)
{
//用整数输入日期,一会利用sprintf转换成char *
int day,i,j;
char remind[MSG_LEN + 1];
int count  =  0;
//there is a space character after the day//错误1:这里有点不恰当,应该是day_str[3]就可以了,存放两位数的字符串,维度是3刚好
char day_str[4];scanf("%2d",&day);
readline(remind,MSG_LEN + 1);
//转换day,使得它成为char *,sprintf的功能是把格式化字符串打印到字符串中,
//sprintf第一个就是要打印的目的字符串(打印到哪),其余的和以前的printf一样//错误2:day应该以2位的方法输出,应该改成sprintf(day_str,"%2d",day);
sprintf(day_str,"%3d",day);while(day != 0){ for(i = 0;i < count; ++i){if(strcmp(p[i],day_str) > 0) break;        }for(j = count - 1;j >= i;--j){strcpy(p[j+1],p[j]); }strcpy(p[i],day_str);strcat(p[i],remind);++ i;//下面这行是多出来的,不知道自己怎么想的,多这么一行,在reminders末尾加一行“”,结果错加到这里strcpy(p[i],"");count ++;scanf("%2d",&day);readline(remind,MSG_LEN + 1);}return count;
}//whileint readline(char *p,int n)
{
char ch;
int  cnt = 0;
while((ch = getchar()) != '\n' && cnt < n){ *p ++ = ch;++ cnt;}*p = '\0';return cnt;
}void print(char (*p)[MSG_LEN + 3])
{
for(; strcmp(*p,"") != 0; ++p){printf("%s\n",*p);}
}

改正后的程序:

//1.c
#include <stdio.h>
#include <string.h>#define MAX_REMINDERS 50
#define MSG_LEN 60int read(char (*p)[MSG_LEN + 3],int n);
int readline(char *,int n);
void print(char (*p)[MSG_LEN + 3]);
int main()
{
char reminders[MAX_REMINDERS + 1][MSG_LEN+ 3];//2 seat for date,others for reminders
read(reminders,MAX_REMINDERS + 1);
print(reminders);return 0;
}int read(char (*p)[MSG_LEN + 3],int n)
{
//用整数输入日期,一会利用sprintf转换成char *
int day,i,j;
char remind[MSG_LEN + 1];
int count  =  0;
//there is a space character after the day
char day_str[3];
scanf("%2d",&day);
readline(remind,MSG_LEN + 1);
//转换day,使得它成为char *,sprintf的功能是把格式化字符串打印到字符串中,
//sprintf第一个就是要打印的目的字符串(打印到哪),其余的和以前的printf一样
sprintf(day_str,"%2d",day);
while(day != 0){ for(i = 0;i < count; ++i){if(strcmp(p[i],day_str) > 0) break;        }for(j = count - 1;j >= i;--j){strcpy(p[j+1],p[j]); }strcpy(p[i],day_str);strcat(p[i]," ");strcat(p[i],remind);count ++;scanf("%2d",&day);readline(remind,MSG_LEN + 1);sprintf(day_str,"%2d",day);}strcpy(p[count],"");return count;
}//whileint readline(char *p,int n)
{char ch;
int  cnt = 0;
ch = getchar();
while(ch != '\n' && cnt < n){if(ch == ' ' && cnt == 0)ch = getchar();else{*p ++ = ch;++ cnt; ch = getchar(); }  }*p = '\0';return cnt;
}void print(char (*p)[MSG_LEN + 3])
{
for(; strcmp(*p,"") != 0; ++p){printf("%s\n",*p);}
}

运行 gcc 1.c -o 123

24  Susan's birthday
5 6:00 -Dinner with Marge and Russ
26 Movie - "Chinatown"
7 10:30 - Dental appointment
5 Saturday class
12 Saturday class
05 Saturday class5 6:00 -Dinner with Marge and Russ7 10:30 - Dental appointment
12 Saturday class
24 Susan's birthday
26 Movie - "Chinatown"

大功告成

心得体会:

(1)本文输出的时候,日期和reminder之间有一个空格,这个空格在把日期copy到reminders之后,在strcat之前,用strcat多拼接一个空格就可以,也就是,reminders的每行拼接顺序是

日期  +  空格    + reminder

(2)在读取字符串的时候,也就是设计readline的时候,务必考虑是否忽略开头的空格,这个程序是忽略开头的空格的,为的是无论输入的时候即使是乱七八糟的,但是输入的时候依然是整齐的(但是数字部分始终2位,注意,不够后面则空格)

例如,重新运行程序,输出仍然很整齐。

5   Saturday class
5       6:00 -Dinner with Marge and Russ
7    10:30 - Dental appointment
12Saturday class
26                           Movie - "Chinatown"
12     Saturday class
05 6:00 -Dinner with Marge and Russ5 Saturday class7 10:30 - Dental appointment
12 Saturday class
12 Saturday class
26 Movie - "Chinatown"

第二部分:延伸拓展

解决本章编程题2题

#include <stdio.h>
#include <string.h>#define MSG_LEN 100
#define MAX_REMINDERS 1000int readline(char *,int );
int read(char (*p)[MSG_LEN + 11],int n);
void print(char (*p)[MSG_LEN + 11]);int main()
{
char reminders[MAX_REMINDERS + 1][MSG_LEN + 11];
read(reminders,MAX_REMINDERS + 1);
print(reminders);return 0;
}int read(char (*p)[MSG_LEN + 11],int n)
{
int month,day,time_24_hour;
char reminder[MSG_LEN + 1];
char str_month[3],str_day[3],str_time_24_hour[7];
int i,j,count = 0;
char prefix_number[13];printf("Enter month and day and time and reminder:\n\
例如:9 26 131313 it's time to work:");scanf("%d",&month);
sprintf(str_month,"%2d",month);
scanf("%d",&day);
sprintf(str_day,"%2d",day);//if month ==0 and day == 0,then return 0
if(month == 0 && day == 0)return 0;
scanf("%d",&time_24_hour);
sprintf(str_time_24_hour,"%6d",time_24_hour);
readline(reminder,MSG_LEN + 1);while(month != 0){  strcpy(prefix_number,str_month);strcat(prefix_number," ");strcat(prefix_number,str_day);strcat(prefix_number," ");strcat(prefix_number,str_time_24_hour);for(i = 0; i < count;++i)  {if(strcmp(prefix_number,p[i]) < 0)break; }for(j = count -1;j >= i; --j){strcpy(p[j + 1],p[j]);     }strcpy(p[i],prefix_number);strcat(p[i]," ");strcat(p[i],reminder);++ count;scanf("%d",&month);scanf("%d",&day);if(month == 0 && day == 0)break;scanf("%d",&time_24_hour);if(month == 0 && day == 0)break;readline(reminder,MSG_LEN +1);sprintf(str_month,"%2d",month);sprintf(str_day,"%2d",day);sprintf(str_time_24_hour,"%6d",time_24_hour);}/*  add a "" in the end of p  */strcpy(p[count],"");return count;
}
int readline(char *p,int n)
{
char ch;
int cnt = 0;while((ch = getchar()) != '\n' && cnt < n){if(ch == ' ' && cnt == 0);else{*p ++ = ch;++ cnt;     }    }
*p = '\0';
return cnt;
}
void print(char (*p)[MSG_LEN + 11])
{
for(;strcmp(*p,"") != 0;++ p){printf("%s\n",*p); }
}

说明:读取字符跳过空格可以简单地用下面实现

scanf(" %c",&ch);

稍微改进下性能:


#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MSG_LEN 100
#define MAX_REMINDERS 1000int readline(char *,int );
int read(char (*p)[MSG_LEN + 11],int n);
void print(char (*p)[MSG_LEN + 11]);int main()
{
char reminders[MAX_REMINDERS + 1][MSG_LEN + 11];
read(reminders,MAX_REMINDERS + 1);
print(reminders);return 0;
}int read(char (*p)[MSG_LEN + 11],int n)
{
int month,day,hour,minute;
char reminder[MSG_LEN + 1];
//change
char str_month[3],str_day[3];
char str_hour[3],str_minute[3];//str_time_24_hour[7];
int i,j,count = 0;
char prefix_number[20];printf("Enter month day hour minute reminder(0 0 to break):\n");
while(true)
{scanf("%d",&month);sprintf(str_month,"%2d",month);scanf("%d",&day);sprintf(str_day,"%2d",day);//if month ==0 and day == 0,then return 0if(month == 0 && day == 0)return 0;//change //scanf("%d",&time_24_hour);scanf("%d",&hour);scanf("%d",&minute);sprintf(str_hour,"%2d",hour);sprintf(str_minute,"%2d",minute);//sprintf(str_time_24_hour,"%6d",time_24_hour);readline(reminder,MSG_LEN + 1);if(day > 31 || day < 0){   printf("\ninvalid input,again.\n");continue;}else break;
}//while
while(month != 0){strcpy(prefix_number,str_month);strcat(prefix_number," ");strcat(prefix_number,str_day);strcat(prefix_number," ");strcat(prefix_number,str_hour);strcat(prefix_number,"时");strcat(prefix_number,str_minute);strcat(prefix_number,"分 ");for(i = 0; i < count;++i)  {if(strcmp(prefix_number,p[i]) < 0)break; }for(j = count -1;j >= i; --j){strcpy(p[j + 1],p[j]);     }strcpy(p[i],prefix_number);strcat(p[i],reminder);++ count;month = 0;day   = 0;hour  = 0;minute= 0;while(true){ scanf("%d",&month);scanf("%d",&day);if(month == 0 && day == 0)break;scanf("%d",&hour);if(month == 0 && day == 0)break;scanf("%d",&minute);  readline(reminder,MSG_LEN +1);sprintf(str_month,"%2d",month);sprintf(str_day,"%2d",day);sprintf(str_hour,"%2d",hour);sprintf(str_minute,"%2d",minute);if(day > 31 || day < 0){printf("\nvalid input,again.\n");continue;}elsebreak;}//while}/*  add a "" in the end of p  */strcpy(p[count],"");return count;
}
int readline(char *p,int n)
{
char ch;
int cnt = 0;while((ch = getchar()) != '\n' && cnt < n){if(ch == ' ' && cnt == 0);else{*p ++ = ch;++ cnt;     }    }
*p = '\0';
return cnt;
}
void print(char (*p)[MSG_LEN + 11])
{
for(;strcmp(*p,"") != 0;++ p){printf("%s\n",*p); }
}

上面程序冗余代码太多,下面这个

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MSG_LEN 100
#define MAX_REMINDERS 1000int readline(char *,int );
int read(char (*p)[MSG_LEN + 11],int n);
void print(char (*p)[MSG_LEN + 11]);int main()
{
char reminders[MAX_REMINDERS + 1][MSG_LEN + 11];
read(reminders,MAX_REMINDERS + 1);
print(reminders);return 0;
}int read(char (*p)[MSG_LEN + 11],int n)
{
int  month,day,hour,minute;
char reminder[MSG_LEN + 1];
char str_month[3],str_day[3];
char str_hour[3],str_minute[3];
int  i = 0,j = 0,count = 0;
char prefix_number[20];while(true)
{
//set month,day,hour,minute to 0
month = 0;
day   = 0;
hour =0;
minute = 0;// input
printf("Enter month day hour minute(0 0 to quit):\n");
scanf("%d",&month);
scanf("%d",&day);
if(month == 0 && day == 0)break;/*  一处  */
scanf("%d",&hour);
scanf("%d",&minute);/*  二处  /readline(reminder,MSG_LEN + 1);/*  ---------- 这 段 代 码 能 放 在 下 面 的 注 释 处------------*/
if(day > 31 || day < 0){printf("\ninvalid input,again.\n");continue;   }/*-----------------------------------------------------------------
特别紧惕:如果上面这段代码放在前一处、二处的任何一处,如果day输入大于31,那么会有
数据残留在内存内,造成的后果是自动执行循环,因为内存中有数据可供scanf执行1次
------------------------------------------------------------------*///transform
sprintf(str_month,"%2d",month);
sprintf(str_day,"%2d",day);
sprintf(str_hour,"%2d",hour);
sprintf(str_minute,"%2d",minute);//set prefix_number
strcpy(prefix_number,str_month);
strcat(prefix_number,"月");
strcat(prefix_number,str_day);
strcat(prefix_number,"日");
strcat(prefix_number,str_hour);
strcat(prefix_number,"时");
strcat(prefix_number,str_minute);
strcat(prefix_number,"分 ");//insert into
for(i = 0;i < count;++ i)if(strcmp(p[i],prefix_number) > 0)break;
for(j = count-1;j >= i; --j){strcpy(p[j + 1],p[j]); }
strcpy(p[i],prefix_number);
strcat(p[i],reminder);
++ count;
}strcat(p[count],"");return count;
}
int readline(char *p,int n)
{
char ch;
int cnt = 0;while((ch = getchar()) != '\n' && cnt < n){if(ch == ' ' && cnt == 0);else{*p ++ = ch;++ cnt;     }    }
*p = '\0';
return cnt;
}
void print(char (*p)[MSG_LEN + 11])
{
for(;strcmp(*p,"") != 0;++ p){printf("%s\n",*p); }
}

教训:如果使用continue结束一次循环,后面绝对不能跟读入数据的语句,总体来说,continue的时候,内存中不能有残留数据。

最好等数据语句(例如scanf,gets,gechar等执行完完整的一次后,才能continue,break一般无此限制,反正也退出循环了。)

如果本最后这个程序中,把continue语句放在readline()语句之前,就会犯这种错误,也就是变量reminder(在readline中)还没有来得及读入自己变量,但是变量已经回车前输出了,所以这个变量就会残留在内存内。导致程序执行出乎意料的结果

(问题)c语言现代方法2th,自己编写的reminder.c程序 找错/修改/拓展延伸相关推荐

  1. 输入三科成绩 C语言,C语言题,对我的程序找错修改。输入10个学生学号,三科成绩,求总成绩和平均分,并按成绩由高到低输出...

    改好的参考(排序要函数,而函数不能定义在函数中的) #include #include char id[10][4];//学号 //  int number[10];//序号 float grade[ ...

  2. 猴子选王c语言链表程序代码,数据结构(C语言)用栈和链表编写猴子选大王程序...

    <数据结构(C语言)用栈和链表编写猴子选大王程序>由会员分享,可在线阅读,更多相关<数据结构(C语言)用栈和链表编写猴子选大王程序(3页珍藏版)>请在人人文库网上搜索. 1.i ...

  3. c语言指针程序找错题,C语言指针错题

    有日子没有学习C语言了, 前些天在看windows程序设计时, 按照win的体系结构,在VC 6里面找到 下面一段代码,发现自己的C语言功底实在是差之又差.代码为我看到的C代码,至目前为止,还只能理解 ...

  4. C程序设计语言现代方法15:编写大型程序

    目录 1. C语言程序一般构成 2. 源文件 2.1 源文件内容 2.2 将文件划分成多个源文件的优点 3. 头文件 3.1 包含头文件的3种方式 3.2 头文件共享内容 3.2.1 宏定义和类型定义 ...

  5. 松下plc程序转c语言,用顺序功能图方式编写的松下PLC程序

    一般的教科书和工程人员都用梯形图编写PLC程序,缺点是不具有模块化,重复利用的可能行小. 而用顺序功能图,就能实现模块化,是较好的方法,值得推广. 下面是我用顺序功能图方式为松下PLC写的程序. 这是 ...

  6. 39种语言编写的Hello World程序

    Hello World程序 维基百科,自由的百科全书 Hello, World!程序是一个只在计算机屏幕上打印出"Hello, World!"(英语,意为"你好,世界!& ...

  7. html本地站点建立代码,实验目的通过编写一小网页熟练HTML语言书写方法;学会建立本地站点.doc...

    实验目的通过编写一小网页熟练HTML语言书写方法:学会建立本地站点.doc 实验一 HTML标记语言 一.实验目的:1.标记符 标记符又称标签,HTML是影响网页内容显示格式的标记符集合,浏览器根据标 ...

  8. C语言编程>第九周 ④ 编写函数fun,它的功能是:利用以下所示的简单迭代方法求方程cos(y)-y=0的一个实根。yn+1=cos(yn)

    例题:编写函数fun,它的功能是:利用以下所示的简单迭代方法求方程cos(y)-y=0的一个实根. yn+1=cos(yn) 迭代步骤如下: (1)取y1初值为0.0. (2)y0=y1,把y1的值赋 ...

  9. xcode编程c语言,使用xcode编写c语言的方法介绍

    使用xcode编写c语言的方法介绍 发布时间:2020-03-26 17:08:31 来源:亿速云 阅读:149 作者:小新 今天小编分享的是使用xcode编写c语言的方法介绍,可能大家对xcode并 ...

最新文章

  1. 415 (Unsupported Media Type)
  2. Delphi 组件开发教程指南(4)组件生成过程(针对TWinControl继承而来的组件)
  3. python3读写csv
  4. Caffe使用step by step:caffe框架下的基本操作和分析
  5. Hadoop安装的ssh免密码登录步骤
  6. MQTT 5.0 新特性(三)| 有效载荷标识与内容类型
  7. android系统各种音量的获取与设置
  8. 紫书 习题 10-7 UVa 10539(long long + 素数筛)
  9. excel获取mysql数据库数据类型_js如何读取excel数据库数据库数据类型
  10. OpenID Connect:OAuth 2.0协议之上的简单身份层
  11. __attribute__ 详解
  12. 基于Windows下python3.4.1IDLE常用快捷键小结
  13. Pytorch在colab和kaggle中使用TensorBoard/TensorboardX可视化
  14. CentOS7安装Redis,全网最快安装教程
  15. 论坛模块_版块管理_增删改查实现上下移动
  16. OpenCV之滑动条的创建和使用
  17. Restorator软件使exe文件都不能打开,exe不支持此接口
  18. 基于WeMos的WiFi避障小车
  19. 外接西数固态硬盘linux,外接固态硬盘安装教程 关于外接固态硬盘安装教
  20. 2018研究生毕业论文重复率检测八要点

热门文章

  1. ACM学习历程—Hihocoder 1290 Demo Day(动态规划)
  2. hdu 3065 AC自动机
  3. 类实现Java模板方法模式中的HookMethod实现
  4. 风云点评:Flash 与 Silverlight 终极大比拼
  5. 牛客网(剑指offer) 第二十题 包含min函数的栈
  6. 【数据结构与算法】之深入解析“外观数列”的求解思路与算法示例
  7. iOS开发之ReplayKit框架学习
  8. 18万,是特斯拉的底线,是马斯克的目标!
  9. 718. Maximum Length of Repeated Subarray 最长重复子数组
  10. SVN基本的理解和使用