C primer plus编程练习答案(上)

C primer plus编程练习

C primer plus编程练习答案

  • C primer plus编程练习
    • 第一章初识C语言
    • 第二章 C语言概述
    • 第三章 数据和C
    • 第四章 字符串的格式化输入/输出
    • 第五章 运算符,表达式和语句
    • 第六章 C控制语句:循环
    • 第七章 C 控制语句:分之合跳转
    • 第八章 字符输入/输出和输入验证
    • 第九章 函数
    • 第十章 数组和指针
    • 第十一章 字符串和字符串函数

第一章初识C语言

  1. 你刚被MacroMuscle有限公司聘用。该公司准备进入欧洲市场,需要一个把英寸单位转换为厘米单位(1英寸=2.54厘米)的程序。该程序要提示用户输入英寸值。你的任务是定义程序目标和设计程序。
#include


#define cm 2.54//宏定义 英寸转换厘米
int main(void)
{
	float inch = 1.0;//英寸


	printf("请输入英寸值:");
	scanf_s("%f", &inch);
	printf("%.3f英寸等于%.3f厘米\n", inch, inch * cm);
	printf("程序结束\n");


	return 0;
}

第二章 C语言概述

  1. 编写一个程序,调用一次 printf()函数,把你的姓名打印在一行。再调用一次 printf()函数,把你的姓名分别打印在两行。然后,再调用两次printf()函数,把你的姓名打印在一行。输出应如下所示(当然要把示例的内容换成你的姓名):

C primer plus编程练习答案(上)_第1张图片

#include
int main(void)
{
	printf("Gustav Mahler\n");
	printf("Gustav\nMahler\n");
	printf("Gustav ");
	printf("Mahler\n");
	
	return 0;
}
  1. .编写一个程序,打印你的姓名和地址。
#include
int main(void)
{
	printf("my name is jo,i live in sd\n");
	return 0;
}
  1. 编写一个程序把你的年龄转换成天数,并显示这两个值。这里不用考虑闰年的问题。
#include
int main(void)
{
	int ageyears;
	int agedays;
	
	ageyears = 30;
	agedays = 365 * ageyears;
	printf("出生年数%d,俺出生的天数是%d\n",ageyears,agedays);
	
	return 0;
}
  1. 编写一个程序,生成以下输出:
    For he’s a jolly good fellow!
    For he’s a jolly good fellow!
    For he’s a jolly good fellow!
    Which nobody can deny!
    除了 main()函数以外,该程序还要调用两个自定义函数:一个名为jolly(),用于打印前 3 条消息,调用一次打印一条;另一个函数名为deny(),打印最后一条消息。
#include
void jolly(void);
void deny(void);

int main(void)
{
	jolly();
	deny();
	
	return 0;
}


void jolly(void)
{
	printf("First he's a jolly good fellow!\n");
	printf("First he's a jolly good fellow!\n");
	printf("First he's a jolly good fellow!\n");
}
void deny(void)
{
	printf("Which nobody can deny!\n");
}
  1. .编写一个程序,生成以下输出:
Brazil, Russia, India, China
India, China,
Brazil, Russia

除了main()以外,该程序还要调用两个自定义函数:一个名为br(),调用一次打印一次“Brazil, Russia”;另一个名为ic(),调用一次打印一次“India,China”。其他内容在main()函数中完成。

#include
void br(void)
{
	printf("Brazil,Russia\n");
}

void ic(void)
{
	
	printf("India,Russia\n");
}
int main(void)
{
	printf("Brazil,Russia,India,China\n");
	
	ic();	
	br();
	
	return 0;
}
  1. 编写一个程序,创建一个整型变量toes,并将toes设置为10。程序中还要计算toes的两倍和toes的平方。该程序应打印3个值,并分别描述以示区分。
#include
#define toes 10

int dob_toes ;
int toes_sq ;

int main()
{
	dob_toes = toes * 2;
	toes_sq = toes * toes;
	
	
	printf("toes = %d ,dob_toes = %d, toes_sq = %d"
			,toes,dob_toes,toes_sq);
	return 0;
}
  1. .许多研究表明,微笑益处多多。编写一个程序,生成以下格式的输出:
Smile!Smile!Smile!
Smile!Smile!
Smile!

该程序要定义一个函数,该函数被调用一次打印一次“Smile!”,根据程序的需要使用该函数。

#include
void po(void);
void ptw(void);
void pth(void);
int main()
{
	
	pth();
	ptw();
	po();
	return 0;
	
}
void pth(void)
{
	printf("smile!smile!smile!\n");
}
void ptw(void)
{
	printf("smile!smile!\n");
	
}

void po(void)
{
	printf("smile!\n");
	
}
  1. ** 在C语言中,函数可以调用另一个函数。编写一个程序,调用一个名为one_three()的函数。该函数在一行打印单词“one”,再调用第2个函数two(),然后在另一行打印单词“three”。two()函数在一行显示单词“two”。main()函数在调用 one_three()函数前要打印短语“starting now:”,并在调用完毕后显示短语“done!”。因此,该程序的输出应如下所示:**
starting now:
one
two
three
done!
#include
void one_three(void);
void two(void);


int main(void)
{
	printf("starting now :\n");
	one_three();	
	printf("done!");
	
	return 0;
}

void one_three(void )
{
	printf("one\n");
	two();
	printf("three\n");
}

void two(void)
{
	printf("two\n");
}

第三章 数据和C

  1. 通过试验(即编写带有此类问题的程序)观察系统如何处理整数上溢、浮点数上溢和浮点数下溢的情况。
#include 
#include 
 
int main()
{
    int a = 2147483647;
    float b = 3.4E38 * 100.0f;
    float c = (3.4E-38) / (100.0E100);
    printf("%d %d %d\n", a, a+1, a+2); //整数上溢
    printf("%e\n", b);                 //浮点数上溢
    printf("%e", c);                   //浮点数下溢
    return 0;
}
  1. 编写一个程序,要求提示输入一个ASCII码值(如,66),然后打印输入的字符。
#include
int main(void)
{
	int i ;
	printf("please input a number like 66 :");
	scanf("%d",&i);
	printf("%c",i);
		
	return 0;
}
  1. 编写一个程序,发出一声警报,然后打印下面的文本:
Startled by the sudden sound, Sally shouted,
"By the Great Pumpkin, what was that!"
#include
#include

int main(void)
{
	
	printf("\aStartled by the sudden sound,Sally shouted,\n"
			"\"By the Great Pumpkin,what was that!\"");
	return 0;
}

  1. 编写一个程序,读取一个浮点数,先打印成小数点形式,再打印成指数形式。然后,如果系统支持,再打印成p记数法(即十六进制记数法)。按以下格式输出(实际显示的指数位数因系统而异):
Enter a floating-point value: 64.25
fixed-point notation: 64.250000
exponential notation: 6.425000e+01
p notation: 0x1.01p+6
#include
int main(void){
    float a;
    printf("Enter a floating-point value:");
    scanf("%f",&a);
    printf("fixed-point notation: %f\n",a);
    printf("exponential notation: %e\n",a);
    printf("p notation:%a\n",a);

    return 0;
}

  1. 一年大约有3.156×107秒。编写一个程序,提示用户输入年龄,然后显示该年龄对应的秒数。
#include

int main(void)
{
	int year;
	printf("input your age:");
	scanf("%d",&year);
	long long second;
	second = year * (3.156*10e7);
	printf("you have live %lld seconds",second);
	
	
	
	return 0;
}
  1. 一个水分子的质量约为3.0×10−23克。1夸脱水大约是950克。编写一个程序,提示用户输入水的夸脱数,并显示水分子的数量。
#include
int main(void)
{
	float mass_mol =3.0e-23;
	float mass_qt = 950;
	float quarts;
	float molecules;
	
	printf("Enter the number of quarters of water:");
	scanf("%f",&quarts);
	molecules = quarts * mass_qt / mass_mol;
	printf("%f quarts of water contain %e molecules.\n",quarts,molecules);
		
	return 0;
}
  1. 1英寸相当于2.54厘米。编写一个程序,提示用户输入身高(/英寸),然后以厘米为单位显示身高。
#include
int main(void)
{
	float i;
	float h;
	printf("input the inch of your height:\n");
	scanf("%f",&i);
	h = 2.54 * i;
	printf("your hight is %.2fcm!\n",h);
	
	return 0;
}
  1. 在美国的体积测量系统中,1品脱等于2杯,1杯等于8盎司,1盎司等于2大汤勺,1大汤勺等于3茶勺。编写一个程序,提示用户输入杯数,并以品脱、盎司、汤勺、茶勺为单位显示等价容量。思考对于该程序,为何使用浮点类型比整数类型更合适?
#include
int main()
{
	float cup;
	printf("Enter the cup number:");
	scanf("%f",&cup);
	
	printf("%.1f杯等于 %.1f 品脱\n",cup,cup/2);
	printf("%.1f杯等于 %.1f 盎司\n",cup,cup*8);
	printf("%.1f杯等于 %.1f 大汤勺\n",cup,cup*8*2);
	printf("%.1f杯等于 %.1f 茶勺\n",cup,cup*8*3*2);
	return 0;
}

第四章 字符串的格式化输入/输出

  1. .编写一个程序,提示用户输入名和姓,然后以“名,姓”的格式打印出
    来。
#include
#include
int main(void)
{
    char char1[20],char2[20];
    printf("please input your first name and your last name:\n");
    scanf("%s%s",char1,char2);
    printf("%s,%s",char1,char2);


    return 0;

}

  1. 编写一个程序,提示用户输入名和姓,并执行一下操作:
    a.打印名和姓,包括双引号;
    b.在宽度为20的字段右端打印名和姓,包括双引号;
    c.在宽度为20的字段左端打印名和姓,包括双引号;
    d.在比姓名宽度宽3的字段中打印名和姓。
#include
#include
int main(void)
{
    char string1[20];
    int len;

    printf("input your first name and last name:like firstname,lastname\n");
    scanf("%s",string1);
    len = strlen(string1);
    printf("\"%s\"\n",string1);
    printf("%20s\n",string1);
    printf("%-20s\n",string1);
    printf("%*s\n",len+3,string1);


    return 0;

}

  1. 编写一个程序,读取一个浮点数,首先以小数点记数法打印,然后以指数记数法打印。用下面的格式进行输出(系统不同,指数记数法显示的位数可能不同):
    a.输入21.3或2.1e+001;
    b.输入+21.290或2.129E+001;
#include

int main(void)
{

    float num;

    printf("Please enter a float number:\n");
    scanf("%f",&num);
    printf("The input is %.1f or %.1e.\n",num,num);

    return 0;
}

  1. 编写一个程序,提示用户输入身高(单位:英寸)和姓名,然后以下面的格式显示用户刚输入的信息:
Dabney, you are 6.208 feet tall

使用float类型,并用/作为除号。如果你愿意,可以要求用户以厘米为单位输入身高,并以米为单位显示出来。

#include
#define LEN 30

int main(void)
{
    float heigh;
    char name[LEN];

    printf("please enter your name:\n");
    scanf("%29s",name);
    printf("Hello!%s,how tall you are (inch):",name);
    scanf("%f",&heigh);
    printf("%s,you r %.3f feet tall.\n",name,heigh/12.0);


    return 0;
}

  1. 编写一个程序,提示用户输入以兆位每秒(Mb/s)为单位的下载速度和以兆字节(MB)为单位的文件大小。程序中应计算文件的下载时间。注意,这里1字节等于8位。使用float类型,并用/作为除号。该程序要以下面的格式打印 3 个变量的值(下载速度、文件大小和下载时间),显示小数点后面两位数字:
At 18.12 megabits per second, a file of 2.20 megabytes
downloads in 0.97 seconds.
#include
int main(void)
{
    int BIT = 8;
    float speed ,size,time;

    printf("Please enter net speed(Mbit/s):");
    scanf("%f", &speed);
    printf("Please enter file size(MB):");
    scanf("%f", &size);
    time = size * BIT / speed;
    printf("At %.2f megabits per secnod, ", speed);
    printf("a file of %.2f megabytes ", size);
    printf("downloads in %.2f seconds.\n", time);


    return 0;
}

  1. 编写一个程序,先提示用户输入名,然后提示用户输入姓。在一行打印用户输入的名和姓,下一行分别打印名和姓的字母数。字母数要与相应名和姓的结尾对齐,如下所示:
Melissa Honeybee
7    8

接下来,再打印相同的信息,但是字母个数与相应名和姓的开头对齐,
如下所示:

Melissa Honeybee
#include 
#include 

int main(void)
{
    int x, y;
    char fname[20], lname[20];

    printf("Please enter your first name: ");
    scanf("%19s", fname);
    printf("Please enter your last name: ");
    scanf("%19s", lname);
    x = strlen(fname);
    y = strlen(lname);
    printf("%s %s\n", fname, lname);
    printf("%*d %*d\n", x, x, y, y);
    printf("%s %s\n", fname, lname);
    printf("%-*d %-*d\n", x, x, y, y);

    return 0;
}

  1. 编写一个程序,将一个double类型的变量设置为1.0/3.0,一个float类型的变量设置为1.0/3.0。分别显示两次计算的结果各3次:一次显示小数点后面6位数字;一次显示小数点后面12位数字;一次显示小数点后面16位数字。程序中要包含float.h头文件,并显示FLT_DIG和DBL_DIG的值。1.0/3.0的值与这些值一致吗?
