001 超全C语言程序设计概念

2023-05-16

前言

此笔记主要参考自赵海英老师的C语言课程,此笔记是在考研重新学习C语言的情况下进行的整理,主要用于后续的C语言概念温故知新。

第一章 基础知识

1、数制及转换

四种数制:二进制 十进制 八进制 十六进制
二进制定义:0 1两种编码符号,逢二进一
八进制定义:0 1…7八种编码符号,逢八进一
十六进制定义:0 1…9 A B…F十六种编码符号,逢十六进一
十进制->二进制:除二取余倒排
二进制->十进制:按位乘权相加
二进制->八进制:三位压成一位
八进制->二进制:一位展成三位
二进制->十六进制:四位压成一位
十六进制->二进制:一位展成四位

注意: C语言中不能用二进制表示整形常量(int)

第二章 C语言组成及数据

1、C语言组成

组成:若干文件
函数:函数头+函数尾
函数头:四部分->函数名+()
函数体:{}+语句
语句:三类语句(1.注释语句/* */ 2.定义语句 3.执行语句)
注:一个C语言源程序只能有一个main函数,以main函数为入口,以main函数结尾。

2、数据与数据类型

数据四类:常量 变量 表达式 函数
常量:值不发生变化的量
变量:值随时随地改变的量
表达式:用运算符把数据连接起来的合法式子
函数:调用具有一定功能的函数作为运行量

注:

  1. 常量、常变量、符号常量
  1. 整型常量、浮点型常量

可以强制指定浮点型常量的类型

数据类型四大类:基本类型、构造类型、指针类型、空类型
基本类型:整型int、字符型char、浮点型(单精度型float、双精度型double)、枚举型enum
构造类型:数组型、结构体类型struct、共用体类型union
指针类型:
空类型:void

3、标识符

1)保留字(关键字):共32个,固定含义,不能再作为他用。如:int、float、char
2)预定义标识符:在C语言中预先定义并具有特定含义的标识符。如:scanf、printf、include。
3)用户自定义标识符:由用户根据需要自定义的标识符。如:变量名、函数名、数组名。

注:

  • 用户自定义标识符只能由字母、数字、下划线组成,并且第一个字符必须是字母或下划线。
  • 在C语言中严格区分字母大小写,主要使用小写字母。

4、常量四类

1)整型常量:三种形式(十六进制、八进制、十进制)
第一种形式->十进制:是用一串连续的0…9数字
第二种形式->八进制:用数字0开头的一串连续合法八进制
第三种形式->十六进制:用0x或0X开头的一串连续合法的十六进制

注: 若表示长整型常量则必须加字母l或L,如0L,34L。

2)实型常量:两种形式(小数、指数)
第一种形式->小数:由数字和小数点组成
第二种形式->指数形式:用"E"或“e”后面紧跟一个整数表示以10为底的幂数。如:1.23E-5

注:
(1)字母E或e的前面后面都必须有数字,且后面必须为整数。
(2)字母E或e的前后及各数字之间不能有空格

3)字符型常量:四种形式(常规、转义、八进制、十六进制)
形式一->一对单引号括一个字符
形式二->转义字符:必须以一个反斜杠“\”开头
常用转义字符有:换行符\n 制表符\t 退格符\b 回车符\r 响铃\a
形式三->\ddd 最多可以有三位八进制数
形式四->\xhh 最多可以有两位十六进制数

4)字符串常量:一种形式
定义:用一对双引号(双撇号)括起来的若干字符。如“abcd”

注:
(1)每一个字符串结尾都右一个字符串结束符‘\0’。
(2)C语言中没有字符串变量,一定要区分字符串常量和字符串变量。

5、变量–先定义后使用

定义格式:数据类型名 变量名类别;如int i;

注:
(1)变量必须先定义后使用
(2)变量名属于用户标识符,遵守用户标识符命名规则
(3)在同一“函数体”{}中不能定义同名变量(函数体内部为局部变量)
(4)同时定义多变量,必须使用逗号分隔
(5)变量可赋初值(初始化),无初值时是随机值

6、函数

函数分为:标准函数、自定义函数

注:abs和fabs的区别:
1)abs返回整型数据的绝对值
头文件:#include<math.h>
用法:int abs(int i);
2)fabs返回浮点型数据的绝对值
头文件:#include<math.h>
用法:double fabs(double x);

7、表达式

定义:用运算符将数据连接起来的合法式子
运算符注意三个属性:功能、优先级、结合性(运算方向)
1)求余(%)
%两侧运算对象必须为整数,符号与被除数相同

注: 单独的常量、变量或函数调用都是C语言的合法表达式,凡是表达式都有一个确定的值

2)隐式转换

char -> int -> unsigned -> long -> double
float -> double

3)赋值运算符及赋值表达
赋值运算符:=
格式:变量名=表达式
赋值运算符的功能:将表达式的值赋给“=”左边的变量。

注:
(1)赋值运算符左边为变量不能为常量
(2)赋值运算符右边可以是合法表达式
(3)赋值表达式的值就是赋值运算符左边变量值
(4)实型数据赋给整型变量时,实型小数舍去;整型数据赋给实型变量时系统自动将整型数据转成实型数据。

4)复合赋值运算符
+=、-=、*=、/=、%=、&=、|=、^=、>>=、<<=

注:复合赋值运算符两个运算符中间不能有空格

5)自增、自减运算符
自增运算符:++,i++(先算后增)++i(先增后算)
自减运算符:–
如:i++; <=>i=i+1; i–; <=>i=i-1;

注:只能用于变量不能用于常量或表达式

6)逗号运算符及其表达式(顺序求值表达式)
格式:表达式1,表达式2,表达式3……
功能:逗号表达式的值就是最后一个表达式的值,求值顺序是从左到右依次求解

