您的位置:首页 > 编程语言

C Primer Plus 第六版编程练习第七章答案和记录一些学习历程

2020-02-03 00:24 831 查看

感觉写博客的话,自己会把书看的更认真些- 。- ,因为也不是计算机科班出身,把自己学习计算机科学的一些历程记录在这个博客里,如博文有问题处,请不吝指教,不胜感激。

1,编写一个程序读取输入,读到#字符停止,然后报告读取空格数,换行符数目以及所有的其它字符数目。

首先:读到#字符使程序停止,我使用这一章学到的getchar()语句,与第五章使用scanf("%lf", &hwen)== 1 语句,读到q或其他不是数字的值使程序停止。
这两种情况区别在于
第一种只在char类型中的#输入请况下使程序停止。——运用情况:同种类型单个字符。
第二种是当程序读取到不是浮点型的数值时程序停止(任意字符都可以)——运用情况:利用两种不同类型输入的区别。
其次:分别用三个变量充当计数器。因此需要一共需要声明4个变量。

/* Programming Exercise 7-1*/
#include <stdio.h>
int main()
{
char ch;
int sp_ct = 0;
int nl_ct = 0;
int other = 0;

printf("please enter the characters: \n");//输入字符
while ((ch = getchar()) != '#')
{ 	if (ch == ' ')
sp_ct++;//计数空格字符
else if (ch == '\n')
nl_ct++;//计数换行字符
else
other++;//计数其他字符
}
printf("spaces: %d, newlines'\\n': %d, others: %d\n", sp_ct, nl_ct, other);

return 0;
}

运行结果:

2,编写一个程序读取输入,读到#字符停止。程序要打印每个输入的字符以及对应的ASCII码(十进制)。一行打印8个字符。建议:使用字符计数和求模运算符(%)在每8个循环周期时打印一个换行符。

首先:输入——读到#字符停止实现方式如题1,
其次:输出——使用转换说明符转换数据类型;
最后:每8个字符换行一次,使用字符计数和求模运算符(%)在每8个循环周期时打印一个换行符。

/* Programming Exercise 7-2*/
#include <stdio.h>
#define SIZE 8

int main(void)
{
char ch;
int count = 0;

printf("please enter the characters:");

while ((ch = getchar()) != '#')//输入#字符停止输入
{
if (ch == '\n')//一个防错模块:输入回车键enter时程序停止。可以不要。
{
printf("\\n-%d\t",ch);
break;
}

else
printf("%c-%d\t",ch,ch);//制表符使输出整齐排列
count++;
while (count % SIZE == 0)// 每8个字符换一次行
printf("\n");
}

return 0;
}

运行结果:

3.编写一个程序,读取整数,直到用户输入0。输入结束后,程序应该报告输入的偶数(不包括0)个数、这些偶数的平均值,输入的奇数个数以及奇数的平均值。

这道题很简单啊。
首先:用累加可以求出总和。
再用:计数器记录数据个数,平均值等于总和除以个数。(需要注意的就是当个数为0的时候,没有平均数,可以输出平均数为零,也可以不输出显示平均数语句。这里我采用的后者)
最后:1个输入,4个输出。一共需要声明5个变量。

/* Programming Exercise 7-3*/
#include <stdio.h>

int main(void)
{
int n;
double sumeven = 0.0;
int ct_even = 0;
double sumodd = 0.0;
int ct_odd = 0;

printf("please enter a number:");
while (scanf("%d", &n) == 1 && n != 0)//当输入非整数或0时结束程序
{
if (n % 2 == 0)
{
sumeven += n;//偶数的总和
ct_even++;//偶数的个数
}
else
{
sumodd += n;//奇数的总和
ct_odd++;//奇数的个数
}
printf("please enter the next number(0 to quit):");
}
printf("\nNumber of evens: %d\n", ct_even);//当偶数个数为0时,不求平均数,只输出偶数个数为0
if (ct_even > 0)
printf("average: %g\n", sumeven / ct_even);
printf("Number of odds: %d\n", ct_odd);//当奇数个数为0时,不求平均数,只输出奇数个数为0
if (ct_odd > 0)
printf("average: %g\n", sumodd / ct_odd);
printf("done!\n");

return 0;
}

运行结果:

4.使用if else语句编写一个程序读取输入,读到#停止。用感叹号代替句号,用两个感叹号代替原来的感叹号,最后报告进行了多少次替代。

