标识符的命名规则和规范
标识符:自己起名字的叫做标识符
标识符的命名规则
1. 由26个英文字母大小写,0-9,_或者$组成
2. 数字不可以开头 3. 不可以使用关键字和保留字,但能包含关键字和保留字
4. C语言中严格区分大小写,长度无限制
5. 标识符不能包含空格
顺序程序设计
数据的表现形式 - 常量和变量 - 常量:用#define
指令来指定用一个符号(一般大写
)来代表一个常量(好处是一改全改
) - 符号常量是预编译指定,在预编译仅仅是进行字符替换,在预编译之后,符号常量将不存在
#define PI 3.14159267 //注意尾部并没有;
const int PI = 3.14;//使用const来定义常量
- `const `和 `#define`的区别
1. const定义的常量时,带类型,define不带类型.
2. const是在编译、运行的时候起作用,而#define是在编译的预处理阶段起作用
3. define只是简单的替换,没有类型检查,简单的字符串替换会导致边界效应
4. const常量可以进行调试的,define是不能进行调试,主要是预编译阶段就已经替换掉了,调试的时候就没有它了
5. const不能重定义,不可以定义两个一样的。而define通过取消某个符号的定义再重新定义
//使用const定义
const int PI = 3,14;
const double PI = 3.14;//这是不可取的
#define PI 3.14
#undenfine PI //可以使用#undefine来取消
#define PI 3.1415 //这是可以使用的
6. define可以配合`ifdef`、`ifndef`、`endif`来使用,可以让代码更加灵活,比如我们可以通过define来启动或者关闭调试信息。
#define PI 3.14
#ifdef PI
printf("存在信息输出");
#endif
#ifndef PI
printf("不存在信息输出");
- 变量:变量必须先定义,后使用
- 常变量(const):定义常变量`const float pi = 3.1415926;`
- 数据类型(`用unsigned代表无符号`)(默认有符号)
- 整型类型
- 基本类型
- 基本整型(`int`)
- 短整型(`short int` )
- 长整型(`long int`)
- 双长整型(`long long int`)
- 字符型(`char`)
- 布尔型(`bool`)
- 浮点类型
- 单精度浮点()
- 双精度浮点
- 复数浮点
- 枚举类型(enum)
- 空类型(void)
- 派生类型
- 指针类型(*)
- 数组类型([])
- 结构体类型(struct)
- 共用体类型(union)
- 函数类型
注:`基本类型(包括整型和浮点型)和枚举类型变量的值都是数值,统称为算数类型`
`算数类型和指针类型统称纯量类型`,`因为其变量的值是以数字来表示`
`数组类型和结构体类型统称为组合类型`
函数类型用来定义函数
运算符和表达式
C运算符
- 算数运算符
- 取模公式:a%b = a-a/b*b
- 关系运算符(0是假)
- 关系运算符只是用非零的数表示真,2也是真.C语言默认是1
- 逻辑运算符
- 位运算符
- 赋值运算符
- 三元运算符(表达式 1 ? 表达式2 : 表达式3)
- 条件运算符
- 逗号运算符
- 指针运算符
- 求字节数运算符
- 强制类型转换运算符
- 成员运算符
- 下标运算符
- 其他运算符
函数
函数参数的传递方式 1. 值传递 1. 基本数据类型 2. 结构体 3. 共用体 4. 枚举类型 2. 引用传递 1. 指针 2. 数组
注意事项
- 函数的形参列表可以是多个
- C语言传递参数
可以是值传递,也可以是传递指针
也叫引用传递 - 函数命名
- 函数中的变量是局部变量
- 基本数据类型默认是值传递
- 如果希望函数内的变量能够改变函数外的白变量,可以使用指针
Static关键字
基本介绍:
局部变量使用static修饰 1. 局部变量别static修饰之后,我们称为静态局部变量 2. 对应静态局部变量在声明时未赋初始值,编译器会自动初始化为零 3. 静态局部变量存储与进程的静态存储区(全局性质),只会被初始一次,即使函数返回,它的值也会保持不变
1.使用非静态函数之前需要声明(使用extern[外部]关键字)
- 2.不同的文件可以使用相同名字的静态函数,互不影响.
- *静态函数只能在声明它的文件中可见,其他文件不能引用该函数*
常用的系统函数
字符串<string.h>
strcoy(s1,s2) | 复制字符串s2到字符串s1 |
strcat(s1,s2) | 连接字符串s2到字符串s1的末尾 |
strcmp(s1,s2) | 如果s1和s2是相同的返回0;如果s1<s2则返回小于0;如果s1>s2则返回大于0 |
strlen(s1) | 返回s1的长度 |
strchr(s1,ch) | 返回一个指针,指向字符串s1中字符ch第一次出现的位置 |
strstr(s1,s2) | 返回一个指针,指向字符串s1中字符串s2的第一次出现的位置 |
C语言宏定义
基本介绍 1. #define
叫做宏定义命令,它也是C语言预处理命令的一种.所谓宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串 2. 宏定义是由源程序中的宏定义命令#define完成的,宏替换是由预处理程序完成的
#define 宏名 字符串(广义)
带参数的宏定义 1. C语言允许宏带有参数,在宏定义中的参数称为"形式参数",在宏调用中的参数称为"实际参数" 2. 对于参数的宏,在展开过程中不仅要进行字符串的替换,还要用实参替换形参 3. 带参宏定义的一般形式为
#define 宏名(形参列表) 字符串 //带参宏定义的一般形式为
宏名(实参列表); //带参宏调用的一般形式
数组
基本介绍
数组可以存放多种同一类型数据.数组也是一种数据类型,是构造类型,传递是以饮用的方式传递(即传递的是地址)
排序和查找
排序:排序也称排序算法(Sort Algorithm),排序是将一组数据,依照指定的顺序进行排列的过程.
#include <stdio.h>
//
// Created by zyq on 2023/3/30.
//
/**
* 冒泡排序
*/
void main() {
int arr[] = {23, 1, 34, 89, 100};
int len = sizeof(arr) / sizeof(int);
int temp = 0;
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
for (int i = 0; i < len; i++) {
printf("%d\t", arr[i]);
}
排序的分类 1. 内部排序:指将需要处理的所有数据都加载到内存存储器中进行排序 2. 外部排序:数据量过大,无法全部加载到内存,需要借助外部存储进行排序
查找:
顺序查找
#include <stdio.h>
//
// Created by zyq on 2023/3/30.
//
/**
* 顺序查找
*/
int fine(int arr[], int len, int flag) {
for (int i = 0; i < len; i++) {
//printf("%d\n", arr[i]);
if (arr[i] == flag) {
return i;
}
}
}
void main() {
int arr[] = {23, 1, 34, 89, 100};
int len = sizeof(arr) / sizeof(int);
int flag = 100;
int a = fine(arr, len, flag);
printf("%d", a);
}
二分查找
#include <stdio.h>
//
// Created by zyq on 2023/3/30.
//
/**
* Binary lookup:二分查找
*/
int binaryLookup(int arr[], int left, int right, int find) {
int mid = (left + right) / 2;
int midValue = arr[mid];
if (left > right) {
return -1;
}
if (midValue > find) {
binaryLookup(arr, left, right - 1, find);
} else if (midValue < find) {
binaryLookup(arr, left + 1, right, find);
} else {
return mid;
}
}
void main() {
int arr[] = {1, 8, 10, 89, 1000, 1234};
int len = sizeof(arr) / sizeof(int);
int index = binaryLookup(arr, 0, len - 1, -1);
printf("%d", index);//0
}
二维数组
//定义二维数组
数据类型 数组名称[][] = {{},{},{}};
#include <stdio.h>
//
// Created by zyq on 2023/3/30.
//
/**
* 二维数组
*/
int main() {
int arr[5][5] = {
{1,4,7,8},
{6,8,3,2},
{7,9,0,7},
{2,12,34,90}
};
//遍历二维数组
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
printf("%d\t",arr[i][j]);
}
printf("\n");
}
return 0;
}
字符数组与字符串
用字符数组存放一个字符串
用字符指针指向一个字符串
字符串注意事项 1. 在C语言中,字符串实际上是使用NULL字符('\0')终止的一维字符数组.因此,一个以null结尾的字符串,包含了组成字符串的字符 2. '\0'是ASCII码中的第0个字符,用NULL表示,称为空字符.该字符即不能显示,也不是控制字符,输出该字符不会有任何效果,它在C语言中仅仅作为字符串的结束标志. 3. 字符数组(字符串)在内存中的布局分析
指针
什么是指针
1. 指针是一个变量,其值为另一个变量的地址.
指针的基本介绍
1. 指针也就是内存的地址;所谓指针变量,也就是保存了内存地址的变量。关于指针的基本使用,在讲变量的时候做了入门级的介绍
2. 获取变量的地址,用&比如:int num = 10;,获取num的地址:&num
3. 指针类型,指针变量存的是一个地址,这个地址指向的空间存的才是值。
int *ptr = &num;//prt就是指向int类型的指针变量,即ptr是int*类型
4. 获取指针类型所指向的值,使用:*
指针数组
基本介绍:要让数组的元素指向int或者其他数据类型的指针.可以使用指针数组
指针数组的定义:
数据类型 *指针数组名[大小]
指向指针的指针(多种指针)
基本介绍
指向指针的指针是一种**多级间接寻址**的形式,或者是一个指针链.通常,一个指针包含一个变量地址.当我们定义个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含及实际值的位置
函数指针
函数指针的定义
returnType (*pointerNme)(param list);
1. returnType为函数的返回类型
2. pointerName为指针名称
3. param list为函数参数列表
4. 参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称
指针的注意事项和细节
1. 指针变量存放的是地址,从这个角度看指针的本质就是地址
2. 变量声明的时候,如果没有确切的地址赋值,为指针变量赋值一个NULL值是一个好的习惯
3. 赋NULL值的指针被称为空指针,NULL指针是一个定义在标准库<stdio.h>中的值为零的常量#define NULL 0
void main(){
int *p = NULL;
int num = 34;
p = #
}
动态内存分配
- 全局变量—内存中的静态存储区
- 非静态的局部变量—内存中的动态存储区—stack栈
- 临时使用的数据—建立动态内存分配区域,需要随时开辟,不需要及时释放—heap堆
内存动态分配的相关函数
---
结构体和共用体
结构体
/**
结构体
*/
void main(){
//结构体的定义
struct Cat{
char* name;
int age;
char* color;
};
//也可以
struct Cat{
char* name;
int age;
char* color;
}a = {"李华",23,"灰色"}....;
struct Cat cat1;
cat1.name = "lihua";
cat1.age = 19;
cat1.color = "baise2";
}
共用体(联合体)
基本介绍
1. 共用体(Union)属于构造类型,他可以包含多个类型的不同成员,和结构体非常类似,但是也有不同的地方
2. 空间大小是共用的,共有数据空间,该空间的大小以占用空间最大的成员变量决定
定义
union 共用体名{
成员列表
};
//定义共用体的三种方式
//第一种
union data{
int n;
char ch;
double f;
};
union data a,b,c;
//第二种
union data{
int n;
char ch;
double f;
} a,b,c;
//第三种
//匿名共用体
union {
int n;
char ch;
double f;
} a,b,c;
使用
结构体和共用体的区别
1. 结构体的各个成员会占用不同的内存.互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员
文件操作
文件操作的基本介绍
1. 文件是数据源(保存数据的地方)
2. 文件在程序中是以流的形式来操作的
![](https://secure2.wostatic.cn/static/2eTaL2KTnLbq3oNPg75Ufn/image.png)
3. 输入流:数据从数据源(文件)到程序(内存)的路径
4. 输出流:数据从程序(内存)到数据(文件)的路径
getchar()&putchar()函数&gets()&puts()
1. `getchar(void)`:从屏幕读取下一个可用字符,并把它返回为一个整数.这个函数在同一个时间内只会读取一个单一的字符,可以在循环内使用这个方法,以便从屏幕上读取多个字符
2. `int putchar(int c)`:把字符输出到屏幕上,并返回相同的字符,这个函数在同一个时间只会输出一个单一的字符.您可以在循环内使用这个方法,以便在屏幕上输出多个字符
3. `gets()`:从stdin读取一行到s指向的缓冲区,知道读取一个终止或者EOF
4. `puts()`:把字符串s和一个尾随的换行符写入到stdout
文件的打开和关闭
**打开文件**
`fopen()`:用来创建一个新的文件或者打开一个已经存在的文件,这个调用会初始化类型FILE的一个对象,类型FILE包含了所有用来控制流的必要的信息
FILE*fopen(const char * filename(字符串的名字),const char * mode(模式));
**关闭文件**
`int fclose(FILE *fp);`
1. 如果关闭成功返回0,关闭发生错误返回EOF
2. 这个函数实际上会清空缓冲区的数据,关闭文件,并释放用于该文件的所有内存
3. EOF是一个定义在头文件的stdio.h中的常量
在这里,**filename** 是字符串,用来命名文件,访问模式 **mode** 的值可以是下列值中的一个:
模式 | 描述 |
---|---|
r | 打开一个已有的文本文件,允许读取文件。 |
w | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。 |
a | 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ | 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。 |
a+ | 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。 |
写入文件
下面是把字符写入到流中的最简单的函数:
int fputc( int c, FILE *fp );
函数 fputc() 把参数 c 的字符值写入到 fp 所指向的输出流中。如果写入成功,它会返回写入的字符,如果发生错误,则会返回 EOF。
您可以使用下面的函数来把一个以 null 结尾的字符串写入到流中:
int fputs( const char *s, FILE *fp );
函数 fputs() 把字符串 s 写入到 fp 所指向的输出流中。
如果写入成功,它会返回一个非负值,如果发生错误,则会返回 EOF。
您也可以使用 **int fprintf(FILE
fp,const char format, ...)
函数把一个字符串写入到文件中。
//创建一个文件指针
FILE* fp = NULL;
//打开文件
fp=fopen("D:/test100.txt","r");
fprintf(fp,"你好北京--\n");
fputs("你好上海\n",fp);
fclose(fp);
printf("完成\n");
读取文件
下面是从文件读取单个字符的最简单的函数:
int fgetc( FILE * fp );
fgetc() 函数从 fp 所指向的输入文件中读取一个字符。返回值是读取的字符,
如果发生错误则返回 EOF。下面的函数允许您从流中读取一个字符串:
char *fgets( char *buf, int n, FILE *fp );
- 函数 fgets() 从 fp 所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。
- 如果这个函数在读取最后一个字符之前就遇到一个换行符 '\n' 或文件的末尾 EOF,则只会返回读取到的字符,包括换行符。
- 也可以使用
**int fscanf(FILE
fp, const char format, ...)
函数来从文件中读取字符串,但是在遇到第一个空格和换行符时,它会停止读取。
char buff[1024];
while (fgets(buff, 1024, (FILE*)fp) !=NULL){
printf("%s\n", buff );
}
fscanf(fp,"%s",buff);
printf("%s\n",buff );
typedef
C 语言提供了 typedef 关键字,您可以使用它来为类型取一个新的名字。下面的实例为单字节数字定义了一个术语 BYTE:
typedef unsigned char BYTE;
在这个类型定义之后,标识符 BYTE 可作为类型 unsigned char 的缩写,例如:
BYTE b1, b2;
按照惯例,定义时会大写字母,以便提醒用户类型名称是一个象征性的缩写,但您也可以使用小写字母,如下:
typedef unsigned char byte;
您也可以使用 typedef 来为用户自定义的数据类型取一个新的名字。例如,您可以对结构体使用 typedef 来定义一个新的数据类型名字,然后使用这个新的数据类型来直接定义结构变量,
typedef vs #define
#define 是 C 指令,用于为各种数据类型定义别名,与 typedef 类似,但是它们有以下几点不同:
- typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
- typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。
#include <stdio.h>
#define TRUE 1
#define FALSE 0
int main( )
{
printf( "TRUE 的值: %d\n", TRUE);
printf( "FALSE 的值: %d\n", FALSE);
return 0;
}