第1章 C语言编程
练习1.1 编写一个程序,用两个printf()语句分别输出自己的名字和地址。
#include <stdio.h>
int main(void) {
printf("姓名:小狮子\n");
printf("地址:月亮之上\n");
return 0;
}
练习1.2 将上一个练习修改成所有的输出只用一个printf()语句。
#include <stdio.h>
int main(void) {
printf("姓名:小狮子\n地址:月亮之上\n");
return 0;
}
练习1.3 编写一个程序,输出下列文本,格式如下所示:"It's freezing in here," he said coldly.
#include <stdio.h>
int main(void) {
printf("\"It's freezing in here,\" he said coldly.\n");
return 0;
}
第2章 编程初步
习题2.1 编写一个程序,提示用户用英寸输入一个距离,然后将该距离值输出为码、英尺和英寸的形式。
#include <stdio.h>
/*
* 1码=3英尺=36英寸
*/
int main()
{
float len_inch = 0.0f; // 英寸
float len_foot = 0.0f; // 英尺
float len_yard = 0.0f; // 码
// 提示用户用英寸输入一个距离
printf("请用英寸输入一个距离:");
scanf("%f", &len_inch);
// 计算英尺
len_foot = len_inch / 12;
// 计算码
len_yard = len_foot / 3;
// 输出计算后的结果
printf("%.2f英寸 = %.2f英尺 = %.2f码\n", len_inch, len_foot, len_yard);
return 0;
}
习题2.2 编写一个程序,提示用户用英尺和英寸输入一个房间的长和宽,然后计算并输出面积,单位是平方码,精度为小数点后两位数。
#include <stdio.h>
int main()
{
float length_in_foot = 0.0f; // 房间的宽度 单位英尺
float width_in_inch = 0.0f; // 房间的宽度 单位英寸
float area_in_yard = 0.0f; // 房间的面积 单位平方码
// 提示用户输入房间的长度
printf("请输入房间的长度(单位:foot):");
scanf("%f", &length_in_foot);
// 提示用户输入房间的宽度
printf("请输入房间的宽度(单位:inch):");
scanf("%f", &width_in_inch);
// 计算房间的面积 1码=3英尺=36英寸
area_in_yard = (length_in_foot / 3) * (width_in_inch / 36);
// 输出房间的面积
printf("房间的面积是:%.2f平方码。\n", area_in_yard);
return 0;
}
习题2.3 一个产品有两个版本:其一是标准版,价格是$3.5,其二是豪华版,价格是$5.5。编写一个程序,使用学到的知识提示用户输入产品的版本和数量,然后根据输入的产品数量,计算并输出价格。
#include <stdio.h>
int main()
{
float price_of_normal = 3.5; // 普通版单价
float price_of_deluxe = 5.5f; // 豪华版单价
int number_of_normal = 0; // 普通版的数量
int number_of_deluxe = 0; // 豪华版的数量
float total_price = 0.0f; // 总价
// 提示用户输入产品的数量
printf("请输入普通版的数量:");
scanf("%d", &number_of_normal);
printf("请输入豪华版的数量:");
scanf("%d", &number_of_deluxe);
// 计算总价
total_price = number_of_normal * price_of_normal + number_of_deluxe + price_of_deluxe;
// 输出总价
printf("总价为:$%.2f\n", total_price);
return 0;
}
习题2.4 编写一个程序,提示用户从键盘输入一个星期的薪水(以美元为单位)和工作时数,它们均为浮点数,然后计算并输出每个小时的平均时薪,输出格式如下所示:
Your average hourly pay rate is 7 dollars and 54 cents.
#include <stdio.h>
int main()
{
float salary = 0.0f; // 一个星期的薪水(以美元为单位)
float hours = 0.0f; // 工作时数
float salary_per_hour = 0.0f; // 每个小时的平均时薪
// 提示用户输入一个星期的薪水
printf("请输入一个星期的薪水(以美元为单位):");
scanf("%f", &salary);
// 提示用户输入工作时数
printf("请输入工作时数:");
scanf("%f", &hours);
// 计算每个小时的平均时薪
salary_per_hour = salary / hours;
// 输出结果
printf("Your average hourly pay rate is %d dollars and %d cents.\n", (int)salary_per_hour, (int)(salary_per_hour * 100) % 100);
return 0;
}
第3章 条件判断
习题3.1 编写一个程序,首先给用户以下两种选择:
(1)将温度从摄氏度转换为华氏度。
(2)将温度从华氏度转换为摄氏度。
接着,程序提示用户输入温度值,并输出转换后的数值。从摄氏度转换为华氏度,可以乘以 1.8 再加上 32。从华氏度转换为摄氏度,可以先减去 32 后,再乘以 5,除以 9。
#include <stdio.h>
#include <ctype.h>
int main()
{
float temperature = 0.0f; // 用户输入的温度值
char ch = '\0';
float result = 0.0f; // 转换后的温度值
// 提示用户都有哪种转换方式
printf("程序提供如下两种转换方式:\n");
printf(" A. 将温度从摄氏度转换为华氏度\n B. 将温度从华氏度转换为摄氏度\n");
// 提示用户输入选择的转换方式
printf("请选择转换方式(A or B):");
scanf("%c", &ch);
if (tolower(ch) == 'a')
{
printf("请输入温度值:");
scanf("%f", &temperature);
result = temperature * 1.8 + 32;
printf("%.2f摄氏度 = %.2f华氏度\n", temperature, result);
}
else if (tolower(ch) == 'b')
{
printf("请输入温度值:");
scanf("%f", &temperature);
result = (temperature - 32) * 5 / 9;
printf("%.2f华氏度 = %.2f摄氏度\n", temperature, result);
}
else
{
printf("选择错误\n");
}
return 0;
}
习题3.2 编写一个程序,提示用户输入3个整数值,分别代表月、日、年。例如用户输入了12、31、2003,程序就以31st December 2003 的格式输出该日期。
必须在日期值的后面加上th、nd、st 和 rd。例如1st、2nd、3rd、4th、11th、12th、13th、14th、21st、22nd、23rd、24th。
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
// 定义一个代表12个月份的枚举类型,枚举器值从1开始
enum Month { January = 1, February, March, April, May, June, July, August, September, October, November, December };
// 提示用户输入月、日、年
printf("请输入月、日、年:");
scanf("%d%d%d", &month, &day, &year);
// 输出日
if (day < 1 || day > 31)
{
printf("输入日期有误 ");
}
else if (day % 10 == 1 && day != 11)
{
printf("%dst ", day);
}
else if (day % 10 == 2 && day != 12)
{
printf("%dnd ", day);
}
else if (day % 10 == 3 && day != 13)
{
printf("%drd ", day);
}
else
{
printf("%dth ", day);
}
// 输出月
switch (month)
{
case January:
printf("January ");
break;
case February:
printf("February ");
break;
case March:
printf("March ");
break;
case April:
printf("April ");
break;
case May:
printf("May ");
break;
case June:
printf("June ");
break;
case July:
printf("July ");
break;
case August:
printf("August ");
break;
case September:
printf("September ");
break;
case October:
printf("October ");
break;
case November:
printf("November ");
break;
case December:
printf("December ");
break;
default:
printf("输入月份有误 ");
break;
}
// 输出年
printf("%d\n", year);
return 0;
}
习题3.3 编写一个程序,根据从键盘输入的一个数值,计算总价(单价是$5),数值超过30的折扣是10%,数值超过50的折扣是15%。
#include <stdio.h>
int main()
{
float unit_price = 5.0f; // 商品单价
float discount = 0.0f; // 商品折扣
int number = 0; // 商品数量
// 提示用户输入商品数量
printf("请输入商品数量:");
scanf("%d", &number);
// 计算折扣
if (number <= 30)
{
discount = 0.0f;
}
else if (number <= 50)
{
discount = 0.1f;
}
else
{
discount = 0.15f;
}
// 输出总价
printf("商品的总价为:%.2f\n", number * unit_price * (1 - discount));
return 0;
}
习题3.4 修改本章最后的计算器例子,让用户选择输入y或Y,以执行另一个计算,输入n或N就结束程序。(注意:这需要实用goto语句,下一章将介绍一个更好的方法。)
#include <stdio.h>
int main()
{
double number1 = 0.0;
double number2 = 0.0;
char operation = 0;
char choice = 0;
begin:
printf("Enter the caculation\n");
scanf("%lf %c %lf", &number1, &operation, &number2);
switch (operation)
{
case '+':
printf("= %lf\n", number1 + number2);
break;
case '-':
printf("= %lf\n", number1 - number2);
break;
case '*':
printf("= %lf\n", number1 * number2);
break;
case '/':
if (number2 == 0)
printf("\n\n\aDivision by zero error!\n");
else
printf("= %lf\n", number1 / number2);
break;
case '%':
if ((long)number1 == 0)
printf("\n\n\aDivision by zero error!\n");
else
printf("= %ld\n", (long)number1 % (long)number2);
break;
default:
printf("\n\n\aIllegal operation!\n");
break;
}
printf("Do you want to continue? (y or n): ");
scanf(" %c", &choice); // 注意:%c 前面的空格不能去掉
if (choice == 'y' || choice == 'Y')
goto begin;
return 0;
}
第4章 循环
习题4.1 编写一个程序,生成一个乘法表,其大小由用户输入来决定。例如,如果表的大小是4,该表就有4行4列。行和列标记为1~4.表中的每一个单元格都包含行列之积,因此第三行第4列的单元格包含12。
#include <stdio.h>
int main()
{
int num_row = 0;
int num_col = 0;
printf("请输入行数和列数:");
scanf("%d%d", &num_row, &num_col);
printf(" ");
for (int i = 1; i <= num_col; i++)
{
printf("%3d ", i);
}
printf("\n");
for (int i = 1; i <= num_row; i++)
{
printf("%-4d", i);
for (int j = 1; j <= num_col; j++)
{
printf("%3d ", i * j);
}
printf("\n");
}
return 0;
}
习题4.2 编写一个程序,为0~127之间的字符码输出可打印的字符。输出每个字符码和它的符号,这两个字符占一行。列要对齐(提示:可以使用在ctype.h中声明的isgraph()函数,确定哪个字符是可以打印的)。
#include <stdio.h>
#include <ctype.h>
int main()
{
for (int i = 0; i <= 127; i++)
{
if (isgraph(i))
{
printf("%d %c\n", i, i);
}
}
return 0;
}
习题4.3 扩展上一题,给每个空白字符输出对应的名称,例如newline,space,tab等。
// 本题略
习题4.4 使用嵌套循环输出一个用星号绘制的盒子,与程序4.2类似,但是它的宽和高由用户输入。
#include <stdio.h>
int main()
{
int height = 0;
int width = 0;
printf("请输入盒子的宽和高:");
scanf("%d%d", &width, &height);
for (int i = 1; i <= height; i++)
{
for (int j = 1; j <= width; j++)
{
if (i == 1 || i == height)
{
printf("*");
}
else
{
if (j == 1 || j == width)
{
printf("*");
}
else
{
printf(" ");
}
}
}
printf("\n");
}
return 0;
}
习题4.5 修改程序4.7的猜谜游戏,在玩家猜错数字后,可以用一个选项让玩家继续玩下去,且想玩多久就玩多久。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
int main()
{
int chosen = 0;
int guess = 0;
int limit = 20;
char another_game = 'Y';
srand(time(NULL));
chosen = 1 + rand() % limit;
printf("\nThis is a guessing game."
"\nI have chosen a number between 1 and 20 which you must guess.\n");
do
{
printf("\nEnter a guess: ");
scanf("%d", &guess);
if (guess == chosen)
{
printf("\nYou guessed it!\n");
return 0;
}
if (guess < 1 || guess > 20)
{
printf("\nI said between 1 and 20.\n");
}
else
{
printf("\nSorry. %d is wrong.\n", guess);
}
printf("\nDo you want to play again(y/n)? ");
scanf(" %c", &another_game);
}while(toupper(another_game) == 'Y');
return 0;
}
第5章 数组
习题5.1 编写一个程序,从键盘上读入5个double类型的值,将它们存储到一个数组中。计算每个值的倒数(值x的倒数是 1.0/x),将结果存储到另一个数组中。输出这些倒数,并计算和输出倒数的总和。
#include <stdio.h>
int main()
{
double original[5] = { 0.0 };
double result[5] = { 0.0 };
double sum = 0.0;
for (int i = 0; i < 5; i++)
{
printf("%d -> ", i + 1);
scanf("%lf", &original[i]);
}
for (int i = 0; i < 5; i++)
{
result[i] = 1.0 / original[i];
}
for (int i = 0; i < 5; i++)
{
printf("result[%d] = %lf\n", i, result[i]);
sum += result[i];
}
printf("sum = %lf\n", sum);
return 0;
}
习题5.2 定义一个数组 data,它包含 100 个 double 类型的元素。编写一个循环,将以下的数值序列存储到数组的对应元素中:
1/(2*3*4) 1/(4*5*6) 1/(6*7*8) ... up to 1/(200*201*202)
编写另一个循环,计算:
data[0] - data[1] + data[2] - data[3] + ... - data[99]
将这个结果乘以 4.0,加 3.0,输出最后的结果。
#include <stdio.h>
int main()
{
double data[100] = { 0.0 };
double sum = 0.0;
double result = 0.0;
for (int i = 1; i <= 100; i++)
{
data[i - 1] = 1.0 / ((2 * i) * (2 * i + 1)*(2 * i + 2));
}
for (int i = 0; i < 100; i++)
{
sum += (i % 2 ? -1 : 1) * data[i];
}
result = sum * 4.0 + 3.0;
printf("计算结果为:%lf\n", result);
return 0;
}
习题5.3 编写一个程序,从键盘上读入 5 个值,将它们存储到一个 float 类型的数组 amounts 中。创建两个包含 5 个 long 元素的数组 dollars 和 cents。将 amounts 数组元素的整数部分存储到 dollars 的对应元素中,amounts 数组元素的小数部分存储到 cents 中,只保存两位数字(例如:amounts[1] 的值是 2.75,则把 2 存储到 dollars[1] 中,把 75 存储 cents[1]中)。以货币格式输出这两个 long 类型数组的值(如$2.75)。
#include <stdio.h>
int main()
{
float amounts[5] = {0.0f};
long dollars[5] = {0L};
long cents[5] = {0L};
for (int i = 0; i < 5; i++)
{
printf("%d -> ", i + 1);
scanf("%f", &amounts[i]);
}
for (int i = 0; i < 5; i++)
{
dollars[i] = (long) amounts[i];
cents[i] = (long)(amounts[i] * 100) % 100;
}
for (int i = 0; i < 5; i++)
{
printf("$%ld.%ld\n", dollars[i], cents[i]);
}
return 0;
}
习题5.4 定义一个 double 类型的二维数组 data[11][5]。用 2.0~3.0 的值初始化第一列元素(每步增加 0.1)。如果行中的第一个元素值是 x,改行的其它元素值分别是 1/x,x²,x³ 和 x⁴。输出数组中的值,每一行放在一行上,每一列要有标题。
#include <stdio.h>
#include <math.h>
int main()
{
double data[11][5] = {0.0};
for (int i = 0; i < 11; i++)
{
data[i][0] = (1 + 0.1 * i);
}
for (int i = 0; i < 11; i++)
{
data[i][1] = 1 / data[i][0];
for (int j = 2; j < 5; j++)
{
data[i][j] = pow(data[i][0], i);
}
}
printf(" ");
for (int i = 0; i < 5; i++)
{
printf(" %02d ", i + 1);
}
printf("\n");
for (int i = 0; i < 11; i++)
{
printf(" %02d ", i + 1);
for (int j = 0; j < 5; j++)
{
printf(" %6.2lf ", data[i][j]);
}
printf("\n");
}
return 0;
}
习题5.5 编写一个程序,计算任意多个班级的学生的平均分。该程序应读取所有班级里学生的所有成绩,再计算平均值。给每个班级输出每个学生的平均分,以及班级的平均分。
#include <stdio.h>
#define CLASS_NUM 2
#define STUDENT_NUM 2
#define COURSE_NUM 2
int main()
{
int score[CLASS_NUM][STUDENT_NUM][COURSE_NUM] = {0};
int average_class = 0;
int average_student = 0;
for (int i = 0; i < CLASS_NUM; i++)
{
for (int j = 0; j < STUDENT_NUM; j++)
{
for (int k = 0; k < COURSE_NUM; k++)
{
printf("Class %02d Student %02d Course %02d -> ", i, j, k);
scanf("%d", &score[i][j][k]);
}
}
}
for (int i = 0; i < CLASS_NUM; i++)
{
average_class = 0;
for (int j = 0; j < STUDENT_NUM; j++)
{
average_student = 0;
for (int k = 0; k < COURSE_NUM; k++)
{
average_class += score[i][j][k];
average_student += score[i][j][k];
}
printf("Class %02d Student %02d 的平均分是 %.2f\n", i, j, average_student * 1.0 / COURSE_NUM);
}
printf("Class %02d 的平均分是 %.2f\n", i, average_class * 1.0 / STUDENT_NUM / COURSE_NUM);
}
return 0;
}
第6章 字符串和文本的应用
习题6.1 编写一个程序,从键盘上读入一个小于1000的正整数,然后创建并输出一个字符串,说明该整数的值。例如,输入941,程序产生的字符串是“Nine hundred and forty one”。
#include <stdio.h>
void one2nineteen(int n)
{
switch (n)
{
case 1:
printf("one");
break;
case 2:
printf("two");
break;
case 3:
printf("three");
break;
case 4:
printf("four");
break;
case 5:
printf("five");
break;
case 6:
printf("six");
break;
case 7:
printf("seven");
break;
case 8:
printf("eight");
break;
case 9:
printf("nine");
break;
case 10:
printf("ten");
break;
case 11:
printf("eleven");
break;
case 12:
printf("twelve");
break;
case 13:
printf("thirteen");
break;
case 14:
printf("fourteen");
break;
case 15:
printf("fifteen");
break;
case 16:
printf("sixteen");
break;
case 17:
printf("seventeen");
break;
case 18:
printf("eighteen");
break;
case 19:
printf("nineteen");
break;
default:
printf("one2nineteen操作失败");
break;
}
}
void fun(int n)
{
switch (n) {
case 20:
printf("twenty");
break;
case 30:
printf("thirty");
break;
case 40:
printf("fourty");
break;
case 50:
printf("fifty");
break;
case 60:
printf("sixty");
break;
case 70:
printf("seventy");
break;
case 80:
printf("eighty");
break;
case 90:
printf("ninety");
break;
default:
printf("fun执行出错");
break;
}
}
void fun2(int n)
{
if (n < 20)
{
one2nineteen(n);
}
else if (n < 100)
{
if (n % 10 == 0)
{
fun(n);
}
else
{
fun(n - n % 10);
printf("-");
one2nineteen(n % 10);
}
}
}
void int2str(int n)
{
if (n < 100)
{
fun2(n);
}
else if (n < 1000)
{
if (n % 100 == 0)
{
one2nineteen(n / 100);
printf(" hundred");
}
else
{
one2nineteen(n / 100);
printf(" hundred and ");
fun2(n % 100);
}
}
}
int main()
{
for (int i = 1; i < 1000; i++)
{
printf("%3d -> ", i);
int2str(i);
printf("\n");
}
return 0;
}
习题6.2 编写一个程序,输入一系列单词,单词之间以逗号分割,然后提取这些单词,并将它们分行输出,删除头尾的空格。例如,如果输入是
John , Jack , Jill
输出将是:
John
Jack
Jill
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
int main()
{
char sequence[100] = { 0 };
bool first = true;
printf("请输入一系列单词,单词之间以逗号分隔:\n");
if (fgets(sequence, sizeof(sequence), stdin) == NULL)
{
printf("输入过程出错\n");
return 1;
}
else
{
for (int i = 0; i < 100 && sequence[i] != '\0'; i++)
{
if (isalpha(sequence[i])) {
first = true;
printf("%c", sequence[i]);
}
else
{
if (first)
{
first = false;
printf("\n");
}
}
}
printf("\n");
}
return 0;
}
习题6.3 编写一个程序,从一组至少有5个字符串的数组里,输出任意挑选的一个字符串。
#include <stdio.h>
int main()
{
char arr[][50] = {
"Hello",
"Hello World",
"Hello World, Hello World!"
};
printf("%s\n", arr[2]);
return 0;
}
习题6.4 回文是正读反读均相同的句子,忽略空白和标点符号。例如,“Madam, I'm Adam”和“Are we no drawn onward, we few? Drawn onward to new era?”都是回文。编写一个程序,确定从键盘输入的字符串是否是回文。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
int main()
{
char sequence[100] = { 0 };
unsigned long head = 0;
unsigned long last = 0;
bool flag = true;
printf("请输入一个字符串:\n");
if (gets(sequence) == NULL)
{
printf("输入过程出错\n");
return 1;
}
else
{
last = strlen(sequence);
for (; head < last; )
{
for (;!isalpha(sequence[head]);)
{
head++;
}
for (; !isalpha(sequence[last]);)
{
last--;
}
if (toupper(sequence[head]) == toupper(sequence[last]))
{
head++;
last--;
}
else
{
flag = false;
break;
}
}
if (flag)
{
printf("是回文\n");
}
else
{
printf("不是回文\n");
}
}
return 0;
}
第7章 指针
习题7.1 编写一个程序,计算从键盘输入的任意个浮点数的平均值。将所有的数存储到动态分配的内存中,之后计算并显示平均值。用户不需要事先指定要输入多少个数。
#include <stdio.h>
#include <stdlib.h>
int main()
{
float number = 0.0f;
float *pNumber = NULL;
int count = 0;
float sum = 0.0f;
pNumber = (float *)malloc(sizeof(float));
if (pNumber == NULL)
{
printf("内存分配失败\n");
return 1;
}
do
{
scanf("%f", &number);
count++;
pNumber = realloc(pNumber, count * sizeof(float));
*(pNumber + count - 1) = number;
} while(number != 0.0f);
for (int i = 0; i < count - 1; i++)
{
sum += *(pNumber + i);
}
printf("平均值是 %f\n", sum / (count - 1));
free(pNumber);
return 0;
}
习题7.2 编写一个程序,从键盘读入任意个谚语,并将它们存储到执行期间分配的内存中。然后,将它们以字长顺序由短到长地输出。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char **pStr = NULL;
char *pBuffer = NULL;
int count = 0;
pStr = malloc(sizeof(char *));
do
{
pBuffer = malloc(100 * sizeof(char));
gets(pBuffer);
count++;
pStr = realloc(pStr, count * sizeof(char *));
*(pStr + count - 1) = pBuffer;
}while(strlen(pBuffer) != 0);
for (int i = 0; i < count - 2; i++)
{
for (int j = 0; j < count - 2 - i; j++)
{
if (strlen(*(pStr + j)) > strlen(*(pStr + j + 1)))
{
pBuffer = *(pStr + j);
*(pStr + j) = *(pStr + j + 1);
*(pStr + j + 1) = pBuffer;
}
}
}
for (int i = 0; i < count - 1; i++)
{
printf("%s\n", *(pStr + i));
}
return 0;
}
习题7.3 编写一个程序,从键盘读入一个字符串,显示删除了所有空格和标点符号的字符串。所有的操作都使用指针完成。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{
char *pStr = NULL;
pStr = malloc(100*sizeof(char));
gets(pStr);
while(*pStr)
{
if (isalpha(*pStr))
{
putchar(*pStr);
}
pStr++;
}
putchar('\n');
return 0;
}
习题7.4 编写一个程序,读入任意天数的浮点温度记录值,每天有6个记录。温度记录存储在动态分配内存的数组中,数组的大小刚好等于输入的温度数。计算出每天的平均温度,然后输出每天的记录,在单独一行上输出平均值,该平均值精确到小数点后一位。
#include <stdio.h>
#include <stdlib.h>
int main()
{
float **pTemp = NULL;
float sum = 0.0f;
int count = 0;
pTemp = malloc(sizeof(float));
do
{
count++;
pTemp = realloc(pTemp, count * sizeof(float *));
*(pTemp + count - 1) = malloc(6 * sizeof(float));
printf("Day %d :\n", count);
for (int i = 0; i < 6; i++)
{
printf("%d -> ", i + 1);
scanf("%f", (*(pTemp + count - 1) + i));
}
}while(**(pTemp + count - 1) != 0.0f);
for (int i = 0; i < count - 1; i++)
{
printf("Day %d :\n", i + 1);
sum = 0;
for (int j = 0; j < 6; j++)
{
sum += *(*(pTemp+i) + j);
printf("%d -> %f\n", j + 1, *(*(pTemp+i) + j));
}
printf("average = %.1f\n", sum / 6);
}
return 0;
}
第8章 程序的结构
习题8.1 定义一个函数,给函数传送任意多个浮点数,计算出这些数的平均值。从键盘输入任意个值,并输出平均值,以说明这个函数的执行过程。
#include <stdio.h>
#include <stdlib.h>
float average(float *, int);
int main()
{
float *pNum = NULL;
int count = 0;
pNum = malloc(count * sizeof(float));
do
{
count++;
pNum = realloc(pNum, count * sizeof(float));
scanf("%f", pNum + count - 1);
} while(*(pNum + count - 1) != 0.0f);
printf("average = %f\n", average(pNum, count - 1));
return 0;
}
float average(float *pNum, int count)
{
float sum = 0.0f;
for (int i = 0; i < count; i++)
{
sum += *(pNum + i);
}
return sum / count;
}
习题8.2 定义一个函数,返回其整数变元的字符串表示。例如,如果这个变元是25,函数就返回"25"。如果变元是-98,函数就返回"-98"。用适当的main()版本说明函数的执行过程。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
char *intToString(int);
int main()
{
printf("%s\n", intToString(-32768));
return 0;
}
char *intToString(int number)
{
char *pStr = malloc(7 * sizeof(char));
int var = 10000;
int weishu = 5;
int count = 0;
if (number < 0)
{
*(pStr + 0) = '-';
count = 1;
number = -number;
}
while (number / var == 0) {
weishu--;
var /= 10;
}
for (; count < 7; count++)
{
*(pStr + count) = '0' + number / (int)(pow(10, weishu - 1));
number %= (int)(pow(10, weishu - 1));
weishu--;
if (weishu <= 0) {
break;
}
}
*(pStr + count + 1) = '\0';
return pStr;
}
习题8.3 扩展为上一题定义的函数,使函数接受第二个变元,以指定结果的字段宽度,使返回的字符串表示右对齐。例如,如果第一个变元的值是-98,字段宽度变元是5,返回的字符串就应该是" -98"。用适当的main()版本说明函数的执行过程。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
char *intToString(int, int);
int main()
{
printf("%s\n", intToString(-98, 5));
return 0;
}
char *intToString(int number, int width)
{
char *pStr = malloc(7 * sizeof(char));
int var = 10000;
int weishu = 5;
int count = 0;
int len = 0;
if (number < 0)
{
*(pStr + 0) = '-';
count = 1;
number = -number;
}
while (number / var == 0) {
weishu--;
var /= 10;
}
for (; count < 7; count++)
{
*(pStr + count) = '0' + number / (int)(pow(10, weishu - 1));
number %= (int)(pow(10, weishu - 1));
weishu--;
if (weishu <= 0) {
break;
}
}
*(pStr + count + 1) = '\0';
len = (int)strlen(pStr);
if (len < width)
{
pStr = realloc(pStr, (width + 1) * sizeof(char));
*(pStr + width) = '\0';
int j = width - 1;
for (int i = len; i > 0; i--, j--)
{
*(pStr + j) = *(pStr + i - 1);
}
for (;j >= 0; j--)
{
*(pStr + j) = ' ';
}
}
return pStr;
}
习题8.4 定义一个函数,其参数是一个字符串,返回该字符串中的单词数(单词以空格或标点符号来分隔。假设字符串不包含单双引号,也就是数没有像isn't这样的单词)。定义第二个函数,它的第一个参数是一个字符串,第二个参数是一个数组,该函数将第一个字符串变元分隔成单词,把这些单词存储在第二个数组变元中,最后返回存储在数组中的单词。定义第三个函数,其参数是一个字符串,返回该字符串中的字母数。使用这些函数实现一个程序,从键盘读入含有文本的字符串,输出文本中的所有单词,输出顺序是按照单词中的字母数,由短到长。
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
int wordCount(const char *);
void stringToArray(char *, char **);
int alphaCount(char *);
int main()
{
char buffer[100] = "";
char *pStr = buffer;
char **pWord = NULL;
char *pTemp = NULL;
int words = 0;
pWord = malloc(20 * sizeof(char *));
gets(buffer);
words = wordCount(pStr);
stringToArray(pStr, pWord);
for (int i = 0; i < words - 1; i++)
{
for (int j = 0; j < words - 1 - i; j++)
{
if (strlen(*(pWord + j)) > strlen(*(pWord + j + 1)))
{
pTemp = *(pWord + j);
*(pWord + j) = *(pWord + j + 1);
*(pWord + j + 1) = pTemp;
}
}
}
for (int i = 0; i < words; i++)
{
printf("%s\n", *(pWord + i));
}
return 0;
}
int wordCount(const char *pStr)
{
int count = 0;
bool isFirst = true;
while (*pStr) {
if (isalpha(*pStr)) {
if (isFirst) {
isFirst = false;
count++;
}
}
else
{
isFirst = true;
}
pStr++;
}
return count;
}
void stringToArray(char *pStr, char **pWord)
{
char *pBuffer = malloc(20 * sizeof(char));
int wordCount = 0;
int i = 0;
while (*pStr) {
if (isalpha(*pStr))
{
while (isalpha(*pStr)) {
*(pBuffer + i) = *pStr;
i++;
pStr++;
}
*(pBuffer + i) = '\0';
*(pWord + wordCount) = pBuffer;
wordCount++;
pBuffer = malloc(20 * sizeof(char));
i = 0;
}
else
{
pStr++;
}
}
}
int alphaCount(char *pStr)
{
int count = 0;
while (*pStr++) {
count++;
}
return count;
}
第9章 函数再探
习题9.1 函数原型:
double power(doulbe x, int n);
会计算并返回xn。因此power(5.0, 4)会计算5.0*5.0*5.0*5.0,它的结果是625.0。将power()函数实现为递归函数,再用适当的main版本演示它的操作。
#include <stdio.h>
double power(double, int);
int main()
{
printf("power(5.0, 4) = %lf\n", power(5.0, 4));
return 0;
}
double power(double x, int n)
{
if (n == 1)
{
return x;
}
else
{
return x * power(x, n - 1);
}
}
习题9.2 函数原型:
double add(double a, double b); // returns a + b
double subtract(double a, double b); // returns a - b
double multiply(double a, double b); // returns a * b
double array_op(double array[], int size, double (\*pfun) (double, double));
array_op()函数的参数是:要运算的数组、数组元素数目以及一个函数指针,该函数指针指向的函数定义了在连续几个元素上进行的操作。在实现array_op()函数时,将subtract()函数传送为第三个参数,subtract()函数会用交替符号组合这些元素。因此,对于有4个元素x1、x2、x3、x4的数组,subtract()函数会计算x1-x2+x3-x4的值。
用适当的main()版本演示这些函数的运作。
#include <stdio.h>
double add(double, double);
double subtract(double, double);
double multiply(double, double);
double array_op(double[], int, double (*) (double, double));
int main()
{
double array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
printf("array_op() = %lf\n", array_op(array, 5, subtract));
return 0;
}
double add(double a, double b)
{
return a + b;
}
double subtract(double a, double b)
{
return a - b;
}
double multiply(double a, double b)
{
return a * b;
}
double array_op(double array[], int size, double (*pfun) (double, double))
{
double sum = 0.0;
for (int i = 0; i < size / 2; i++)
{
sum += subtract(array[i * 2], array[i * 2 + 1]);
}
if (size % 2 != 0) {
sum += array[size - 1];
}
return sum;
}
习题9.3 定义一个函数,它的参数是字符串数组指针,返回一个将所有字符串合并起来的字符串指针,每个字符串都用换行符来终止。如果输入数组中的原字符串将换行符作为最后一个字符,函数就不能给字符串添加另一个换行符。编写一个程序,从键盘读入几个字符串,用这个函数输出合并后的字符串。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARR_LEN 5
#define BUF_LEN 100
char *custom_concat(char *[]);
int main()
{
char *pStr[ARR_LEN] = { NULL };
for (int i = 0; i < ARR_LEN; i++)
{
pStr[i] = malloc(BUF_LEN * sizeof(char));
gets(pStr[i]);
}
printf("%s\n", custom_concat(pStr));
return 0;
}
char *custom_concat(char *pStr[])
{
char *pResult = NULL;
char *pTemp = NULL;
int totalLen = 0;
for (int i = 0; i < ARR_LEN; i++)
{
totalLen += strlen(pStr[i]);
}
pResult = malloc((totalLen + 1) * sizeof(char));
pTemp = pResult;
for (int i = 0; i < ARR_LEN; i++)
{
strncpy(pTemp, pStr[i], strlen(pStr[i]));
pTemp += strlen(pStr[i]);
}
return pResult;
}
习题9.4 一个函数的原型是:
char *to_string(int count, double first, ...);
这个函数返回一个字符串,这个字符串含有第二及其后参数的字符串表示,每个参数都有两位小数,参数间用逗号隔开。第一个参数是从第二个参数算起的参数个数。编写一个main()函数,演示这个函数的运作。
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
char *to_string(int , double, ...);
int main()
{
printf("%s\n", to_string(4, 1.0, 2.0, 3.0, 4.0));
return 0;
}
char *to_string(int count, double first, ...)
{
char *pStr = malloc(100 * sizeof(char));
char buffer[100] = "";
va_list parg;
va_start(parg, first);
sprintf(buffer, "%.2f", first);
strcat(pStr, buffer);
for (int i = 1; i < count; i++) {
sprintf(buffer, ", %.2f", va_arg(parg, double));
strcat(pStr, buffer);
}
va_end(parg);
return pStr;
}
第10章 基本输入输出操作
习题10.1 编写一个程序,读入、存储以及输出下列5种类型的字符串,每个字符串占一行,字符串间不能有空格。
- 类型1:一串小写字母,后跟一个数字(如 number1)
- 类型2:两个单词,每个单词的第一个字母大写,单词间用-分隔(如Seven-Up)
- 类型3:小数(如7.35)
- 类型4:一串大小写字母以及空格(如Oliver Hardy)
- 类型5:一串除了空格及数字外的任何字符(如floating-point)
以下是这5种输入类型的例子,要分开读入这些字符串:
baby1on5Jhon-Boy3.14159Stan Laurel'Winner!'
#include <stdio.h>
int main()
{
char str[5][100] = {""};
for (int i = 0; i < 5; i++)
{
printf("%d -> ", i + 1);
gets(str[i]);
}
for (int i = 0;i < 5; i++)
{
printf("%s", str[i]);
}
printf("\n");
return 0;
}
习题10.2 编写一个程序,读入以下数值,并输出它们的和:
$3.50, $ 0.75, %9.95, %2. 50
#include <stdio.h>
int main()
{
float number[4] = { 0.0f };
float sum = 0.0f;
char str[100] = "";
int i = 0;
for ( ; i < 99; )
{
str[i] = getchar();
if (('0' <= str[i] && str[i] <= '9') || str[i] == '.')
{
i++;
}
else if (str[i] == '\n')
{
break;
}
}
str[i] = '\0';
sscanf(str, "%4f%4f%4f%4f", &number[0], &number[1], &number[2], &number[3]);
for (int i = 0;i < 4; i++)
{
sum += number[i];
}
printf("average = %.2f\n", sum / 4);
return 0;
}
习题10.3 定义一个函数,其参数是一个double类型的数组,输出该数组和数组中的元素个数。这个函数的原型如下:
void show(double array[], int array_size, int field_width);
输出的值5个一行,每个值有两位小数,字符宽度是12。在程序中使用这个函数输出从1.5到4.5的值,每次增加0.3(如:1.5、1.8、2.1、...、4.5)。
#include <stdio.h>
void show(double[], int, int);
int main()
{
double array[] = {1.5, 1.8, 2.1, 2.4, 2.7, 3.0, 3.3, 3.6, 3.9, 4.2, 4.5};
show(array, 11, 12);
return 0;
}
void show(double array[], int array_size, int field_width)
{
char buffer[10] = "";
sprintf(buffer, "%%%d.2f", field_width);
for (int i = 0; i < array_size; i++)
{
if (i % 5 == 0) {
printf("\n");
}
printf(buffer, array[i]);
}
printf("\n");
}
习题10.4 定义一个函数,使用getchar()函数从stdin中读入一个字符串,这个字符串用特定的字符终止,这个特定的终止字符作为第二个变元传给这个函数。因此,函数的原型如下:
char *getString(char *buffer, char end_char);
返回值是一个指针,它是这个函数的第一个变元。编写一个程序,使用这个函数从键盘上读取并输出5个以冒号终止的字符串。
#include <stdio.h>
char *getString(char *, char);
int main()
{
char buffer[5][100];
for (int i = 0; i < 5; i++)
{
getString(buffer[i], ':');
}
for (int i = 0; i < 5; i++)
{
printf("%s\n", buffer[i]);
}
return 0;
}
char *getString(char *buffer, char end_char)
{
char *pStr = buffer;
char ch = '\0';
for (;;)
{
ch = getchar();
if (ch != end_char) {
*pStr++ = ch;
}
else
{
*pStr = '\0';
break;
}
}
return buffer;
}
第11章 结构化数据
习题11.1 定义一个结构类型Length,它用码、英尺和英寸表示长度。定义一个add()函数,它相加两个Length变元,返回Length类型的总和。定义第二个函数show(),显示其Length变元的值。编写一个程序,从键盘输入任意个单位的码、英尺以及英寸的长度,使用Length类型、add()、和show()函数去汇总这些长度,并输出总长。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
struct Length
{
int yard;
int foot;
int inch;
};
struct Length *add(struct Length *, struct Length *);
void show(struct Length *);
int main()
{
struct Length *pSum = NULL;
struct Length **pLength = NULL;
int count = 0;
char ch = '\0';
pSum = malloc(sizeof(struct Length));
pSum->yard = 0;
pSum->foot = 0;
pSum->inch = 0;
pLength = (struct Length **) malloc(sizeof(struct Length *));
do
{
count++;
pLength = (struct Length **) realloc(pLength, count * sizeof(struct Length *));
*(pLength + count - 1) = malloc(sizeof(struct Length));
printf("请输入Length:\n");
printf("Length.yard -> ");
scanf("%d", &(*(pLength + count - 1))->yard);
printf("Length.foot -> ");
scanf("%d", &(*(pLength + count - 1))->foot);
printf("Length.inch -> ");
scanf("%d", &(*(pLength + count - 1))->inch);
getchar();
ch = getchar();
} while(tolower(ch) == 'y');
for (int i = 0; i < count; i++)
{
pSum = add(pSum, *(pLength + i));
}
show(pSum);
return 0;
}
struct Length *add(struct Length *a, struct Length *b)
{
struct Length *pLength = (struct Length *)malloc(sizeof(struct Length));
pLength->yard = a->yard + b->yard;
pLength->foot = a->foot + b->foot;
pLength->inch = a->inch + b->inch;
return pLength;
}
void show(struct Length *length)
{
printf("yard=%d, foot=%d, inch=%d\n", length->yard, length->foot, length->inch);
}
习题11.2 定义一个结构类型,它含有一个人的姓名及电话号码。在程序中使用这个结构,输入一个或多个姓以及对应的电话号码,将输入的数据存储到一个结构数组中。程序允许输入姓氏,输出对应于该姓氏的所有电话号码,可以选择是否要输出所有的姓名及他们的电话号码。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
struct Contacts
{
char *name;
int phoneCount;
char **phone;
};
struct Contacts *newContacts();
void printContacts(struct Contacts *);
int main()
{
struct Contacts **pContacts = NULL;
char isContinue = '\0';
int count = 0;
char buffer[100] = "";
pContacts = malloc(sizeof(struct Contacts *));
do
{
count++;
pContacts = realloc(pContacts, count * sizeof(struct Contacts *));
*(pContacts + count - 1) = newContacts();
printf("是否继续输入联系人信息(y/n):");
isContinue = getchar();
getchar();
} while (tolower(isContinue) == 'y');
printf("请输入姓名:");
gets(buffer);
for (int i = 0; i < count; i++)
{
if (strcmp(buffer, (*(pContacts + i))->name) == 0) {
printContacts(*(pContacts + i));
}
}
return 0;
}
struct Contacts *newContacts()
{
struct Contacts *pContacts = NULL;
char buffer[100] = "";
int count = 0;
char isContinue = '\0';
pContacts = malloc(sizeof(struct Contacts));
printf("请输入姓名:");
gets(buffer);
pContacts->name = malloc((strlen(buffer) + 1) * sizeof(char));
strcpy(pContacts->name, buffer);
pContacts->phone = malloc(sizeof(char *));
do
{
count++;
pContacts->phone = realloc(pContacts->phone, count * sizeof(char *));
printf("请输入电话号码:");
gets(buffer);
*(pContacts->phone + count - 1) = malloc((strlen(buffer) + 1) * sizeof(char));
strcpy(*(pContacts->phone + count - 1), buffer);
printf("是否继续输入电话号码(y/n):");
isContinue = getchar();
getchar();
} while(tolower(isContinue) == 'y');
pContacts->phoneCount = count;
return pContacts;
}
void printContacts(struct Contacts *pContacts)
{
printf("==========\n");
printf("name = %s\n", pContacts->name);
for (int i = 0; i < pContacts->phoneCount; i++)
{
printf("phone = %s\n", *(pContacts->phone + i));
}
printf("==========\n");
}
习题11.3 修改上一题的程序,将数据存储到链表中,按照姓名的字母顺序由小到大排序。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
struct Contacts
{
char *name;
int phoneCount;
char **phone;
struct Contacts *next;
};
struct Contacts *newContacts();
void printContacts(struct Contacts *);
int main()
{
struct Contacts *pHead = NULL;
struct Contacts *pCurrent = NULL;
struct Contacts *p = NULL;
struct Contacts *q = NULL;
char isContinue = '\0';
int count = 0;
pHead = malloc(sizeof(struct Contacts));
do
{
count++;
pCurrent = newContacts();
if (count == 1) {
pHead->next = pCurrent;
}
else
{
p = pHead;
q = pHead->next;
while (q) {
if (strcmp(pCurrent->name, q->name) > 0) {
p = q;
q = q->next;
}
else
{
break;
}
}
pCurrent->next = q;
p->next = pCurrent;
}
printf("是否继续输入联系人信息(y/n):");
isContinue = getchar();
getchar();
} while (tolower(isContinue) == 'y');
pCurrent = pHead;
for (int i = 0; i < count; i++)
{
printContacts(pCurrent->next);
pCurrent = pCurrent->next;
}
return 0;
}
struct Contacts *newContacts()
{
struct Contacts *pContacts = NULL;
char buffer[100] = "";
int count = 0;
char isContinue = '\0';
pContacts = malloc(sizeof(struct Contacts));
printf("请输入姓名:");
gets(buffer);
pContacts->name = malloc((strlen(buffer) + 1) * sizeof(char));
strcpy(pContacts->name, buffer);
pContacts->phone = malloc(sizeof(char *));
do
{
count++;
pContacts->phone = realloc(pContacts->phone, count * sizeof(char *));
printf("请输入电话号码:");
gets(buffer);
*(pContacts->phone + count - 1) = malloc((strlen(buffer) + 1) * sizeof(char));
strcpy(*(pContacts->phone + count - 1), buffer);
printf("是否继续输入电话号码(y/n):");
isContinue = getchar();
getchar();
} while(tolower(isContinue) == 'y');
pContacts->phoneCount = count;
pContacts->next = NULL;
return pContacts;
}
void printContacts(struct Contacts *pContacts)
{
printf("==========\n");
printf("name = %s\n", pContacts->name);
for (int i = 0; i < pContacts->phoneCount; i++)
{
printf("phone = %s\n", *(pContacts->phone + i));
}
printf("==========\n");
}
习题11.4 编写一个程序,从键盘上输入一段文本,然后使用结构计算每个单词的出现次数。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
struct WordUnit
{
int count;
char *word;
struct WordUnit *next;
};
void statistics(struct WordUnit *, char *);
void printWordUnit(struct WordUnit *);
int main()
{
char buffer[100] = "";
char temp[10] = "";
struct WordUnit *pHead = NULL;
struct WordUnit *pCurrent = NULL;
pHead = malloc(sizeof(struct WordUnit));
pHead->next = NULL;
gets(buffer);
for (int i = 0, j = 0; i < strlen(buffer) && j < strlen(buffer);)
{
for (int i = 0; i < 10; i++)
{
temp[i] = '\0';
}
if (isalpha(buffer[i]))
{
for (j = i; j < strlen(buffer) && isalpha(buffer[j]); j++)
;
for (int k = i; k < j; k++)
{
temp[k - i] = buffer[k];
}
statistics(pHead, temp);
i = j;
}
else
{
i++;
}
}
printWordUnit(pHead->next);
return 0;
}
void statistics(struct WordUnit *head, char *word)
{
bool isNewWord = true;
struct WordUnit *p = head->next;
struct WordUnit *q = head;
while (p) {
if (strcmp(p->word, word) == 0) {
p->count++;
isNewWord = false;
break;
}
q = p;
p = p->next;
}
if (isNewWord) {
p = malloc(sizeof(struct WordUnit));
p->count = 1;
p->word = malloc((strlen(word) + 1) * sizeof(char));
strcpy(p->word, word);
q->next = p;
}
}
void printWordUnit(struct WordUnit *p)
{
while (p) {
printf("%10s %2d\n", p->word, p->count);
p = p->next;
}
}
习题11.5 编写一个程序,读取任意多个姓名。用一个二叉树按升序输出所有的姓名,排序时先排姓氏,后排名字(例如 Ann Choosy 在 Bill Champ 的后面,在 Arthur Choosy 的前面)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct Name
{
char *firstName;
char *lastName;
struct Name *leftChild;
struct Name *rightChild;
};
struct Name *readName();
void printName(struct Name *);
void insertName(struct Name *, struct Name *);
int main()
{
struct Name *root = NULL;
char isContinue = '\0';
int count = 0;
do
{
if (count == 0) {
root = readName();
}
else
{
insertName(root, readName());
}
count++;
printf("是否继续输入姓名:");
isContinue = getchar();
getchar();
} while(tolower(isContinue) == 'y');
printName(root);
return 0;
}
struct Name *readName()
{
struct Name *p = malloc(sizeof(struct Name));
char buffer[20] = "";
printf("请输入姓氏:");
gets(buffer);
p->lastName = malloc((strlen(buffer) + 1) * sizeof(char));
strcpy(p->lastName, buffer);
printf("请输入名字:");
gets(buffer);
p->firstName = malloc((strlen(buffer) + 1) *sizeof(char));
strcpy(p->firstName, buffer);
p->leftChild = NULL;
p->rightChild = NULL;
return p;
}
void printName(struct Name *p)
{
if (p != NULL) {
printName(p->leftChild);
printf("%s %s\n", p->lastName, p->firstName);
printName(p->rightChild);
}
return;
}
void insertName(struct Name *root, struct Name *p)
{
if (root != NULL) {
if (strcmp(root->lastName, p->lastName) >= 0)
{
if (root->leftChild != NULL) {
insertName(root->leftChild, p);
}
else{
root->leftChild = p;
}
}
else
{
if (root->rightChild != NULL) {
insertName(root->rightChild, p);
}
else
{
root->rightChild = p;
}
}
}
return ;
}
第12章 处理文件
习题12.1 编写一个程序,将任意数目的字符串写入文件。字符串由键盘输入,程序不能删除这个文件,因为下一题还要使用这个文件。
#include <stdio.h>
#include <stdbool.h>
int main()
{
char buffer[100] = "";
const char fileName[10] = "data.txt";
FILE *pFile = NULL;
pFile = fopen(fileName, "a");
if (!pFile) {
printf("打开文件失败\n");
return 1;
}
do {
fgets(buffer, 100, stdin);
if (buffer[0] == '\n')
{
break;
}
fputs(buffer, pFile);
} while (true);
fclose(pFile);
return 0;
}
习题12.2 编写一个程序,读取上一题创建的文件。每次都以反向的顺序读取一个字符串,然后按照读取顺序将它们写入一个新文件。例如,程序读取最后一个字符串,将它写入新文件,再读取倒数第二个字符串,将它写入新文件,依次类推。
#include <stdio.h>
#include <stdbool.h>
int count(char *);
int main()
{
char buffer[100] = "";
char fileName[10] = "data.txt";
char fileNameNew[10] = "data2.txt";
FILE *pFile = NULL;
FILE *pFileNew = NULL;
pFile = fopen(fileName, "a");
if (!pFile) {
printf("打开文件失败\n");
return 1;
}
do {
fgets(buffer, 100, stdin);
if (buffer[0] == '\n')
{
break;
}
fputs(buffer, pFile);
} while (true);
fclose(pFile);
pFile = fopen(fileName, "r");
if (!pFile) {
printf("打开文件失败\n");
return 1;
}
fclose(pFile);
pFileNew = fopen(fileNameNew, "a");
for (int i = count(fileName) - 1; i >= 0; i--)
{
pFile = fopen(fileName, "r");
for (int j = 0; j < i; j++)
{
fgets(buffer, 100, pFile);
}
fgets(buffer, 100, pFile);
fclose(pFile);
fputs(buffer, pFileNew);
}
fclose(pFileNew);
return 0;
}
int count(char *pName)
{
FILE *pFile = NULL;
pFile = fopen(pName, "r");
int count = 0;
char buffer[100] = "";
while (fgets(buffer, 100, pFile)) {
count++;
}
fclose(pFile);
return count;
}
习题12.3 编写一个程序,从键盘读入姓名和电话号码,将它们写入一个文件。如果这个文件不存在,就写入一个新文件。如果文件已存在,就将它们写入该文件。这个程序需要提供列出所有数据的选项。
#include <stdio.h>
struct Contacts
{
char name[20];
char phone[3][15];
};
char fileName[20] = "contacts.txt";
void add();
int main()
{
add();
return 0;
}
void add()
{
struct Contacts con;
FILE *pFile = NULL;
pFile = fopen(fileName, "a");
printf("\n请输入姓名:");
fgets(con.name, 20, stdin);
for (int i = 0; i < 3; i++)
{
printf("请输入第 %d 个电话号码:", i + 1);
fgets(con.phone[i], 15, stdin);
}
fprintf(pFile, "%20s%15s%15s%15s", con.name, con.phone[0], con.phone[1], con.phone[2]);
fclose(pFile);
}
习题12.4 扩展上一题的程序,提取对应指定的姓名的所有电话号码。这个程序允许进一步查询,添加新的姓名和电话号码,删除已有的项。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
struct Contacts
{
char name[20];
char phone[3][15];
};
char fileName[20] = "contacts.txt";
void add();
void printContacts(struct Contacts *);
bool searchByContactsName(char *, struct Contacts *, char *);
void printAll(char *);
void deleteByContactsName(char *fileName, char *contactsName);
int main()
{
// 此处省略了函数的调用
return 0;
}
void add()
{
struct Contacts con;
FILE *pFile = NULL;
pFile = fopen(fileName, "a");
printf("\n请输入姓名:");
fgets(con.name, 20, stdin);
for (int i = 0; i < 3; i++)
{
printf("请输入第 %d 个电话号码:", i + 1);
fgets(con.phone[i], 15, stdin);
}
fprintf(pFile, "%20s%15s%15s%15s", con.name, con.phone[0], con.phone[1], con.phone[2]);
fclose(pFile);
}
void printContacts(struct Contacts *p)
{
printf("姓名:%s\n\t电话1:%s\n\t电话2:%s\n\t电话3:%s\n", p->name, p->phone[0], p->phone[1], p->phone[2]);
}
void deleteByContactsName(char *fileName, char *name)
{
FILE *pFileOld = NULL;
FILE *pFileNew = NULL;
struct Contacts c;
char tempFileName[20] = "temp.txt";
if (!searchByContactsName(fileName, &c, name))
return;
pFileOld = fopen(fileName, "r");
pFileNew = fopen(tempFileName, "a");
while(fscanf(pFileOld, "%20s%15s%15s%15s", c.name, c.phone[0], c.phone[1], c.phone[2]) != EOF)
{
if (strcmp(name, c.name)) {
fprintf(pFileNew, "%20s%15s%15s%15s", c.name, c.phone[0], c.phone[1], c.phone[2]);
}
}
fclose(pFileOld);
fclose(pFileNew);
remove(fileName);
rename(tempFileName, fileName);
}
bool searchByContactsName(char *fileName, struct Contacts *c, char *name)
{
FILE *pFile = fopen(fileName, "r");
while(fscanf(pFile, "%20s%15s%15s%15s", c->name, c->phone[0], c->phone[1], c->phone[2]) != EOF)
{
if (strcmp(c->name, name) == 0) {
return true;
}
}
return false;
}
void printAll(char *fileName)
{
struct Contacts c;
FILE *pFile = NULL;
pFile = fopen(fileName, "r");
while(fscanf(pFile, "%20s%15s%15s%15s", c.name, c.phone[0], c.phone[1], c.phone[2]) != EOF)
{
printContacts(&c);
}
fclose(pFile);
}
第13章 支持功能
习题13.1 定义一个COMPARE(x, y)宏。如果x<y,就返回-1,如果x==y,就返回0,如果x>y就返回1.编写一个例子,说明这个宏可以正常工。这个宏会优于完成相同任务的函数码?
#include <stdio.h>
#define COMPARE(x, y) (x) > (y) ? 1 : ((x) == (y) ? 0 : -1)
int main()
{
printf("%d\n", COMPARE(5, 3));
return 0;
}
习题13.2 定义一个函数,返回含有当前时间的字符串,如果变元是0,它的格式就是12小时制(a.m./p.m.),如果变元是1,它的格式就是24小时制。编写一个程序,说明这个函数可以正常工作。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
char *getTimeString(int format);
int main()
{
printf("%s\n%s\n", getTimeString(0), getTimeString(1));
return 0;
}
char *getTimeString(int format)
{
char *pStr = NULL;
char buffer[20] = "";
struct tm *t = NULL;
time_t val = time(NULL);
t = localtime(&val);
if (format == 0) {
sprintf(buffer, "%02d:%02d:%02d", t->tm_hour, t->tm_min, t->tm_sec);
}
else
{
sprintf(buffer, "%02d:%02d:%02d", t->tm_hour > 12 ? t->tm_hour - 12 : t->tm_hour, t->tm_min, t->tm_sec);
}
pStr = (char *)malloc((strlen(buffer) + 1) * sizeof(char));
strcpy(pStr, buffer);
return pStr;
}
习题13.3 定义一个print_value(expr)宏,在新的一行上输出 exp = result,其中result的值由expr算出。编写一个例子,说明这个宏可以正常工作。
#include <stdio.h>
#define print_value(expr) printf("exp = %d\n", expr)
int main()
{
print_value(3 + 2);
return 0;
}
网友评论