《c程序设计(谭浩强)》读书笔记

第1章~第3章

1.关于scanf和printf的格式问题:

1 scanf("%d,%d", &a, &b);
View Code

上面的语句分析:"%d,&d"指定输入的数据按照什么格式输入, &是地址符, &a的含义是“变量a的地址”,整个语句的作用是:从键盘读入两个整数,送到变量a和b的地址出,然后把两个整数分别赋予a和b。

scanf(格式控制,地址列表);

printf(格式控制,输出列表);

a=12;b=34;

printf("a=%5d b=%4d ",a,b); 

输出:(口表示空格)

口口口12

口口34

2.结构化程序设计方法:

强调程序设计风格和程序结构的规范化,提倡清晰的结构。

常用方法:

(1)自顶向下、逐步细化:将问题求解由抽象逐步具体化的过程。

(2)模块化设计:当程序复杂是非常有必要。根据程序的模块的功能将它划分为若干子模块,子模块再细分,这个过程是自顶向下的。程序中的子模块常用函数实现。

(3)结构化编码:就是将设计好的一个结构化的算法用程序语言表示,用3个基本的结构语句(if-else,while,for语句)实现。

3.指数形式的常量:

12.34e-8:代表12.34*10^8  因为无法表示指数符号,所以用e或者E代表以10为地鼠的指数,注意e或E前面必须要有数字,且指数必须为整数。

4.注意c中的转义字符及其作用:转义字符常以“”开头。

5.标识符:数字、字母和下划线组合而成,不能以数字开头。

6.不同类型数据间的混合运算:

 自动进行类型转换再运算。通常是向精度高的类型转换。

7.强制类型转换:

(类型名) 表达式

例子:

1 double x;
2 int a;
View Code

a=(int)x ;

把x强制类型转换为int型,得到一个临时的中间值,再把中间值赋给a;注意x的值和类型都没有变化。

 第4章 选择结构程序设计

 选择结构和条件判断:

 (1)if-else语句:实现两个分支的选择结构

 (2)switch语句:实现多分支的选择结构

第5章 循环结构程序设计

(1)while语句:

(2)do-while语句:

(3)for语句:

用break语句跳出循环。

用continue语句提前结束本次循环,进入下一次循环条件检查。

第6章  数组

1.定义一维数组:

类型符  数组名[常量表达式];

常量表达式中可以包含常量和符号常量,但不能包含变量。数组的大小一依赖于程序运行过程中变量的值。

说明:可变长数组

void fun(int n)

{
    int a[n];  //合法,数组大小由形参n传入,函数调用过程n的大小不变,数组的长度是固定的。

}

2.定义二维数组:

类型符  数组名[常量表达式1][常量表达式2];

二维数组中元素的排列顺序是按行存放的,在内存中先存放第一行的元素,接着存放第二行的元素。。。

3.字符数组:

字符数组结束的标志:''

char c[]={"china"};

c h i n a

 

4.字符串处理函数:

包含在头文件中:

#include<string.h>

说明:库函数不是c语言本身的组成部分,而是c语言编译系统为方便用户使用而提供的公共函数。不同的编译系统可能有微小差别,使用时可以查询库函数手册。

(1)puts函数:输出字符串的函数

用法:puts(字符数组);

char str[]={"china beijing"};

puts(str);

输出结果:

china

beijing

(2)gets函数:输入字符串的函数

用法:gets(字符数组);

gets(str);  //str是已定义的数组

(3)strcat函数:字符串连接函数

用法:strcat(字符数组1,字符数组2);

printf("%s",strcat(str1,str2));

(4)strcpy和strncpy函数:字符串复制函数

用法:

strcpy(字符数组1,,字符数组2); 将字符数组2复制到字符数组1中去。

strncpy(字符数组1,,字符数组2,n);将字符数组2中最前面的n个字符复制到字符数组1中,取代字符数组1中最前面的n个字符.

                                              n不大于字符数组中原有字符个数(不包括结束标志符)。

strcpy(str1,str2);

strncpy(str1,str2,n);

(5)strcmp函数:字符串比较函数

strcmp(字符串1,字符串2);

相等返回0,str1>str2返回正数,str1<str2返回负数

strcmp(str1,str2);

(6)strlen函数:测量字符串长度的函数

strlen("china"); //值是5,不包含结束标志符

(7)strlwr函数:将字符串中的大写字母转换为小写字母

       strupr函数:转换为大写

    strlwr(str);

    strupr(str);

 

第7章  用函数实现模块化程序设计

函数就是功能,每一个函数实现一个特定的功能,函数名应反映函数所代表的功能。

1.函数定义:包括函数声明和函数实现

类型名  函数名(形参列表)

{

  函数体

}

(1)定义空函数:

类型名 函数名()

{   }

在程序设计过程中,往往根据需要确定若干个模块,分别由一些函数实现。在第一阶段往往只涉及最基本的模块,在需要扩充的地方定义一个空函数,函数暂时没写好,只是先占一个位置,以后再用一个编写好的函数代替它。这样做,使程序结构清晰,可读性好,扩充功能也方便。