这个就更简单了,
输入:用一个变量记录输入
输出:用一个计数器记录需要进行多少次替代。(分开记录替代次数就两个变量)
一共需要声明两个变量。

/* Programming Exercise 7-4*/
#include <stdio.h>

int main(void)
{
char ch;
int count = 0;
printf("please enter the characters:");
while((ch = getchar()) != '#')
{
if(ch == '.')//输入句号,计数器+1
{
putchar('!');
count++;
}
else if(ch == '!')//输入感叹号,计数器+1
{
putchar('!');
putchar('!');
count++;
}
else
{
putchar(ch);
}
}
printf("\nexchanged %d times\n", count);

return 0;
}

运行结果:

5.用switch重写练习4。

/* Programming Exercise 7-5*/
#include <stdio.h>

int main(void)
{
char ch;
int ct1 = 0;
int ct2 = 0;
printf("please enter a charaters(# to quit):");
while ((ch = getchar()) != '#')
{
switch(ch)//根据ch选择case
{
case '.' :
putchar('!');
ct1++;
break;
case '!' :
putchar('!');
putchar('!');
ct2++;
break;
default://其他情况直接输出字符
putchar(ch);
}
}
printf("\n%d replacement(s) of . with !\n", ct1);
printf("%d replacement(s) of ! with !!\n", ct2);

return 0;
}

运行结果:

6.编写程序读取输入,读到#停止,报告ei出现的次数。

首先:关键在于记录前一个字符的同时也要记录后一个字符,也就是说ei是紧密连接在一起的,中间不能有其他字符。才能计数一个。所以应该使用多重嵌套(三重嵌套太复杂)或用变量表示两者关系。
那么这样:我们使用e=1表示前面读取了一个e,当第二次输入时如果是i,则计数,如果不是i,就不计数,并把e重置为e=0。

/* Programming Exercise 7-6*/
#include <stdio.h>
int main(void)
{
char ch;
int e=0;
int count=0;

printf("please enter the characters(# to quit):");
while((ch = getchar()) != '#' )
{
if( ch=='e' )
e=1;//前一个字符读得e
else
{
if( ch=='i' && e==1 )
count++;//后一个字符读的i
e=0;//无论后一个字符是否读到i都将其重置。
}
}
printf( "\nei appeared %d times.\n", count);

return 0;
}

运行结果:

7.编写一个程序,提示用户输入一周工作的小时数,然后打印工资总额、税金和净收入。做如下假设:a.基本工资 = 10美元/小时b.加班(超过40小时) = 1.5倍的时间 c.税率: 前300美元为15% 续150美元为20% 余下的为25%。用#define定义符号常量。不用在意是否符合当前的税法。

这道题很简单,把表达式写对就可以了。
输入:一个变量。
输出:四个变量记录。
实现方式:八个明示常量。使用else if配对的方式做选择比较方便。

// Programming Exercise 7-7//
#include <stdio.h>
#define BASEPAY 10
#define BASEHRS 40
#define OVERTIME 1.5
#define AMT1 300
#define AMT2 150
#define RATE1 0.15
#define RATE2 0.20
#define RATE3 0.25
int main(void)
{
double hours;
double gross;
double net;
double taxes;
printf("Enter the number of hours worked this week: ");
scanf("%lf", &hours);
if (hours <= BASEHRS)
gross = hours * BASEPAY;
else
gross = BASEHRS * BASEPAY + (hours - BASEHRS) * BASEPAY * OVERTIME;
if (gross <= AMT1)
taxes = gross * RATE1;
else if (gross <= AMT1 + AMT2)
taxes = AMT1 * RATE1 + (gross - AMT1) * RATE2;
else
taxes = AMT1 * RATE1 + AMT2 * RATE2 + (gross - AMT1 - AMT2) * RATE3;
net = gross - taxes;
printf("gross: $%.2f; taxes: $%.2f; net: $%.2f\n", gross, taxes, net);

return 0;
}

运行结果:

8.修改练习7的假设a,让程序可以给出一个供选择的工资等级菜单。使用switch完成工资等级选择。运行程序后,显示的菜单应该类似这样: Enter the number corresponding to the desired pay rate or action:1) $8.75/hr 2) $9.33/hr 3)$10.00/hr 4) $11.20/hr 5) quit 如果选择 1~4 其中的一个数字,程序应该询问用户工作的小时数。程序要通过循环运行,除非用户输入 5。如果输入 1~5 以外的数字,程序应提醒用户输入正确的选项,然后再重复显示菜单提示用户输入。使用#define创建符号常量表示各工资等级和税率。