7)强制类型转换(显示转换)
格式:(类型名)表达式 或 (类型名)(表达式)
利用强制类型转换运算符可以将一个表达式的值转换成指定的类型。
如:(int) x+y <=> (int)(x+y)
强制类型转换得到的是一个中间值,而原来表达式或变量的类型并未发生变化。如:若变量x为int型,则表达式(float)x的结果是一个单精度型,但是x还是int型。

第三章 顺序结构设计

1、 定义:从main()函数开始,由上往下一条一条执行

2、三大类语句->执行语句:5类

控制语句
函数调用语句
表达式语句
空语句
复合语句{}

3、标准输入与输出

标准输入输出函数是以一些库函数来实现的。

注:标准函数/库函数使用前必须:#include<头文件名>在包含的程序文件中

1)printf()
格式1:printf(“格式控制”)
功能:按格式控制指定的格式输出数据

格式2:printf(“普通/占位符”,输出列表的值)
功能:按格式将值输出

注:
1)先计算后输出
2)“”占位符是以%开始的,被替换,”普通字符“将原样输出。且输出值,先计算后输出。如:printf(“a=%d,b=%d”,3,4+7);f隐含输出6位小数。

2)scanf()
格式(“普通/占位符”,地址列表)
scanf()五考点
考点1:“普通/占位符”,输入普通字符必须原样输入
考点2:“占位符”,输入整型数据时4种输入
考点3:“占位符”,输入字符型数据只有1种输入(不能有空格、回车、及退格符)
考点4:“占位符”,整型数据和字符型数据混合输入时,字符型数据前不能有空格、回车、退格符。
考点5:地址列表,要有&(取地址符)

4、字符型数据的输入与输出

1)putchar()
格式:putchar(字符常量或字符变量)
功能:输出一个字符但不输出单引号

2)getchar()
功能:接收一个从键盘输入的字符

注: getchar没有任何参数,函数返回值就是输入的字符

第四章 选择结构

1、 定义:从main()开始,从上往下有些语句执行有些不执行。

2、两类表达式

1)关系运算符及关系表达式

2)逻辑云算符与逻辑表达式
在C语言中逻辑表达式的值只有1或0两种值,真为“1”,假为“0”。
逻辑与优先级高于逻辑或
a || b && c等价于a || (b && c),但省略括号会有警告(最好加上括号)

3、if语句(三种格式)

1)格式1:

if(表达式)
语句序列1=if子句
后继语句

2)格式2:

if(表达式)
语句序列1else
语句序列2

3)if语句的嵌套:

if(表达式1if(表达式2)
语句序列11else
语句序列12else
语句序列2

注:
1)可以单独的if不能单独的else;
2)else与上面最近的未配对的if配对;

4、switch语句格式:

switch(表达式)
{
case	常量表达式1:子句1case	常量表达式2:子句2;
……………………
case	常量表达式n:子句n;
default:子句n+1}

注:
1)switch后必须用小括号将表达式括起来;
2)case后为常量或字符型,不能有变量和逗号运算符;
3)各个case后常量值不能相同;
4)case和default只是一个入口标号,不起中断作用,他们之间顺序可以任意颠倒;
5)执行过程是:1)程序执行到switch计算小括号内表达式的值,若该值与某个case后面的值相同时,则程序跳转到该case所在地方往后执行;2)若没有一个case后的值与之相同,当有default时直接跳转到default所在语句往后执行,当没有default时,跳出switch语句;3)只要执行了switch中的某条语句,则程序会一直往后执行,直到所有switch语句执行结束,即使遇到新的case或default语句程序也会执行新的case和default语句,只有遇到break才会提前中断switch语句;
6)case和default都必须出现在switch语句中。

第五章 循环结构

1、 定义:从main()开始,从上往下,使得某些语句重复执行

2、 循环结构程序:在顺序结构中加入循环控制语句;

3、 循环语句四类:
1)方式1:

while()
{
循环体语句序列;
}

2)方式2:

do
{
循环体语句序列;
}while();

3)方式3:

for(exp1;exp2;exp3	)
{
循环体语句序列;
}

4)方式4:

if(){}	else{}goto配合使用。

注:exp1初始化一次,exp2为条件判断语句,exp3使循环能结束。

4、 两个控制语句——break,continue
1)break:
格式:break;
功能:中止退出,用在循环体中和switch体;(1:中止循环 2:跳出switch语句)

2)continue:
格式:continue:
功能:结束一次循环,跳回循环条件变化语句,继续下一次循环。
范围:循环体中。

5、 双循环
执行:先内后外,执行一次外循环->执行所有内循环->执行下一次外循环

第六章 数组

特点:
1)同一数组中的所有元素都属于同一种数据类型,数组元素用数组名和相应的下标来确定;
2)分配的空间为连续的内存空间
方法:一个数组元素其实就是一个变量(可称为带下标的变量)

1、一维数组的定义和引用(只有一个下标)

1)一维数组的定义格式:类型名 数组名[常量表达式],如float a[25]
定义数组有4个注意:
(1)数组名属于用户定义标识符,要遵守标识符命名规则;
(2)定义一维数组时,数组名后必须用一个方括号[]将常量表达式括起来,常量表达式的值表示所定义的数组共有多少个元素(数组大小)。
(3)定义数组[]时方括号中的表达式不能含有变量。另外表达式的值必须要大于0且为正整数。
(4)C语言每个数组在内存中分配空间时是连续分配的。

2)一维数组的元素的引用格式
数组名[下标]

注: C语言中不能对数组进行整体引用只能单独引用其中的元素,引用时下标可以是表达式。数组元素下标的值在0~N-1之间。

2、一维数组的初始化