(2)c程序设计人员有一个习惯,就是把全局变量的首字母大写。例如  float Max=0; 同名的全局变量会被局部变量 屏蔽。

在不必要时尽量不用全局变量:原因有

(1)空间消耗多

(2)通用性降低

(3)降低程序的可读性和清晰性,容易出错。

2.静态局部变量(static局部变量):(注意:在c和c++中是下面的情况,但在java中不是这样的!!)

静态局部变量的值在函数调用结束后不消失而继续保留原值,其占用的存储单元不释放。下一次再调用这个函数时,该变量已经有值(上一次函数调用结束时的值)。static变量在整个程序运行过程中都不释放,在函数调用结束后仍然存在,但只有创建它的函数能引用它,不能被其他函数引用。

用法:若非必要,不要多用静态局部变量,因为调用时不知道当前static变量的值是什么,是否被修改过。

 

3.寄存器变量(register变量):一般变量是存放在内存中的,存取速度较慢。如果需要频繁存取的,可以定义为寄存器变量,用关键字register声明。

register int pi;

使用:现在计算机优化的编译系统能识别使用频繁的变量,自动将它们放到寄存器中,不再需要程序设计者指定。

4.变量有3种存储位置:

(1)动态存储区:动态的局部变量

(2)静态存储区:静态局部变量(即static变量),还有全局变量(即外部变量)

(3)寄存器:register变量 

5.用extern关键字做“外部变量声明”,扩展外部变量的作用域。 

例子:

 1 int main()
 2 {
 3    extern int A,B,C;  //把外部变量A,B,C的作用域扩展到此处
 4    scanf("%d%d%d",7A,&B,&C);
 5    printf(max());
 6 }
 7 int A,B,C; //定义外部变量A,B,C
 8 int max()
 9 {
10   int m=A>B?A:B;
11   return m>C? m:C;
12 }
View Code

将外部变量声明放在引用它的所有函数之前,可以避免使用extern关键字声明。

上面的代码和下面的代码是等价的:

 1 int A,B,C; //定义外部变量A,B,C
 2 
 3 int main()
 4 {
 5    scanf("%d%d%d",7A,&B,&C);
 6     printf(max());
 7 }
 8 int max()
 9 {
10   int m=A>B?A:B;
11   return m>C? m:C;
12 }
View Code

 (1)将外部变量的作用域扩展到其他文件

使用:其他文件要引用另一个文件中已定义的外部变量。

1 //file1.c
2 #include<stdio.h>
3 int A ; //定义外部变量
4 
5 //file2.c
6 extern A; //把file1文件中已定义的外部变量的作用域扩展到本文件
View Code

(2)将外部变量的作用域限制在本文件中

 1 //file1.c
 2 #include<stdio.h>
 3 static int A;  
 4 int main()
 5 {
 6 ......
 7 }
 8 
 9 //file2.c
10 extern A;
11 void fun(int n)
12 {
13    A=A+n;  //error,A的作用域被限制在文件file1中!
14 }
View Code

使用注意:在程序设计过程中,每个人各自完成不同模块,可能使用同名的外部变量,只须在每个文件中定义外部变量时加上static即可!

(3) static声明一个变量的作用:

 1.对局部变量用static声明,把它分配到静态存储区,在整个程序执行过程不释放。

 2.对外部变量用static声明,是把该外部变量的作用域限制在本文件中。

 (4)关于变量的声明和定义

       定义:建立存储空间的声明称为定义。

       声明:不需要建立存储空间的声明称为声明。

(5)内部函数和外部函数

1.内部函数:一个函数只能被本文件中的其他函数所调用,则这个函数称为内部函数。在定义内部函数时,用static修饰符修饰。

      static int fun();//函数fun只能被本文件调用

用法:通常把只能由本文件使用的函数和外部变量放在文件的开头,前面都冠以static使之局部化,其他文件不能引用,提高程序可靠性。

好处:内部函数又称为静态函数,使用内部函数,可以把函数的作用域只局限于所在文件。这样子在不同文件中即使具有同名的函数也互不干扰。在一个大工程中,在各人编写自己的文件模块时,使用内部函数,可以不必担心所用函数是否会与其他文件模块的函数同名。

2.外部函数: 在定义函数时,在函数首部的最左端加挂念子extern修饰,在此函数是外部函数,可以供其他文件调用。省略extern则默认为外部函数。

extern int  fun();//函数fun可以被其他文件调用。

 第8章  指针

指针是很灵活但也很容易出错的工具,初学者不易学会,要谨慎使用~~

1.指针指向内存地址。

2.指针引用数组,也是指向数组的首地址,而不是整个数组。

3.指针引用字符串,也是指向字符串第一个字符的地址。

1 char *string;               //定义个char*型变量
2 string="I love China!"; //把字符串第1个元素的地址赋给字符指针变量string
3 
4 //这里的string被定义为一个指针变量,基类是字符型,它只能指向一个字符型数据。

如果再对指针变量赋值,如:

1 string="I am a student";

这时候string就指向了新的字符串。
执行语句:

