当前位置:我的异常网» C语言 » C语言札记
C语言札记
www.myexceptions.net 网友分享于:2013-07-20 浏览:3次
C语言笔记!
C语言笔记!
2010年11月27日
C语言概述
#include ; /*函数包含文件*/
main() /*main主函数,必有,内容用大括号括起*/
{
printf(格式控制,输出列表) /*格式控制包括[文字]和[数据格式说明],转义符:\n 回车换行;\r 本行行首;\t 横右8位,不够补全;\b 光标左一字;\f 走纸换页
格式符(%...):d-带符号十进制整数;o-不带符号八进制整数;x-不带符号十六进制整数;u-不带符号十进制整数;c-一个字符;s-字符串;f-单、双精度默认6位小数;e-标准指数形式输出单、双精度数,默认六位小数*/
}
2、C语言基本数据类型
基本类型:整型 浮点型(单、双精度) 字符型 枚举型
构造类型:数组类型 结构体类型 共用体类型
指针类型
空类型
数值数据的表示:
??整数:
十进制整数:123,-567
八进制整数:011,072(前面加0)
十六进制整数:0x12,-0xf1(前面加0x)
整数存储空间2字节(1字节=8二进制位)
取值范围:-32768 ~ 32767 (超过则溢出出错)
* 如超过,则使用长整型-4字节(后面加L,大小写都可以)---2147483648 ~ 2147483647
??浮点小数(表示实数)*小数点不可省略
十进制小数:1.45 , -34.0 , 0.0 , .56
指数:2.78E12 , 1.34e-4
单精度储存6 ~ 7位有效位数,4字节
双精度储存16 ~ 17位有效位数
文字数据的表示:
??单个字符:
用单引号括起:'a' 'A' '+' '?'
汉字或汉字符号不属于单个字符
转义字符表示特殊的单个字符:'\n'
单个字符占用一个字节,内容为ASCII码
??字符串:
双引号括起字符序列:"you are stupid"
从左到右存储在连续空间,一个字符占一字节
C语言存储时自动在末尾加结束标志'\0'(ASCII码为0)--即六个字符占七个字节
'a'与"a"不同,"a"占两个字节
变量的定义和赋值:
??变量定义
类型标识符 变量名;
* 变量名只能为字符、数字、下划线,首字不为数字,不能与保留字相同
大写与小写不同,但习惯上用小写
??类型标识符:int 整型(2字节);float 单精度浮点型(4字节);double 双精度浮点型(8字节);char 字符型(1字节)
例:int i,j; float x; double y; char c
* char类型只能存放单个字符,字符串或汉字用数组存储
??变量的赋值
赋值号=,判断相等时用==
** 注意--赋值两侧类型不同时:
1、实数赋给整数,舍弃小数部分
2、整数赋给浮点数,自动填0
3、字符赋给整型,高字节置0,低字节为十进制ASCII码
C语言类型修饰符:
long 长型 ; short 短型 ; signed 有符号型 ; unsign 无符号型
??long int(简称long),长整型,占4字节
??long double占16字节,约24有效数字,取值超过double型
??signed和unsigned适用于char、int、long,区别在于最高位是否为符号位
表达式数据类型转换:
??自动类型转换
表达式中含float型或double型,都换成double型运算
表达式无float或double,但有long,则自动转换成long型运算,结果long型
其他都为int型
* 1*2*3*4*5*6*7*8*9结果为整型,无法正确显示, 1L*2*3*4*5*6*7*8*9则可以表示为long,正常显示
??强制类型转换
(类型)表达式 ?? f=(float)x/y
用途:如求余两边必为整数
防止丢失整数除法中小数部分
注意,不改变变量数值,只改变表达式运算时的值
3、控制结构(一)
程序设计的一般方法
??算法+数据结构
??程序设计一般方法
1)明确处理对象,选择算法
2)画流程图
3)编写程序
4)调试程序
结构化程序设计
??基本思想
+ 三种结构:顺序结构 选择结构 循环结构
+ 三种结构都具有一个入口一个出口
+ 限制无条件转移语句(goto)的使用
??顺序结构:按照书写顺序依次进行
选择结构:判断后决定执行
循环结构:反复执行直到某一条件
顺序结构
??可以独立存在,整个程序都存在顺序结构
选择结构
??if语句(两种结果) 或 switch语句(多种结果)
if选择结构
if (条件)
语句1;
else
语句2;
** 语句多于一条时,内容用大括号{}括起
??if语句的嵌套
形式一:
if (条件1) 语句1
else if (条件2) 语句2
else 语句3
形式二:
if (条件1)
if (条件2) 语句1
else 语句2
else 语句3
switch语句
??用于多重分支
??格式:
switch (整型表达式) /* 整型表达式等于数值m即执行语句m,否则执行语句n+1 整型表达式可为字符型表达式 */
{
case 数值1:语句1;break; /* 如果没有break,则会顺序执行,直到break */
case 数值2:语句2;break;
case 数值3:语句3;break;
... ... ... ...
case 数值n:语句n;break;
default:语句n+1
}
4、控制结构--循环控制
while语句
??一般形式
while (条件) 语句体
??条件成立则执行语句,直到不成立
??条件与初值相关,习惯上累计求和初值0,累计求积初值1
* 特别注意避免死循环,必须有改变条件的语句并能使程序在有限步结束
do-while语句
??一般形式
do
循环体语句
while (条件);
??* 先执行语句再判断条件
* while后必须有分号
??** 区别:当一开始条件不成立,while不执行语句,do-while执行一次语句
for语句
??一般形式
for (表达式1;条件;表达式2)
语句
* 表达式1、2如果有多条语句,用逗号","来进行分隔
??执行表达式1,判断条件,执行语句和表达式2,循环2、3步直到条件不成立
??可改写成while语句
表达式1;
while (条件)
{语句
表达式2;
}
??表达式1为初值,表达式2为循环变量增值
??例:for (s=0,n=1;n >= == !=(不等于)
??两个数据在进行值的比较,结果为布尔型(真或假)
C语言中,任何非0值表示真,0表示假
- 例:34>3,先算5>4,结果1,再算1>3,不成立,结果为0)
??、>=优先级等,高于==、!=后二者相等(1==4>3,先算4>3结果为1,再算1==1,结果为1)
??关系运算符级别小于算术运算符。例:2+3>5-1,先算+ -,再算>
逻辑运算符和逻辑表达式
??逻辑运算符:
&&(逻辑与运算符) ||(逻辑或运算符) !(逻辑非运算符)
逻辑运算结果只为真(1)或假(0)
??格式(条件用小括号括起):
逻辑与:条件1&&条件2
逻辑或:条件1||条件2
逻辑非:!条件
??逻辑运算符结合性:
逻辑与、或:自左而右
逻辑非:自右而左 **
??优先级:非! 高于 与&& 高于 或||
??非 的优先级高于算术运算符,算数运算符高于关系运算符,关系运算符高于 与、或
??逻辑运算符可以直接连接数据:2||0&&(3-2*4)结果为1
赋值运算符和赋值表达式
??赋值运算符:=
??将其右边的表达式赋予左边的变量
变量=表达式
??结合性从右至左
??优先级低于算术运算符、关系运算符和逻辑运算符
----------第二种赋值运算符--------
??复合赋值运算:
+= -= *= /= %=
例:a+=3+1 等价于 a=a+(3+1)
??复合赋值运算符左边必须是变量
右边的表达式计算完成后才参与复合赋值运算
??复合赋值运算符结合性与优先级等同于赋值运算符
例:a+=a-=a*a 先计算(1)=a*a 然后a=a-(1) 最后a=a+a
自增运算符与自减运算符
??主要用于给一个变量加1或减1
??自增、自减运算符:
++ 自增运算符 -- 自减运算符
a++等价于++a等价于a=a+1
a--等价于--a等价于a=a-1
??前置运算:运算符位于变量前 先做自增或自减运算,再将变化后的变量值参与表达式中其他运算
后置运算:运算符位于变量后 在变量参与表达式中其他运算后,再做自增或自减运算
* 例:a=10时,x=a++结果为x=10,a=11
a=10时,x=++a结果为x=11,a=11
??自增或自减运算与该变量在表达式中运算顺序无关
** 例:a1=a2=a3=a4=10
b1=(a1++)+(a1++)+(a1++) b1的结果为30
b2=(++a2)+(++a2)+(++a2) b2的结果为39(a2自增3次为13,然后算a2+a2+a2=39)
逗号运算符和逗号表达式
??逗号运算符用于连接表达式
a=a+1,b=3*4;
??逗号运算符连接起来的表达式称为逗号表达式
表达式1,表达式2,表达式3, ... ,表达式n
??运算过程:自左而右,整个表达式的值为最后一个表达式的值
??逗号表达式的优先级最低
条件运算符和条件表达式
??条件运算符是C语言唯一的三目运算符
需要3个数据或表达式构成条件表达式
??格式:表达式1?表达式2:表达式3
如果表达式1成立,则表达式2的值是整个表达式的值,否则表达式3的值为整个表达式的值
例: max=((a>b)?a:b)
----等价于----
if (a>b) max=a;
else max=b;
??结合方向:从右往左
a>b?a:b>c?b:c
??条件运算符优先级高于赋值运算符,低于关系和算术运算符
6、函数
函数的概述
??分类:主函数、库函数、用户自定义函数
??调用过程
C程序从主函数开始,其他函数被主函数或其他函数调用,返回的结果到调用函数
??所有函数定义时互相独立,不能在一个函数内部定义另一个函数,不能嵌套定义,不能调用主函数
函数的定义 格式:
类型标识符 函数名(形式参数类型说明表列)
{
函数体
}
??类型标识符为函数类型,与return语句返回值类型相同,默认为整型
如果函数不返回值,则类型标识符为void,如main函数
??命名规则同标识符
??形式参数类型说明表:形式参数主要接收主调函数传递的数值,类型必须与传过来的数据类型一致
命名符合变量的命名原则
如果不需要接受数据,可以不带形参,但括号不能省略
??每个形参必须单独说明类型,形参定义之间逗号间隔
??函数定义传统格式
类型标识符 函数名(形式参数表列) float max(x,y)
形式参数类型说明 float x,y;
{ {float z;
函数体 if (x>y) z=x;
} else z=y;
return z;}
函数的返回值
??格式:return (表达式); 例:return z;return 0;return (x>y?x:y);
??函数返回值类型与函数类型相同,若不同,函数类型决定返回值类型
??无返回值函数类型说明为void
函数的调用
??格式:函数名(实参表列); 例:max(a,b);
??实参表列可以没有,小括号不可省略
??实参和形参个数相等、类型一致、顺序对应,进行数据的“单向值传递”--形参的值不影响实参的值
??实参可以是常量、变量、表达式或函数
*********************
??函数的声明:函数同变量一样,在调用前应在主调函数中事先说明,即“声明”
??格式:在主调函数开始位置加上被调函数的“函数原形”,即函数定义的第一行
??例:float min(float x,float y);或float min(float,float);或float min();
??以下情况不用声明
-当被调用函数的定义位置在主函数之前
-被调用函数是整型int
*********************
??函数不能嵌套定义,单不能嵌套调用
递归调用
??函数可以直接或间接调用函数本身,成为递归调用
??递归调用可解决具有递归性质的问题
??凡可以化为a(n)=f(a(n-1))都可采用递归调用[(n)和(n-1)为脚标]
??*** 递归调用必须可以满足一定条件时结束递归调用
??由多个通项表示的情况,需要给出最后一个递归调用的所有项的值
例:a[3]=a[2]+a[1];a[2]=a[1];则必须给出a[1]=1;
7、数组
一维数组的定义
??格式:
类型标识符 数组名[元素个数]; int a[5];
??数组名命名规则同变量名的命名
"[]"是数组标志,不可改换
数组元素的个数必须是固定值,可以为 整型常量、符号常量或整型常量表达式
??定义数组时,数组下标从0开始,定义int a[n],最大到a[n-1]
一维数组的引用
??格式:
数组名 [下标]
??下标可以用整型常量、整型变量或整型表达式
??数组元素按下标顺序存放
??使用方法与同类型变量相同
一维数组的初始化
??格式:
类型标识符 数组名[元素个数]={元素值表列}; float x[3]={1.5,3.2,9};
??元素值表列个数可以小于元素个数,未赋初值的整型元素值为0
??当全部数组元素赋初值,元素个数可省略,但[]不可省
??数组只能在定义时初始化,
int a[5];
a[5]={1,2,3,4,5}; 是错误的
多维数组的定义
??定义格式:
类型标识符 数组名[元素个数1][元素个数2];
int a[2][3],b[30][5];
??C语言把二维数组看作一维数组集合
??二维数组元素按行存放
??多维数组定义类似:
类型标识符 n维数组名[元素个数1][元素个数2]...[元素个数n];
??多维数组存储顺序:左边下标变化最慢,越往右变化越快
多维数组的引用
??格式:
数组名 [下标1][下标2]
??可将二维数组看作一个行列式或矩阵理解
二维数组的初始化
??按行初始化
int a[2][3]={{1,2,3},{4,5,6}};
??按存储顺序赋初值
int a[2][3]={1,2,3,4,5,6};
??部分元素赋初值
int a[2][3]={{1,2},{3}};
int a[4][4]={{1},{0,1},{,,1},{,,,1}}
int b[2][3]={{},{,2}};
??若全部赋初值,则元素个数1可省略,元素个数2不能省略
int a[][3]={1,2,3,4,5,6};
int a[][3]={{1,2,3},{},{4,5}};
数组作为函数参数
??一维数组元素作函数参数
- 与同类型简单量相同
??数组名作函数参数
- 形参和实参都是数组名,传递整个数组,即形参数组和实参数组完全等同
这样形参数组修改,则实参数组也同时被修改了
- 形参的数组要定义,与实参数组类型一致,但大小可以小于实参数组
- 形参数组的元素个数可省略,由专门的参数传递元素个数
8、字符和字符串
单个字符的输入输出
1) 输入:getchar() 定义在头文件"stdio.h"
??作用是从输入设备读取一个字符
??没有参数,格式:
getchar();
??执行结果是得到一个字符
char c;
c=getchar();
** getchar()可接受回车字符,scanf()将回车作为数据间隔符或结束符
??getchar()接受的字符可不赋给任何变量
2) 输出:putchar() 定义在头文件"stdio.h"
??作用是将一个字符输出到输出设备
??格式:putchar(字符型或整型数据);
char c='a';
putchar(c);
??结果是输出字符变量的值
??可以输出字符型变量、整型变量、字符型常量以及控制字符和转义字符
字符数组与字符串
1) 字符数组
??数组元素是字符型的数组
??字符数组的赋值
- char c[3];
c[0]='i';c[1]='a';c[2]='e';
- for语句读取
- 初始化定义
??输出一次只能输出一个字符
??只能处理已知个数的字符序列,并且长度不可变化
2) 字符串
??字符序列当作字符串处理,基于字符数组
??字符串在实际存储时尾部添加结束标志'\0'
??'\0'是空操作符,ASCII码为0,表示什么都不操作
??字符串定义即在字符数组定义基础上,最后加上c[n]='\0';
??字符串也可以采用字符串输入输出格式符"%s"
格式:
char c[9];
scanf("%s",c);
* 注意:
当格式符为"%s"时,scanf()函数地址列表是字符数组的名字,无需加地址符&
错--> scanf("%s",c[9]);
错--> scanf("%s",c);
错--> scanf("%s",&c);
??输出格式:printf("%s",c);
注意:同输入一样,没有&
??利用"%s"输入输出字符串,只要字符个数小于字符数组长度就可以了
??字符串的初始化可采用如下方法
-1- char c[9]={"i like c"};
-2- char c[9]="i like c";
-3- char c[]="i like c";
字符数组长度可以大于字符串长度,便于以后变化
字符串的输入和输出函数
??输入函数gets()和输出函数puts() 定义在头文件"stdio.h"
??输出函数puts():
puts(字符数组名); 或 puts(字符串);
- 例: char str[]="i like c";puts(str); 或
puts("i like c");
- 一次只能输出一个字符串
- 可以输出转义字符
- 输出字符串之后自动换行
??输入函数gets():
gets(字符数组名);
- 在读入一个字符串自动加'\0'
- 一次只能输入一个字符串
- 可以读入包括空格和TAB的全部字符,直到遇到回车(不读回车)
scanf()不能读入空格、TAB及回车
??C语言提供很多字符串操作函数,对应头文件 string.h
1) strlen(字符串)
- 测试字符串实际长度,不包含'\0'
- strlen("Beijing")值为7
2) strcpy(字符数组1,字符串2)
- 用于将 字符串2 复制到 字符数组1
- strcpy(str1,str2);strcpy(str1,"i like c");
- 字符数组1 必须足够大
- 只能复制 字符串2 '\0'前的字符串
3) strcat(字符数组1,字符串2)
- 将 字符串2 的内容连接在 字符数组1 后面,返回 字符数组1 的地址
- 字符数组1 必须足够大,以容纳本身+字符串2
- 连接前 字符数组1 的'\0'被 字符串2 覆盖,保留 字符串2 的'\0'
4) sytvmp(字符串1,字符串2)
- 比较 字符串1 和 字符串2
- 两字符串自左而右逐一比较,按ASCII码,直到字符不同或遇到'\0'
- 如果全部相同,返回值0;如果不相同,返回两个字符串中第一个不相同的字符的ASCII码的差,串1 大为正,串2 大为负
5) strlwr(字符串)
- 将所有大写字母转换成小写字母
6) strupr(字符串)
- 将所有小写字母转换成大写字母
二维字符串数组
??多个字符串用二维字符串,比如30名学生的姓名,则30个字符串,name[30][20]
??如果2个班级各30名学生的姓名,则name[2][30][20]
??二维字符串数组初始化
- 采用二维字符数组初始化形式或字符串初始化形式
char name[2][10]={{'j','o','h','n','\0'},{'m','a','r','r','y','\0'}};
char name[2][10]={{"john"},{"marry"}};
char name[2][10]={"john","marry"};
??二维字符串数组的赋值和引用
- 二维字符串数组可看作元素是一个字符串的一维数组
char name[3][30];
for (i=0;i
系统将到包含C库函数的头文件目录中寻找
形式二:#include "文件名"
系统先在当前目录找,找不到在到操作系统的path命令设置的自动搜索路径中查找,最后到C语言头文件所在目录查找
- 在包含头文件时用形式一,其他情况用形式二
??一个#include命令只能指定一个被包含文件
??文件包含可以嵌套:
如果文件1包含了文件2,文件2包含了文件3,则文件1也要包含文件3,并且文件3的包含要写在文件2的包含之前
文件1种的包含:
#include "文件3"
#include "文件2"
10、指针(一)
地址与指针
??变量的地址称为变量的指针,存放变量地址的变量成为指针变量
指向变量的指针变量
??指针变量的定义
类型名 *指针变量名;
??"*"不能省略,定义时是说明符,不是变量名一部分
类型名表示指针变量所指向的变量的类型,而且只能指向这种类型的变量
??指针变量允许在定义时进行初始化 int *p=&i;
&:取地址运算符 *:指针运算符
例:int *p=&a; 其中 p 为 a 的地址,*p 则指向 a 变量
??若:p=&a 则
&*p=&(*p)=&a=p *&a=*(&a)=*p=a
因此 & 和 * 最后抵消
??不能给指针变量赋常数值
指针变量没指向确定地址前,不要对它所指向的对象赋值
??指针变量作为函数参数
- 通过指针变量作函数参数,无需返回值和全局变量,主调函数就可以使用被调函数改变的值
指针与数组
??指向数组元素的指针定义
- 定义与赋值
数组名代表了数组的首地址,则p=a; /*(a[5])*/为指向数组第一个元素
- 如果p指向一个数组元素,则p+1指向下一个数组元素,不同类型的数组元素,p值得改变不同
- 数组名作函数参数,形参数组元素值与实参数组元素值同时变化
指针与字符串
??char *string="Hello"; 则*string指向H
??char *string; char *string;
string="Hello"; 这种方法正确 *string="Hello"; 这种写法错误
11、指针(二)
返回指针值的函数
??返回值为指针型数据的函数,定义形式:
类型名 *函数名(参数表);
例:int *func(int x,int y);
- 返回值为指向int型数据的指针
- 函数名前*指标是返回值为指针型数据
指向函数的指针
??定义指针变量指向函数
类型名 (*指针变量名)();
例:int (*p)();
??赋值时使指针变量等于一个函数名
??调用:
(*指针变量名)(实参表)
??调用函数 将函数作为参数在函数间传递
??这类指针变量等于函数的入口地址,对它们作加减运算无意义
指针数组
??如果一个数组元素都是指针类型,称之为指针数组
??定义:
类型名 *数组名[常量表达式];
例:int *a[5];
??主要用于管理同种类型的指针,最常用于处理字符串
??两个字符串互换,只要交换数组中指向这两个字符串的指针即可
指针与多维数组
??不带任何下标的二维数组名表示二维数组的起始地址,进行加法操作时表示作为其元素的一个一维数组的起始地址
??只带一维下标的二维数组名表示作为其元素的一个一维数组的起始地址
??指向二位数组元素的指针变量
- 定义,赋值,引用与一维数组相同
- int a[2][3],*p;
p=a[0];
则*(p+1)==a[0][1]
??任何一个二维数组a[n]的元素a[j]的地址,都可用a[0]+i*n+j来表示
??指向二维数组中一维数组的指针变量
- 指针变量可以指向作为二维数组元素的一个一维数组,对这种指针变量进行加减操作则指针在二维数组行上移动
- 定义
类型符 (*指针变量名)[指向的一维数组元素的个数];
??例:int a[2][3],(*p)[3];
p=a
则 *(*(p+1)+1)等于a[1][1]
??注意 *********
int (*q)[3],*p[3];
q是指向包含整形元素的一维数组的一个指针变量
p是由p[0] p[1] p[2]三个指向正型数据的指针组成的数组
指向指针的指针
??单级间指 二级间指(两次运用指针变量引用变量)
命令行参数
??C编写程序,编译链接后将生成可执行文件,可以在操作系统状态下作为外部命令执行
??C允许main函数带两个参数
??带参数的main函数一般形式为:
main(int argc,char *argv[])
{......}
其中,参数argc为整型,是命令行中参数的个数,命令名也作为一个参数
argv为指向字符串的指针数组,它的元素依次指向命令行中的各个字符串,包括命令名
文章评论