格式:类型名 数组名[常量表达式]={初值1,…}

注:
1)定义一维数组是可以将各元素的初值依次放在一对{}中赋给数组(必须用{}括起来,且初值之间用一个逗号分隔);
2)多则出错,少则补0;
3)定义赋初值的个数等于数组长度,则长度可以省路;
4)不赋初值则数组元素的值为随机值
5)只能在定义数组的同时用{}给数组元素整体赋值。

3、二维数组的定义和引用(有两个下标)

1)二维数组的定义格式:类型名 数组名[常量表达式1][常量表达式2];如int a[10][10];

注:
1)数组名要遵守用户自定义标识符的命名规则;
2)定义二维数组第一个方括号常量表示行数,第二个方括号表示列数。
3)定义数组时方括号中的表达式不能有变量,且表达式的值必须是大于0的正整数;
4)在内存中二维数组元素的存放也是连续的,先行后列原则。

2)二维数组的引用
数组名[行下标][列下标]

注:
1)不能整体引用,只能引用其中的元素
2)引用二维数组时,必须同时有行下标和列下标。从0开始依次加1.

4、二维数组的初始化

法一:可将初值依次放在一对{ }中,与一维数组初始化格式相同。
如:int a[2][3]={1,2,3,4,5,6};

法二:定义二维数组同时,按行初始化每一行初值均用一对{}括起来,采用嵌套的{}格式。如:int a[2][3]={{1,2,3},{4,5,6}};

注: 定义二维数组的同时给数组初始化,则可以省路行数,但不能省神略列数。

5、字符数组

存储字符串的两种方法:1)字符数组存放 2)字符型指针变量
1)字符数组的初始化
如:char s[]={'a','b','c','d'};字符数组的初始化与其它类型的数组初始化方式一样,只是其初始值是字符。
2)字符串
因为字符串最后都有一个字符串结束符(‘\0’),所以用字符数组来存放字符串时一定要有一个元素存放字符串结束符’\0’。

注:
1)字符串常量最后有一个’\0’,如“abcd”由5个字符组成。“”等价于“\0”,是一个空字符串。
2)用字符串给一字符数组进行初始化有三种情况:(1)char a[]=“abcd”; (2)char a[]={“abcd”}; (3)char a[]={‘a’,‘b’,‘c’,‘d’,‘\0’};

6、字符串的使用

1)字符串存储(赋值)四种方法
法1: scanf()键盘输入

注:
(1)用%s格式输入时,遇到空格符或回车符则自动结束输入。scanf(“%s,%s”,a,b);
(2)不能正确读取数据。scanf输入多个字符串,以回车、空格或tab建作为分隔
char a[100], b[100];
int i = 0;
scanf(“%s%s”, a, b);

输入
how are

a被赋值how,b被赋值为are(多余部分为’\0’)
错误示例如下:

char a[100], b[100];
int i = 0;
scanf("%s\n%s", a, b);

输入
how are\nyou

以为a赋值为how are,b赋值为you,实际上a和b的值和上一个例子一样。
原因:
以为a赋值为how are,b赋值为you,实际上a和b的值和上一个例子一样。
原因:
scanf输入多个字符时,是用空格、回车或者tab作为分隔,所以输入how are\nyou时,第一个空格就会成为分隔(这样回车就是结束符,回车后的you直接被忽略),尽管scanf中试图指定\n为分隔,但系统不这么执行。

法1: printf()输出

注: 输出时则从当前地址开始直到遇到结束符’\0‘为止。

法2: get()键盘输入
格式:gets(字符数组)
功能:读取一个字符串赋给字符数组

注:
1)用该函数输入字符时,只有遇到回车符系统才结束读取字符
2)不论用%s还是gets()在输入时均不需要输入双引号,若输入时用了双引号 则双引号也作为字符串的有效字符。

法2: puts()输出
格式:puts(字符数组或字符串常量)
功能:在屏幕上输出字符数组中的字符

注: 用该函数输出与用%s输出一样,区别是该函数将’\0’转化为’\n’输出。

法3: 字符串初始化
如:(1)char a[]="abcd"; (2)char a[]={"abcd"}; (3)char a[]={'a','b','c','d','\0'};

法4: strcpy()函数

2)字符串函数
strcat()函数
格式:strcat(字符数组2,字符数组2);
功能:连接两个字符串

strcpy()函数
格式:strcpy(字符数组2,字符数组2);
功能:将字符数组2中的字符串替换到字符数组1中,函数值为数组1的首地址。

注: 从第一个字符开始替换,'\0’也替换过去。

strcmp()函数
格式:strcmp(字符数组2,字符数组2);
功能:函数返回相同位置不同字符的ASCII码差值

注: 不能用关系用算符直接进行字符串大小或字符数组大小的比较

strlen()函数
格式:strlen(字符数组)
功能:求出字符数组的实际长度,不包括结束符号

注:
数组的长度必须是常量而不是变量,有种情况除外,那就是在被调用函数中定义的数组,其长度可以是变量或者非常量表达式:

 void func(int n)
{
	int a[n];
}     

**strcpy和strncpy对比 **
重点注意注释中对printf结果的描述;

注: 简记就是strcpy会复制\0,strncpy是指定几位就复制几位,不会自动复制\0

#include<stdio.h>
#include<string.h>
int main(){
    char str1[] = "1234567890";
    char str2[] = "china";
    int l1 = strlen(str1);
    int l2 = strlen(str2);
    int l3;
    strcpy(str1, str2);
    printf("%s\n", str1);
    l3 = strlen(str1);
    printf("%d %d %d\n", l1, l2, l3);   // 输出10,5,5
    return 0;
}
#include<stdio.h>
#include<string.h>
int main(){
    char str1[] = "1234567890";
    char str2[] = "china";
    int l1 = strlen(str1);
    int l2 = strlen(str2);
    int l3;
    strncpy(str1, str2, 5);
    printf("%s\n", str1);
    l3 = strlen(str1);
    printf("%d %d %d\n", l1, l2, l3);   // 输出10,5,10
    return 0;
}              