1 printf("%s
",string); //输出字符串string

输出结果如下:
I am a student

说明:

通过字符数组名或者字符指针变量可以输出一个字符串,但对于一个数值型数组,只能逐个元素输出。

数组名做函数参数,只是把数组的首地址传给形参,函数里修改值会影响传入数组的实参的值。

第9章   结构体变量struct

 

 1.用关键字struct声明用户自定义的结构体类型。

 struct 结构体名

{

  类型名 成员名1;

  类型名 成员名2; 

  类型名 成员名3;

  ...

};

先声明结构体类型,然后定义该类型的变量。

 使用方式1:

1 struct student
2 {
3  int id;
4   char name[8];
5   char sex;
6   int age;
7 };
8 student stu1,stu2;
View Code


使用方式2:

1 struct student
2 {
3  int id;
4   char name[8];
5   char sex;
6   int age;
7 }stu1,stu2;
View Code

结构体类型也可以和基本数据类型一样,使用结构数组、结构指针等,是一种用户自定义的非常灵活的类型。


2.用关键字union定义联合类型(共用体):

 1 union Data //声明共用体类型
 2 
 3 {
 4 
 5  int i;
 6 
 7  char c;
 8 
 9  float f;
10 
11 };
12 
13 Data a; //定义变量
View Code

联合类型的所有成员变量共享一块内存,内存长度取决于所有成员中占用内存最长的一个成员。比如上面的Data的实例变量a占用4个字节(float类型占用4个字节)。
union在某个时刻只能有一个值,起作用的成员是最后一次被赋值的成员。

不能引用实例变量名,只能用点运算符(.)操作成员。

 3.枚举类型用关键字enum声明:

enum     Weekday  {sun,mon,tue,wed,thu,fri,sat};


 关键字   枚举变量名   0         1   2     3     4    5   6 (每一个元素默认代表一个整数,从0开始。不能对枚举元素赋值!)

4.用typedef关键字声明新类型名。在c++里是typename。

 

 《c程序设计(第四版)学习辅导》第二部分  深入学习c程序设计

 

 第11章  预处理指令

 

 c程序中,在正式编译之前,要先对源码中一些“预处理指令”进行“预处理”,把预处理指令转换成相应的代码段。这项工作由c预处理器完成。

1.c提供的预处理功能包括有以下三种:

(1)宏定义

(2)文件包含

(3)条件编译

这些指令以“#”开头,指令后没有分号。

(1)宏定义

①宏定义: 

#define 标识符  字符串

#define PI 3.1415926

说明:宏定义只是用宏名简单替代一个字符串,只是简单的置换,不做正确型检查。

 ②带参数的宏定义: 

#define 宏名(参数表) 字符串

#define s(a,b) a*b

......

area=s(3,2); //用3*2代替s(3,2)

带参数的宏定义展开置换:从左到右替换,如果宏定义中的字符不是参数字符,则保留。(例如上面的*号)。宏定义对空格非常敏感,一定要谨慎使用空格。

 使用宏的次数多时,宏展开后源代码会变长,函数调用不会使代码变长。

宏替换不占用运行时间,只占用预处理时间,函数调用占用运行时间。

一般用宏代表简短的表达式比较适合。

(2)文件包含

①文件包含指令

#include<...>     //标准方式,系统到存放c库函数头文件的目录中寻找包含的文件

#include"..."       //系统先在用户当前目录中寻找包含的文件,如找不到,再按照标准方式寻找。

 (3)条件编译

在满足某条件时对某一组语句进行编译,当条件不满足时则编译另一组语句。

使用形式:(else语句可以缺省)

①:

1 #ifdef 标识符    //如果指定的标识符已经被宏定义过
2     程序段1
3 #else
4       程序段2
5 #endif
View Code

②:

1 #ifndef 标识符  //指定的标识符没有被定义过
2     程序段1
3 #else
4       程序段2
5 #endif
View Code

③:当指定的表达式值为真(非0)事就编译程序段1,否则编译程序段2

1 #if 表达式
2     程序段1
3 #else
4       程序段2
5 #endif
View Code


第12章  位运算

运算符 含义 运算规则 常用功能
& 按位与 0&0=0,0&1=0,1&1=1 清零,取一个数中某些指定位,保留某些位
| 按位或 0|0=0,0|1=1;1|1=1  
^ 按位异或 0^0=0,0^1=1;1^0=1;1^1=0 使特定位反转,交换两个值而不用临时变量
~ 按位取反 0变1,1变0  
<< 左移 二进制数向左移位,高位左移后溢出丢弃,低位补0  
>> 右移 二进制数向右移位,高位补0,低位被丢弃  

 

 

 

 

 说明:

1.位运算符中,只有~取反是单目运算符,其他都是双目运算符,需要2个操作数。

2.参与位运算的对象只能是整型或者字符型的数据,不能为实型数据。

3.不同长度的数据进行位运算,系统将二者按右端对齐,正数额左侧补满0,负数的左侧补满1,无符号整数则左侧补满0.

4.还与一个位段的概念,就是把一个多字节数据分成多位段。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

原文地址:https://www.cnblogs.com/zhiaiyaya/p/3205479.html