这道题还是有点复杂啊,成功运行花了一个小时。。。
首先:重复显示菜单,为了方便起见,我们先把这个显示菜单做成一个函数,然后调用它。
其次:程序需要循环运行,直到输入5结束,说明我们在用户输入1,2,3,4,5(程序停止是它的子层)和其他输入(提示输入正确的选项,这是它的子层)(这几个选项是一层)的时候,外层还要有一个大循环,用于不断循环运行计算工资程序。所以这个程序大体需要三层嵌套。
最后:观察这几个输入最外层的共性,于是采用scanf成功读入作为外层判断依据。

// Programming Exercise 7-8//
#include <stdio.h>

#define BASEPAY1 8.75
#define BASEPAY2 9.33
#define BASEPAY3 10.00
#define BASEPAY4 11.20
#define BASEHRS 40
#define OVERTIME 1.5
#define AMT1 300
#define AMT2 150
#define RATE1 0.15
#define RATE2 0.20
#define RATE3 0.25
#define LONG 65

void copy(char n, int m);//声明打印*号函数
void head(void);//声明选择菜单函数

int main(void)
{
double hours;
double gross;
double net;
double taxes;
double basepay;//基本工资
int num;//选择选项

head();//调用选择菜单函数

while(scanf("%d", &num) != 0)//循环读取用户输入选择
{
switch(num)//选择基本工资
{
case 1: basepay = BASEPAY1;
break;
case 2: basepay = BASEPAY2;
break;
case 3: basepay = BASEPAY3;
break;
case 4: basepay = BASEPAY4;
break;
}
if (num > 0 && num < 5)//对1,2,3,4这四个选项进行计算
{
printf("Enter the number of hours worked this week: ");
scanf("%lf", &hours);
if (hours <= BASEHRS)
gross = hours * basepay;
else
gross = BASEHRS * basepay + (hours - BASEHRS) * basepay * OVERTIME;
if (gross <= AMT1)
taxes = gross * RATE1;
else if (gross <= AMT1 + AMT2)
taxes = AMT1 * RATE1 + (gross - AMT1) * RATE2;
else
taxes = AMT1 * RATE1 + AMT2 * RATE2 + (gross - AMT1 - AMT2) * RATE3;
net = gross - taxes;
printf("gross: $%.2f; taxes: $%.2f; net: $%.2f\n\n", gross, taxes, net);
head();//未输入5之前循环调用选择菜单函数
}
else if(num == 5)//输入5跳出循环
break;
else
{
printf("incorrect input,please re-enter!\n");//提示输入错误
head();//再次调用选择菜单函数
}
}
return 0;
}

void copy(char n, int m)//定义打印*号函数
{
int count;
for(count = 0; count < m; count++)
putchar(n);
printf("\n");
}
void head(void)//定义选择菜单函数
{
copy('*', LONG);
printf("Enter the number corresponding to the desired pay rate or action: \n");
printf("1) $8.75/hr           2) $9.33/hr\n3) $10.00/hr          4) $11.20/hr\n5) quit \n");
copy('*', LONG);
}

运行结果:

9.编写一个程序,只接受正整数输入,然后显示所有小于或等于该数的素数。

又到到了喜闻乐见的找素数环节:本来想了一下,用2到他本身的数除一遍这个数就可以了。但是又仔细的想了一下,万一这个数很大很大,从2到本身除下去,那的花多久时间啊。后来一百度:我发现还有什么费马小定理,lucas序列,椭圆曲线算法的解法。。。看来这个东西远不止我想的那么简单啊哈哈哈哈。
首先:第一个难点应该在于如何限定输入正整数,scanf语句无法限定输入,所以我们先定义输入为整型,然后用scanf读取输入,判断是否成功读取且读取的数大于0,即可达成我们的目的。(好像浮点型会被强制转换为整型,暂时还没想到什么好办法限定浮点型不能输入)
其次:如何判断一个数是不是素数,大体意思是从2除到他本身,但是因为因为如果一个数不是素数,那么它一定可以由两个自然数相乘得到,其中一个大于或等于它的平方根,一个小于或等于它的平方根,并且成对出现。
所以:我们对这个办法进行优化;我们对这个数从2除到他的平方根(如果他不是素数,那么必有一个可以整除他的除数小于他的平方根)。这样可以节约一半时间。C中要调用math.h头文件可以有开方函数,我们不哟个开方函数,对分母平方也可以达到相同目的。
注:
还有一种筛法:我们已知2是最小素数,于是从2开始筛选(定义筛选的基数为n,此时n = 2)。那么所有的2的倍数都不是素数,因为至少可以被2整除。之后对3、4、5、6…进行筛选(此时n = 3、4、5、6、7…)这个叫做厄拉多塞筛法。有空写一下这个程序。。。