#include 
#include 

int main(void)
{
    float f_value = 1.0 / 3.0;
    double d_value = 1.0 / 3.0;

    printf("1.0 / 3.0 display 6 decimal places:\n");
    printf("f_value = %.6f\nd_value = %.6lf\n", f_value, d_value);
    printf("\n1.0 / 3.0 display 12 decimal places:\n");
    printf("f_value = %.12f\nd_value = %.12lf\n", f_value, d_value);
    printf("\n1.0 / 3.0 display 16 decimal places:\n");
    printf("f_value = %.16f\nd_value = %.16lf\n", f_value, d_value);
    printf("\nfloat and double maximum significant digits:\n");
    printf("FLT_DIG = %d, DBL_DIG = %d\n", FLT_DIG, DBL_DIG);
    //↑FLTDIG代表float有效十进制数字位数;
    //↑DBL_DIG代表double有效十进制数字位数;

    return 0;
}

  1. 编写一个程序,提示用户输入旅行的里程和消耗的汽油量。然后计算并显示消耗每加仑汽油行驶的英里数,显示小数点后面一位数字。接下来,使用1加仑大约3.785升,1英里大约为1.609千米,把单位是英里/加仑的值转换为升/100公里(欧洲通用的燃料消耗表示法),并显示结果,显示小数点后面 1 位数字。注意,美国采用的方案测量消耗单位燃料的行程(值越大越好),而欧洲则采用单位距离消耗的燃料测量方案(值越低越好)。使用#define 创建符号常量或使用 const 限定符创建变量来表示两个转换系数。
#include 
#define GALLON_TO_LITRE 3.785f
#define MILE_TO_KM 1.609f

int main(void)
{
    float range, oil;

    printf("Please input the range you traveled(in mile):");
    scanf("%f", &range);
    printf("Please input the oil you spend(in gallon):");
    scanf("%f", &oil);

    printf("Fuel consumptions:\n");
    printf("In USA, your oil wear is %.1f mile/gallon.\n", range / oil);
    printf("In Europe, your oil wear is ");
    printf("%.1f litre/100km.\n", (oil * GALLON_TO_LITRE) / (range * MILE_TO_KM));

    return 0;
}

第五章 运算符,表达式和语句

编写一个程序,把用分钟表示的时间转换成用小时和分钟表示的时间。使用#define或const创建一个表示60的符号常量或const变量。通过while循环让用户重复输入值,直到用户输入小于或等于0的值才停止循环。

#include
int main(void)
{
	const int minperhour = 60;
	int minutes,hours,mins;
	
	printf("Enter the number of minutes to convert:");
	scanf("%d",&minutes);
	while(minutes>0)
	{
		hours = minutes / minperhour;
		mins = minutes % minperhour;
		printf("%d minutes = %d hours,%d minutes\n ",minutes,hours,mins);	
		printf("Enter next value (0 to quit):");
		scanf("%d",&minutes);
	}
	
	printf("Bye\n");
	
	return 0;
}
  1. 编写一个程序,提示用户输入一个整数,然后打印从该数到比该数大10的所有整数(例如,用户输入5,则打印5~15的所有整数,包括5和15)。要求打印的各值之间用一个空格、制表符或换行符分开。
#include
int main(void)
{
	int i;
	printf("please input a number :");
	scanf("%d",&i);
	for(int j=i;j<=i+10;j++)
	{
		printf("%d ",j);
	}
	
	return 0;
}
  1. 编写一个程序,提示用户输入天数,然后将其转换成周数和天数。例如,用户输入18,则转换成2周4天。以下面的格式显示结果:编写一个程序,提示用户输入天数,然后将其转换成周数和天数。例如,用户输入18,则转换成2周4天。以下面的格式显示结果:
18 days are 2 weeks, 4 days.

通过while循环让用户重复输入天数,当用户输入一个非正值时(如0或-20),循环结束。

#include

int main(void)
{
	const  int daysperweek = 7;
	int days,weeks,day_rem;
	printf("Enter the number of days:");
	scanf("%d",&days);
	while(days>0)
	{
		weeks = days/daysperweek;
		day_rem = days % daysperweek;
		printf("%d day are %d weeks and %d days.\n",days,weeks,day_rem);
		
		printf("Enter the number of days(0 or less to end:");
		scanf("%d",&days);	
	}	
	printf("Done!\n");
	
	return 0;
}
  1. 编写一个程序,提示用户输入一个身高(单位:厘米),并分别以厘米和英寸为单位显示该值,允许有小数部分。程序应该能让用户重复输入身高,直到用户输入一个非正值。其输出示例如下:
182.0 cm = 5 feet, 11.7 inches
Enter a height in centimeters (<=0 to quit): 168.7
168.0 cm = 5 feet, 6.4 inches
Enter a height in centimeters (<=0 to quit): 0
bye
#include 

#define FEET_TO_CM  30.48
#define INCH_TO_CM  2.54

int main()
{
    int feet = 0;
    float inches = 0, cm = 0;

    printf("Input the hight in centimeters:");
    scanf("%f", &cm);

    while(cm > 0)
    {
        feet = cm / FEET_TO_CM;
        inches = (cm - feet*FEET_TO_CM) / INCH_TO_CM;
        printf("%.1f cm = %d feet, %.1f inches\n", cm, feet, inches);

        printf("Input the hight in centimeters( <= 0 to Quit):");
        scanf("%f", &cm);
    }

    printf("bye\n");
    return 0;
}

  1. 修改程序addemup.c(程序清单5.13),你可以认为addemup.c是计算20天里赚多少钱的程序(假设第1天赚$1、第2天赚$2、第3天赚$3,以此类推)。修改程序,使其可以与用户交互,根据用户输入的数进行计算(即,用读入的一个变量来代替20)。
#include

int main(void)
{
	int count ,sum;
	int n;
	printf("Enter the upper limit:");
	scanf("%d",&n);
	count = 0;
	sum = 0;
	while(count++ <n)
		sum = sum + count;
	printf("sum = %d\n",sum);
	
	return 0;
}
  1. 修改编程练习5的程序,使其能计算整数的平方和(可以认为第1天赚$1、第2天赚$4、第3天赚$9,以此类推,这看起来很不错)。C没有平方函数,但是可以用n * n来表示n的平方。
#include

int main(void)
{
	int count ,sum;
	int n;
	printf("Enter the upper limit:");
	scanf("%d",&n);
	count = 0;
	sum = 0;
	while(count++ <n)
	{
		int j ;
		j= count*count;
		sum = sum + j;
	}
	printf("sum = %d\n",sum);
	
	return 0;
}
  1. 编写一个程序,提示用户输入一个double类型的数,并打印该数的立方值。自己设计一个函数计算并打印立方值。main()函数要把用户输入的值传递给该函数。
#include
void showCube(double x)
{	
	printf("The cube of %e is %e.\n",x,x*x*x);
}

int main(void)
{
	double val;
	printf("Enter a float-point value:");
	scanf("%lf",&val);
	showCube(val);
	
	return 0;
}
  1. .编写一个程序,显示求模运算的结果。把用户输入的第1个整数作为求模运算符的第2个运算对象,该数在运算过程中保持不变。用户后面输入的数是第1个运算对象。当用户输入一个非正值时,程序结束。其输出示例如下:
This program computes moduli.
Enter an integer to serve as the second operand: 256
Now enter the first operand: 438
438 % 256 is 182
Enter next number for first operand (<= 0 to quit): 1234567
1234567 % 256 is 135
Enter next number for first operand (<= 0 to quit): 0
Done
#include
int main(void)
{
	int first ,second;
	printf("This program computer moduli.\n");
	printf("Enter an integer to server as the second operand:");
	scanf("%d",&second);
	printf("Now enter the first operand:");
	scanf("%d",&first);
	while(first>0)
	{
		printf("%d %% %d is %d\n",first ,second,(first % second));
		printf("Enter next number for first operand(<=0 to quit):");
		scanf("%d",&first);
	}
	printf("Done!\n");
	
	return 0;
}

编写一个程序,要求用户输入一个华氏温度。程序应读取double类型的值作为温度值,并把该值作为参数传递给一个用户自定义的函数Temperatures()。该函数计算摄氏温度和开氏温度,并以小数点后面两位数字的精度显示3种温度。要使用不同的温标来表示这3个温度值。下面是华氏温度转摄氏温度的公式:
摄氏温度 = 5.0 / 9.0 * (华氏温度 - 32.0)
开氏温标常用于科学研究,0表示绝对零,代表最低的温度。下面是摄氏温度转开氏温度的公式:
开氏温度 = 摄氏温度 + 273.16
Temperatures()函数中用const创建温度转换中使用的变量。在main()函数中使用一个循环让用户重复输入温度,当用户输入 q 或其他非数字时,循环结束。scanf()函数返回读取数据的数量,所以如果读取数字则返回1,如果读取q则不返回1。可以使用==运算符将scanf()的返回值和1作比较,测试两值是否相等。

#include
void Temperatures(double fahrenheit)
{
	const double F_TO_C = 32.0;
	const double C_TO_T = 273.16;
	
	double celsius,kelvin;
	celsius = 5.0 / 9.0 * (fahrenheit - F_TO_C);
	kelvin = celsius + C_TO_T;
	printf("%.2f.fahrenheit,equal %.2f celsius,and %.2f kelvin\n",fahrenheit,celsius,kelvin);
	
	
}

int main(void)
{
	double input;
	printf("This programmer convert fahrenheit to celsius and kelvin.\n");
	printf("Enter a fahrenheit to start:");
	while(scanf("%lf",&input)==1)
	{
		Temperatures(input);
		printf("Enter next fahrenheit!(q to quit):");
	}
	printf("Done!\n");
	return 0;
}

第六章 C控制语句:循环

  1. 编写一个程序,创建一个包含26个元素的数组,并在其中储存26个小写字母。然后打印数组的所有内容。
#include
#define N 26
int main(void)
{
	char char1[N];
	int i;
	for(i=0;i<N;i++)
		char1[i]= 'a'+i;
	for(i=0;i<N;i++)
		printf("%c",char1[i]);
		
	//printf("\n");	
	return 0;
}

2.使用嵌套循环,按下面的格式打印字符:

$
$$
$$$
$$$$
$$$$$
#include

int main(void)
{
	int i,j;
	for(i=0;i<5;i++)
	{
		for(j=0;j<i+1;j++)
		printf("$");
		printf("\n");
	}
	
	return 0;
}
    
  1. 使用嵌套循环,按下面的格式打印字母:
F
FE
FED
FEDC
FEDCB
FEDCBA

注意:如果你的系统不使用ASCII或其他以数字顺序编码的代码,可以把字符数组初始化为字母表中的字母:char lets[27] =“ABCDEFGHIJKLMNOPQRSTUVWXYZ”;402然后用数组下标选择单独的字母,例如lets[0]是‘A’,等等。

#include

int main(void)
{
	char ch = 'F';
	int i,j;
	
	for(i=0;i<6;i++)
	{
		int k= 0;
		for(j= 0;j<i+1;j++)
		{
			printf("%c",ch-k);
			k++;
		}
	
		printf("\n");
	}
	
	return 0;
}
    

4.使用嵌套循环,按下面的格式打印字母:

A
BC
DEF
GHIJ
KLMNO
PQRSTU

如果你的系统不使用以数字顺序编码的代码,请参照练习3的方案解决。

#include

int main(void)
{
	char ch = 'A';
	int i,j;
	int k= 0;
	for(i=0;i<6;i++)
	{
		
		for(j= 0;j<i+1;j++)
		{
			printf("%c",ch+k);
			k++;
		}
		
		printf("\n");
	}
	
	return 0;
}
    

5.编写一个程序,提示用户输入大写字母。使用嵌套循环以下面金字塔型的格式打印字母:

A
ABA
ABCBA
ABCDCBA
ABCDEDCBA

打印这样的图形,要根据用户输入的字母来决定。例如,上面的图形是在用户输入E后的打印结果。提示:用外层循环处理行,每行使用3个内层循环,分别处理空格、以升序打印字母、以降序打印字母。如果系统不使用ASCII或其他以数字顺序编码的代码,请参照练习3的解决方案。

#include

int main(void)
{
	int line, line_all, row_blank, row_plus, row_minus;
	char ch;

	printf("please input :\n");
	scanf("%c", &ch, 1);
	line_all = ch - 'A' + 1;
	for (line = 1; line <= line_all; line++)
	{
		for (row_blank = 0; row_blank < line_all - line; row_blank++)
			printf("%c", ' ');
		for (row_plus = 0; row_plus < line; row_plus++)
			printf("%c", 'A' + row_plus);
		for (row_minus = line - 2; row_minus >= 0; row_minus--)
			printf("%c", 'A' + row_minus);
		printf("\n");
	}

	while(1);
	return 0;
}

6.编写一个程序打印一个表格,每一行打印一个整数、该数的平方、该数的立方。要求用户输入表格的上下限。使用一个for循环。

#include
int main(void)
{
	int lower,upper,index;
	int square,cube;
	
	printf("Enter starting integer:");
	scanf("%d",&lower);
	printf("Enter ending integer:");
	scanf("%d",&upper);
	
	printf("%5s  %10s %15s\n","num","square","cube");
	for(index =lower;index <= upper;index++)
	{
		square = index * index;
		cube = index * square;
		printf("%5d %10d %15d\n",index,square,cube);
	}
	
	return 0;
}
  1. 编写一个程序把一个单词读入一个字符数组中,然后倒序打印这个单词。提示:strlen()函数(第4章介绍过)可用于计算数组最后一个字符的下标。
