明解C语言读书笔记
1.puts 可按顺序输出作为实参的字符串,并在结尾换行,puts(“……”)与printf(“……\n”)的作用基本相同,但是不能进行格式设定和数值的输出。
2.格式化字符串中转化说明以外的字符,基本都会原样输出
printf的格式化字符串“%%”两个%只显示一个,例如“5%%3”显示为5%3,puts不具备转换说明功能,所以只用一个%
3./除法结果是小于代数商的最大整数还是大于,取决于编译器,%取余运算也是这样
4.int类型的取值范围是-32767——32767
浮点数不能进行取余,只有整数能
%09.9f 0标志,数值前面有空余位,用0补齐 9连同小数点和小数点后后共九位,.9表示小数点取九位,如果设定-,会左对齐,未设定右对齐
精度指最小位数,不指定,整数的时候默认为1,浮点数默认为6
5.>=与<=之间没有空格
6.条件运算符 ?: 是三目运算符
用条件运算符求差的绝对值 (a-b)>0?(a-b):(b-a)
一道有意思的题:求a,b,c最大值,max=a
if(b>max) max=b ; if(c>max) max=c;
7.短路求值
8.do{}while()语句 do……while +switch语句 做一个石头剪刀布游戏
9.用递增递减运算符简化程序代码 如 printf(“%d”,no);no--;可以写成printf(“%d”,no--); 后置递减预算符:no的值在显示之后递减。 同样使用符合赋值运算符更简洁
10.今天白天刷PTA的时候一道题的判断老是过不了,今晚上我看while的判定我发现问题了,这个问题我在C++ primer里也看到过,while 和 for的问题。 在节点尤其重要 明解C语言92页
11.putchar(‘A’)可显示单一字符A
12.在多重循环语句中,break仅结束本层循环,continue仅跳过本次循环,再次进入本层循环
13.这本书有一些印刷错误和内容错误,但是不多
14.标识符(变量名or函数名)不能以数字开头,必须以字母或者下划线_开头,但是以下划线开头的标识符(如_x,_comp)和仅有一个大写英文字母的标识符(如A、Z),有可能是编译内部使用的,因此最好不要用作变量和函数的标识符。
15.puts输出字符串常量换行的时候必须再加双引号“”
puts(“A”
“B”);
16.宏名一般用大写字母表示,使用宏可以提高程序的质量
17.比如max是求两个数最大值的函数,求四个数最大值可以用
max(max(a,b),max(c,d))
18.明解的很多基础小函数给了我很大的启发
19.static会在main执行之前被创建,整个程序结束消失,如果不显示初始化,会被初始化为0
20.程序运行时,会执行main的主体部分,不会执行函数体之外的
21.哨兵查找法,翁恺讲过
22.负数的符号和绝对值:符号位从1变为0,反码:符号位1不变,其余取反,补码:反码+1
符号和绝对值、反码、补码的共同之处是最高位表示数值的符号
23.按位运算只能用于整数,用于浮点数会出错,感觉这一块有点难,不要对负数进行位移
24.整形后缀
25.浮点型后缀,大小写F表示float,大小写L表示long double,有时可以忽略整数部分和小数部分
26.当用浮点数进行循环控制时可能会进行死循环
27.函数式宏 #define sqr(x)((x)*(x))可计算各种数据类型的平方和,类似于C++的模板和Java的泛型,函数式宏也有副作用,也会变得臃肿
#define max(x,y) (((x)>y)?(x):(y))
下面是使用了该宏的表达式的计算四个数最大值:
max(max(a,b),max(c,d))
max(max(max(a,b),c),d)
28.冒泡排序:每一趟把最值,次最值放在一边
29.枚举 Invalid 枚举类型和switch的混合使用,使用宏定义月份会很麻烦,用枚举就很简单,只需要一行
30.使用树、图表、分治法的时候递归算法用的很多
31.getchar读取字符并返回,getchar和switch结合,统计输入字符类型数,再加个while循环哈哈,C语言的字符都是作为非负值处理,每个字符都有对应的编码(整数值)
32.C语言满足 缓存已满、输入换行符、立即输出 才会进行实际的输入输出操作,分别称为全缓冲、行缓冲、无缓冲
33.数字字符n-‘0’得到整数n,用转义字符表示字符串字面量中的字符
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("sizeof(\"123\") =%u\n ", (unsigned)sizeof("123"));
printf("sizeof(\"AB\\tC\") =%u\n ", (unsigned)sizeof("AB\tC"));
printf("sizeof(\"abc\\0def\") =%u\n ", (unsigned)sizeof("abc\0def"));
}
34.字符串
char a[5] = {‘a’,'s','d','f','\0'};
printf("字符串a为\"%s\"。\n", a);
a是字符串string的缩写
或者直接用 a[5]="asdf";初始化“asdf”也可以用{}括起来,{“asdf”}
a[0] = '\0';可以让a变成空串
scanf读取字符串的时候不能加& scanf(“%s”,a);
字符串数组,就是由字符串构成的二维数组
int i;
char cs[][6] = { "Turbo","NA","DOHC" };
for (i = 0; i < 3; i++)
printf("cs[%d]=\"%s\"\n", i, cs[i]);
35.str_toupper将字符改为大写
str_tolower将字符改为小写,
36.遍历字符串,直到出现null,字符串也可以进行格式转换,进行左右对齐和空位,字符串字面量具有静态存储器
37.值传递只能改变实参副本的值,要想改变值,得用指针
int *a; int b=11;a=&b;&b的类型也是指向int型变量的指针型,取址运算符与其说是取得地址,不如说是生成指针。&b为指向b的指针,其值是b的地址。当a指向b时,*a就是b的别名
38.对于register关键字声明的寄存器对象,不能加取地址运算符&
39.在两种情况下数组名不会被视为指向起始元素的指针:
(1)作为sizeof运算符的操作数时,生成整体数组的长度
(2)作为取地址符&操作数,是指向数组整体的指针
int a【5】;
int *p=a;
p+i指向a【i】仅当 p指向a【0】的时候
*(p+i)就是a【i】本身以及别名
*(a+2)、p[2],*(p+2)都是a【2】的别名
a+i &a【i】 &p【i】 p+i是指针
a的数组包含5个元素,但是指向a的指针可以包括6个,最后一个指针指向尾元素后的元素,作为判定会比较方便。
赋值的左操作数不可以是指针名
指向数组的指针的下标操作数 可互换 *(p+i)等于*(i+p) p【i】等于i【p】
40.用数组和指针实现的字符串
数组: char str【】=“ABC”;
指针 char *ptr =“123”;
指针ptr不能用如下方式进行声明:
char *ptr={‘1’,‘2’,‘3’,‘\0’};
数组用的{}形式的初始值,不可用于单一的变量,指针是指向字符串首个字符的指针,也可以通过下标运算符【】访问字符串中的字符。
数组实现的字符串不能进行直接赋值,要初始化赋值,如果要赋值,需要进行遍历
指针实现的字符串可以进行赋值
用指针形成而字符串数组无法保证字符串的顺序和连续性,但是数组形成的字符串数组所有元素连续
41.用指针写一个算字符串数组长度和复制字符串的函数
while(*d++=*s++)
;
42.不要改变字符串字面量,也不要对超过字符串字面量的内存空间写入操作。是否可以改变字符串字面量中的字符,取决于编译器。
43.struct 只是结构名,struct student是类型名,如同枚举类型中的“enum枚举名”,结构体可以用(*).或者->访问成员和赋值
44. .运算符和->运算符统称为访问运算符,指向结构p的指针m若想访问p的成员q,则(*m).q或者m->q。结构体可以嵌套结构体
45.结构体可以赋值和作为返回类型,数组不可以
46.time_t类型:日历时间 time函数:获取当前的日历时间
有三种调用方式,当前时间被存储在current变量中,
A time(¤t) B current=time(NULL) C current=time(¤t)
tm结构体:分解时间
localtime函数:从日历时间转换为分解时间
timer=localtime(¤t)
47.fscanf比scanf多了一个参数:指向文件流的指针,fprintf同理,功能是相同的
fgetc比getchar多了
48.do{
}while(……); 语句结尾有分号,只要while里的控制表达式不为0,do里的循环体就会不断执行
49.随机数:
rand生成伪随机数,伪随机数看起来像随机数,却是基于某种规律生成打的,因此能预测接下来会生成什么数值,随机数种子默认为1
srand生成随机数
一般把运行程序时的时间当(随机数)种子
srand(time(NULL)) 根据当前时间设定随机数的种子
#pragma warning(disable:4996)
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int retry;
srand(time(NULL));
printf("在这个编程环境中能够生成0~%d的随机数。\n", RAND_MAX);
do {
printf("\n生成了随机数%d。\n", rand());
printf("在运行一次?……(0)否(1)是:");
scanf("%d", &retry);
} while (retry == 1);
return 0;
}
如果要生成比n小的随机数,就用rand()%n
例如生成1~999的随机数
ans=1+rand()%999
生成100~999的随机数
ans=100+rand()%900
在调用rand前调用srand函数(至少一次),否则随机数种子会默认为1,生成相同的序列。
一旦调用rand函数,就会生成一个0~RAND_MAX的随机数,RAND_MAX的值取决于编译环境,即大于等于32767
50.对原命题取非,等于对该命题的各个子命题取非,再互换其中所有的逻辑与和逻辑或
x&&y和!(!x||!y)相等
x||y和!(!x&&!y)相等
51.对于有静态存储器的数组(包括在函数外定义的数组和在函数内加上static定义的数组)而言,即使不赋予该数组初始值,所有元素也会被初始化为0;
可以通过sizeof(a)/sizeof(a【0】)来计算数组元素个数
52.八进制转移字符和十六进制转义字符
数字字符‘0’的字符编码换算成十进制数是48,用八进制转义字符可以表示为‘\60’,用十六进制转义字符则可以表示为‘\x30’
\n换行符:将光标符移动到下一行的开头,连续输出两次可以输出空行
\b退格符,将光标往后退一位,输出“\b \b”能够消除最后一个字符
52.字符常量 单引号\' 双引号”或\”
字符串常量 双引号\” 单引号'或者\’
明解C语言中篇读书笔记:
1.用CLOCK_PER_SEC把时钟数换算成秒数的方法是固定的,需要大家牢记
#pragma warning(disable:4996)
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int sleep(unsigned long x) {
clock_t c1 = clock(), c2;
do {
if ((c2 = clock()) == (clock_t )- 1)
return 0;
} while (1000.0 * (c2 - c1) / CLOCKS_PER_SEC < x);
return 1;
}
int main(void) {
int i;
clock_t c;
for (i = 10; i > 0; i--) {
printf("\r%2d", i);
fflush(stdout);
sleep(1000);
}
printf("\r\aFIRE!!\n");
c = clock();
printf("程序开始运行后经过了%.1f秒.\n", (double)c / CLOCKS_PER_SEC);
return 0;
}
2.如果不想在while{}语句里使用break跳出循环,可以使用do{}while()语句
3.调用printf,可以再格式字符串设置*,赋给*一个参数来指定显示的位数
printf(“%*d”,i,x),把整数X以i位输出,
4.double和float在print中的格式字符串都是%f,但是在scanf中double是%lf
5.C语言三种方式初始化字符串
char s【】=“ABCD”;
char s【】={“ABCD”};
char s【】={‘A’,‘B’,‘C’,‘D’,‘\0’};
最常见和好的是第一种,第二种几乎不会出现,第三种比较繁琐。只有当数组元素个数不等于不包含空字符串的字符串常量的字符数量时,才不会添加字符。只有添加\0才是字符串,否则只是字符数组
6.signed char的CHAR_MIN是-127,unsigned char 的是0
7.在大多数情况下,用“执行字符串的指针数组”来实现长度不同的字符串的集合,要比二维数组来实现要好得多。
8.isdigit函数判断字符是否为数字字符;
还可以通过c>='0' && c<='9'判断。
数字字符减去‘0’,可以得到对应的整数值;整数值加上‘0’,可以得到对应的数字字符。
9.getch函数用于获取玩家从键盘输入的字符,它与getchar函数的不同在于,无需按回车符就可获取信息
putch函数负责把字符显示在画面上。函数输出字符后,字符立即显示在画面上,因此不需要fflush函数(用于强制输出)进行清空操作
10.包含头文件保护的头文件
11.函数宏
12.C语言的高手往往喜欢嵌套表达式的方式,否则,代码段会变得很长。
13.1、右键点击解决工程->项目属性
2、配置属性->生成事件->生成后事件
在命令行中输入:"$(TargetPath) >$(outdir)\1.txt"
3、重新编译整个项目,此时就会在debug目录下多了一个1.txt文件,里面就是程序运行时的控制台输出结果。
14.RAND_MAX对象宏
15.灵活使用转义字符,可以让画面上的字符消失或者移动
16.字符串常量 双引号 \" 单引号 ' 或 \'
字符常量 双引号 '\"' 或 ' " ' 单引号' \' '
17.‘0’的字符编码换成十进制是48,八进制转义字符 ‘\60’ 十六进制转义字符‘\x30’
18.\r将光标转移到本行开头
19.clock函数 格式clock_t clock(void) <time.h>把clock_t定义为等同于算数型 typedef unsigned clock_t
20.strlen计算s所指字符串的长度,不包含空字符 头文件是<string.h> 格式size_t strlen(const char*s)
21.printf(“%*d”,c,x)至少用c位数表示x
printf(“%*s”,n,“”)显示n个空白字符 (至少用n位数表示空的字符串)
22.汉字等全角字符通常占两个字节,为了处理不能用半角字符表示的字符,原则上会用<stddef.h>头文件中定义的wchar_t型的宽字符
/* 宽字符的使用示例 */
#include <wchar.h>
#include <stdio.h>
#include <locale.h>
int main(void)
{
int i;
wchar_t c = L'a';
wchar_t *h[3] = {L"石头", L"剪刀", L"布"};
setlocale(LC_ALL, "");
wprintf(L"%lc\n", c);
for (i = 0; i < 3; i++)
wprintf(L"h[%d] = %ls\n", i, h[i]);
return 0;
}
23.读取字符串
/* 把读取到的字符串形式的整数转换为数值并显示 */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char temp[20]; /* 用于读取的字符串 */
printf("请输入整数:");
scanf("%s", temp);
printf("你输入了%d。\n", atoi(temp));
return 0;
}
24.atoi函数、atof函数 :把字符串转化为数值
检验字符是否是数字 isdigit,还有判断是否是控制字符、显示字符、不包含空白字符的显示字符等等函数……
25.超过32767的值都不能用int和rand函数来处理,尽管rand函数的返回值类型是int型,但是随机数RAND_MAX不一定等于int型能够表示的最大值
26.为了完全消除屏幕上的数值,先通过回车符\r把光标移到开头,然后显示3*level个空白字符,然后再次通过回车符\r把光标移到本行开头。这里的3*level为特定题,数字要为能覆盖原来那行的字符数
printf(“\r%*s\r”,3*level,“”)
27.fgutc从流中读取一个字符,fputc向流输出一个字符
27.mktime函数与localtime函数进行的转换正好相反。蔡勒公式,格里高利历
28.sprintf和printf一样,都是把参数展开并整理后输出,但是sprintf函数并不把参数输出到标准输出流(控制台画面),而是把参数
29.把字符串str设置为空字符串的方法 str【0】=‘\0’,strcpy(str,“”)strcpy把第二个字符串复制到第一个,strcat把第二个字符串拼接到第一个后面
30.strncmpx函数比较字符串开头部分 strncmp比较字符串,toupper将小写转化为大写,tolower转化为小写
31.字符串的集合可以用二维数组或指针数组来表示,字符串的长度不同时(特别是包含全角字符时)。多数情况下用后者。
以前觉得C++比C多一个面向对象,那么C++一定比C好。通过明解C语言的学习,我又补充了好几千字的读书笔记,特别是今天明解C语言 中级篇的第二章 显示的操纵,消除字符,倒计时,第一章的随机数抽签系统,让我觉得C语言还是挺神奇的,要好好整一整。
另外是图书馆借书破50本大关,有13本非专业书,希望把剩下的书在寒假前好好笑话一下,然后寒假搞一下机器学习、数据库以及计算机网络等等硬课,刷OJ,学英语等等。
把线代、微积分、概率论等数学课基础夯实。
感觉有点累,但是加油,冲啊。提高效率,感受这些课的魅力,并且灵活运用。
刚又学了一个显示名字,然后消去名字,整个过程循环,看起来非常好玩,C语言挺神奇啊
网友评论