第七章 函数与预编译

C语言程序的框架有两种:
1)单框架:一个main()
2)一个main()+多个子函数

注:
1)一个C源程序文件可由一个或多个函数组成
2)一个C语言程序可由一个或多个源程序文件组成
3)C语言程序执行总是从main开始,结束于main,可调用其他函数。
4)函数不能嵌套定义,但可以互相调用,不能调用main

函数的分类:
1)无参函数和有参函数
2)库函数和用户自定义函数+main()

1、函数定义

函数返回值类型 函数名(形式参数列表)
{
函数体;
}
说明:
1)函数体可以没有语句,但不能没有花括号,函数名后必须有一对小括号。
2)定义有参函数时,形参的定义可以采用传统方式或现代方式。

传统方式:

int max(x,y)
int x,y;	//不能定义形参以外的其它变量
{	

}

现代方式:

int max(int x,int y)
{	

}	//推荐使用现代方法

3)不能在定义函数时在函数首部小括号后直接跟分号;
4)定义函数时,必须采用传统方式或现代方式指定形参的类型;
5)函数返回值类型有两类:1)非void 2)空类型void(void类型不能有return 语句)

2、函数调用:两种方式

方式1:void型:变量名=函数名(实参列表);//需把函数值赋给一个变量
方式2:非void型:函数名(实参列表);

3、函数使用例题分析

1)原型声明
方式1:#include<头文件>

方式2:声明的格式:
函数类型 函数名(形参类型1 形参1,形参类型2 形参2……);
函数类型 函数名(形参类型1,形参类型2……);

2)函数调用过程
在进行函数调用时系统将实参值对应地传给形参,是一种值的单向传递
实参和形参之间的传递关系:实参、形参应遵守3一致:个数、类型、位置次序

4、变量三属性:类型、作用范围、存储类别

1)作用范围——局部变量和全局变量
局部变量 :(内部变量)
定义:在一个函数内部定义的变量叫做局部变量

注:
1)局部变量只能在它所在的函数内有效
2)在不同的函数中可以出现同名的变量,他们分别属于不同的变量
3)复合语句中定义的变量只能在符合语句中有效
4)所有形式参数都是局部变量

全局变量:
定义:在函数外部定义的变量为全局变量

注:
1)全局变量的有效范围是在本文件内从定义该变量位置到本文件的结束
2)全局变量可以在它的有效范围内被任何函数引用
3)在同一文件中若全局变量与局部变量重名,局部变量”屏蔽“全局变量

2)存储类别
auto类别变量:
(1)auto类别变量用完后释放空间
(2)局部变量默认为auto类别,无初始化时,初值为随机值
(3)使用时间短,一般为auto类别

static类别变量:
(1)static类别从定义到程序运行结束均占用内存空间
(2)全局变量默认为static类别,无初始化时,初值为0
(3)static类别变量只进行一次初始化,下次调用时,使用上次的结果值

register类别变量:
(1)register类别只能是局部变量才能被说明
(2)一般不能够直接使用

extern类别变量:
(1)extern类别变量可以加大变量的作用范围
(2)两种格式说明:
格式1:定义同时说明类别:存储类别 类型名 变量名
格式2:分别定义、说明:
类型名 变量名;
存储类别 变量名;

注:可使全局变量作用范围扩大至另一文件中。

5、预编译命令

1)预编译命令
文件包含(include)

#include<>	//指定标准路径下搜索库文件
#include” “	//自定义路径下搜索

2)宏
第一种 无参宏定义
格式:#define 宏名 宏内容
功能:用一个指定的标识符(宏名)来代表一串字符(宏内容)
如:#define PI 3.1415

注:
1)宏名我们一般用大写字母表示,遵守自定义标识符命名规则
2)#define可以在函数外定义也可以在函数内定义,但该命令应该在单独一行 上,#undef命令可以提前中止宏名的作用
3)在进行宏定义时,可以引用已经定义的宏名进行层层置换
4)在进行宏替换时,必须先替换完所有的宏后再进行运算,同时替换过程不能乱加括号。

第二种 带参宏定义
#define 宏名(参数列表) 宏内容
功能:提供一种更加灵活的替换方式
如:#define s(x,y) x*y+2

注:
1)在定义有参宏时,参数列表必须用一对小括号括起来且小括号和宏名之间不能有空格
2)对有参宏名进行替换时,需要将形参改成相应的实参,并且注意分清形参和实参的对应关系。

第八章 指针

1、指针变量定义

C语言有两种变量:1)变量(普通变量)存储内容值 2)地址变量(指针变量)存储地址值
定义格式:类型名 *指针变量名 如:int *p1;

注:
1)定义变量(普通变量、指针变量)都必须在前面有类型名
2)在定义指针变量时,指针变量名前的 * 表示现定义的是一个指针类型的变量。星号并不是指针变量的一部分,只是一个标志。
3)指针变量是专门用来存地址,禁止将一个整型值直接赋给一个指针变量

2、指针变量的引用

”&“取地址运算符,通过&运算符可以取出普通变量的地址。
”*“指针运算符,* 可以取出指针变量所指向的普通变量的值(间接引用普通变量)

注:
1)可以通过赋值使一个指针变量”指向“某一普通变量(指针变量=&普通变量)
2)在C语言中正确的做法使先让指针变量指向一个确定的存储单元后,再通过该指针变量引用所指向的存储单元。(先定义初始化再调用,如不初始化会指向随机空间,后续调用会出现错误)
3)变量名(普通变量、指针变量)都表示其存储单元内的值
4)若指针变量p指向a,即将变量a的地址赋给指针变量p
5)所有指针变量在内存中分配的字节数相同(均为2字节)