#include
#include

int main(void)
{
	char ch[30];
	scanf("%s",&ch);
	int len = strlen(ch);
	for(int i=0;i<len;i++)
	{
		printf("%c",ch[len-i-1]);	
	}	
	
	return 0;
}
  1. 编写一个程序,要求用户输入两个浮点数,并打印两数之差除以两数乘积的结果。在用户输入非数字之前,程序应循环处理用户输入的每对值。
#include
int main(void)
{
	double n,m;
	double res;
	
	while(scanf("%lf %lf",&n,&m)==2)
	{
		res = (n-m)/(n*m);
		printf("(%.3g - %.3g)/(%.3g * %.3g)=%.5g\n",n,m,n,m,res);
		printf("Enter next pair (non-numeric to quit):");
	}
	
	return 0;
}
  1. 修改练习8,使用一个函数返回计算的结果。
#include
float get(float,float);
int main(void)
{
	double n,m;
	double res;
	printf("input two float number:");
	scanf("%f%f",&n,&m);
	
	res = get(n,m);
	
	printf("(%.3g - %.3g)/(%.3g * %.3g)=%.5g\n",n,m,n,m,res);
	printf("Enter next pair (non-numeric to quit):");
	
	return 0;
}

float get(float n,float m)
{
	
	double res;
	res = (n-m)/(n*m);
	
	return res;

}
  1. 编写一个程序,要求用户输入一个上限整数和一个下限整数,计算从上限到下限范围内所有整数的平方和,并显示计算结果。然后程序继续提示用户输入上限和下限整数,并显示结果,直到用户输入的上限整数小于下限整数为止。程序的运行示例如下:
Enter lower and upper integer limits: 5 9
The sums of the squares from 25 to 81 is 255
Enter next set of limits: 3 25
The sums of the squares from 9 to 625 is 5520
Enter next set of limits: 5 5
Done
#include
int main(void)
{	
	int up,low,i;
	
	printf("Enter lower and upper integer limits:");
	
	while(1)
	{
		int sum = 0;
		scanf("%d%d",&low,&up);
		if(up>low)
		{
			for(i=low;i<=up;i++)
			{
				sum += i*i;
			}
			printf("The sums of the squares from %d to %d is %d\n",low,up,sum);
			
		}
		
		else
		{
			break;
		}
		printf("Enter next set of limits:\n");	
	}
	printf("Done!");
	return 0;
}

11.编写一个程序,在数组中读入8个整数,然后按倒序打印这8个整数。

#include
#define N 8
int main(void)
{
	int i,ch[8];
	printf("please input 8 numbers:");
	for(i=0;i<N;i++)
	{
		scanf("%d",&ch[i]);
	}
	for(i=N-1;i>=0;i--)
	{
		printf("%d\t",ch[i]);
	}
	
	return 0;
}

12
考虑下面两个无限序列:

1.0 + 1.0/2.0 + 1.0/3.0 + 1.0/4.0 + ...
1.0 - 1.0/2.0 + 1.0/3.0 - 1.0/4.0 + ...

编写一个程序计算这两个无限序列的总和,直到到达某次数。提示:奇数个-1 相乘得-1,偶数个-1相乘得1。让用户交互地输入指定的次数,当用户输入0或负值时结束输入。查看运行100项、1000项、10000项后的总和,是否发现每个序列都收敛于某值?

#include
int main(void)
{
	float f1,f2,f3,f4;
	int a;
	printf("输入项数(小于等于0退出):"); 
	while(scanf("%d",&a),a>0)
	{
	for(f1=0,f3=0,f2=1,f4=1;
		f2<=a;f2++,f4*=-1)
		{
			f1+=1.0/f2; 
			f3+=1/(f2*f4);
		}
		printf("f1=%f\nf3=%f\n\输入项数(小于等于0退出):",f1,f3);
	}
	return 0; 
}

  1. 编写一个程序,创建一个包含8个元素的int类型数组,分别把数组元素设置为2的前8次幂。使用for循环设置数组元素的值,使用do while循环显示数组元素的值。
#include
#define Size 8

int main(void)
{
	int twopows[Size];
	int i;
	int value = 1;
	for(i = 0;i<Size;i++)
	{
		twopows[i]=value;
		value *= 2;
	}
	i = 0;
	do
	{
		printf("%d\t",twopows[i]);
		i++;	
	}while(i<Size);
	printf("\n");
	
	return 0;
}

编写一个程序,创建两个包含8个元素的double类型数组,使用循环提示用户为第一个数组输入8 个值。第二个数组元素的值设置为第一个数组对应元素的累积之和。例如,第二个数组的第 4个元素的值是第一个数组前4个元素之和,第二个数组的第5个元素的值是第一个数组前5个元素之和(用嵌套循环可以完成,但是利用第二个数组的第5个元素是第二个数组的第4个元素与第一个数组的第5个元素之和,只用一个循环就能完成任务,不需要使用嵌套循环)。最后,使用循环显示两个数组的内容,第一个数组显示成一行,第二个数组显示在第一个数组的下一行,而且每个元素都与第一个数组各元素相对应。

#include
#define size 8

int main(void)
{
	double arr[size];
	double arr_cumul[size];
	int i;
	printf("Enter %d numbers:\n",size);
	
	for(i=0;i<size;i++)
	{
		printf("value #%d:",i+1);
		scanf("%lf",&arr[i]);
	}
	arr_cumul[0]=arr[0];
	for(i = 1;i <size;i++)
		arr_cumul[i]=arr_cumul[i-1]+arr[i];
	for(i=0;i<size;i++)
		printf("%8g",arr[i]);
	printf("\n");
	for(i=0;i<size;i++)
		printf("%8g",arr_cumul[i]);
	printf("\n");
		
			
	return 0;	
}

编写一个程序,读取一行输入,然后把输入的内容倒序打印出来。可以把输入储存在char类型的数组中,假设每行字符不超过255。回忆一下,根据%c转换说明,scanf()函数一次只能从输入中读取一个字符,而且在用户按下Enter键时scanf()函数会生成一个换行字符(\n)。

#include 
int main(void)
{
  char ch[255];
  int i = -1;

  printf("please input some chars\n");
  do 
  {
    i++;
    scanf("%c", &ch[i]);
  } while (ch[i] != '\n');
  for (; i >= 0; i--)
  {
    printf("%c", ch[i]);
  }
  return 0;
}

  1. Daphne以10%的单利息投资了100美元(也就是说,每年投资获利相当于原始投资的10%)。Deirdre以 5%的复合利息投资了 100 美元(也就是说,利息是当前余额的 5%,包含之前的利息)。编写一个程序,计算需要多少年Deirdre的投资额才会超过Daphne,并显示那时两人的投资额。
#include
#define RATE_SIMP 0.10
#define RATE_COMP 0.05
#define INIT_AMT  100.0

int main(void)
{
	double daphne = INIT_AMT;
	double deidre = INIT_AMT;
	int years = 0;
	while(deidre<= daphne)
	{
		daphne += RATE_SIMP * INIT_AMT;
		deidre += RATE_COMP * deidre;
		++years;
	}
	
	printf("Investment value after %d years:\n",years);
	printf("Dephne:$%.2f\n",daphne);
	printf("Deidre:$%.2f\n",deidre);
	
	
	return 0;
}

17
Chuckie Lucky赢得了100万美元(税后),他把奖金存入年利率8%的账户。在每年的最后一天, Chuckie取出10万美元。编写一个程序,计算多少年后Chuckie会取完账户的钱?

#include 
int main(void)
{
  double award = 100.0;
  int year = 0;
  
  do{
    year++;
    award = award * (1 + 0.08) - 10;
  }while (award > 0);
  printf("%d 年后Chuckie会取完账户的钱。\n", year);

  getchar();
  return 0;
}

18

Rabnud博士加入了一个社交圈。起初他有5个朋友。他注意到他的朋友数量以下面的方式增长。第1周少了1个朋友,剩下的朋友数量翻倍第2
周少了2个朋友,剩下的朋友数量翻倍。一般而言,第N周少了N个朋友,剩下的朋友数量翻倍。编写一个程序,计算并显示Rabnud博士每周的朋友数量。该程序一直运行,直到超过邓巴数(Dunbar’s number)。邓巴数是粗略估算一个人在社交圈中有稳定关系的成员的最大值,该值大约是150。

#include 
int main()
{
    int week = 0, friends = 5;
    do
    {
      week++;
      friends = 2 * (friends - week);
      printf("第%d周,Rabnud博士的朋友数量为:%d\n", week, friends);
    }while (friends <= 150);
    printf("Done!");
    return 0;
}

第七章 C 控制语句:分之合跳转

  1. 编写一个程序读取输入,读到#字符停止,然后报告读取的空格数、换行符数和所有其他字符的数量。
#include
int main(void)
{
	char ch;
	int sp_ct = 0;
	int nl_ct = 0;
	int other = 0;
	
	while((ch = getchar())!='#')
	{
		if(ch == ' ')
			sp_ct++;
		else if(ch=='\n')
			nl_ct++;
		else
			other++;
	}
	printf("spaces: %d, newlines: %d, others: %d\n", sp_ct, nl_ct, other);
	
	
	
	return 0;
}
  1. 编写一个程序读取输入,读到#字符停止。程序要打印每个输入的字符以及对应的ASCII码(十进制)。一行打印8个字符。建议:使用字符计数和求模运算符(%)在每8个循环周期时打印一个换行符。
#include 
#define CHARS_PER_LINE 8	
int main(void)
{
    char ch;
    int n_chars = 1;		

    printf("Enter some characters(# to quit):\n");
    while ((ch = getchar()) != '#')
    {
        printf("%3c(%3d) ", ch, ch);
        if (n_chars++ % CHARS_PER_LINE == 0)
            printf("\n");
    }
    printf("\n");

    return 0;
}



  1. 编写一个程序,读取整数直到用户输入 0。输入结束后,程序应报告用户输入的偶数(不包括 0)个数、这些偶数的平均值、输入的奇数个数及其奇数的平均值。
#include 
int main(void)
{
    int num;
    int n_even = 0, n_odd = 0;		//偶数和奇数个数
    int sum_even = 0, sum_odd = 0;	//偶数和奇数和

    printf("Enter some integers(0 to quit):\n");
    scanf("%d", &num);
    while (num != 0)
    {
        if (num % 2 == 0)
        {
            n_even++;
            sum_even += num;
        }							//计算偶数个数和偶数和
        else
        {
            n_odd++;
            sum_odd +=num;
        }							//计算奇数个数和奇数和
        scanf("%d",&num);
    }
    printf("The number of even numbers is %d, "
            "and the everage of even numbers is %.2f\n",
            n_even, (n_even == 0) ? 0 : (float)sum_even / n_even);
    printf("The number of odd numbers is %d, "
            "and the everrage of odd numers is %.2f\n",
            n_odd, (n_odd == 0) ? 0 : (float)sum_odd / n_odd);

    return 0;
}
  1. 使用if else语句编写一个程序读取输入,读到#停止。用感叹号替换句号,用两个感叹号替换原来的感叹号,最后报告进行了多少次替换。
#include 
int main(void)
{
    char ch;
    int n_repl = 0;         //替换次数
    
    printf("Enter some texts(# to quit):\n");
    while ((ch = getchar()) != '#') {
        if (ch == '.')
        {
            ch = '!';
            n_repl++;
        }					//替换句号
        else if (ch == '!')
        {
            printf("!");
            n_repl++;
        }					//替换感叹号
        printf("%c", ch);
    }
    printf("\n%d substitutions were made.\n", n_repl);
    
    return 0;
}
  1. 使用switch重写练习4。
#include
int main(void)
{
	char ch;
	int n_repl = 0;
	
	printf("Enter some text(# to quit):\n");
	while((ch = getchar())!='#')
	{
		switch(ch)
		{
			case'.':
				ch = '!';
				n_repl++;
				break;
			case'!':
				printf("!");
				n_repl++;
				break;
			default:
				break;
		}
		printf("%c",ch);
	}
	printf("\n%d substitutions were made.\n",n_repl);
	
	return 0;
}
  1. 编写程序读取输入,读到#停止,报告ei出现的次数。
注意:
该程序要记录前一个字符和当前字符。用“Receive  your  eieio  award”这样的输入来测试。
#include 
int main(void)
{
    char ch;
    char last_ch = 0;		 
    int count=0;

    printf("Enter some texts(# to quit):\n");
    while ((ch = getchar()) != '#')
    {
        if ((ch == 'i') && (last_ch == 'e'))
            count++;
        last_ch = ch;		
    }
    printf("\"ei\" appeared %d times.\n", count);
    
    return 0;
}


  1. 编写一个程序,提示用户输入一周工作的小时数,然后打印工资总额、税金和净收入。做如下假设:
a.基本工资 = 1000美元/小时
b.加班(超过40小时) = 1.5倍的时间
c.税率: 前300美元为15%
		续150美元为20%
		余下的为25%

用#define定义符号常量。不用在意是否符合当前的税法。

