(问题)c语言现代方法2th,自己编写的reminder.c程序 找错/修改/拓展延伸
这是问题
下面的程序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程序 找错/修改/拓展延伸相关推荐
- 输入三科成绩 C语言,C语言题,对我的程序找错修改。输入10个学生学号,三科成绩,求总成绩和平均分,并按成绩由高到低输出...
改好的参考(排序要函数,而函数不能定义在函数中的) #include #include char id[10][4];//学号 // int number[10];//序号 float grade[ ...
- 猴子选王c语言链表程序代码,数据结构(C语言)用栈和链表编写猴子选大王程序...
<数据结构(C语言)用栈和链表编写猴子选大王程序>由会员分享,可在线阅读,更多相关<数据结构(C语言)用栈和链表编写猴子选大王程序(3页珍藏版)>请在人人文库网上搜索. 1.i ...
- c语言指针程序找错题,C语言指针错题
有日子没有学习C语言了, 前些天在看windows程序设计时, 按照win的体系结构,在VC 6里面找到 下面一段代码,发现自己的C语言功底实在是差之又差.代码为我看到的C代码,至目前为止,还只能理解 ...
- C程序设计语言现代方法15:编写大型程序
目录 1. C语言程序一般构成 2. 源文件 2.1 源文件内容 2.2 将文件划分成多个源文件的优点 3. 头文件 3.1 包含头文件的3种方式 3.2 头文件共享内容 3.2.1 宏定义和类型定义 ...
- 松下plc程序转c语言,用顺序功能图方式编写的松下PLC程序
一般的教科书和工程人员都用梯形图编写PLC程序,缺点是不具有模块化,重复利用的可能行小. 而用顺序功能图,就能实现模块化,是较好的方法,值得推广. 下面是我用顺序功能图方式为松下PLC写的程序. 这是 ...
- 39种语言编写的Hello World程序
Hello World程序 维基百科,自由的百科全书 Hello, World!程序是一个只在计算机屏幕上打印出"Hello, World!"(英语,意为"你好,世界!& ...
- html本地站点建立代码,实验目的通过编写一小网页熟练HTML语言书写方法;学会建立本地站点.doc...
实验目的通过编写一小网页熟练HTML语言书写方法:学会建立本地站点.doc 实验一 HTML标记语言 一.实验目的:1.标记符 标记符又称标签,HTML是影响网页内容显示格式的标记符集合,浏览器根据标 ...
- 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的值赋 ...
- xcode编程c语言,使用xcode编写c语言的方法介绍
使用xcode编写c语言的方法介绍 发布时间:2020-03-26 17:08:31 来源:亿速云 阅读:149 作者:小新 今天小编分享的是使用xcode编写c语言的方法介绍,可能大家对xcode并 ...
最新文章
- 415 (Unsupported Media Type)
- Delphi 组件开发教程指南(4)组件生成过程(针对TWinControl继承而来的组件)
- python3读写csv
- Caffe使用step by step:caffe框架下的基本操作和分析
- Hadoop安装的ssh免密码登录步骤
- MQTT 5.0 新特性(三)| 有效载荷标识与内容类型
- android系统各种音量的获取与设置
- 紫书 习题 10-7 UVa 10539(long long + 素数筛)
- excel获取mysql数据库数据类型_js如何读取excel数据库数据库数据类型
- OpenID Connect:OAuth 2.0协议之上的简单身份层
- __attribute__ 详解
- 基于Windows下python3.4.1IDLE常用快捷键小结
- Pytorch在colab和kaggle中使用TensorBoard/TensorboardX可视化
- CentOS7安装Redis,全网最快安装教程
- 论坛模块_版块管理_增删改查实现上下移动
- OpenCV之滑动条的创建和使用
- Restorator软件使exe文件都不能打开,exe不支持此接口
- 基于WeMos的WiFi避障小车
- 外接西数固态硬盘linux,外接固态硬盘安装教程 关于外接固态硬盘安装教
- 2018研究生毕业论文重复率检测八要点
热门文章
- ACM学习历程—Hihocoder 1290 Demo Day(动态规划)
- hdu 3065 AC自动机
- 类实现Java模板方法模式中的HookMethod实现
- 风云点评:Flash 与 Silverlight 终极大比拼
- 牛客网(剑指offer) 第二十题 包含min函数的栈
- 【数据结构与算法】之深入解析“外观数列”的求解思路与算法示例
- iOS开发之ReplayKit框架学习
- 18万,是特斯拉的底线,是马斯克的目标!
- 718. Maximum Length of Repeated Subarray 最长重复子数组
- SVN基本的理解和使用