说明:
1)int fun(int a[10] <=>int fun(int *a)<=>int fun(int a[])
若数组作形参,则数组名做指针变量来处理(数组名是个地址常量,不能放在赋值运算符左侧)

3、指向数组的指针变量

1)指向数组元素的指针变量
由于数组元素与普通变量一样,所以定义指向数组元素的指针变量与定义指向普通变量的指针变量完全一样。
如:int a,s[10]; int *p; p=&a; p=&s[2];

2)指向一维数组的指针变量

注:
1)在C语言中规定,数组名代表数组的首地址,而且是一个地址常量。
2)当指针变量指向数组中某个元素时,指针变量+1指向数组的下一个元素,指针变量-1指向数组中的前一个元素
3)当指针变量指向数组时,下标运算([])用于数组也可用于指针变量后
4)若两个指针变量指向同一个数组,则这两个指针变量可以进行大小比较
5)在形参中的数组实际是一个指针变量,并不是真正的数组,因为该”数组名“的值时刻以改变的,而真正的数组名的值是不能改变的
6)若形参是数组或指针变量,则该函数中可通过该形参改变实参的值。

4、指向多维数组的指针变量

如:int a[3][4]; a+1是跳过一行,因为二维数组名是行指针,加1是跳过一行而不是一个元素。
切记:
(1)只有列才是指向”真正“的指针,即指向某一个元素的存储单元。
(2)一维数组名表示的是列指针,二维数组名表示的是行指针。

5、指向由m个元素组成的一维数组的指针变量

定义指向由m个元素组成的一维数组的指针变量的格式:基类型 (*指针变量名)[m];
如:char (*r)[80];

6、指向字符串的指针变量

字符串常量:C语言对字符串常量是按首地址处理字符串常量。

7、指向函数的指针变量

函数与数组名一样,是起始地址,而且是一个地址常量。
定义指向函数的指针变量方式:类型名 (*指针变量名)();

注:
1)在定义指向函数的指针变量时,要注意两个小括号必须要有,不需要定义形参。
2)单独的函数名代表函数的首地址(函数的入口地址)
3)函数的指针变量只能指向函数的入口处(函数的首地址),不指向函数中的某条指令(对指向函数的指针变量+1是没有意义的)
4)给指向函数的指针变量赋值时,只写函数名即可,不必给参数。

8、返回指针的函数

类型名	函数名(形参){

}
返回指针的函数的定义方式为:
类型名	*函数名(形参列表){
}  //return 地址值

9、指针数组和指向指针的指针变量

1)指针数组
若一个数组的所有元素均为指针类型(地址),则称为指针数组。
格式:类型名 *数组名[常量表达式]
如:int *s[10];

注:
(1)要注意与定义指向由m个元素组成的一维数组的指针变量的区别;
类型名 *数组名[常量表达式];
类型名 (*指针名)(常量表达式);
(2)它的每个元素都市一个指针类型(地址),即每个元素都相当于一个指针变量

2)指向指针的指针变量(二级指针)
用来存放指针变量地址的指针变量称为指向指针的指针变量
格式:基类型名 **指针变量名
如:int a=3;int *p=&a;int **k=&p;

10、空指针

指针变量可以有空值,指针变量不指向任何变量,不指向任何有用的存储单元。
在系统中已经将NULL定义为0,即NULL的值为0;
int a,b,c,*p=NULL;
此时p的值为空指针,不指向任何有用的存储单元。尽管NULL的值为0,但我们不能认为p指向了地址为0的存储单元。

注:
1)当一个指针变量为空指针时,我们不能引用它所指向的存储单元。
2)若某指针(地址)的类型为void型,则有引用时应进行相应的强制类型转换。

第九章 构造类型

1、结构体类型

1)构造结构体类型

struct 结构体类型名{
成员1的定义;
成员2的定义;
……
成员n的定义;
};

注:
1)定义成员的方式与定义普通变量的方式一样
2)成员列表必须用一对花括号括起来;
3)结构体名可以省略

2)定义结构体变量
法1:定义结构体类型名,再定义结构体变量

struct studentint sn;
int	age;
char	sex;
int	s[3];;//	类型定义
struct student stu1,stu2,st[25];	//变量定义

法2:在定义结构体类型的同时可以定义结构体变量

struct studentint sn;
int	age;
char	sex;
int	s[3];
}stu1,stu2,st[25];	

法3:类型、变量同时定义,类型名student省略;

structint sn;
int	age;
char	sex;
int	s[3];
}stu1,stu2,st[25];	

注: 结构变量在内存中占用字节数为各成员占用字节数总和。

3)结构体变量的初始化及引用

  • 在定义结构体变量的同时可以将各成员的初值按顺序放在一对花括号中,来进行结构体变量的初始化。若初值个数多于成员个数则出错,若初值个数少于成员个数,则多余成员则自动赋0.
  • 结构体变量不能整体引用,只能引用它的成员(同数组相似)
    引用结构体成员的方式:结构体变量名.成员名(其中 . 为成员运算符)

4)指向结构体数据类型的指针
(1)指向结构体变量的指针
可以用指针变量指向结构变量也可以用指针变量指向结构体变量中的成员。要注意指针变量的类型必须与它所指向的变量类型相同。当指针变量指向结构体变量时,对指针变量+1则跳过整个结构体而不是跳过一个成员。当指针变量p指向结构体变量aa时,引用aa中的成员的方式有三种:

(*p).num;
p->num;
aa.num;

(2)指向结构体数组的指针