#include 
#define BASE 1000		//基本工资 100美元/h
#define TIME 40			//超过40h为加班
#define	MUL	1.5			//加班时间算作平时的1.5倍
#define	RATE1 0.15		//前300美元的税率
#define RATE2 0.2		//300-450美元的税率
#define RATE3 0.25		//大于450美元的税率
#define BREAK1 300		//税率的第一个分界点
#define BREAK2 450		//税率的第二个分界点
int main(void)
{
    double hour, tax, gross;
    
    printf("Input your work hours in a week: ");
    scanf("%lf", &hour);
    if (hour <= TIME)
        gross = hour * BASE;
    else
        gross = TIME * BASE + (hour - TIME) * MUL * BASE;
    //计算总收入
    if (gross <= BREAK1)
        tax = gross * RATE1;
    else if (gross <= BREAK2)
        tax = BREAK1 * RATE1 + (gross - BREAK1) * RATE2;
    else
        tax = BREAK1 * RATE1 + (BREAK2 - BREAK1) * RATE2
            + (gross - BREAK2) * RATE3;
    //计算税金
    printf("Your gross income is $%.2lf\nYour tax is $%.2lf\n"
            "Your net income is $%.2lf\n",
            gross, tax, (gross - tax));
    
    return 0;
}


  1. 修改练习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创建符号常量表示各工资等级和税率。

#include 
#define BASE1 8.75
#define BASE2 9.33
#define BASE3 10.00
#define BASE4 11.20
//四种等级的基本工资
#define TIME 40			//超过40h为加班
#define	MUL	1.5			//加班时间算作平时的1.5倍
#define	RATE1 0.15		//前300美元的税率
#define RATE2 0.2		//300-450美元的税率
#define RATE3 0.25		//大于450美元的税率
#define BREAK1 300		//税率的第一个分界点
#define BREAK2 450		//税率的第二个分界点
int main(void)
{
    double base, hour, tax, gross;
    int count, num;
    const int LENGTH = 65;	//*的长度
    
    printpart: for (count = 0; count < LENGTH; count++)
                    printf("*");
    printf("\nEnter the number corresponding to the desired pay rate or action:\n");
    printf("%-36s%s","1) $8.75/hr", "2) $9.33/hr\n");
    printf("%-36s%s","3) $10.00/hr", "4) $11.20/hr\n");
    printf("%s\n", "5) quit");
    for (count = 0; count < LENGTH; count++)
        printf("*");
    printf("\n");
    //打印表格
    while (scanf("%d", &num) == 1) {
    switch (num)
    {
        case 1:	base = BASE1;
                break;
        case 2: base = BASE2;
                break;
        case 3: base = BASE3;
                break;
        case 4: base = BASE4;
                break;
        case 5: printf("quit.\n");
                return 0;
        default: printf("Please input the right option.\n");
                goto printpart;
    }	//选择基本工资等级

    printf("Input your work hours in a week: ");
    scanf("%lf", &hour);
    if (hour <= TIME)
        gross = hour * base;
    else
        gross = TIME * base + (hour - TIME) * MUL * base;
    //计算总收入
    if (gross <= BREAK1)
        tax = gross * RATE1;
    else if (gross <= BREAK2)
        tax = BREAK1 * RATE1 + (gross - BREAK1) * RATE2;
    else
        tax = BREAK1 * RATE1 + (BREAK2 - BREAK1) * RATE2
            + (gross - BREAK2) * RATE3;
    //计算税金
    printf("Your gross income is $%.2lf\nYour tax is $%.2lf\n"
            "Your net income is $%.2lf\n",
            gross, tax, (gross - tax));
    printf("\nYour next choice:\n");
    }
    return 0;
}

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

#include  
#include  
int main(void) 
{ 
	 int limit; 
    int num; 
    int div; 
    bool numIsPrime;  // use int if stdbool.h not available 
     
    printf("Enter a positive integer: "); 
    while (scanf("%d", &limit) == 1 && limit > 0) 
    { 
        if (limit > 1) 
            printf("Here are the prime numbers up through %d\n", limit); 
        else 
            printf("No primes.\n"); 
        for (num = 2; num <= limit; num++) 
        {  
              for (div = 2, numIsPrime = true; (div * div) <= num; div++) 
                 if (num % div == 0) 
                          numIsPrime = false; 
              if (numIsPrime) 
                 printf("%d is prime.\n", num); 
        } 
        printf("Enter a positive integer (q to quit): "); 
    } 
    printf("Done!\n"); 
                 
    return 0; 
 }
  1. 1988年的美国联邦税收计划是近代最简单的税收方案。它分为4个类别,每个类别有两个等级。
    下面是该税收计划的摘要(美元数为应征税的收入):
    C primer plus编程练习答案(上)_第2张图片
    例如,一位工资为20000美元的单身纳税人,应缴纳税费0.15×17850+0.28×(20000−17850)美元。编写一个程序,让用户指定缴纳税金的种类和应纳税收入,然后计算税金。程序应通过循环让用户可以多次输入。
#include 
#define RATE1 0.15
#define RATE2 0.28
#define SINGLE 17850	//单身人群的税率分界点
#define HOST 23900		//户主人群的税率分界点
#define MAR_SHA	29750	//已婚共有人群的分界点
#define MAR_DEV	14875	//已婚离异人群的分界点
int main(void)
{
    int num;
    double income, tax_break, tax;

    printpart: printf("Please enter Corresponding"
                    "figures to select the type\n");
    printf("1 single, 2 host, 3 married and shared, "
            "4 married but devoced and 5 to quit.\n");
    scanf("%d", &num);
    switch (num)
    {
        case 1: tax_break = SINGLE;
                break;
        case 2: tax_break = HOST;
                break;
        case 3: tax_break = MAR_SHA;
                break;
        case 4: tax_break = MAR_DEV;
                break;
        case 5:	printf("quit.\n");
                return 0;
        default: printf("Please input right number.");
                 goto printpart;		//回到输入阶段
    }
    printf("Enter your income: ");		//指定种类和收入
    while (scanf("%lf", &income) == 1)
    {
        if (income <= tax_break)
            tax = income * RATE1;
        else
            tax = tax_break * RATE1 + (income - tax_break) * RATE2;
        //计算税金
        printf("The tax is $%.2lf.\n", tax);
        printf("Your next input: \n");
        goto printpart;					//回到输入阶段
    }

    return 0;
}
 
  1. 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磅的甜菜。然后,该程序要计算货物总价、折扣(如果有的话)、运费和包装费。随后,程序应显示所有的购买信息:物品售价、订购的重量(单位:磅)、订购的蔬菜费用、订单的总费用、折扣(如果有的话)、运费和包装费,以及所有的费用总额。
#include 
#include 
#define ARTICHOKE 2.05		//洋蓟2.05美元/磅
#define BEET 1.15			//甜菜1.15美元/磅
#define CARROT 1.09			//胡萝卜1.09美元/磅
#define	DISCOUNT_LIMIT 100
//包装费和运费打折要求订单100美元
#define DISCOUNT_RATE 0.05	//折扣为%5
#define BREAK1 5
#define BREAK2 20			//装运费的分界点
#define	FEE1 6.5
#define	FEE2 14
#define FEE3_RATE 0.5
//不同重量区间的装运费,其中超过20磅的每续重一磅
//增加0.5元
int main(void)
{
    double weight;
    double weight_artichoke = 0;
    double weight_beet = 0;
    double weight_carrot = 0;	//购买三种蔬菜的重量
    double total_weight;	//总重量
    double veg_cost;		//三种蔬菜总共花费
    double order_cost;		//订单总额
    double total_cost;		//费用总额
    double pack_tran_fee;	//装运费
    double discount;
    int count = 0;
    char ch;

    printf("Please select the vegetables you want to buy:\n");
    printf("a: artichoke  $%.2f/lb\n", ARTICHOKE);
    printf("b: beet       $%.2f/lb\n", BEET);
    printf("c: carrot     $%.2f/lb\n", CARROT);
    printf("q: quit.\n");
    //打印选择信息
    while ((ch = tolower(getchar())) != 'q')
    {
    //	if (ch == '\n')
    //		continue;					//滤掉回车
        switch (ch)
        {
            case 'a': printf("Input the weight of artichoke in pound: ");
                      scanf("%lf", &weight);
                      weight_artichoke += weight;
                      count++;
                      printf("Continue entering a, b, c or q: ");
                      break;
            case 'b': printf("Input the weight of beet in pound: ");
                      scanf("%lf", &weight);
                      weight_beet += weight;
                      count++;
                      printf("Continue entering a, b, c or q: ");
                      break;
            case 'c': printf("Input the weight of carrot in pound: ");
                      scanf("%lf", &weight);
                      weight_carrot += weight;
                      count++;
                      printf("Continue entering a, b, c or q: ");
                      break;
            default: printf("Please enter the right character.");
        }
        while (getchar () != '\n')
            continue;					//滤掉输入重量后面的所有字符
        
    }
    if (!count)
    {
        printf("Bye.\n");
        return 0;
    }										//开始输出q,直接退出
    total_weight = weight_artichoke + weight_beet + weight_carrot;
    veg_cost = weight_artichoke * ARTICHOKE + weight_beet * BEET
                + weight_carrot * CARROT;
    discount = 0;
    if (veg_cost >= DISCOUNT_LIMIT)
    {
        discount = veg_cost * DISCOUNT_RATE;
        order_cost = veg_cost - discount;
    }
    else
        order_cost = veg_cost;				//折扣计算
    
    if (total_weight <= BREAK1)
        pack_tran_fee = FEE1;
    else if (total_weight <= BREAK2)
        pack_tran_fee = FEE2;
    else
        pack_tran_fee = FEE2 + (total_weight - BREAK2) * FEE3_RATE;
    //装运费计算
    total_cost = order_cost + pack_tran_fee;
    
    printf("\nHere is what you choose:\n");
    if (weight_artichoke) {
        printf("artichoke   Price: $%.2f/lb  weight: %.2f pounds  cost: $%.2f\n",
                ARTICHOKE, weight_artichoke, weight_artichoke * ARTICHOKE);
    }
    if (weight_beet) {
        printf("beet        Price: $%.2f/lb  weight: %.2f pounds  cost: $%.2f\n",
                BEET, weight_beet, weight_beet * BEET);
    }
    if (weight_carrot) {
        printf("carrot      Price: $%.2f/lb  weight: %.2f pounds  cost: $%.2f\n",
                CARROT, weight_carrot, weight_carrot * CARROT);
    }
    printf("The order cost: $%.2f\n", veg_cost);

    if (discount)
        printf ("You have %%%.f discount, and the reduced money is $%.2f\n",
                DISCOUNT_RATE * 100, discount);
    printf("The packing and transpoting fee is $%.2f\n", pack_tran_fee);
    printf("The total cost is $%.2f\n", total_cost);
    //输出订单信息

    return 0;
}
    

第八章 字符输入/输出和输入验证

设计一个程序,统计在读到文件结尾之前读取的字符数。

#include
int main(void)
{
	int ch;
	int count = 0;
	
	while((ch=getchar())!= EOF)
		count++;
	printf("The number of characters is %d\n",count);
	return 0;
}

**编写一个程序,在遇到 EOF 之前,把输入作为字符流读取。程序要打印每个输入的字符及其相应的ASCII十进制值。注意,在ASCII序列中,空格字符前面的字符都是非打印字符,要特殊处理这些字符。如果非打印字符是换行符或制表符,则分别打印\n或\t。否则,使用控制字符表示法。例如,ASCII的1是Ctrl+A,可显示为^A。注意,A的ASCII值是Ctrl+A的值加上64。其他非打印字符也有类似的关系。除每次遇到换行符打印新的一行之外,每行打印10对值。(注意:不同的操作系统其控制字符可能不同。)
**

#include 
#define SPACE 32
#define CTRL 64
#define COL 10				//每行打印10对
int main(void)
{
    char ch;
    int count = 0;

    while ((ch = getchar()) != EOF)
    {
        count++;
    //打印字符输出
        if (ch >= SPACE)
            printf("%c ", ch);
    //换行符和制表符的输出
        else if (ch == '\n' || ch == '\t')
            printf("%s", ch == '\n' ? "\\n" : "\\t");
    //一般控制字符的输出
        else
            printf("^%c", ch + CTRL);
        printf("%-5d", ch);
        if (ch == '\n')
            count = 0;
        if (count % COL == 0)	//10对换行
            printf("\n");
    }

    return 0;
}

编写一个程序,在遇到 EOF 之前,把输入作为字符流读取。该程序要报告输入中的大写字母和小写字母的个数。假设大小写字母数值是连续的。或者使用ctype.h库中合适的分类函数更方便。

#include 
#include 
int main(void)
{
    int lower = 0, upper = 0;
    char ch;

    printf("Input some texts:\n");
    while ((ch = getchar()) != EOF)
    {
        if (islower(ch))
            lower++;
        if (isupper(ch))
            upper++;
    }
    printf("lower:%d, upper:%d\n", lower, upper);

    return 0;
}

编写一个程序,在遇到EOF之前,把输入作为字符流读取。该程序要报告平均每个单词的字母数。不要把空白统计为单词的字母。实际上,标点符号也不应该统计,但是现在暂时不同考虑这么多(如果你比较在意这点,考虑使用ctype.h系列中的ispunct()函数)。