// Programming Exercise 7-8//
#include <stdio.h>
int main(void)
{
int limit;
int num;
int div;
int numIsPrime;//判断数字是否为素数
printf("Enter a positive integer: ");
if (scanf("%d", &limit) != 0 && limit > 0)//判断输入是否为正整数
{
if (limit == 1)//输入为1时的特殊情况
printf("No primes.\n");
else
printf("Here are the prime numbers up through %d\n", limit);//小于等于该输入数字的素数
for (num = 2; num <= limit; num++)//遍历所有小于等于该数字的数字
{
for (div = 2, numIsPrime = 1; (div * div) <= num; div++)//判断这些数字是否是素数
if (num % div == 0)//不是素数
numIsPrime = 0;
if (numIsPrime == 1)//是素数
printf("%d is prime.\n", num);
}
}
else//如果输入其他字符,则提示无法读取
printf("This program can't read your input!\n");

return 0;
}

运行结果:

10.1988年的美国联邦税收计划是近代最简单的税收方案。它分为4个类别,每个类别有两个等级。 下面是该税收计划的摘要(美元数为应征税的收入):例如,一位工资为20000美元的单身纳税人,应缴纳税0.15×17850+0.28×(20000−17850)美元。编写一个程序,让用户指定缴纳税金的种类和应纳税收入,然后计算税金。程序应通过循环让用户可以多次输入。

这道题和第8题思路差不多。比第8题还要简单些,只有一个输出。

// Programming Exercise 7-10//
#include <stdio.h>
#define BASEPAY1 17850.00
#define BASEPAY2 23900.00
#define BASEPAY3 29750.00
#define BASEPAY4 14875.00
#define RATE1 0.15
#define RATE2 0.28
#define LONG 44
void copy(char n, int m);//声明打印*号函数
void head(void);//声明选择菜单函数

int main(void)
{
double basepay;
double income;
double taxes;
int type;

head();//调用菜单
while(scanf("%d", &type) != 0)
{
switch(type)
{
case 1: basepay = BASEPAY1;
break;
case 2: basepay = BASEPAY2;
break;
case 3: basepay = BASEPAY3;
break;
case 4: basepay = BASEPAY4;
break;
}
if (type > 0 && type < 5)
{
printf("Enter the gross of your income: \n");
scanf("%lf", &income);
if (income <= basepay)
taxes = income * RATE1;
else
taxes = (income - basepay) * RATE2 + basepay* RATE1;

printf("income: $%.2f; taxes: $%.2f\n\n", income, taxes);
head();//未输入5之前循环调用选择菜单函数
}
else if(type == 5)
break;
else
{
printf("incorrect input,please re-enter!\n");
head();//调用菜单
}
}
return 0;
}

void copy(char n, int m)//生成*函数定义
{
int count;
for(count = 0; count < m; count++)
putchar(n);
printf("\n");
}
void head(void)//选择菜单函数定义
{
copy('*', LONG);
printf("Please enter what's the type of tax payment?\n");
printf("1) 单身               2) 户主\n3) 已婚,共有         4) 已婚离异\n5) 退出程序 \n");
copy('*', LONG);
}

运行结果:

11.ABC 邮购杂货店出售的洋蓟售价为 2.05 美元/磅,甜菜售价为 1.15 美元/磅,胡萝卜售价为 1.09美元/磅。在添加运费之前,100美元的订单有5%的打折优惠。少于或等于5磅的订单收取6.5美元的运费和包装费,5磅~20磅的订单收取14美元的运费和包装费,超过20磅的订单在14美元的基础上每续重1磅增加0.5美元。 编写一个程序,在循环中用switch语句实现用户输入不同的字母时有不同的响应,即输入a的响应是让用户输入洋蓟的磅数,b是甜菜的磅数,c是胡萝卜的磅数,q 是退出订购。程序要记录累计的重量。即,如果用户输入 4 磅的甜菜,然后输入 5磅的甜菜,程序应报告9磅的甜菜。然后,该程序要计算货物总价、折扣(如果有的话)、运费和包装费。随后,程序应显示所有的购买信息:物品售价、订购的重量(单位:磅)、订购的蔬菜费用、订单的总费用、折扣(如果有的话)、运费和包装费,以及所有的费用总额。