注:
1)可以用结构体变量的成员作为实参,它与普通变量作为实参的用法是一样的
2)用结构体变作为实参时,要求形参必须是同一结构体类型的变量,传递后各形参与实参对应成员值是一样的。
3)也可以用结构体类型的地址(指针变量或数组)作为实参,要求形参必须是同一类型的指针变量或数组,只要是地址传递,则可以通过形参来改变实参的值。

注:
1、同类型的结构体变量可以直接相互赋值
2、结构体变量所占内存长度是各成员所占内存的长度之和。每个成员分别占有其自己的内存单元。

2、链表

1)链表概述

  • 链表是一种数组结构,采用动态分配存储单元方式。能够有效节省存储空间(同数组比较)
  • 链表都有一个“头指针”变量(head),用于指向链表中的第一个元素(即用于存放链表中的第一个元素的地址)。链表中的元素称为结点,链表直弄所有的结点都是结构体类型,且同一链表中的结点都是同一结构体类型。每个结点包括数据部分和下一个结点地址两部分内容。链表的最后一个元素(结点)称为链尾,不再指向其它结点(该结点的指针成员值为NULL)
  • 链表的访问都是通过指针变量从头节点开始。

由于链表中的结点是一个结构体类型,并且结点中有一个成员用于指向下一个结点。所以定义作为结点的格式如下:

struct	结构体名
{
定义数据成员;
struct	结构体名	*指针变量名;
}

如:

struct	student
{
int num;
float score;
struct student *next;
};
struct student a,*p;

2)动态存储分配函数
(1)malloc函数
格式:malloc()
作用:在内存的动态存储区中分配一个长度为size字节的连续空间,函数返回值作为一个指向分配区域起始地址的指针,若返回失败则返回NULL。
如:开辟一个用于存放struct student 数据的内存空间,并让p指向该空间。

struct student  *p=(struct  student *)malloc(sizeof( struct student))
//malloc返回的是空类型地址,需进行强制类型转换

(2)free()函数
格式:free(p);
作用:释放用malloc分配发内存

3、共用体类型

1)共同体类型所有成员共用同一段内存,所有成员的起始地址是一样的。

格式:union  共用体名
{
成员列表;
}

注:
(1)成员列表为定义该共用体的成员,成员定义的方式与普通变量的方式一样;
(2)成员列表必须用一对花括号括起来;
(3)共用体名可以省略。

例如:union  data
{
int i;
char ch[10];
float s;
};

注: 由于共用体类型变量的所有成员都共用一段内存,所以共用体类型所占用内存等于该共用体类型中占用字节数最多的成员所占字节数。

2)共用体变量的引用

注:
(1)不能整体引用共用体变量,只能引用其成员。引用的格式:共用体变量名.成员名
(2)同类型成员共享值
(3)在内存中整型数据的二进制低8位占用前面一个字节,高8位占用后面一个字节(小端模式)
(4)共用体变量之间可以相互赋值,赋值后两个变量应是哦你个同一成员
(5)共用体变量的地址与各成员的地址都相同的
(6)在定义共用体时,可以对其进行初始化,但只能有一个初值,且必须用花括号将初值括起来。相当于给第一个成员赋值。
(7)共用体、结构体的成员均可以时共用体或结构体类型
(8)不能用共用体类型变量做函数参数
(9)计算机共用体占用字节数(最大成员字节数)
(10)同类型共用体变量之间可以相互赋值

4、typedef

typedef 已有类型名 新的类型名
1)typedef可用于定义各种类型名,但不可定义变量,即只要见到typedef则该语句最后的标识符一定是一个类型名而不是变量名
2)typedef只能对已经存在的类型新增一个别名,而不是创造新类型。即在typedef后面一定是一个已有的类型。

第十章 位运算/文件

1、位运算

位运算的操作对象只能是整型或字符型数据
C语言提供6种位运算符:
& 按位与
| 按位或
^ 按位异或
~ 取反
<< 左移,相当与*2
>> 右移,正数高位补0,负数由计算机决定

符合赋值运算符
+= 加法赋值
-= 减法赋值
*= 乘法赋值
/= 除法赋值
%= 模运算赋值
<<= 左移赋值
>>= 右移赋值
&= 位逻辑与赋值
|= 位逻辑或赋值
^= 位逻辑异或赋值
1)按位与运算(&)
两个相应的二进制位都是1时,他们按位运算后的结果为1,否则为0;
1&1=1
1&0=0
0&0=0
作用: 清零

2)按位或运算(|)
两个相应的二进制中只要有一个为1,则他们的按位或运算后结果为1.
1 | 1=1
1 | 0=1
0 | 0=0
作用: 将特定位置1.

3)按位异或运算(^)
当两个相应为同为1或同为0时,按位异或运算的结果为0;两个相应位一个为1另一 个为0时,按位异或运算的结果为1.
1 ^ 1 =0
0 ^ 0 =0
0 ^ 1 =1

4)按位取反运算(~)
按位取反运算符是一个单目运算符,按位取反后0变为1,1变为0.

注: 对一个数按位取反得到的值为该数+1后再承 -1.

5)按位左移运算(<<)
格式:数<<n
功能:将二进制位按位依序左移n位。
对一个十进制数左移n位后得到的值为该数乘以2的n次方

6)按位右移运算(>>)
格式:数>>n
功能:将二进制位依序右移n位
若该数为一个负数并且不能被2的n次方整除则得到的数为商-1

2、文件

1)文件概念
文件:记录在外部存储介质(外存)上的数据集合
文件的分类:
(1)文本文件(ASCII码文件):每个字符存储到文件中。
(2)二进制文件:以二进制存储
C语言中对文件的存储是以字符(字节)为单位的
(3)文件类型指针:
FILE就是一个文件类型名,它是一个结构体类型,对一个文件进行操作,是通过文件指针进行的,定义如下:FILE *fp,*in,*out;