#include 
#include 
int main(void)
{
    char ch;
    int inword = 0;			//在单词中为1否则为0
    int words = 0;			//单词数
    int chars = 0;			//字符数

    printf("Please enter some words:\n");
    while ((ch = getchar()) != EOF)
    {
        if (!isspace(ch) && !ispunct(ch))
            chars++;
    //开始一个新的单词
        if (!isspace(ch) && !ispunct(ch) && !inword)
        {
            inword = 1;
            words++;
        }
    //单词末尾
        if (isspace(ch) || ispunct(ch) && inword)
            inword = 0;
    }
        printf("There are %d words and %d letters\n",
                words, chars);
        printf("The average number of letters of ");
        printf("each word is %.2f.\n",
                ((double)chars / (double)words));

        return 0;
    }




  1. 修改程序清单8.4的猜数字程序,使用更智能的猜测策略。例如,程序最初猜50,询问用户是猜大了、猜小了还是猜对了。如果猜小了,那么下一次猜测的值应是50和100中值,也就是75。如果这次猜大了,那么下一次猜测的值应是50和75的中值,等等。使用二分查找(binary search)策略,如果用户没有欺骗程序,那么程序很快就会猜到正确的答案。
#include 
#define LOW 1			//初始下限
#define HIGH 100		//初始上限
int get_guess(void);
int main(void)
{
    char response;
    int guess;
    int low = LOW;
    int high = HIGH;

    guess = (low + high) / 2;
    printf("Pick an integer from %d to %d. I will try to guess ",
            LOW, HIGH);
    printf("it.\nRespond with a y if my guess is right, with an s if it\n");
    printf("is small and with a b if it is big.\n");
    printf("Uh...is your number %d?\n", guess);
    while ((response = getchar()) != 'y')
    {
        if (response == 's')
        {
            low = guess;
            guess = (guess + high) / 2;
        }
        else if (response == 'b')
        {
            high = guess;
            guess = (guess + low) / 2;
        }
        else
            printf("Sorry, I understand only y, s and b.\n");
        
        printf("Well, then, is it %d?\n", guess);
        //跳过剩余输入行
        while (getchar() != '\n')
            continue;
        //使取值能到达上限
        if (guess == HIGH - 1)
            guess++;
    }
    printf("I knew i could do it!\n");
    
    return 0;
}

修改程序清单8.8中的get_first()函数,让该函数返回读取的第1个非空白字符,并在一个简单的程序中测试。

#include 
#include 
char get_first(void);
int main(void)
{
    char ch;
    while ((ch = get_first()) != EOF)
    {
        putchar(ch);
        printf("\n");
    }
    return 0;
}

char get_first(void)
{
    char ch;
    while (isspace(ch = getchar()))
        continue;
    while (getchar() != '\n')
        continue;

    return ch;
}


  1. 修改第7章的编程练习8,用字符代替数字标记菜单的选项。用q代替5作为结束输入的标记。
#include 
#define BASE1 8.75
#define BASE2 9.33
#define BASE3 10.00
#define BASE4 11.20
//四种等级的基本工资
#define TIME 40			//超过40h为加班
#define	MUL	1.5		//加班时间算作平时的1.5倍
#define	RATE1 0.15		//前300美元的税率
#define RATE2 0.2			//300-450美元的税率
#define RATE3 0.25		//大于450美元的税率
#define BREAK1 300		//税率的第一个分界点
#define BREAK2 450		//税率的第二个分界点
#define LENGTH 65		//长度

char get_choice(void);
void calculate(double base);
int main(void)
{
    double base;
    char choice;
    
    while ((choice = get_choice()) != 'q')
    {
        switch (choice)
        {
            case 'a': base = BASE1;
                      break;
            case 'b': base = BASE2;
                      break;
            case 'c': base = BASE3;
                      break;
            case 'd': base = BASE4;
                      break;
            default: printf("Please respond with a, b, c, d or q.\n");
                     break;
        }
        if (choice >= 'a' && choice <= 'd')
            calculate(base);
    }

    return 0;
}
    
//计算和输出结果的函数
void calculate(double base)
{
    double hour, gross, tax;

    printf("Input your work hours in a week: ");
    scanf("%lf", &hour);
    while (getchar() != '\n')
        continue;					//跳过回车
    if (hour <= TIME)
        gross = hour * base;
    else
        gross = TIME * base + (hour - TIME) * MUL * base;
    //计算总收入
    if (gross <= BREAK1)
        tax = gross * RATE1;
    else if (gross <= BREAK2)
        tax = BREAK1 * RATE1 + (gross - BREAK1) * RATE2;
    else
        tax = BREAK1 * RATE1 + (BREAK2 - BREAK1) * RATE2
            + (gross - BREAK2) * RATE3;
    //计算税金
    printf("Your gross income is $%.2lf\nYour tax is $%.2lf\n"
            "Your net income is $%.2lf\n",
            gross, tax, (gross - tax));
    printf("\n");
}

//打印选择界面并让用户输入的函数
char get_choice(void)
{
    char ch;
    int count;

    for (count = 0; count < LENGTH; count++)
        printf("*");
    printf("\nEnter the letter corresponding to the desired pay rate or action:\n");
    printf("%-36s%s","a) $8.75/hr", "b) $9.33/hr\n");
    printf("%-36s%s","c) $10.00/hr", "d) $11.20/hr\n");
    printf("%s\n", "q) quit");
    for (count = 0; count < LENGTH; count++)
        printf("*");
    printf("\n");

    ch = getchar();
    while (getchar() != '\n')
        continue;					//跳过输出行剩余内容

    return ch;
}

编写一个程序,显示一个提供加法、减法、乘法、除法的菜单。获得用户选择的选项后,程序提示用户输入两个数字,然后执行用户刚才选择的操作。该程序只接受菜单提供的选项。程序使用float类型的变量储存用户输入的数字,如果用户输入失败,则允许再次输入。进行除法运算时,如果用户输入0作为第2个数(除数),程序应提示用户重新输入一个新值。该程序的一个运行示例如下:

Enter the operation of your choice:
a. add        s. subtract
m. multiply     d. divide
q. quit
a
Enter first number: 22 .4
Enter second number: one
one is not an number.
Please enter a number, such as 2.5, -1.78E8, or 3: 1
22.4 + 1 = 23.4
Enter the operation of your choice:
a. add        s. subtract
m. multiply     d. divide
559q. quit
d
Enter first number: 18.4
Enter second number: 0
Enter a number other than 0: 0.2
18.4 / 0.2 = 92
Enter the operation of your choice:
a. add        s. subtract
m. multiply     d. divide
q. quit
q
Bye.
#include 
float get_float(void);
char get_choice(void);
char get_first(void);
int main(void)
{
    char choice;
    float num1, num2;
    
    while ((choice = get_choice()) != 'q')
    {
        printf("Enter first number: ");
        num1 = get_float();
        printf("Enter second number: ");
        num2 = get_float();
        
        switch (choice)
        {
            case 'a': printf("%.2f + %.2f = %.2f\n",
                        num1, num2, num1 + num2);
                      break;
            case 's': printf(".2%f - %.2f = %.2f\n",
                        num1, num2, num1 - num2);
                      break;
            case 'm': printf("%.2f * %.2f = %.2f\n",
                        num1, num2, num1 * num2);
                      break;
            case 'd':
                      if (!num2)
                      {
                          printf("Enter a number other than 0: ");
                          num2 = get_float();
                      }
                      printf("%.2f / %.2f = %.2f\n",
                      num1, num2, num1 / num2);
                      break;
            default:  printf("Program error!\n");
                      break;
        }
    }
    printf("Bye.\n");

    return 0;
}

//打印界面和让用户选择的函数
char get_choice(void)
{
    char ch;
    printf("Enter the operation of your choice:\n");
    printf("%-36s%s\n", "a. add", "s. subtract");
    printf("%-36s%s\n", "m. multiply", "d. divide");
    printf("q. quit\n");
    ch = get_first();
    while (ch != 'a' && ch != 's' && ch != 'm' && ch != 'd'
            && ch != 'q')
    {
        printf("Please enter a, s, m, d or q.\n");
        ch = get_first();
    }

    return ch;
}

//获得输入值并处理错误输入的函数
float get_float(void)
{
    float input;
    char ch;
    
    while (scanf("%f", &input) != 1)
    {
        while ((ch = getchar()) != '\n')
            putchar(ch);
        printf(" is not an number.\n");
        printf("Please enter a number, such as 2.5, -1.78E8, or 3: ");
    }
    while (getchar() != '\n')
        continue;

    return input;
}

//读取输入行的第一个字符
char get_first(void)
{
    char ch;

    ch = getchar();
    while (getchar() != '\n')
        continue;

    return ch;
}

第九章 函数

  1. 设计一个函数min(x, y),返回两个double类型值的较小值。在一个简单的驱动程序中测试该函数。
#include 
double min(double x, double y);
int main(void)
{
    double num1, num2;

    printf("Enter two numbers: ");
    scanf("%lf%lf", &num1, &num2);
    printf("The smaller one is: %f\n", min(num1, num2));

    return 0;
}

double min(double n1, double n2)
{
    return (n1 < n2 ? n1 : n2);
}
  1. .设计一个函数chline(ch, i, j),打印指定的字符j行i列。在一个简单的驱动程序中测试该函数。
a.donut()接受一个int类型的参数,打印若干(参数指定数目)个0
b.gear()接受两个int类型的参数,返回int类型的值
c.guess()不接受参数,返回一个int类型的值
d.stuff_it()接受一个double类型的值和double类型变量的地址,把第1个
值储存在指定位置
#include 
void chline(char ch, int i, int j);
int main(void)
{
    int row, col;
    char ch;
    printf("Input a character you want to print: ");
    ch = getchar();
    printf("Input the number of rows and columns: ");
    scanf("%d%d", &row, &col);
    chline(ch, row, col);

    return 0;
}

void chline(char ch, int i , int j)
{
    int row, col;
    for (row = 1; row <= i; row++)
    {
        for(col = 1; col <=j; col++)
            putchar(ch);
        putchar('\n');
    }

    return;
}
  1. 编写一个函数,接受3个参数:一个字符和两个整数。字符参数是待打印的字符,第1个整数指定一行中打印字符的次数,第2个整数指定打印指定字符的行数。编写一个调用该函数的程序。
#include 
void chline(char ch, int i, int j);
int main(void)
{
    int row, col;
    char ch;
    printf("Input a character you want to print: ");
    ch = getchar();
    printf("Input the number of rows and columns: ");
    scanf("%d%d", &row, &col);
    chline(ch, row, col);

    return 0;
}

void chline(char ch, int i , int j)
{
    int row, col;
    for (row = 1; row <= i; row++)
    {
        for(col = 1; col <=j; col++)
            putchar(ch);
        putchar('\n');
    }

    return;
}
  1. 两数的调和平均数这样计算:先得到两数的倒数,然后计算两个倒数的平均值,最后取计算结果的倒数。编写一个函数,接受两个double类型的参数,返回这两个参数的调和平均数。
#include 
double har_mean(double num1, double num2);
int main(void)
{
    double num1, num2;
    printf("Enter two numbers: ");
    scanf("%lf%lf", &num1, &num2);
    printf("The harmonic mean is: %f\n", har_mean(num1, num2));
}

double har_mean(double num1, double num2)
{
    return 1 / (1 / num1 + 1 / num2);
}

编写并测试一个函数larger_of(),该函数把两个double类型变量的值替换为较大的值。例如, larger_of(x, y)会把x和y中较大的值重新赋给两个变量。

#include 
void larger_of(double * x, double * y);
int main(void)
{
    double num1, num2;

    printf("Input two numbers: ");
    scanf("%lf%lf", &num1, &num2);
    printf("Originally, num1 = %f, num2 = %f\n",
            num1, num2);
    larger_of(&num1, &num2);
    printf("Now, num1 = %f, num2 = %f\n", num1, num2);

    return 0;
}

void larger_of(double * x, double * y)
{
    *x > *y ? (*y = *x) : (*x = *y);
}


  1. 编写并测试一个函数,该函数以3个double变量的地址作为参数,把最小值放入第1个函数,中间值放入第2个变量,最大值放入第3个变量。
#include 
void sort(double * x, double * y, double * z);
int main(void)
{
    double num1, num2 ,num3;

    printf("Enter 3 numbers: ");
    scanf("%lf%lf%lf", &num1, &num2, &num3);
    printf("Originally\nnum1 = %.2f, num2 = %.2f, num3 = %.2f\n",
            num1, num2, num3);
    sort(&num1, &num2, &num3);
    printf("Now\nnum1 = %.2f, num2 = %.2f, num3 = %.2f\n",
            num1, num2, num3);

    return 0;
}

void sort(double * x, double * y, double * z)
{
    double temp;
    if (*y < *x)
    {
        temp = *y;
        *y = *x;
        *x = temp;
    }
    if (*z < *x)
    {
        temp = *z;
        *z = *x;
        *x = temp;
    }
    if (*z < *y)
    {
        temp = *z;
        *z = *y;
        *y = temp;
    }
}

        
  1. 下编写一个函数,从标准输入中读取字符,直到遇到文件结尾。程序要报告每个字符是否是字母。如果是,还要报告该字母在字母表中的数值位置。例如,c和C在字母表中的位置都是3。合并一个函数,以一个字符作为参数,如果该字符是一个字母则返回一个数值位置,否则返回-1。
void salami(num)
{
int num, count;
for (count = 1; count <= num; num++)
printf(" O salami mio!\n");
}
#include 
#include 
int get_ch(char ch);
int main(void)
{
    char ch;

    printf("Input some texts:\n");
    while ((ch = getchar()) != EOF)
        printf("%d ", get_ch(ch));
    return 0;
}