这个题目难倒是不难,就是要计算的太多了。。。
首先:我们理一下,第一个模块应该是订购模块,主要统计各蔬菜重量。如之前8和10题的选择菜单一样,要注意的就是因为是字符输入,window系统enter键既是回车也是换行。所以要将缓冲区的换行符清空。其他基本一样。
其次:再根据重量确定运费,订购蔬菜费。用else if联合语句。
最后:计算一下总花费,折扣。

/* Programming Exercise 7-11 */
#include <stdio.h>
#include <ctype.h>
#define LONG 34

void copy(char n, int m);//声明打印*号函数
void head(void);//声明选择菜单函数

int main(void)
{
const double price_artichokes = 2.05;
const double price_beets = 1.15;
const double price_carrots = 1.09;
const double DISCOUNT_RATE = 0.05;
const double under5 = 6.50;
const double under20 = 14.00;
const double base20 = 14.00;
const double extralb =  0.50;
char ch;
double lb_artichokes = 0;
double lb_beets = 0;
double lb_carrots = 0;
double lb_temp;
double lb_total;
double cost_artichokes;
double cost_beets;
double cost_carrots;
double cost_total;
double final_total;
double discount;
double shipping;

head();//调用菜单
while ((ch = getchar()) != 'q' && ch != 'Q') //输出q或Q退出订购
{
if (ch == '\n')
continue;
while (getchar() != '\n')
continue;
ch = tolower(ch);//调用大写字母转换小写字母函数,兼容大小写。
switch (ch)//记录累计重量。
{
case 'a' : 	printf("Enter pounds of artichokes: ");
scanf("%lf", &lb_temp);
lb_artichokes += lb_temp;
break;
case 'b' :  printf("Enter pounds of beets: ");
scanf("%lf", &lb_temp);
lb_beets += lb_temp;
break;
case 'c' :  printf("Enter pounds of carrots: ");
scanf("%lf", &lb_temp);
lb_carrots += lb_temp;
break;
default  :  printf("%c is not a valid choice.\n", ch);
}
head(); //再次调用订购菜单
}
cost_artichokes = price_artichokes * lb_artichokes;
cost_beets = price_beets * lb_beets;
cost_carrots = price_carrots * lb_carrots;
cost_total = cost_artichokes + cost_beets + cost_carrots; //计算订购总花费。
lb_total = lb_artichokes + lb_beets + lb_carrots;//计算订购总重量
if (lb_total <= 0)//总重为0磅时的运费
shipping = 0.0;
else if (lb_total < 5.0)//总重为0到5磅时的运费
shipping = under5;
else if (lb_total < 20)//总重为5到20磅时的运费
shipping = under20;
else //总重超过20磅时的运费
shipping =  base20 + extralb * lb_total;
if (cost_total > 100.0)//计算折扣
discount = DISCOUNT_RATE * cost_total;
else     discount = 0.0;
final_total = cost_total + shipping - discount;  //最终花费
printf("Your order:\n");
printf("%.2f lbs of artichokes at $%.2f per pound:$ %.2f\n",
lb_artichokes, price_artichokes, cost_artichokes);
printf("%.2f lbs of beets at $%.2f per pound: $%.2f\n",
lb_beets, price_beets, cost_beets);
printf("%.2f lbs of carrots at $%.2f per pound: $%.2f\n",
lb_carrots, price_carrots, cost_carrots);
printf("Total cost of vegetables: $%.2f\n", cost_total);   if (cost_total > 100)
printf("Volume discount: $%.2f\n", discount);
printf("Shipping: $%.2f\n", shipping);
printf("Total charges: $%.2f\n", final_total);

return 0;
}
void copy(char n, int m)//生成*函数定义
{
int count;
for(count = 0; count < m; count++)
putchar(n);
printf("\n");
}
void head(void)//选择菜单函数定义
{
copy('*', LONG);
printf("Please enter to buy what you want.\n");
printf("(a) artichokes      (b) beets\n(c) carrots         (q) exit \n");
copy('*', LONG);
}

运行结果:

  • 点赞 1
  • 收藏
  • 分享
  • 文章举报
我再也不爱zht了 发布了23 篇原创文章 · 获赞 8 · 访问量 1412 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: