《The C programming language》学习笔记
Brian和Dennis的《c程序设计语言》(The C Programming Language)真不愧为c语言方面的经典书籍,薄薄的一本,却让人爱不释手,每次阅读都能有所收获。好记忆不如烂笔头,有些规则、算法还是记录下来比较好,记录下来常常回顾,才是提升编程内功的不二法门。
变量与表达式
1 整数除法操作将执行舍位。
2 浮点常量取的是整数,在书写时最好还是为它加上一个显示的小数点,这样可以强调其浮点信息,便于阅读。
3 在允许使用某种类型变量值的任何场合,都可以使用该类型的更复杂的表达式。
for语句
4 for语句比较适合初始化和增长步长都是单条语句并且逻辑相关的情形,因为它将循环控制语句集中放在一起,且比while语句更紧凑。
符号常量
5 #define指令可以把符号常量定义为一个特点的字符串:
#define 名字 替换文本
6 符号常量名通常用大写字母拼音,这样可以很容易和小写字母拼音的变量名区别
7 #define指令行的末尾没有分号。
字符输入\输出
8 文本流是由多行字符构成的字符序列,而每行字符则由0个或多个字符组成,行末是一个换行符。标准库负责使每个输入输出流都能够遵循这一模型。
9 文件复制10 任何整型( int )也可以用于存储字符型数据。
void main(){int c;c = getchar(); /*Each time it is called, getchar reads the next input character from a text stream and returns that as its value*/while (c != EOF) {putchar(c);c = getchar();}}
11 EOF定义在头文件<stdio.h>中,是一个整型数。其具体数值并不重要,它与任何char型的值都不相同。
12 赋值可以作为更大的表达式的一部分出现。
#include<stdio.h>/* copy input tooutput; 2nd version */void main(){int c;while ((c =getchar()) != EOF)putchar(c);}
13 for循环改写
#include <stdio.h>/* count characters in input; 2nd version */void main(){double nc;for (nc = 0; gechar() != EOF; ++nc);printf("%.0f\n", nc);/*%.0f强制不打印小数点和小数部分*/}
14 行计数
/*程序虽然简单,但是确实是经典!*/#include <stdio.h>/* count lines in input */void main(){int c, nl;nl = 0;while ((c = getchar()) != EOF)if (c == '\n')++nl;printf("%d\n", nl);}
15 单词计数
#include <stdio.h>/*常量,让程序更易读*/#define IN 1 /* 在单词内 */#define OUT 0 /* 在单词外 *//* 统计输入的行数、单词数与字符数 */void main(){int c, nl, nw, nc, state;state = OUT;/*state记录程序当前是否位于一个单词之中*/nl = nw = nc = 0;while ((c = getchar()) != EOF) {++nc;if (c == '\n')++nl;if (c == ' ' || c == '\n' || c = '\t')state = OUT;else if (state == OUT) {state = IN;++nw;}}printf("%d %d %d\n", nl, nw, nc);}
16 &&比||高一个优先级。由&&或||连接的表达式由左至右求值,并保证求值过程中只要能够判断最终的结果为真或假,求值就立即终止。
数组
17 统计各个数字、空白符(包括空格、制表符及换行符)及其他字符出现的次数
#include <stdio.h>void main(){int c, i, nwhite, nother;int ndigit[10];nwhite = nother = 0;for (i = 0; i < 10; ++i)ndigit[i] = 0;while ((c = getchar()) != EOF)if (c >= '0' && c <= '9')++ndigit[c-'0'];else if (c == ' ' || c == '\n' || c == '\t')++nwhite;else++nother;printf("digits =");for (i = 0; i < 10; ++i)printf(" %d", ndigit[i]);printf(", white space = %d, other = %d\n",nwhite, nother);}
函数
18 C语言中,被调函数不能直接修改主调函数中变量的值,只能修改其私有临时副本的值。
字符数组
19 读入一行文本并把最长的文本打印出来。
基本框架:
while (there's another line)if (it's longer than the previous longest)(save it)(save its length)print longest line
#include <stdio.h>#define MAXLINE 1000 /* maximum input line length */int getline(char line[], int maxline);void copy(char to[], char from[]);/* print the longest input line */void main(){int len; /* current line length */int max; /* maximum length seen so far */char line[MAXLINE]; /* current input line */char longest[MAXLINE]; /* longest line saved here */max = 0;while ((len = getline(line, MAXLINE)) > 0)if (len > max) {max = len;copy(longest, line);}if (max > 0) /* there was a line */printf("%s", longest);return 0;}/* getline: read a line into s, return length */int getline(char s[],int lim){int c, i;for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)s[i] = c;if (c == '\n') {s[i] = c;++i;}s[i] = '\0';return i;}/* copy: copy 'from' into 'to'; assume to is big enough */void copy(char to[], char from[]){int i;i = 0;while ((to[i] = from[i]) != '\0')++i;}
外部变量与作用域
20 在每个需要访问外部变量的函数中,必须声明相应的外部变量,此时说明其类型。声明可以用extern语句显式声明,也可以通过上下文隐式声明。
#include <stdio.h>#define MAXLINE 1000 /* maximum input line size */int max; /* maximum length seen so far */char line[MAXLINE]; /* current input line */char longest[MAXLINE]; /* longest line saved here */int getline(void);void copy(void);/* print longest input line; specialized version */void main(){int len;extern int max;extern char longest[];max = 0;while ((len = getline()) > 0)if (len > max) {max = len;copy();}if (max > 0) /* there was a line */printf("%s", longest);return 0;}/* getline: specialized version */int getline(void){int c, i;extern char line[];for (i = 0; i < MAXLINE - 1&& (c=getchar)) != EOF && c != '\n'; ++i)line[i] = c;if (c == '\n') {line[i] = c;++i;}line[i] = '\0';return i;}/* copy: specialized version */void copy(void){int i;extern char line[], longest[];i = 0;while ((longest[i] = line[i]) != '\0')++i;}
21 在源文件中,如果外部变量的定义出现在使用它的函数之前,那么那个函数就没有必要使用extern声明。因此,main,getline,copy中的几个extern声明都是多余的。
常量
字符常量'\0'表示值为0的字符。也就是空字符(null)。我们通常用'\0'的形式代替0,以强调某些表达式的字符属性,但其数字值为0。
字符串常量就是字符数组。字符串的内部表示使用一个空字符'\0’作为串的结尾,因此。存储字符串的物理存储单元数比括在双引号中的字符数多一个。
/* strlen: return length of s */int strlen(chars[]){int i;while (s[i]!= '\0')++i;return i;}
我们应该搞清楚字符常量与仅包含一个字符的字符串之间的区别:'x‘与”x“是不同的。前者是一个整数,其值是字母x在机器字符集中对应的数值(内部表示值);后者是一个包含一个字符(即字母x)以及一个结束符‘\0’的字符数组。
在没有显式说明的情况下,enum类型中第一个枚举名的值为0,第二个为1依此类推。如果只指定了部分枚举名的值,那么未指定值的枚举名的值将依着最后一个指定值向后递增。
枚举为建立常量值与名字之问的关联提供了一种便利的方式。相对于#define语句来说,它的优势在于常量值可以自动牛成。
类型转换
atoi()函数将一串数字转换为相应的数值。
/* atoi: convert s to integer */int atoi(char s[]){int i, n;n = 0;for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)n = 10 * n + (s[i] - '0');return n;}
函数lower是将char类型转换为int类型的另个例子,它将ASCII字符集中的字符映射到对应的小写字母。如果待转换的字符不是大写字母,lower函数将返回字符本身。
/* lower: convert c to lower case; ASCII only */int lower(int c){if (c >= 'A' && c <= 'Z')return c + 'a' - 'A';elsereturn c;}
自增运算符与自减运算符
下面的函数squeeze(s, c),它删除字符串s中出现的所有字符c:
/* squeeze: delete all c from s */void squeeze(char s[], int c){int i, j;for (i = j = 0; s[i] != '\0'; i++)if (s[i] != c)s[j++] = s[i];s[j] = '\0';}
标准函数strcat(s,t),它将字符串t连接到字符串s的尾部。
/* strcat: concatenate t to end of s; s must be big enough */void strcat(char s[], char t[]){int i, j;i = j = 0;while (s[i] != '\0') /* find end of s */i++;while ((s[i++] = t[j++]) != '\0') /* copy t */;}
函数getbits(x,p,n),它返回x中从右边数第p位开始向右数n位的字段。这里假定最右边的一位是第O位,n与p都是合理的正值。
/* getbits: get n bits from position p */unsigned getbits(unsigned x, int p, int n){return (x >> (p+1-n)) & ~(~0 << n);}
函数bitcount统计其整型参数的值为1的二进制位的个数。
/* bitcount: count 1 bits in x */int bitcount(unsigned x){int b;for (b = 0; x != 0; x >>= 1)if (x & 01)b++;return b;}
运算符优先级与求值次序
运算符 |
结合性 |
() [] -> . |
从左到右 |
! ~ ++ -- + - * (type) sizeof |
从右到左 |
* / % |
从左到右 |
+ - |
从左到右 |
<< >> |
从左到右 |
< <= > >= |
从左到右 |
== != |
从左到右 |
& |
从左到右 |
^ |
从左到右 |
| |
从左到右 |
&& |
从左到右 |
|| |
从左到右 |
?: |
从右到左 |
= += -= *= /= %= &= ^= |= <<= >>= |
从右到左 |
, |
从左到右 |
经典代码
1 折半查找
/* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */int binsearch(int x, int v[], int n){int low, high, mid;low = 0;high = n - 1;while (low <= high) {mid = (low+high)/2;if (x < v[mid])high = mid - 1;else if (x > v[mid])low = mid + 1;else /* found match */return mid;}return -1; /* no match */}
2 将字符串转化为对应数值
#include <ctype.h>/* atoi: convert s to integer; version 2 */int atoi(char s[]){int i, n, sign;for (i = 0; isspace(s[i]); i++) /* skip white space */;sign = (s[i] == '-') ? -1 : 1;if (s[i] == '+' || s[i] == '-') /* skip sign */i++;for (n = 0; isdigit(s[i]); i++)n = 10 * n + (s[i] - '0');return sign * n;}
3 Shell排序
Shell排序算法是D. L. Shell于1959年发明的,其基本思想是:先比较距离远的元素,而不是像简单交换排序算法那样先比较相邻的元素。这样可以快速减少大量的无序情况,从而减轻后续的工作。被比较的元素之间的距离逐步减少,直到减少为1,这时排序变成了相邻元素的互换。
/* shellsort: sort v[0]...v[n-1] into increasing order */void shellsort(int v[], int n){int gap, i, j, temp;for (gap = n/2; gap > 0; gap /= 2)for (i = gap; i < n; i++)for (j=i-gap; j>=0 && v[j]>v[j+gap]; j-=gap) {temp = v[j];v[j] = v[j+gap];v[j+gap] = temp;}}
4 倒置字符串s中各个字符的位置
#include <string.h>/* reverse: reverse string s in place */void reverse(char s[]){int c, i, j;for (i = 0, j = strlen(s)-1; i < j; i++, j--) {c = s[i];s[i] = s[j];s[j] = c;}}
5 将数字转换为字符串
/* itoa: convert n to characters in s */void itoa(int n, char s[]){int i, sign;if ((sign = n) < 0) /* record sign */n = -n; /* make n positive */i = 0;do { /* generate digits in reverse order */s[i++] = n % 10 + '0'; /* get next digit */} while ((n /= 10) > 0); /* delete it */if (sign < 0)s[i++] = '-';s[i] = '\0';reverse(s);}
6 删除字符串尾部的空格符、制表符与换行符
/* trim: remove trailing blanks, tabs, newlines */int trim(char s[]){int n;for (n = strlen(s)-1; n >= 0; n--)if (s[n] != ' ' && s[n] != '\t' && s[n] != '\n')break;s[n+1] = '\0';return n;}
知识补充
1 static类型的内部变量是一种只能在某个特定函数中使用但一直占据存储空间的变量。
2 在不进行显式初始化的情况下,外部变量和静态变量都将被初始化为0,面自动变量和寄存器变量的初值则没有定义(即初值为无用的信息)。
3 打印出数字
#include <stdio.h>/* printd: print n in decimal */void printd(int n){if (n < 0) {putchar('-');n = -n;}if (n / 10)printd(n / 10);putchar(n % 10 + '0');}
4 快速排序
/* qsort: sort v[left]...v[right] into increasing order */void qsort(int v[], int left, int right){int i, last;void swap(int v[], int i, int j);if (left >= right) /* do nothing if array contains */return; /* fewer than two elements */swap(v, left, (left + right)/2); /* move partition elem */last = left; /* to v[0] */for (i = left + 1; i <= right; i++) /* partition */if (v[i] < v[left])swap(v, ++last, i);swap(v, left, last); /* restore partition elem */qsort(v, left, last-1);qsort(v, last+1, right);}/* swap: interchange v[i] and v[j] */void swap(int v[], int i, int j){int temp;temp = v[i];v[i] = v[j];v[j] = temp;}
5 宏替换
#define max(A, B) ((A) > (B) ? (A) : (B))
6 保证hdr.h文件的内容只被包含一次
#ifndef HDR#define HDR/* contents of hdr.h go here */#endif
7 比较字符串大小
/* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */int strcmp(char *s, char *t){int i;for (i = 0; s[i] == t[i]; i++)if (s[i] == '\0')return 0;return s[i] - t[i];}
8 类型名
int 整型int * 指向整型的指针int *[3] 包含3个指向整型的指针的数组int (*)[] 指向未指定元素个数的整型数组的指针int *() 未指定参数、返回指向整型的指针的函数int (*[])(void) 一个数组,其长度未指定,数组的元素为指向函数的指针,该函数没有参数且返回一个整型值
转载请注明出处: http://blog.csdn.net/lsh_2013/article/details/45064991
《The C programming language》学习笔记相关推荐
- 第二行代码学习笔记——第六章:数据储存全方案——详解持久化技术
本章要点 任何一个应用程序,总是不停的和数据打交道. 瞬时数据:指储存在内存当中,有可能因为程序关闭或其他原因导致内存被回收而丢失的数据. 数据持久化技术,为了解决关键性数据的丢失. 6.1 持久化技 ...
- 第一行代码学习笔记第二章——探究活动
知识点目录 2.1 活动是什么 2.2 活动的基本用法 2.2.1 手动创建活动 2.2.2 创建和加载布局 2.2.3 在AndroidManifest文件中注册 2.2.4 在活动中使用Toast ...
- 第一行代码学习笔记第八章——运用手机多媒体
知识点目录 8.1 将程序运行到手机上 8.2 使用通知 * 8.2.1 通知的基本使用 * 8.2.2 通知的进阶技巧 * 8.2.3 通知的高级功能 8.3 调用摄像头和相册 * 8.3.1 调用 ...
- 第一行代码学习笔记第六章——详解持久化技术
知识点目录 6.1 持久化技术简介 6.2 文件存储 * 6.2.1 将数据存储到文件中 * 6.2.2 从文件中读取数据 6.3 SharedPreferences存储 * 6.3.1 将数据存储到 ...
- 第一行代码学习笔记第三章——UI开发的点点滴滴
知识点目录 3.1 如何编写程序界面 3.2 常用控件的使用方法 * 3.2.1 TextView * 3.2.2 Button * 3.2.3 EditText * 3.2.4 ImageView ...
- 第一行代码学习笔记第十章——探究服务
知识点目录 10.1 服务是什么 10.2 Android多线程编程 * 10.2.1 线程的基本用法 * 10.2.2 在子线程中更新UI * 10.2.3 解析异步消息处理机制 * 10.2.4 ...
- 第一行代码学习笔记第七章——探究内容提供器
知识点目录 7.1 内容提供器简介 7.2 运行权限 * 7.2.1 Android权限机制详解 * 7.2.2 在程序运行时申请权限 7.3 访问其他程序中的数据 * 7.3.1 ContentRe ...
- 第一行代码学习笔记第五章——详解广播机制
知识点目录 5.1 广播机制 5.2 接收系统广播 * 5.2.1 动态注册监听网络变化 * 5.2.2 静态注册实现开机广播 5.3 发送自定义广播 * 5.3.1 发送标准广播 * 5.3.2 发 ...
- 第一行代码学习笔记第九章——使用网络技术
知识点目录 9.1 WebView的用法 9.2 使用HTTP协议访问网络 * 9.2.1 使用HttpURLConnection * 9.2.2 使用OkHttp 9.3 解析XML格式数据 * 9 ...
- 安卓教程----第一行代码学习笔记
安卓概述 系统架构 Linux内核层,还包括各种底层驱动,如相机驱动.电源驱动等 系统运行库层,包含一些c/c++的库,如浏览器内核webkit.SQLlite.3D绘图openGL.用于java运行 ...
最新文章
- 关于学习Python的一点学习总结(24->列表推导)
- vmware 上部署 kvm虚拟机
- express 解析 ajax post 数据 body 为空对象
- dwr消息推送和tomcat集群
- bat删除计算机用户,自动清除电脑垃圾及删除windows默认共享盘符的批处理bat
- boost::fusion::remove_if用法的测试程序
- Linux ubuntu安装搜狗输入法
- (计算机组成原理)第七章输入和输出系统-第四节1:I/O方式之程序查询方式
- Grafana-zabbix配置模板
- 字符串常量在内存中的存放位置由系统自动安排。_C++核心编程--内存分区模型...
- jquery中的live()方法
- 土豆视频ipad 5.0 客户端
- java编写自动化脚本_自动化脚本
- Ubuntu 开机自动运行命令或程序
- 江苏计算机编程中小学,编程教育走进小学低年级
- 基于ARM开发板的嵌入式项目设计(C完整代码)
- 紫书 UVa437巴比伦塔
- 最短路径和最少花费问题--动态规划
- MQTT系列 | Retained消息和LWT和Keep Alive
- C++ 模板类与头文件
热门文章
- HDU 5971 2016ICPC大连 A: Wrestling Match(二分图判断)
- bzoj 4033: [HAOI2015]树上染色(树形DP)
- Horizo​​ntal Pod Autoscaler (HPA) 根据资源横向扩展
- postman使用教程,接口自动化测试
- Echarts数据可视化event图表事件的相关操作,开发全解+完美注释
- zynq开发系列4:MIO按键中断控制LED
- quartus仿真10:74283的基本功能
- 多线程资源共享之同步锁
- Java Collection Framework
- 学习总结 java 创建及其练习