int get_ch(char ch)
{
    if (isalpha(ch))
        return tolower(ch) - 'a' +1;
    else
        return -1;
}
    

    
        
  1. 第6章的程序清单6.20中,power()函数返回一个double类型数的正整数次幂。改进该函数,使其能正确计算负幂。另外,函数要处理0的任何次幂都为0,任何数的0次幂都为1(函数应报告0的0次幂未定义,因此把该值处理为1)。要使用一个循环,并在程序中测试该函数。
#include 
double power(double n, int p);
int main(void)
{
    double x, xpow;
    int exp;

    printf("Enter a number and the interger power (q to quit):\n");
    while (scanf("%lf%d", &x, &exp) == 2)
    {
        xpow = power(x, exp);
        printf("%.3g to the power %d is %g\n", x, exp, xpow);
        printf("Enter the next pair of numbers or q to quit.\n");
    }
    printf("Bye.\n");
}

double power(double n, int p)
{
    int count;
    double pow = 1;
    
    if (p == 0)
        if (n == 0)
        {
            pow = 1;
            printf("It is not defined, so the value is treated as 1\n");
        }
        else
            pow = 1;
    
    else if (p > 0)
        for (count = 0; count < p; count++)
            pow *= n;
    
    else
        if (n != 0)
            for (count = 0; count > p; count--)
                pow /= n;
        else
            pow = 0;

        return pow;
}
  1. 使用递归函数重写编程练习8。
#include 
double power(double n, int p);
int main(void)
{
    double x, xpow;
    int exp;

    printf("Enter a number and the interger power (q to quit):\n");
    while (scanf("%lf%d", &x, &exp) == 2)
    {
        xpow = power(x, exp);
        printf("%.3g to the power %d is %g\n", x, exp, xpow);
        printf("Enter the next pair of numbers or q to quit.\n");
    }
    printf("Bye.\n");
}

double power(double n, int p)
{
    int count;
    double pow;

    if (p > 0)
        pow = n * power(n, p - 1);
    else if (p < 0)
        if (n != 0)
            pow = (1.0 / n) * power(n, p + 1);
        else
            pow = 0;
    else
        pow = 1;

    return pow;
}
  1. 为了让程序清单9.8中的to_binary()函数更通用,编写一to_base_n()函数接受两个在2~10范围内的参数,然后以第2个参数中指定的进制打印第1个参数的数值。例如,to_base_n(129, 8)显示的结果为201,也就是129的八进制数。在一个完整的程序中测试该函数。
#include 
void to_base_n(unsigned long n, unsigned int base);
int main(void)
{
    unsigned long num;
    unsigned int base;

    printf("Enter an integer and the base from 2 to 10 (q to quit): ");
    while (scanf("%lu%u", &num, &base) == 2)
    {
        printf("Equivalent number on the base of %u: ", base);
        to_base_n(num, base);
        printf("\nEnter your next pair of numbers(q to quit): ");
    }
    printf("Done.\n");

    return 0;
}

void to_base_n(unsigned long n, unsigned int base)
{
    int r;

    r = n % base;
    if (n >= base)
        to_base_n(n / base, base);
    printf("%d", r);
}




编写并测试Fibonacci()函数,该函数用循环代替递归计算斐波那契数。

#include 
unsigned long Fibonacci(unsigned n);
int main(void)
{
    unsigned int num;
    int count;

    printf("Input the number of the items (q to quit): ");
    while (scanf("%u", &num) == 1)
    {
        for (count = 1; count <= num; count++)
            printf("%lu ", Fibonacci(count));
        printf("\nYour next input(q to quit): ");
    }
    printf("Bye.\n");

    return 0;
}

unsigned long Fibonacci(unsigned n)
{
    int count, temp;
    int n1 = 1, n2 = 1;

    if (n > 2)
        for (count = 3; count <= n; count++)
        {
            temp = n1 + n2;
            n1 = n2;
            n2 = temp;
        }
    else
        n2 = 1;

    return n2;
}
        

第十章 数组和指针

修改程序清单10.7的rain.c程序,用指针进行计算(仍然要声明并初始化数组)。

#include
#define months 12
#define years 5

int main(void)
{
	const float rain[years][months]=
	{
		{4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
        {8.5,8.2,1.2,1.6,2.4,0.0,5.2,0.9,0.3,0.9,1.4,7.3},
        {9.1,8.5,6.7,4.3,2.1,0.8,0.2,0.2,1.1,2.3,6.1,8.4},
        {7.2,9.9,8.4,3.3,1.2,0.8,0.4,0.0,0.6,1.7,4.3,6.2},
        {7.6,5.6,3.8,2.8,3.8,0.2,0.0,0.0,0.0,1.3,2.6,5.2}	
	};
	
	   int year, month;
    float subtot, total;

    printf(" YEAR	    RAINFALL (inches)\n");
    for (year = 0, total = 0; year < years; year++)
    {	//每一年,个月降水量总和
        for (month = 0, subtot = 0; month < months; month++)
            subtot += *(*(rain + year) + month);
        printf("%5d %15.1f\n", 2010 + year, subtot);
        total += subtot;	//5年的总降水量
    }
    printf("\n The yearly average is %.1f inches.\n\n", total / years);
    printf(" MONTHLY AVERAGES:\n\n");
    printf(" Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct ");
    printf(" Nov  Dec\n");

    for (month = 0; month < months; month++)
    {
        for (year = 0, subtot = 0; year < years; year++)
            subtot += *(*(rain + year) +month);
        printf("%4.1f ", subtot / years);
    }
    printf("\n");

    return 0;
}

编写一个程序,初始化一个double类型的数组,然后把该数组的内容拷贝至3个其他数组中(在main()中声明这4个数组)。使用带数组表示法的函数进行第1份拷贝。使用带指针表示法和指针递增的函数进行第2份拷贝。把目标数组名、源数组名和待拷贝的元素个数作为前两个函数的参数。第3个函数以目标数组名、源数组名和指向源数组最后一个元素后面的元素的指针。也就是说,给定以下声明,则函数调用如下所示:

double source[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
double target1[5];
double target2[5];
double target3[5];
copy_arr(target1, source, 5);
copy_ptr(target2, source, 5);
copy_ptrs(target3, source, source + 5);
#include 
#define SIZE 5
void copy_arr(double ar1[], double ar[], int n);
void copy_ptr(double * ar2, double * ar, int n);
void copy_ptrs(double * ar3, double * ar, double * end);
void print_array(double ar[], int n);				//打印数组的函数

int main(void)
{
    double source[SIZE] = {1.1, 2.2, 3.3, 4.4, 5.5};
    double target1[SIZE];
    double target2[SIZE];
    double target3[SIZE];

    copy_arr(target1, source, SIZE);
    copy_ptr(target2, source, SIZE);
    copy_ptrs(target3, source, source + SIZE);
    print_array(target1, SIZE);
    print_array(target2, SIZE);
    print_array(target3, SIZE);

    return 0;
}

void copy_arr(double ar1[], double ar[], int n)
{
    int index;
    for (index = 0; index < n; index++)
        ar1[index] = ar[index];
}

void copy_ptr(double * ar2, double * ar, int n)
{
    int i;
    for (i = 0; i < n; i++)
        *(ar2++) = *(ar++);
}

void copy_ptrs(double * ar3, double * ar, double * end)
{
    int i;
    for (i = 0; ar < end; i++)
        *(ar3++) = *(ar++);
}

void print_array(double ar[], int n)
{
    int index;
    for (index = 0; index < n; index++)
        printf("%g ", ar[index]);
    printf("\n");
}

3.编写一个函数,返回储存在int类型数组中的最大值,并在一个简单的程序中测试该函数。

#include
int max(int arg[],int n)
{
	int i,max;
	
	for(i=0,max=arg[0];i<n;i++)	
	{
		if(max<arg[i])
			max = arg[i];
	}
	
	return max;
}
int main(void)
{
 	int num[] = {23,2,32,66,3,5,25,7,3,20};
 	printf("The biggest number is %d\n",max(num,10));
 	
 	
 	return 0;
}

编写一个函数,返回储存在double类型数组中最大值的下标,并在一个简单的程序中测试该函数。

#include 
int max_index(double *ar, int n);
int main(void)
{
    double array[] = {1.5, 3.75, 4.3, 2.6, 2.15, 6.66};

    printf("The index of the maximum number is: %d\n", max_index(array, 6));

    return 0;
}

int max_index(double ar[], int n)
{
    int i, max;

    for (max = 0, i = 1; i < n; i++)
        if (ar[max] < ar[i])
            max = i;

    return max;
}

  1. 编写一个函数,返回储存在double类型数组中最大值和最小值的差值,并在一个简单的程序中测试该函数。
#include 
double gap(double ar[], int n);
int main(void)
{
    double array[] = {1.5, 3.75, 4.3, 2.6, 2.15, 6.66};

    printf("The difference between the maximum and minimum "
           "values is:\n%g\n", gap(array, 6));
    
    return 0;
}

double gap(double ar[], int n)
{
    int i;
    double max, min;

    max = min = ar[0];
    for (i = 0; i < n; i++)
    {
        if (max < ar[i])
            max = ar[i];
        if (min > ar[i])
            min = ar[i];
    }

    return (max - min);
}

6.编写一个函数,把double类型数组中的数据倒序排列,并在一个简单的程序中测试该函数。

#include 
#define SIZE 6
void reverse(double ar [], int n);
void print_ar(double ar[], int n);			//打印数组的函数
int main(void)
{
    double array[] = {1.5, 3.75, 4.3, 2.6, 2.15, 6.66};

    printf("The original array:\n");
    print_ar(array, SIZE);
    reverse(array, SIZE);					//使数据倒序排列
    printf("The present array:\n");
    print_ar(array, SIZE);

    return 0;
}

void reverse(double ar [], int n)
{
    int i;
    double temp;

    for (i = 0; i < n / 2; i++)
    {
        temp = ar[i];
        ar[i] = ar[n - i -1];
        ar[n - i -1] = temp;
    }
}


void print_ar(double ar[], int n)
{
    int i;

    for (i = 0; i < n; i++)
        printf("%g ", ar[i]);
    printf("\n");
}


编写一个程序,初始化一个double类型的二维数组,使用编程练习2中的一个拷贝函数把该数组中的数据拷贝至另一个二维数组中(因为二维数组是数组的数组,所以可以使用处理一维数组的拷贝函数来处理数组中的每个子数组)。

#include 
#define ROWS 3
#define COLS 2
void copy_ar(double ar1[], double ar[], int n);		//拷贝数组的函数
void print_ar(double ar[][COLS], int rows);			//打印数组的函数
int main(void)
{
    int rows;
    double target[ROWS][COLS];
    double source[ROWS][COLS] = { {1.2, 2.3}, {4.6, 5.2}, {7.8, 8.6} };
    
    printf("The original array:\n");
    print_ar(source, ROWS);
    for (rows = 0; rows < ROWS; rows++)
        copy_ar(target[rows], source[rows], COLS);
    printf("The copied array:\n");
    print_ar(target, ROWS);

    return 0;
}

void copy_ar(double ar1[], double ar[], int n)
{
    int index;
    for (index = 0; index < n; index++)
        ar1[index] = ar[index];
}

void print_ar(double ar[][COLS], int rows)
{
    int r, c;
    for (r = 0; r < rows; r++)
    {
        for (c = 0; c < COLS; c++)
            printf("%g ", ar[r][c]);
        printf("\n");
    }
}


使用编程练习2中的拷贝函数,把一个内含7个元素的数组中第3~第5个元素拷贝至内含3个元素的数组中。该函数本身不需要修改,只需要选择合适的实际参数(实际参数不需要是数组名和数组大小,只需要是数组元素的地址和待处理元素的个数)。

#include 
#define SIZE_SOU 7			//源数组元素个数
#define SIZE_TAR 3			//待拷贝元素个数
void copy_ptr(double * ar2, double * ar, int n);
int main(void)
{
    int i;

    double target[SIZE_TAR];
    double souce[SIZE_SOU] = {1.5, 3.75, 4.3, 2.6, 2.15, 3.27, 6.66};
    copy_ptr(target, souce + 2, SIZE_TAR);
    for (i = 0; i < SIZE_TAR; i++)
        printf("%g ", target[i]);
    printf("\n");

    return 0;
}

void copy_ptr(double * ar2, double * ar, int n)
{
    int i;
    for (i = 0; i < n; i++)
        *(ar2++) = *(ar++);
}

9.编写一个程序,初始化一个double类型的3×5二维数组,使用一个处理变长数组的函数将其拷贝至另一个二维数组中。还要编写一个以变长组为形参的函数以显示两个数组的内容。这两个函数应该能处理任意N×M数组(如果编译器不支持变长数组,就使用传统C函数处理N×5的数组)。

#include 
#define ROWS 3
#define COLS 5
void copy_ar(double ar1[][COLS], double ar[][COLS], int n);		//拷贝数组的函数
void print_ar(double ar[][COLS], int rows);						//打印数组的函数
int main(void)
{
    double target[ROWS][COLS];
    double source[ROWS][COLS] =
    {
        {1.2, 2.3, 2.6, 3.5, 3.2},
        {4.6, 5.2, 2.8, 3.3, 2.1},
        {7.8, 8.6, 7.2, 3.9, 6.6}
    };
    
    printf("The original array:\n");
    print_ar(source, ROWS);
    copy_ar(target, source, ROWS);
    printf("The copied array:\n");
    print_ar(target, ROWS);

    return 0;
}

void copy_ar(double ar1[][COLS], double ar[][COLS], int rows)
{
    int r, c;
    for (r = 0; r < rows; r++)
        for (c = 0; c < COLS; c++)
            ar1[r][c] = ar[r][c];
}

void print_ar(double ar[][COLS], int rows)
{
    int r, c;
    for (r = 0; r < rows; r++)
    {
        for (c = 0; c < COLS; c++)
            printf("%g ", ar[r][c]);
        printf("\n");
    }
}
  1. 编写一个函数,把两个数组中相对应的元素相加,然后把结果储存到第 3 个数组中。也就是说,如果数组1中包含的值是2、4、5、8,数组2中包含的值是1、0、4、6,那么该函数把3、4、9、14赋给第3个数组。函数接受3个数组名和一个数组大小。在一个简单的程序中测试该函数。
#include 
#define SIZE 4
void print_ar(double ar[], int n);		//打印数组元素的函数
//将两个数组相加放入第三个数组的函数
void add_ar(double ar1[], double ar2[], double ar3[], int n);
int main(void)
{
    double ar1[SIZE] = {2, 4, 5, 8};
    double ar2[SIZE] = {1, 0, 4, 6};
    double ar3[SIZE];
    
    printf("The first array:  ");
    print_ar(ar1, SIZE);
    printf("The second array: ");
    print_ar(ar2, SIZE);
    add_ar(ar1, ar2, ar3, SIZE);
    printf("The third array:  ");
    print_ar(ar3, SIZE);

    return 0;
}

void print_ar(double ar[], int n)
{
    int i;

    for (i = 0; i < n; i++)
        printf("%g ", ar[i]);
    printf("\n");
}

void add_ar(double ar1[], double ar2[], double ar3[], int n)
{
    int i;

    for (i = 0; i < n; i++)
        ar3[i] = ar1[i] + ar2[i];
}

编写一个程序,声明一个int类型的3×5二维数组,并用合适的值初始化它。该程序打印数组中的值,然后各值翻倍(即是原值的2倍),并显示出各元素的新值。编写一个函数显示数组的内容,再编写一个函数把各元素的值翻倍。这两个函数都以函数名和行数作为参数。

#include 
#define ROWS 3
#define COLS 5
void change_ar(int ar[][COLS], int rows);		//变化数组的函数
void print_ar(int ar[][COLS], int rows);		//打印数组的函数
int main(void)
{
    int array[ROWS][COLS] =
    {
        {1, 2, 6, 3, 3},
        {6, 5, 2, 3, 2},
        {7, 8, 7, 3, 6}
    };
    
    printf("The original array:\n");
    print_ar(array, ROWS);
    change_ar(array, ROWS);
    printf("The present array:\n");
    print_ar(array, ROWS);

    return 0;
}

void change_ar(int ar[][COLS], int rows)
{
    int r, c;
    for (r = 0; r < rows; r++)
        for (c = 0; c < COLS; c++)
            ar[r][c] *= 2;
}

void print_ar(int ar[][COLS], int rows)
{
    int r, c;
    for (r = 0; r < rows; r++)
    {
        for (c = 0; c < COLS; c++)
            printf("%3d ", ar[r][c]);
        printf("\n");
    }
}
  1. 重写程序清单10.7的rain.c程序,把main()中的主要任务都改成用函数来完成。
#include 
#define	MONTHS 12			//一年的月份数
#define YEARS 5				//一年的年数
void rainfall(float rain[][MONTHS], int years);
int main(void)
{
    //用2010~2014年的降水量数据初始化数组
    const float rain[YEARS][MONTHS] =
    {
        {4.3,4.3,4.3,3.0,2.0,1.2,0.2,0.2,0.4,2.4,3.5,6.6},
        {8.5,8.2,1.2,1.6,2.4,0.0,5.2,0.9,0.3,0.9,1.4,7.3},
        {9.1,8.5,6.7,4.3,2.1,0.8,0.2,0.2,1.1,2.3,6.1,8.4},
        {7.2,9.9,8.4,3.3,1.2,0.8,0.4,0.0,0.6,1.7,4.3,6.2},
        {7.6,5.6,3.8,2.8,3.8,0.2,0.0,0.0,0.0,1.3,2.6,5.2}
    };
    rainfall(rain, YEARS);

    return 0;
}
    
    
void rainfall(float rain[][MONTHS], int years)
{
    float subtot, total;
    int y, m;
    printf(" YEAR	    RAINFALL (inches)\n");
    for (y = 0, total = 0; y < years; y++)
    {	//每一年,各月降水量总和
        for (m = 0, subtot = 0; m < MONTHS; m++)
            subtot += rain[y][m];
        printf("%5d %15.1f\n", 2010 + y, subtot);
        total += subtot;	//5年的总降水量
    }
    printf("\n The yearly average is %.1f inches.\n\n", total / YEARS);
    printf(" MONTHLY AVERAGES:\n\n");
    printf(" Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct ");
    printf(" Nov  Dec\n");

    for (m = 0; m < MONTHS; m++)
    {
        for (y = 0, subtot = 0; y < years; y++)
            subtot += rain[y][m];
        printf("%4.1f ", subtot / years);
    }
    printf("\n");
}


编写一个程序,提示用户输入3组数,每组数包含5个double类型的数(假设用户都正确地响应,不会输入非数值数据)。该程序应完成下列任务。

a.把用户输入的数据储存在3×5的数组中
b.计算每组(5个)数据的平均值
c.计算所有数据的平均值
d.找出这15个数据中的最大值
e.打印结果

每个任务都要用单独的函数来完成(使用传统C处理数组的方式)。完成任务b,要编写一个计算并返回一维数组平均值的函数,利用循环调用该函数3次。对于处理其他任务的函数,应该把整个数组作为参数,完成任务c和d的函数应把结果返回主调函数。
14. 以变长数组作为函数形参,完成编程练习13。

#include 
#define ROWS 3
#define	COLS 5
#define NUM 15		//共计15个数
void get_num(double ar[][COLS], int rows);		//把用户输入的数据储存在数组中
double aver_row(double ar[]);					//计算每组数据的平均值
double aver_all(double ar[][COLS], int rows);	//计算所有数据的平均值
double max_num(double ar[][COLS], int rows);		//找出15个数据的最大值
//打印结果
void print_result(double ar[][COLS], int rows);

int main(void)
{
    double array[ROWS][COLS];

    get_num(array, ROWS);
    print_result(array, ROWS);

    return 0;
}


void get_num(double ar[][COLS], int rows)
{
    int r, c;
    double a = 1.0;			//是为了让vc6.0编译器链接浮点链接库

    printf("Please enter 3 groups of numbers, and there\n"
           "are 5 numbers in each group:\n");

    for (r = 0; r < rows; r++)
        for (c = 0; c < COLS; c++)
            scanf("%lf", &ar[r][c]);
}

double aver_row(double ar[])
{
    int c;
    double sub;

    for (c = 0, sub = 0.0; c < COLS; c++)
        sub += ar[c];

    return (sub / COLS);
}

double aver_all(double ar[][COLS], int rows)
{
    int r, c;
    double total;

    for (r = 0, total = 0.0; r < rows; r++)
        for (c = 0; c < COLS; c++)
            total += ar[r][c];
    return (total / NUM);
}

double max_num(double ar[][COLS], int rows)
{
    int r, c;
    double max;
    
    for (r = 0, max = ar[0][0]; r < rows; r++)
        for (c = 0; c < COLS; c++)
            if (max < ar[r][c])
                max = ar[r][c];
    
    return max;
}

void print_result(double ar[][COLS], int rows)
{
    int r, c, row;
    //打印数组
    printf("The array:\n");
    for (r = 0; r < rows; r++)
    {
        for (c = 0; c < COLS; c++)
            printf("%-5g", ar[r][c]);
        printf("\n");
    }
    //输出每组平均值
    for (row = 0; row <ROWS; row++)
        printf("The average value in row %d is: %g\n",
                row, aver_row(ar[row]));
    //输出所有数据平均值
    printf("The average value in the array is: %g\n",
            aver_all(ar, ROWS));
    //输出15个数据的最大值
    printf("The maximum number in the array is: %g\n",
            max_num(ar, ROWS));
    printf("Bye.\n");
}

第十一章 字符串和字符串函数

1.设计并测试一个函数,从输入中获取下n个字符(包括空白、制表符、换行符),把结果储存在一个数组里,它的地址被传递作为一个参数。

#include
#define N 40
char *gets_n(char ar[],int n)
{
	int count= 0;
	
	while(count < n)
		ar[count++] = getchar();
	ar[count] = '\0';
	
}
int main(void)
{
	char str[N];
	int n;
	printf("how many chars do you want input:\t");
	scanf("%d",&n);
	
	gets_n(str,n);
	puts(str);
	
	return 0;
}
  1. 修改并编程练习1的函数,在n个字符后停止,或在读到第1个空白、制表符或换行符时停止,哪个先遇到哪个停止。不能只使用scanf()。
#include
#include
#define SIZE 256
char *gets_n(char *ar,int n)
{
	int i;
	for(i = 0;i<n;i++)
	{
		*(ar+i)=getchar();
		if(isspace(*(ar+i)))
			break;
	}
	*(ar+i)='\0';
	
	return ar;
	
}

int main(void)
{
	char str[SIZE];
	
	printf("Enter some character :\n");
	gets_n(str,250);
	puts(str);
	
	return 0;
}
  1. 设计并测试一个函数,从一行输入中把一个单词读入一个数组中,并丢弃输入行中的其余字符。该函数应该跳过第1个非空白字符前面的所有空白。将一个单词定义为没有空白、制表符或换行符的字符序列。
#include
#include
#define N 256
void get_word(char *ar)
{
	char ch;
	int i=0;
	while(isspace(ch=getchar()))
		continue;
	do
		*ar++ = ch;
	while(!isspace(ch = getchar()))
		;
}

int main(void)
{
	char str[N];
	printf("Enter some characters:\n");
	get_word(str);
	puts(str);
	
	return 0;
}
  1. 设计并测试一个函数,它类似编程练习3的描述,只不过它接受第2个参数指明可读取的最大字符数。
#include
#include
#define N 256

void get_words(char *ar,int n)
{
	char ch;
	int i = 0;
	while(isspace(ch=getchar()))
		continue;
	do
	{
		*(ar+i)=ch;
		i++;
	}
	while(!isspace(ch = getchar())&&i<(n-1))
		;
	
}

int main(void)
{
	char str[250];
	int n=0;
	printf("enter how many characters do you want to show :\n");
	scanf("%d",&n);
	printf("Enter some character:\n");
	
	get_words(str,n);
	puts(str);
	
}
  1. 设计并测试一个函数,搜索第1个函数形参指定的字符串,在其中查找第2个函数形参指定的字符首次出现的位置。如果成功,该函数返指向该字符的指针,如果在字符串中未找到指定字符,则返回空指针(该函数的功能与 strchr()函数相同)。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。
#include
#include
#define QUIT "quit"
#define SIZE 256

char *str_ch(char *str,char c)
{
	int flag = 0;
	int count = 0;
	
	while(count++ < strlen(str))
		if(*str++ == c)
		{
			flag = 1;
			break;
		}
		if(flag)
			return str-1;
		else
			return NULL;	
}


int main(void)
{
	char str[SIZE];
	char ch;
	char*ret_val;
	
	printf("Input a string(type quit to quit):\n");
	gets(str);
	while(strcmp(str,QUIT))
	{
		printf("Input a character:");
		scanf("%c",&ch);
		while(getchar()!='\n')
			continue;
		ret_val = str_ch(str, ch);
        if (ret_val != NULL)
            printf("Find! The string start with the %c:\n"
            "%s\n", ch, ret_val);
        else
            printf("Can't find!\n");
        printf("Input a string (type quit to quit):\n");
        gets(str);
	}
	
	printf("Bye.\n");
	
	return 0;	
}
  1. 编写一个名为is_within()的函数,接受一个字符和一个指向字符串的指针作为两个函数形参。如果指定字符在字符串中,该函数返回一个非零值(即为真)。否则,返回0(即为假)。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。
#include
#include
#define QUIT "quit"
#define SIZE 256

int is_within(char*str,char c)
{
	int flag = 0;
	size_t count = 0;
		
	while(count++ <strlen(str))
	{
		if(*str++ == c)
		{
			flag = 1;
			break;
		}
	}
	return flag;
}

int is_within(char * str, char c);
int main(void)
{
    char str[SIZE];
    char ch;

    printf("Input a string (type quit to quit):\n");
    while (strcmp(gets(str), QUIT))
    {
        printf("Input a character: ");
        scanf("%c", &ch);
        while (getchar() != '\n')		//跳过剩余输入部分
            continue;
        if (is_within(str, ch))
            printf("Find!\n");
        else
            printf("Can't find!\n");
        printf("Input a string (type quit to quit):\n");
    }
    printf("Bye.\n");
        
    return 0;
}

strncpy(s1, s2, n)函数把s2中的n个字符拷贝至s1中,截断s2,或者有必要的话在末尾添加空字符。如果s2的长度是n或多于n,目标字符串不能以空字符结尾。该函数返回s1。自己编写一个这样的函数,名为mystrncpy()。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。

#include
#include
#define QUIT "quit"
#define SIZE 256

char *mystrncpy(char*p1,char*p2,int n)
{
	int i = 1;
	char*p=p1;
	
	while(*p++)
		continue;
	*--p1=*p2;
	while(i<n&&*p2)
	{
		*++p1 = *++p2;
		i++;	
	}	
	
	return p;
}

int main()
{
	char s1[SIZE];
	char s2[SIZE];
	int num;
	
	printf("Input the first string(type \"quit\" to quit):\n");
	 while (strcmp(gets(s1), QUIT))		//输入quit结束
    {
        printf("Input the second string:\n");
        gets(s2);
        printf("Input the number of char copied from s2: ");
        scanf("%d", &num);
        getchar();						//跳过回车
        //当s2的长度大于或等于要拷贝的字符数时,要给s1末尾加上'\0',
        //并且注意要在调用函数之前,不然strlen(s1)会发生改变
        if (strlen(s2) >= num)
            s1[strlen(s1) + num] = '\0';
        puts(mystrncpy(s1, s2, num));	//输出拷贝后的字符串s1
        printf("Input the first string (type quit to quit):\n");
    }
    
    printf("Bye.\n");
	
	
	return 0;
}

  1. 编写一个名为string_in()的函数,接受两个指向字符串的指针作为参数。如果第2个字符串中包含第1个字符串,该函数将返回第1个字符串开始的地址。例如,string_in(“hats”, “at”)将返回hats中a的地址。否则,该函数返回空指针。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。
#include 
#include 
#define SIZE 40
#define QUIT "quit"
char * s_gets(char * st, int n);				//读取字符串输入的函数
char * string_in(char * s1, char * s2);
int main(void)
{
    char str1[SIZE];
    char str2[SIZE];
    char * ret_val;
    
    printf("Input the first string (type quit to quit):\n");
    while (strcmp(s_gets(str1, SIZE), QUIT))		//输入quit结束
    {
        printf("Input the second string:\n");
        s_gets(str2, SIZE);
        ret_val = string_in(str1, str2);
        if (ret_val)
        {
            printf("Find!\n");
            puts(ret_val);
        }
        else
            printf("Can't find!\n");
        printf("Input the first string (type quit to quit):\n");
    }
    
    printf("Bye.\n");
}

//自定义的字符串输入函数
char * s_gets(char * st, int n)
{
    int i = 0;

    if (fgets(st, n, stdin))	//即返回值st不等于NULL
    {
        while (st[i] != '\n' && st[i] != '\0')
            i++;
        if (st[i] == '\n')
            st[i] = '\0';
        else
            while (getchar() != '\n')
                continue;
    }

    return st;
}


//在s1中检测s2
char * string_in(char * s1, char * s2)
{
    int i;
    
    while (*s1)
    {
        i = 0;
        while (s1[i] == s2[i])
        {
            i++;
            if (!s2[i])
                return s1;
        }
        s1++;
    }

    return NULL;
}



        
  1. 编写一个函数,把字符串中的内容用其反序字符串代替。在一个完整的程序中测试该函数,使用一个循环给函数提供输入值。
#include 
#include 
#define SIZE 40
#define QUIT "quit"
char * s_gets(char * st, int n);
void reverse(char * st);
int main(void)
{
    char str[SIZE];
    while (strcmp(s_gets(str, SIZE), QUIT))		//输入quit结束
    {
        reverse(str);
        puts(str);
    }
    
    return 0;
}


//自定义的字符串输入函数
char * s_gets(char * st, int n)
{
    int i = 0;
    
    printf("Input the first string (type quit to quit):\n");
    if (fgets(st, n, stdin))	//即返回值st不等于NULL
    {
        while (st[i] != '\n' && st[i] != '\0')
            i++;
        if (st[i] == '\n')
            st[i] = '\0';
        else
            while (getchar() != '\n')
                continue;
    }

    return st;
}

//使字符串倒序的函数
void reverse(char * st)
{
    unsigned int i;
    char temp;

    size_t length = strlen(st);
    for (i = 0; i < length / 2; i++)
    {
        temp = st[length - i -1];
        st[length - i - 1] = st[i];
        st[i] = temp;
    }
    st[length] = '\0';
}

编写一个函数接受一个字符串作为参数,并删除字符串中的空格。在一个程序中测试该函数,使用循环读取输入行,直到用户输入一行空行。该程序应该应用该函数只每个输入的字符串,并显示处理后的字符串。

#include 
#define SIZE 40
char * s_gets(char * st, int n);
void delete_space(char * st);
int main(void)
{
    char str[SIZE];
    while (*s_gets(str, SIZE) != '\n')
        delete_space(str);
    printf("Bye.\n");
    
    return 0;
}

//删除空格的函数
void delete_space(char * st)
{
    int i;
    char * p = st;
    
    printf("\nThe original string is:\n");
    puts(st);
    while (*st)
    {	//如果遇到空格,后面所有字符往前进一格
        if (*st == ' ')
            for (i = 0; st[i] != '\0'; i++)
                st[i] = st[i + 1];
        else
            st++;
    }
    printf("Now, the string is:\n");
    puts(p);
    printf("\n");
}

//自定义的字符串输入函数
char * s_gets(char * st, int n)
{
    int i = 0;
    
    printf("Input the first string (blank line to quit):\n");
    if (fgets(st, n, stdin) != NULL && st[0] != '\n')	//即返回值st不等于NULL
    {
        while (st[i] != '\n' && st[i] != '\0')
            i++;
        if (st[i] == '\n')
            st[i] = '\0';
        else
            while (getchar() != '\n')
                continue;
    }

    return st;
}

编写一个函数,读入10个字符串或者读到EOF时停止。该程序为用户提供一个有5个选项的菜单:打印源字符串列表、以ASCII中的顺序打印字符串、按长度递增顺序打印字符串、按字符串中第1个单词的长度打印字符串、退出。菜单可以循环显示,除非用户选择退出选项。当然,该程序要能真正完成菜单中各选项的功能。

#include 
#include 
#include 
#define LIM 10
#define SIZE 80
char * s_gets(char * st, int n);			//获取字符串输入
char get_choice(void);						//获取选择
void print_sour(char * st[], int n);		//打印源字符串
void print_ascii(char * st[], int n);		//按ASCII码顺序打印
void print_length(char * st[], int n);		//按长度顺序打印
void print_first_word(char * st[], int n);	//按第一个单词的长度顺序打印
int first_word(char * st);					//计算第一个单词数

int main(void)
{
    char str[LIM][SIZE];
    char * ptr[LIM];
    int row = 0;							//输入的字符串数量
    char choice;							//用户输入的选择字符

    printf("Input some strings before EOF (no more than 10):\n");
    while (row < LIM && s_gets(str[row], SIZE) != NULL)
    {
        ptr[row] = str[row];				//设置指针指向字符串
        row++;
    }
    while((choice = get_choice()) != 'q')
    {
        printf("\n");
        switch (choice)
        {
            case 'a': print_sour(ptr, row);
                      break;
            case 'b': print_ascii(ptr, row);
                      break;
            case 'c': print_length(ptr, row);
                      break;
            case 'd': print_first_word(ptr, row);
                      break;
            default: printf("Error!\n");
                     break;
        }
        printf("\n");
    }
    printf("Bye.\n");
    
    return 0;
}

//获取用户选择
char get_choice(void)
{
    char ch;
    
    printf("a. print the sourse strings.     b. print in order of ASCII.\n");
    printf("c. print in order of length.	 d. print in order of the first word's length.\n");
    printf("q. quit.\n");
    printf("Enter a character (a, b, c, d or q):");
    ch = getchar();
    while (getchar() != '\n')
        continue;
    while (ch < 'a' || ch > 'd' && ch != 'q')
    {
        printf("Please input the right option (a, b, c, d or q): ");
        ch = getchar();
        while (getchar() != '\n')
        continue;
    }
    return ch;
}
    
//打印源字符串
void print_sour(char * st[], int n)
{
    int i;

    for (i = 0; i < n; i++)
        puts(st[i]);
}
    
//按ASCII中的顺序打印字符串
void print_ascii(char * st[], int n)
{
    int i, j;
    char * temp;

    for (i = 0; i < n - 1; i++)
        for (j = i + 1; j < n; j++)
            if (strcmp(st[i], st[j]) > 0)
            {
                temp = st[j];
                st[j] = st[i];
                st[i] = temp;
            }
    for (i = 0; i < n; i++)
        puts(st[i]);
}

//按长度顺序打印
void print_length(char * st[], int n)
{
    int i, j;
    char * temp;

    for (i = 0; i < n - 1; i++)
        for (j = i + 1; j < n; j++)
            if (strlen(st[i]) > strlen(st[j]))
                {
                    temp = st[j];
                    st[j] = st[i];
                    st[i] = temp;
                }
    for (i = 0; i < n; i++)
        puts(st[i]);
}
//按第一个单词的长度顺序打印
void print_first_word(char * st[], int n)
{
    int i, j;
    char * temp;

    for (i = 0; i < n - 1; i++)
        for (j = i + 1; j < n; j++)
            if (first_word(st[i]) > first_word(st[j]))
                {
                    temp = st[j];
                    st[j] = st[i];
                    st[i] = temp;
                }
    for (i = 0; i < n; i++)
    puts(st[i]);
}

//计算第一个单词的长度
int first_word(char * st)
{
    int i = 0;
    int count = 0;

    while (!isalpha(st[i]))
            i++;
    while (isalpha(st[i]))
    {
        i++;
        count++;
    }

    return count;
}
    
//自定义的输入函数
char * s_gets(char * st, int n)
{
    int i = 0;
    if (fgets(st, n, stdin) != NULL)	//即返回值st不等于NULL
    {
        while (st[i] != '\n' && st[i] != '\0')
            i++;
        if (st[i] == '\n')
            st[i] = '\0';
        else
            while (getchar() != '\n')
                continue;
        return st;
    }
    else
        return NULL;
}

编写一个程序,读取输入,直至读到 EOF,报告读入的单词数、大写字母数、小写字母数、标点符号数和数字字符数。使用ctype.h头文件中的函数。

#include 
#include 
int main(void)
{
    char ch;
    int word = 0, upper = 0, lower = 0;
    int punct = 0, digit = 0, inword = 0;
    
    while ((ch = getchar()) != EOF)
    {
        if (!isspace(ch) && (!ispunct(ch)) && !inword)
        {
            inword = 1;
            word++;
        }
        if (isspace(ch) || ispunct(ch) && inword)
            inword = 0;
        if (isupper(ch))
            upper++;
        if (islower(ch))
            lower++;
        if (ispunct(ch))
            punct++;
        if (isdigit(ch))
            digit++;
    }
    printf("words: %d, upper: %d, lower: %d, punct: %d, digit: %d.\n",
            word, upper, lower, punct, digit);

    return 0;
}

编写一个程序,反序显示命令行参数的单词。例如,命令行参数是see you later,该程序应打印later you see。

#include 
int main(int argc, char * argv[])
{
    int count;

    for (count = argc - 1; count > 0; count--)
        printf("%s ", argv[count]);

    return 0;
}

编写一个通过命令行运行的程序计算幂。第1个命令行参数是double类型的数,作为幂的底数,第2个参数是整数,作为幂的指数。

#include 
#include 
double mypower(double n, int exp);
int main(int argc, char * argv[])
{
    printf("The result is: %g",
            mypower(atof(argv[1]), atoi(argv[2])));
}


double mypower(double n, int exp)
{
    double pow;

    if (exp > 0)
        for (pow = 1; exp > 0; exp--)
            pow *= n;
    else if (exp < 0)
    {	if (!n)
            printf("It's not defined!\n");
        for (pow = 1; exp < 0; exp++)
            pow *= (1 / n);
    }
    else if (n)
        pow = 1;
    else
    {	pow = 1 / n;
        printf("It's not defined!\n");
    }

    return pow;
}

使用字符分类函数实现atoi()函数。如果输入的字符串不是纯数字,该函数返回0。

#include 
#include 
int myatoi(char * st);
int main(void)
{
    char str[40];
    gets(str);
    printf("%d\n", myatoi(str));
}

int myatoi(char * st)
{
    int sum = 0;

    while (*st)
    {	//把字符数字逐位转化为数值
        if (isdigit(*st))
            sum = 10 * sum + (*st - '0');
        else
            return 0;		//不是纯数字则返回0
        st++;
    }

    return sum;
}
  1. 编写一个程序读取输入,直至读到文件结尾,然后把字符串打印出来。该程序识别和实现下面的命令行参数:
-p     按原样打印
-u     把输入全部转换成大写
-l     把输入全部转换成小写

如果没有命令行参数,则让程序像是使用了-p参数那样运行。

#include 
#include 
#include 
#define SIZE 80
#define LIM 10
int main(int argc, char * argv[])
{
    int col;
    int i;
    int row = 0;
    char str[LIM][SIZE];
    
    while (row < LIM && fgets(str[row], SIZE, stdin) != NULL)
    {
        if (argc == 1);
        else if (!strcmp(argv[1], "-p"));
        else if (!strcmp(argv[1], "-u"))
            for (col = 0; str[row][col] != '\0'; col++)
                str[row][col] = toupper(str[row][col]);
        else if (!strcmp(argv[1], "-l"))
            for (col = 0; str[row][col] != '\0'; col++)
                str[row][col] = tolower(str[row][col]);
        row++;
    }
    for (i = 0; i < row; i++)
        fputs(str[i], stdout);

    return 0;
}


你可能感兴趣的:(c,primer,plus,c语言,c++,开发语言)