2)文件的打开与关闭
文件的打开:fopen()函数
格式:fopen(文件名,文件使用方式);
功能:按指定的“使用方式”打开文件,函数返回所打开文件的指针,该指针的基类型为文件类型,文件名和文件使用方式均为字符串。
如以只读方式打开文件data.txt,并用指针变量fp指向它

FILE *fp;
fp=fopen("data.txt","r");

注:
1)文件使用方式只能用小写字母,文件名用大写或小写是一样的。
2)在“文件使用方式”中,若含有字母b,则打开的是一个二进制文件(bit)
3)当fopen()打开失败时,函数返回NULL。

if((fp=fopen(“文件名”,“文件使用方式”)==NULL))
{
printf("can not open the file!");
exit(0);	
}

文件的关闭:fclose()函数
文件使用完后应该关闭该文件
格式:fclose(文件指针);
如:fclose(fp);

3)文件的读、写操作
文件打开后可以对文件进行操作,C语言中对文件的操作是通过库函数实现的,文件读写操作有以下四类:
读/写文件中的一个字符:fputc()、fgetc()
读/写文件中的一个字符串:fputs()、fgets()
读/写文件中的一个数据块:fread()、fwrite()
对文件进行格式化读/写:fprintf()、fscanf()

(1)fputc()
格式:fputc(字符,字符指针)
功能:把一个字符写到文件指针所指向的文件中去。其中字符可以是字符常量也可以是字符变量。若输出成功则函数返回输出的字符,失败则返回EOF(stdio.h中定义为-1)

(2)fgetc()
格式:fgetc(文件指针)
功能:从文件指针所指文件中读取一个字符。若读取成功则函数返回读取的字符,失败(遇到文件结束)则返回EOF.

(3)fgets()
格式:fgets(str,n,fp)
功能:其中str表示一个字符指针,可以是字符数组名也可以是字符指针变量名。从fp所指文件中读取n-1个字符(不是n个字符)。并在这些字符的最后面加一个字符串结束符’\0’后赋给str。函数返回str的地址。

(4)fputs()
格式:fputs(str,fp);
功能:向fp所指文件中写(输出)str中的字符串,str可以是字符串常量、字符数组或字符指针变量,在输出时字符串的结束符不输出。若成功则返回0,失败则返回EOF

(5)fread()、fweite()
格式:fread(buffer,zize,count,fp);
fwrite(buffer,size,count,fp);
buffer是数据的地址
size是每次读写的字节数
count表示让函数进行多少次读写
fp是要进行读写的文件指针变量
功能:用来读写一个连续的数据块

**注:**1)这两个函数按二进制方式进行读写

(6)fprintf()、fscanf()
格式:fprintf(文件指针,格式说明符,输出列表);
fscanf(文件指针,格式说明符,输入列表);
功能:按格式说明符所指定格式向文件中读写(输入输出)数据。其中格式说明符和输入(输出)列表的用法与printf和scanf函数相同。
补充: feof(文件指针)
作用是测试文件的当前读写位置是否在文件末尾,若是则返回非0值(真),否则返回0(假)

4)文件当前读写位置函数
(1)重新定位指针
格式:rewind(文件指针);
作用:使当前的读写位置重新指向文件的开头,函数无返回值。

(2)fseek()
格式:fseek(文件指针,位移量,起始点);
功能:将当前的读写位置从“起始点”开始按“位移量”所指定的移动字节数向后移动。
起始点有:
SEEK_SET 或0 (表示“文件的开始”)
SEEK_CUR 或1 (表示“当前位置”)
SEEK_END 或2 (表示“文件末尾”)
位移量:要在数值后加字母1或L。如:fseek(fp,100L,SEEK_SET);

(3)ftell()
格式:ftell(文件指针);
功能:返回当前文件的位置,用相对于文件头的位移量表示。若返回-1L则表示出错。

取n-1个字符(不是n个字符)。并在这些字符的最后面加一个字符串结束符’\0’后赋给str。函数返回str的地址。

(4)fputs()
格式:fputs(str,fp);
功能:向fp所指文件中写(输出)str中的字符串,str可以是字符串常量、字符数组或字符指针变量,在输出时字符串的结束符不输出。若成功则返回0,失败则返回EOF

(5)fread()、fweite()
格式:fread(buffer,zize,count,fp);
fwrite(buffer,size,count,fp);
buffer是数据的地址
size是每次读写的字节数
count表示让函数进行多少次读写
fp是要进行读写的文件指针变量
功能:用来读写一个连续的数据块

**注:**1)这两个函数按二进制方式进行读写

(6)fprintf()、fscanf()
格式:fprintf(文件指针,格式说明符,输出列表);
fscanf(文件指针,格式说明符,输入列表);
功能:按格式说明符所指定格式向文件中读写(输入输出)数据。其中格式说明符和输入(输出)列表的用法与printf和scanf函数相同。
补充: feof(文件指针)
作用是测试文件的当前读写位置是否在文件末尾,若是则返回非0值(真),否则返回0(假)

4)文件当前读写位置函数
(1)重新定位指针
格式:rewind(文件指针);
作用:使当前的读写位置重新指向文件的开头,函数无返回值。

(2)fseek()
格式:fseek(文件指针,位移量,起始点);
功能:将当前的读写位置从“起始点”开始按“位移量”所指定的移动字节数向后移动。
起始点有:
SEEK_SET 或0 (表示“文件的开始”)
SEEK_CUR 或1 (表示“当前位置”)
SEEK_END 或2 (表示“文件末尾”)
位移量:要在数值后加字母1或L。如:fseek(fp,100L,SEEK_SET);

(3)ftell()
格式:ftell(文件指针);
功能:返回当前文件的位置,用相对于文件头的位移量表示。若返回-1L则表示出错。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

001 超全C语言程序设计概念 的相关文章

随机推荐

  • Ubuntu在线配置:golang调用python环境

    Anolis amp amp CentOS配置 xff1a Anolis和CentOS配置 xff1a golang调用python环境 Ubuntu离线配置 xff1a Ubuntu离线配置 xff1a golang调用python环境
  • 【string 与 char】C++ 中string与char

    C 43 43 中string类的定义如下 xff1a span class token comment A string of 64 c char span span class token keyword typedef span ba
  • Ubuntu16.04 登陆完后出现蓝屏

    解决方法 xff1a 问题分析启动 Ubuntu 可以进入登录界面 xff0c 说明系统是可以运行起来的 没有发生大块的核心数据损坏 xff0c linux 系统一般都可以修复 xff0c 一定要淡定 于是开始放狗 xff08 google
  • 招聘会岗位筛选爬虫——广州市高校毕业生就业指导中心(广州市高指中心)

    2020 09 21更新 xff1a 目前该网站已实现此功能 xff1a 为什么爬虫 xff1f 由于没有筛选功能 xff0c 导致获取相关想要的信息费时费力 目标网站 xff1a 广州市高校毕业生就业指导中心的某个现场招聘会 以 2019
  • Access to from origin ‘null‘ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin‘ heade

    Access to XMLHttpRequest at span class token string 39 http localhost 8080 postgres mvt source 834 428 10 39 span from o
  • [实验一] 选择器

    该个栏目的博客都是基于南京大学的数字逻辑与计算机组成的课程设计 xff0c 方便以后进行总结归纳而准备的 这次实验是实验一 xff1a 选择器 设计一个简单的选择器 xff0c 介绍一些常用的多路选择器的设计方法 Verilog语言中的al
  • VMware虚拟机中安装的Linux系统无法识别U盘解决方法

    文章目录 1 问题描述2 解决方法3 参考文献 1 问题描述 如图1所示 xff0c 在VMware安装的Linux系统 xff08 Ubuntu 无法读取U盘 图 1 U盘读取失败 2 解决方法 原因在于所用的U盘为3 0接口 xff0c
  • 解决error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools"两个方法

    简述 在Windows下的pycharm安装出现 Microsoft Visual C 43 43 14 0 is required Get it with 34 Microsoft Visual C 43 43 Build Tools的解
  • ubuntu 18.04源码安装mysql 5.7.18

    一 安装依赖包 sudo apt update sudo apt install cmake bison libncurses5 dev build essential 二 下载 mysql 5 7 18源码 源码 传送门 选择那个包含bo
  • 什么叫做装箱和拆箱?一看就懂系列

    有很多同学对与装箱和拆箱还是有点搞不太明白 首先讲一下概念 xff1a 1 装箱指的是把值类型转化为引用类型 2 拆箱当然指的就是把引用类型转化为值类型 估计很多同学可能还分不清哪些是属于引用类型和值类型 这个就需要自己去强化记忆一下了 光
  • java 和javascript的区别?你是否还在把他们混为一谈呢

    1 javascript是基于对象的 xff0c 它是一种脚本语言 xff0c 是一种基于对象和事件驱动的编程语言 xff0c 因而它本身提供了非常丰富的内部对象供设计人员使用 而Java是面向对象的 xff0c 即Java是一种真正的面向
  • vs2019智能提示设置为中文

    官网修改中文提示地址 xff1a https docs microsoft com zh cn dotnet core install localized intellisense 1 去官网下载intellisense语言包 下载链接 x
  • .net中的定时任务

    FluentScheduler是什么 xff1f FluentScheduler是 net中的任务调度框架 xff0c 也就是你如果想在 net程序跑一段代码 xff0c 同时又不影响主程序的运行时 就可以使用FluentScheduler
  • 实用的Visual Studio插件

    打开Visual Studio 扩展 管理扩展 安装自己需要的插件 01 CodeMaid CodeMaid快速整理代码文件 xff0c 规范你的代码 xff0c 提高代码阅读体验 代码自动对齐 xff0c 格式化代码 xff08 ps x
  • mysql 数据库信息探索

    mysql 数据库信息探索 xff08 1 xff09 查询数据库的表数量 SELECT COUNT TABLES table schema FROM information schema TABLES GROUP BY table sch
  • .net 6 基于AspNetCoreRateLimit的限流

    1 安装包 AspNetCoreRateLimit 2 在appsetting cs中加入IpRateLimiting配置节点 span class token comment 限流配置 span span class token stri
  • 关于汉字转拼音并排序解决方案

    使用方法 xff1a 写一个静态帮助类 span class token keyword public span span class token keyword static span span class token keyword c
  • .NET Core6 中使用AutoMapper

    1 引入AutoMapper包 2 新建一个类 xff1a MappingProfile xff0c 类名自定义 xff0c 但是必须要继承 Profile类 用于创建映射规则 如图 xff1a Student为源数据 xff08 我这里是
  • 使用Python调用百度OCR

    使用Python调用百度OCR 注册 登录百度智能云创建应用安装python SDK接口说明代码实现 xff08 本地图片 xff09 代码实现 xff08 使用url上的图片并使用可选参数 xff09 注册 登录百度智能云 注册请点击 登
  • 001 超全C语言程序设计概念

    前言 此笔记主要参考自赵海英老师的C语言课程 xff0c 此笔记是在考研重新学习C语言的情况下进行的整理 xff0c 主要用于后续的C语言概念温故知新 第一章 基础知识 1 数制及转换 四种数制 xff1a 二进制 十进制 八进制 十六进制