《The C Programming Language》阅读笔记1

第1章 导言


1.1 入门
书本非常详细,hello world程序,略。

练习1-1 略
练习1-2 “\c”并不属于转义字符,作者骗人的


1.2 变量与算术表达式
同样非常详细,不过有问题可以注意
作者为整型右对齐修改后的代码:

printf("%3d %6d\n",fahr,celsius);

这句话中输出celsius的值从-17到148,实际只需3个数字宽(注意负号和小数点都需要占1个数字宽)。因此代码改成

printf("%3d %3d\n",fahr,celsius);

即可达到右对齐效果。如果小于%3d,例如%2d,则数字宽为3的数依旧左对齐。
同理,浮点数右对齐

printf("%3.0f %6.1f\n",fahr,celsius);

修改为

printf("%3.0f %5.1f\n",fahr,celsius);

也可达成目的。

练习1-3 略
练习1-4 略


1.3 for语句
详细,略。for语句和while语句翻译成汇编仅有少许差异,然而这并不是优化关键点,因此没必要为了他们的执行效率而只用一个。如何选择while和for?注意作者的一句话:“在实际编程中,可以选择while与for中的任意一种循环语句,主要要看使用哪一种更清晰。for语句比较适合初始化和增加步长都是单条语句并且逻辑相关的情形,因为它将循环控制语句集中放在一起,且比while语句更紧凑。

练习1-5 略


1.4 符号常量
简单,略


1.5 字符输入/输出
1.5.1文字复制
注意EOF并不是真的打EOF进去……规定中在Windos 操作系统EOF是Ctrl+Z ;Linux系统下则是Ctrl + D。

练习1-6 犯了个很白痴的错误:printf(“%d”,c)中%d打成了%c,结果Termina输出了一个小方框……
练习1-7 EOF值是-1哟

1.5.2 字符计数
测试书本原代码时遇上一个很好玩的东西,如下:

当我输入“abdfdskfj”9个字符时,它会计算出10个字符。从这里可以看出,它是将换行符’\n’也计入了。经过网上搜索得出结论,getchar()先等待缓存区存入我们输入的字符,直到遇到回车键“\n”,开始每次从stdin流中取出一个数字赋给c,同时“\n”也会作为取出的字符
那如果我不想计算’\n’呢,就可以将

for(nc = 0; getchar() != EOF; ++nc);

改为

for(nc = 0; getchar() != '\n'; ++nc);

但是这也会带来一个问题,就是当按下回车键时,也会跳出循环,就无法再接受下一次输入了。

1.5.3 行计数

练习1-8 略
练习1-9 答案中提供了3种思路。
第一是用一个标志inspace,值为0代表在空格外,值为1代表在空格内,当检测到空格同时inspace=1,则代表这是第一个空格,可以输出空格:

#include <stdio.h>

int main(void)
{
    int c;
    int inspace;

    inspace = 0;
    while((c = getchar()) != EOF){
        if(c == ' ')
        {//注意这里一定要有括号,否则底下的else会依照就近原则选择if语句
            if(inspace == 0){
                inspace = 1;
                putchar(c);
                }
            }
        else
        {
            inspace = 0;
            putchar(c);
        }
    }
    return 0;
}

第二种思路是通过比较本次输入值与前次输入值是否都为空格,如果都是的话则输出空格值:

#include <stdio.h>

int main()
{
    int c, pc; //c为本次输入,pc为前次输入
/* set pc to a value that wouldn't match any character, in case
this program is ever modified to get rid of multiples of other
characters */
    pc = EOF;
    while ((c = getchar()) != EOF) {//注意不要漏括号
        if (c == ' '){
            if (pc != ' ') 
                putchar(c);
        }
        else{
            putchar(c);
            pc = c;
        }
        return 0;
}

第三种思路是遇到第一个空格后判断之后接受到的是否为非空格,是的话继续输出,否则原地等待。注意该思路容易有漏洞:

#include <stdio.h>

int main(void)
{
    int c;

        while ((c = getchar()) != EOF) {
            if (c == ' ') {
                putchar(c);
                while((c = getchar()) == ' ' && c != EOF)//漏洞在这!!!等待同时要注意是否遇上了结束信号!!!
                        ;//原地等待
            }
            if (c == EOF)
                break; //如果遇上结束符号则跳出循环
            putchar(c);//遇上字符打出字符
}
return 0 

练习1-10 网上的课后答案两种方法本质是相同的,只是后一种方法用了符号常量,同时用了switch语句。应注意如果用putchar输出,每次只能输出一个字符。

1.5.4 单词计数
我们发现这里作者又用了标志量state来记录在单词内和在单词外的两种状态,这给我们一种启示,或许这种思路更容易写代码。有学过VHDL的人就更清楚状态转换这种东西。

练习1-11 这道题是锻炼我们单元测试的能力,课后答案如下:
0.inputfile contains zero words
1.inputfile contains 1 enormous word without any new lines
2.inputfile contains all white space without newlines
3.inputfile contains 66000 newlines
4.inputfile contains word /{huge sequence of white-space of different kinds}/ word
5.input file contains 66000 single letter words, 66 to the line
6.input file contains 66000 words without any newlines
7.input file is /usr/dictcontents (or equivalent)
8.input file is full collection of moby words
9.input file is binary (e.g. its own executable)
10.input file is /dev/nul (or equivalent)
我归纳了一下,是
0.一个单词都没有情况
1.单行超长单词
2.单行超长泛空格符
3.行数极限
4.词+超长泛空格+词
5.多行单字符词极限
6.单行多字符词极限
7.8.9.10是文件格式测试
然而我还没总结出思路是什么……其中选择6600是为了检测整型是否溢出。
接下来答案给出了生成输入文件0-6的代码,我就不贴了,感兴趣可以自己去看看。
练习1-12 跟练习1-9思路一致,只要把检测到第一个空格时输出空格换成输出换行符即可。


今天先写到这~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值