作为一个刚入坑的 C语言初学者,我选择了《C程序设计语言》(谭浩强) 作为自学教材。课后的习题当然是要完成的。习题不便于保存在本机的 .c 文件里(至少当时的问题想法不方便),便有了这篇文章。
声明: 我使用的 IDE 是 C-Free。
Tip:篇幅很长,建议使用 Ctrl + F 搜索或者是看目录。搜索格式:习题 x-x
=========
#include
int main()
{
printf("Hello,world\n");
}
题目让我们删除一些内容,在看看会发生什么?
其实不论删除什么(除了Hello,world)中的任何一个令牌,都无法编译。
这一题就这样吧。
=========
题目的意思是在 Hello,world 的后面加上一个C语言中没有的转义字符。最后的结果是无法通过编译,编译器报错。
=========
首先亮出温度转换程序(书中给的转换程序太多了,我随便选了一个。其实不论怎么样,加一个标题都是很简单的。)。
#include
int main()
{
int fahr, celsius; // fahr 为华氏度,celsius 为摄氏度
int lower,upper,step;
lower = 0; // 温度的下限
upper = 300; // 温度的上限
step = 20; // 步长
fahr = lower;
while (fahr <= upper)
{
celsius = 5*(fahr-32)/9;
printf ("%3d\t%3d\n",fahr,celsius);
fahr = fahr + step;
}
return 0;
}
这里给出的程序和书中的不太一样。这是我个人的习惯。但意思和书上的差不多
执行结果:
题目要求我们打印一个标题,也就是在第一行显示出华氏度与摄氏度。我们只要在程序中加入一个 printf 就好了。具体实现见代码。
注意:这个 printf 一定不能加在 while块(for同理)中,不然会循环打印。
#include
int main()
{
int fahr, celsius;
int lower,upper,step;
lower = 0;
upper = 300;
step = 20;
fahr = lower;
//我们在这里加上表的标题。其实只要不加在循环中,加在哪里都是可以的。
printf ("华氏度\t摄氏度\n") ;
while (fahr <= upper)
{
celsius = 5*(fahr-32)/9;
printf ("%3d\t%3d\n",fahr,celsius);
fahr = fahr + step;
}
return 0;
}
=========
题目让我们打印摄氏度度转换为华氏度的转换表。这个问题的很好处理。但是,因为摄氏度转为华氏度的计算中含有小数点,所以这里我们要把 fahr 与 celsius 改成 folat 类型。下面是我们要修改的地方。
代码如下:
#include
int main()
{
float fahr,celsius;
int lower,upper,step;
lower = 0;
upper = 300;
step = 20;
celsius = lower;
printf ("摄氏度℃ 华氏度℉\n");
while (celsius <= upper)
{
fahr = celsius * 1.8 + 32.0;
printf("%6.1f\t%10.2f\n",celsius,fahr);
celsius = celsius + step;
}
return 0;
}
=========
代码如下:(以 练习1-3 中的代码为例。)
#include
int main()
{
int fahr, celsius;
int lower,upper,step;
lower = 0;
upper = 300;
step = 20;
fahr = upper;
printf ("华氏度\t摄氏度\n") ;
while (fahr >= lower)
{
celsius = 5*(fahr-32)/9;
printf ("%3d\t%3d\n",fahr,celsius);
fahr = fahr - step;
}
return 0;
}
=========
拿到这个题目,我们要知道 getchar () != EOF 的值为多少,只需要用 printf 把它的值打印出来就好了。
在这里我加入了一个 word 变量来取代它的值。
思路:
代码如下:
#include
int main()
{
int word;
while (word = getchar() != EOF)
printf("%d",word);
return 0;
}
题末
=========
由于 EOF 的值在 stdio.h 头文件中已经定义,所以我们只需要用 printf 将它的值整形打印出来就行了。
代码如下:
#include
int main()
{
printf("EOF = %d",EOF);
}
=========
代码如下:
#include
int main()
{
int TabCharNum,SpaceNum,LinefeedNum,word;
TabCharNum = SpaceNum = LinefeedNum = 0;
while((word = getchar()) != EOF)
{
if(word == '\t')
++TabCharNum;
if(word == ' ')
++SpaceNum;
if(word == '\n')
++LinefeedNum;
}
printf("制表符=%d\n空格=%d\n换行符=%d\n",TabCharNum,SpaceNum,LinefeedNum);
return 0;
}
=========
首先,题目让我们把输入复制到输出,实际上就是输入什么就打印什么。多个空格用一个空格代替,这个我们先设置一个变量并初始为零,再判断输入的字符是不是空格。如果是空格,再判断下一个字符是不是空格。如果是,这个变量就加一,如果不是,这个变量就归零。再判断这个变量是否大于1。如果大于一,输出空,否则就输出下一个字符。
代码如下:
#include
int main()
{
int SpaceNum,word;
SpaceNum = 0;
while((word = getchar()) != EOF)
{
if(word == ' ')
{
++SpaceNum;
}
else
{
SpaceNum = 0;
}
if(SpaceNum > 1)
{
;
}
else
{
putchar(word);
}
}
return 0;
}
=========
这道题具体的思路和 习题 1-9 差不多。只要判断输入字符是不是这些转移字符,再 printf 出这个字符来就行了。
代码如下:
#include
int main()
{
int word;
while((word = getchar()) != EOF)
{
if(word == '\t')
printf("\\t");
if(word == '\\')
printf("\\\\");
if(word == '\b')
printf("\\b");
if(word != '\t' && word != '\\' && word != '\b')
putchar(word);
}
return 0;
}
==========
这里先鸽一下。估计要鸽很久,至少要等到我高考完了之后(没准我心血来潮读了高四高五呢)。
下面我专门更新一下习题 1-13.
==========
题目让我们编写一个程序,打印输入单词长度的直方图。实际上就是统计输入额内容中,单词长度为1的单词有多少个,单词长度为2的单词有多少个……然后再把结果打印出来。
首先我们给单词下一个定义(这里的定义是我自己的想法,不一定是正确的,也不一定是里奇的想法):
不包含\t \n与空格的一串连续的字母
有了定义就简单了。
首先,我们设置一个变量 WordLength,用于临时保存单词的长度,然后开始读取单词的长度,如果读到了 \t \n 或者是空格,就说明这个单词结束了,停止计算单词的长度,然后把读到的长度保存到一个变量里面去,临时保存长度的变量 WordLength 归零,重新开始新一轮的计算。等到所有内容都计算完后,开始打表。
水平直方图比较简单。下面我假设长度为 3 的单词有 5 个,且所有的单词长度都在区间 [1,20] 中。
首先我们可以设置一个变量 Num 变量,赋值1;设置一个 PrintChar 变量,赋值1。
打印表头3 |,表示这一行是长度为 3 的单词,并且用 | 将表头与表隔开来。
然后用 PrintChart 的值去与 5 比较,如果 PrintChart ≤ 5,就打印一个■表示1格,并且 PrintfChart 自加1。如果 PrintfChart >5,那么就打印 [5] 表示有 5 个单词的长度为 3。
代码如下:
#include
#include
int main()
{
// 设置标题
SetConsoleTitle("统计单词长度-水平直方图");
printf("提示:输入完文本后,另起一行按下 Ctrl + z 结束输入。\n");
// 初始化 保存相应单词长度的单词数量 的数组 和其他变量
int WordLengthNum[21] = {0};
int Num;
int WordLength = 0;
int PrintChart = 1;
int word;
// 获取单词长度并保存
while((word = getchar()) != EOF)
{
if(word == '\t'||word == '\n'||word == ' ')
{
++WordLengthNum[WordLength];
WordLength = 0;
}
else
{
++WordLength;
}
}
system("cls");// 清屏,把上面我们输入的内容清除
// 绘制直方图
printf("==========\n下面是我们要打印的水平表\n==========\n");
for(Num = 1;Num <= 20;++Num)
{
printf("%d |",Num);
for(PrintChart = 1; PrintChart <= WordLengthNum[Num];++PrintChart)
{
printf("■");
}
printf("[%d]\n",WordLengthNum[Num]);
}
printf("==========\n");
printf("Press any key to exit.");
system("pause>nul");
return 0;
}
我们用下面的示例文本放到程序里面去。
a a a a a a a a a a
bb bb bb bb bb bb bb
ccc ccc ccc ccc
dddd dddd dddd dddd dddd dddd dddd
eeeee eeeee eeeee eeeee eeeee
ffffff ffffff ffffff ffffff ffffff ffffff ffffff ffffff
ggggggg ggggggg ggggggg
上面的文本中,a有10个,bb有7个,ccc有4个,dddd有7个,eeeee有5个,ffffff有8个,ggggggg有3个,它们分别对应着单词长度为1-7的单词数量。
执行结果:
完美运行。
但当我们输入的单词有几十个甚至是上百个上千个,很可能会出现下面的情况
那么这种情况要怎么解决呢?
根据我多年写批处理的经验,我们只需要添加一段代码,修改一下缓冲区的大小,把水平方向的缓冲区拉长就可以了。(不是修改这个窗口的大小!!)
具体怎么实现我也不知道,我百度了一下,找到了代码。
代码如下:
#include
int main()
{
// 设置缓冲区的大小
SMALL_RECT winPon={0,0,25,10};
HANDLE con=GetStdHandle(STD_OUTPUT_HANDLE);
COORD buf={10000,25};// 缓冲区长10000,高25
SetConsoleScreenBufferSize(con,buf);
}
// 包含头文件 windows.h 后直接把 main 中的代码插到程序的 main 中就行了。
修改之后就会发现,窗口底部多了个横着的滚动条,我们可以拖动滚动条来看数据。
最后的效果:
OK,水平表就这么打好了。
垂直直方图比较困难。但不是不能实现。
C语言它是一行一行输入输出的,不能一列一列地输出(可能可以但我不知道)。那我们只能按着它的习惯来横着输出垂直的直方图。
先写到这,上课去了。