编程珠玑第三章习题答案
2014-11-02 22:55
609 查看
1 税收问题
.if-else语句的每个分支的形式都差不多,我们可以用数组来使循环简单一点。数组中每个点表明一个阶段,用level[i]表示阶段i的起始点,tax[i]表示阶段i的税率。然后就是输入一个收入,利用二分搜索找到一个最接近于这个收入的税率计算的分段点,当然也可以不用二分搜索找到这个分段点。
int level[100] = { 2200, 2700, ....}
double taxi[100] = {0, 0.14, 0.15, 0.16, ...}
#include "stdafx.h"
#include <iostream>
using namespace std;
int binarysearch(int start, int end, int find, int* a);
int main(int argc, char* argv[])
{
int lower_limit[40];
int iter;
int find;
for(int i = 0; i < 40; i++) //初始化下限数组
{
lower_limit[i] = 2200 + i * 500;
}
cin >> find;
while(find != -1)
{
iter = binarysearch(0,39,find,lower_limit);
cout << lower_limit[iter] <<endl;
cin >> find;
}
return 0;
}
int binarysearch(int start, int end, int find, int* a)
{
int mid;
if(start == end)
return end;
else
{
mid = (start + end)/2;
if(find <= a[mid])
return(binarysearch(start,mid,find,a));
else
return(binarysearch(mid+1,end,find,a));
}
}
可以通过观察法,找规律确定税率的分段点。
其实观察书中下限的数据为2200,2700,3200,3700.........
就是2200+i*500
那么只要将要找的数据find:
iter = (find-2200)/500;
if((find-2200)%500 == 0)
return iter;
else
return iter +1;
就可以了,不用搜索。找到这个分段点了之后就可以计算税收了:
假定找到的这个最接近的分段点是iter,如果不是在第一个分段点内,那么taxresult=(level[iter-1]-2200)*taxi[iter-1]+(income-level[iter-1])*taxi[iter]
3、编写标语函数,输入一个大写字母,输出一个字符数组,该字符数组用字符图形方式描绘该字母
这题不大懂,百度了下答案,发现答案的重点在于将26个字母用特定的表示方式表示出来,可以考虑为字母的外形设计一个定制模板,自己规定一套模板编写的格式,然后写一个解析程序,每次打印字母时,只需解析字母对应的模板即可,这样主要的工作量就花在每个字母模板的编写上,当然模板的编写是相当简单的,将字母图形转化为相应的模板格式即可。例如
这个I可以用39x,63b3x3b,39x表示。
这个方法倒是提醒了我一些当遇到复杂的表示方法时,可以找出这个复杂方法的共性,然后用简单的表现形式代替复杂的表现形式,最后只要通过解析简单的表现形式即可。
4.有意思的题:给定两个日期,计算两者之间的天数;给定一个日期,返回值为周几;给定月和年,使用字符数组生成该月的日历
先看下关于题目背景的科普知识:
问题的提出:日历的编排是每400年一个大循环周期,即今年的月、日、星期几和400年前的完全一样。现行天文历法根据天体运行规律,取每年365.2425天。这样,每400年共有365.2425×400=146097天。如果以365天作为一年,每400年就少了0.2425×400=97天。这97天要靠设置闰年(每年366)天来凑齐,所以,每400年要设置97个闰
判断闰年的方法:
判断星期几的方法:(以1900作为参考)
参考:http://blog.163.com/shadow_hier/blog/static/4051874220095873612503/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int monthdays[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
typedef struct
{
int year;
int month;
int day;
}Date;
//判断是否是闰年
bool isrunyear(Date *date)
{
if(((date->year%4==0) && (date->year%100!=0))
|| (date->year % 400) == 0)
return true;
return false;
}
//计算某个日期是一年中的第几天
int yearday(Date *date)
{
int total = 0;
for(int i = 1; i < date->month; i++)
{
total+=monthdays[i];
}
if(date->month > 2 && isrunyear(date))
{
total+=1;
}
return total+date->day;
}
//计算两个日期之间的天数间隔(date2 晚于 date1)
int betweenday(Date *date1, Date *date2)
{
if(date1->year == date2->year)
return yearday(date2) - yearday(date1);
else
{
int totaldays = 0;
for(int i = date1->year; i < date2->year; i++)
{
Date d;
Date *date;
date = &d;
d.year = i;
totaldays+=isrunyear(date)?366:365;
}
return totaldays - yearday(date1) + yearday(date2);
}
}
//判断某日子属于一周中第几天
int weekday(Date *date)
{
Date d;
Date *d1;
d1 = &d;
d.year = 1900; //选取1900年作为参考,日历都是以1900为参考的,1900.1.1为星期一,其它日期相对它的天数与7取余 //数再加上1就是对应的星期几。这里用1~7表示星期一到星期天
d.month = 1;
d.day = 1;
return betweenday(d1,date)%7+1;
}
//输出某年某月日历
void printyearmonth(Date *date)
{
printf("%d年%d月\n",date->year,date->month);
printf("日 一 二 三 四 五 六\n");
date->day = 1;
int first = weekday(date);
int i;
if(first != 7)
{
//先输出1号前面的空白
for(i = 0; i < first; i++)
{
printf(" ");
}
//输出1号后非空白部分
for(i = 1; i <= 7 - first; i++)
//把第一周的情况不全,从first开始的星期几到星期天
{
printf("%-3d",i);
}
printf("\n");
}
//计算该月总天数
int monthday = (date->month==2)?(isrunyear(date)?29:28):monthdays[date->month];
for(i = 8 - first; i <= monthday; i++)
{
printf("%-3d",i);
if(i % 7 == 7 - first)
printf("\n");
}
printf("\n");
}
int getlength(char *a)
{
return 0;
}
void main()
{
Date d1;
Date *date1;
date1 = &d1;
d1.year = 2011;
d1.month = 2;
d1.day = 1;
Date d2;
Date *date2;
date2 = &d2;
date2->year = 2013;
date2->month = 4;
date2->day = 5;
printf("%d\n", betweenday(date1,date2));
printf("%d\n", weekday(date2));
printyearmonth(date1);
}
5、查找后缀连字符的连接
因为这里要确定的是输入单词中是否有规则中的后缀,因为是后缀所以尾部一定要完全一样才可以。所以这里对于单词的比较是从右到左的比进行的。所以最开始的时候需要把规则中的后缀都全部翻转了,同时对于输入的单词也需要进行翻转。另外这里保存规则中的字符数组的时候可以采用多种方法。如果是采用二维字符数组,那么会比较浪费空间,最好是用带有单词指针数组的字符数组来保存。
[cpp] view
plaincopy
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
char *p[] = {"et-ic", "al-is-tic", "s-tic", "p-tic", "-lyt-ic", "ot-ic", "an-tic",
"n-tic", "c-tic", "at-ic", "h-nic", "n-ic", "m-ic", "l-lic", "b-lic", "-clic", "l-ic",
"h-ic", "f-ic", "d-ic", "-bic", "a-ic", "-mac", "i-ac"};
//带有单词指针的字符数组
//返回后缀连字符连接
int getlastsamechar(char* a)
//a就是输入的某个单词,判断a中是否包含了规则中的合法连字符的情况
{
int result = -1;
//先将后缀字符数组每项反转
int i = 0;
int j = 0;
int alen = strlen(a);
char* aswap = new char[alen + 1];
strcpy(aswap, a);
for(i = 0; i < alen/2; i++)
{
char c = aswap[i];
aswap[i] = aswap[alen - 1 - i];
aswap[alen - 1 - i] = c;
}
printf("%s\n",aswap);
int n = sizeof(p)/sizeof(char*);
//规则中连字符共有n个
for(i = 0; i < n; i++)
{
int len = strlen(p[i]);
char* b = new char[len+1];
strcpy(b,p[i]);
//去掉字符串里的-
for(j = 0; j < len; j++)
//翻转某个连字符
{
if(b[j] == '-')
{
for(int q = j; q < len; q++)
{
b[q] = b[q+1];
}
len--;
}
}
for(j = 0; j < len/2; j++)
{
char c = b[j];
b[j] = b[len - 1 - j];
b[len - 1- j] = c;
}
if(alen >= len)
{
for(j = 0; j < len; j++)
{
if(aswap[j] != b[j])
{
break;
}
}
delete b;
if(j == len)
{
result = i; //找到输入的字符串a中有的p中的第i个连字符
break;
}
}
}
delete aswap;
return result;
}
void main()
{
char *a = "clinic";
int result = getlastsamechar(a);
printf("%d\n",result);
if(-1 != result)
{
char* res = new char[strlen(p[result]) + 1];
strcpy(res, p[result]);
printf("%s\n", res);
//输出字符串a中存在的那个连字符
}
}
8、获取数码管显示方式
把7段显示用7bit来表示。
[cpp] view
plaincopy
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
//数字0-9的数码管显示方式
char *number[] = {"1011111","0000101","1110110","1110101","0101101",
"1111001","1111011","0010101","1111111","1111101"};//从左往右数分别是数码管的七段显示的标号1~7
//获取16bit的正整数
char** getNumber(int bit)
{
char** result= new char*[5];
for(int i = 4; i >= 0; i--)
{
result[i] = number[bit%10];//计算这个五位数的一位,对应就是其在number数组中的标号,直接从number数组中就可 //以获取数字的数码管显示方式。
bit/=10;
}
return result;
}
void main()
{
char** num = getNumber(54673);
for(int i = 0; i < 5; i++)
{
printf("%s\n",*num);
num++;
}
}
.if-else语句的每个分支的形式都差不多,我们可以用数组来使循环简单一点。数组中每个点表明一个阶段,用level[i]表示阶段i的起始点,tax[i]表示阶段i的税率。然后就是输入一个收入,利用二分搜索找到一个最接近于这个收入的税率计算的分段点,当然也可以不用二分搜索找到这个分段点。
int level[100] = { 2200, 2700, ....}
double taxi[100] = {0, 0.14, 0.15, 0.16, ...}
#include "stdafx.h"
#include <iostream>
using namespace std;
int binarysearch(int start, int end, int find, int* a);
int main(int argc, char* argv[])
{
int lower_limit[40];
int iter;
int find;
for(int i = 0; i < 40; i++) //初始化下限数组
{
lower_limit[i] = 2200 + i * 500;
}
cin >> find;
while(find != -1)
{
iter = binarysearch(0,39,find,lower_limit);
cout << lower_limit[iter] <<endl;
cin >> find;
}
return 0;
}
int binarysearch(int start, int end, int find, int* a)
{
int mid;
if(start == end)
return end;
else
{
mid = (start + end)/2;
if(find <= a[mid])
return(binarysearch(start,mid,find,a));
else
return(binarysearch(mid+1,end,find,a));
}
}
可以通过观察法,找规律确定税率的分段点。
其实观察书中下限的数据为2200,2700,3200,3700.........
就是2200+i*500
那么只要将要找的数据find:
iter = (find-2200)/500;
if((find-2200)%500 == 0)
return iter;
else
return iter +1;
就可以了,不用搜索。找到这个分段点了之后就可以计算税收了:
假定找到的这个最接近的分段点是iter,如果不是在第一个分段点内,那么taxresult=(level[iter-1]-2200)*taxi[iter-1]+(income-level[iter-1])*taxi[iter]
3、编写标语函数,输入一个大写字母,输出一个字符数组,该字符数组用字符图形方式描绘该字母
这题不大懂,百度了下答案,发现答案的重点在于将26个字母用特定的表示方式表示出来,可以考虑为字母的外形设计一个定制模板,自己规定一套模板编写的格式,然后写一个解析程序,每次打印字母时,只需解析字母对应的模板即可,这样主要的工作量就花在每个字母模板的编写上,当然模板的编写是相当简单的,将字母图形转化为相应的模板格式即可。例如
x | x | x | x | x | x | x | x | x |
x | x | x | x | x | x | x | x | x |
x | x | x | x | x | x | x | x | x |
x | x | x | ||||||
x | x | x | ||||||
x | x | x | ||||||
x | x | x | ||||||
x | x | x | ||||||
x | x | x | ||||||
x | x | x | x | x | x | x | x | x |
x | x | x | x | x | x | x | x | x |
x | x | x | x | x | x | x | x | x |
这个方法倒是提醒了我一些当遇到复杂的表示方法时,可以找出这个复杂方法的共性,然后用简单的表现形式代替复杂的表现形式,最后只要通过解析简单的表现形式即可。
4.有意思的题:给定两个日期,计算两者之间的天数;给定一个日期,返回值为周几;给定月和年,使用字符数组生成该月的日历
先看下关于题目背景的科普知识:
问题的提出:日历的编排是每400年一个大循环周期,即今年的月、日、星期几和400年前的完全一样。现行天文历法根据天体运行规律,取每年365.2425天。这样,每400年共有365.2425×400=146097天。如果以365天作为一年,每400年就少了0.2425×400=97天。这97天要靠设置闰年(每年366)天来凑齐,所以,每400年要设置97个闰
判断闰年的方法:
判断闰年一般的规律为: 四年一闰,百年不闰,四百年再闰。其简单计算方法:1。能被4整除而不能被100整除。(如2004年就是闰年,1800年不是。)2。能被400整除。(如2000年是闰年)
判断星期几的方法:(以1900作为参考)
参考:http://blog.163.com/shadow_hier/blog/static/4051874220095873612503/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
int monthdays[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
typedef struct
{
int year;
int month;
int day;
}Date;
//判断是否是闰年
bool isrunyear(Date *date)
{
if(((date->year%4==0) && (date->year%100!=0))
|| (date->year % 400) == 0)
return true;
return false;
}
//计算某个日期是一年中的第几天
int yearday(Date *date)
{
int total = 0;
for(int i = 1; i < date->month; i++)
{
total+=monthdays[i];
}
if(date->month > 2 && isrunyear(date))
{
total+=1;
}
return total+date->day;
}
//计算两个日期之间的天数间隔(date2 晚于 date1)
int betweenday(Date *date1, Date *date2)
{
if(date1->year == date2->year)
return yearday(date2) - yearday(date1);
else
{
int totaldays = 0;
for(int i = date1->year; i < date2->year; i++)
{
Date d;
Date *date;
date = &d;
d.year = i;
totaldays+=isrunyear(date)?366:365;
}
return totaldays - yearday(date1) + yearday(date2);
}
}
//判断某日子属于一周中第几天
int weekday(Date *date)
{
Date d;
Date *d1;
d1 = &d;
d.year = 1900; //选取1900年作为参考,日历都是以1900为参考的,1900.1.1为星期一,其它日期相对它的天数与7取余 //数再加上1就是对应的星期几。这里用1~7表示星期一到星期天
d.month = 1;
d.day = 1;
return betweenday(d1,date)%7+1;
}
//输出某年某月日历
void printyearmonth(Date *date)
{
printf("%d年%d月\n",date->year,date->month);
printf("日 一 二 三 四 五 六\n");
date->day = 1;
int first = weekday(date);
int i;
if(first != 7)
{
//先输出1号前面的空白
for(i = 0; i < first; i++)
{
printf(" ");
}
//输出1号后非空白部分
for(i = 1; i <= 7 - first; i++)
//把第一周的情况不全,从first开始的星期几到星期天
{
printf("%-3d",i);
}
printf("\n");
}
//计算该月总天数
int monthday = (date->month==2)?(isrunyear(date)?29:28):monthdays[date->month];
for(i = 8 - first; i <= monthday; i++)
{
printf("%-3d",i);
if(i % 7 == 7 - first)
printf("\n");
}
printf("\n");
}
int getlength(char *a)
{
return 0;
}
void main()
{
Date d1;
Date *date1;
date1 = &d1;
d1.year = 2011;
d1.month = 2;
d1.day = 1;
Date d2;
Date *date2;
date2 = &d2;
date2->year = 2013;
date2->month = 4;
date2->day = 5;
printf("%d\n", betweenday(date1,date2));
printf("%d\n", weekday(date2));
printyearmonth(date1);
}
5、查找后缀连字符的连接
因为这里要确定的是输入单词中是否有规则中的后缀,因为是后缀所以尾部一定要完全一样才可以。所以这里对于单词的比较是从右到左的比进行的。所以最开始的时候需要把规则中的后缀都全部翻转了,同时对于输入的单词也需要进行翻转。另外这里保存规则中的字符数组的时候可以采用多种方法。如果是采用二维字符数组,那么会比较浪费空间,最好是用带有单词指针数组的字符数组来保存。
[cpp] view
plaincopy
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
char *p[] = {"et-ic", "al-is-tic", "s-tic", "p-tic", "-lyt-ic", "ot-ic", "an-tic",
"n-tic", "c-tic", "at-ic", "h-nic", "n-ic", "m-ic", "l-lic", "b-lic", "-clic", "l-ic",
"h-ic", "f-ic", "d-ic", "-bic", "a-ic", "-mac", "i-ac"};
//带有单词指针的字符数组
//返回后缀连字符连接
int getlastsamechar(char* a)
//a就是输入的某个单词,判断a中是否包含了规则中的合法连字符的情况
{
int result = -1;
//先将后缀字符数组每项反转
int i = 0;
int j = 0;
int alen = strlen(a);
char* aswap = new char[alen + 1];
strcpy(aswap, a);
for(i = 0; i < alen/2; i++)
{
char c = aswap[i];
aswap[i] = aswap[alen - 1 - i];
aswap[alen - 1 - i] = c;
}
printf("%s\n",aswap);
int n = sizeof(p)/sizeof(char*);
//规则中连字符共有n个
for(i = 0; i < n; i++)
{
int len = strlen(p[i]);
char* b = new char[len+1];
strcpy(b,p[i]);
//去掉字符串里的-
for(j = 0; j < len; j++)
//翻转某个连字符
{
if(b[j] == '-')
{
for(int q = j; q < len; q++)
{
b[q] = b[q+1];
}
len--;
}
}
for(j = 0; j < len/2; j++)
{
char c = b[j];
b[j] = b[len - 1 - j];
b[len - 1- j] = c;
}
if(alen >= len)
{
for(j = 0; j < len; j++)
{
if(aswap[j] != b[j])
{
break;
}
}
delete b;
if(j == len)
{
result = i; //找到输入的字符串a中有的p中的第i个连字符
break;
}
}
}
delete aswap;
return result;
}
void main()
{
char *a = "clinic";
int result = getlastsamechar(a);
printf("%d\n",result);
if(-1 != result)
{
char* res = new char[strlen(p[result]) + 1];
strcpy(res, p[result]);
printf("%s\n", res);
//输出字符串a中存在的那个连字符
}
}
8、获取数码管显示方式
把7段显示用7bit来表示。
[cpp] view
plaincopy
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
//数字0-9的数码管显示方式
char *number[] = {"1011111","0000101","1110110","1110101","0101101",
"1111001","1111011","0010101","1111111","1111101"};//从左往右数分别是数码管的七段显示的标号1~7
//获取16bit的正整数
char** getNumber(int bit)
{
char** result= new char*[5];
for(int i = 4; i >= 0; i--)
{
result[i] = number[bit%10];//计算这个五位数的一位,对应就是其在number数组中的标号,直接从number数组中就可 //以获取数字的数码管显示方式。
bit/=10;
}
return result;
}
void main()
{
char** num = getNumber(54673);
for(int i = 0; i < 5; i++)
{
printf("%s\n",*num);
num++;
}
}
相关文章推荐
- 编程珠玑 第二版 第三章 习题答案
- 数据挖掘概念与技术(原书第三版)范明 孟小峰译-----第三章课后习题答案
- c++ primer plus第三章习题答案
- 《UNIX环境高级编程》学习笔记--第三章习题2参考答案
- C++Primer Plus笔记——第三章 处理数据及课后习题答案
- 编程珠玑之第三章习题1
- c++ primer(第五版)学习笔记及习题答案代码版(第三章)字符串、向量和数组
- 鸟哥的linux私房菜基础学习篇课后习题与答案 第三章
- 【《Python编程: 从入门到实践》习题答案--第三章:<list 列表简介>】
- 03 快学scala第三章习题答案
- C++Primer第五版 第三章习题答案(11~20)
- C++Primer第五版 第三章习题答案(41~45)
- 《统计建模与R软件》第三章课后习题3.1-3.4解题答案
- 数据库原理 西安电子科技大学(第三版) 付婷婷 第三章 课后习题答案
- 编程珠玑第三章课后习题
- 编程珠玑第二版第三章习题(Java)
- 数据库系统概论课后习题答案第三章
- java学习之路4-java编程经典第三章习题及答案
- 编程珠玑第三章习题1
- Unix环境高级编程 第三章习题答案