C语言复习

近期应聘,复习一下C语言的相关内容,将重点内容截取出来备忘
C 程序结构:
预处理器指令
函数
变量
语句 & 表达式
注释
基本数据类型占用空间(64位机器为例)
char : 1个字节
int :4个字节
float:4个字节
double:8个字节
C 中的变量定义:
int i, j, k;
char c, ch;
float f, salary;
double d;
extern int d = 3, f = 5; // d 和 f 的声明与初始化
int d = 3, f = 5; // 定义并初始化 d 和 f
byte z = 22; // 定义并初始化 z
char x = ‘x’; // 变量 x 的值为 ‘x’
前缀指定基数:
0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。
字符常量:
转义序列 含义
\ \ 字符
’ ’ 字符
" " 字符
? ? 字符
\a 警报铃声
\b 退格键
\f 换页符
\n 换行符
\r 回车
\t 水平制表符
\v 垂直制表符
\ooo 一到三位的八进制数
\xhh . . . 一个或多个数字的十六进制数
定义常量
在 C 中,有两种简单的定义常量的方式:
使用 #define 预处理器。
使用 const 关键字。

位运算符
& 按位与操作,按二进制位进行"与"运算。
| 按位或运算符,按二进制位进行"或"运算。
^ 异或运算符,按二进制位进行"异或"运算。
~ 取反运算符,按二进制位进行"取反"运算。
<< 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
>> 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
杂项运算符
sizeof() 返回变量的大小。
& 返回变量的地址。 &a; 将给出变量的实际地址。 取地址运算父
* 指向一个变量。 a; 将指向一个变量。 指针运算符(取值运算符)
? : 条件表达式 如果条件为真 ? 则值为 X : 否则值为 Y
算术运算符
/ 分子除以分母
% 取模运算符,整除后的余数
判断语句:
if() {} else if() {} else {}
switch() {case ‘’: …break; case ‘’: …break; default:… }
Exp1 ? Exp2 : Exp3;
C 循环
循环类型
while 循环
for 循环
for ( init; condition; increment )
{
statement(s);
}
do…while 循环
循环控制语句
break 语句 终止循环或 switch 语句,程序流将继续执行紧接着循环或 switch 的下一条语句。
continue 语句 告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。
goto 语句 将控制转移到被标记的语句。但是不建议在程序中使用 goto 语句。
定义函数
return_type function_name( parameter list )
{
body of the function
}
根据函数能否被其他源文件调用,将函数区分为内部函数和外部函数。
内部函数 如果一个函数只能被本文件中其他函数所调用,它称为内部函数。在定义内部函数时,在函数名和函数类型的前面加 static,即
static 类型名 函数名 (形参表)
内部函数又称静态函数。使用内部函数,可以使函数的作用域只局限于所在文件。
外部函数 如果在定义函数时,在函数的首部的最左端加关键字 extern,则此函数是外部函数,可供其它文件调用。
extern int max (int a,int b)
C 语言规定,如果在定义函数时省略 extern,则默认为外部函数。
函数参数
传值调用 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数不会影响实际参数。
void swap(int x, int y)
{
int temp;
temp = x; /
保存 x 的值 /
x = y; /
把 y 赋值给 x /
y = temp; /
把 temp 赋值给 y */
return;
}
引用调用 通过指针传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。
void swap(int *x, int *y)
{
int temp;
temp = x; / 保存地址 x 的值 */
x = y; / 把 y 赋值给 x /
y = temp; / 把 temp 赋值给 y /
return;
}
函数参数传递常用的三种方式:(指针相关)

1. 值传递
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
swap(a, b);
2. 指针传递
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
y = temp;
}
swap(&a, &b);
3. 引用传递(C++支持)
void swap(int &x, int &y)
{
int temp;
temp = x;
x = y;
y = temp;
}
swap(a, b);
C 作用域规则:
局部变量 在某个函数或块的内部声明的变量称为局部变量。它们只能被该函数或该代码块内部的语句使用。局部变量在函数外部是不可知的。
全局变量 全局变量是定义在函数外部,通常是在程序的顶部。全局变量在整个程序生命周期内都是有效的,在任意的函数内部能访问全局变量。
在程序中,局部变量和全局变量的名称可以相同,但是在函数内,局部变量的值会覆盖全局变量的值。
函数的参数,形式参数,被当作该函数内的局部变量,它们会优先覆盖全局变量。
当局部变量被定义时,系统不会对其初始化,您必须自行对其初始化。定义全局变量时,系统会自动对其初始化:
int 0
char ‘\0’
float 0
double 0
pointer NULL
C 数组:它可以存储一个固定大小的相同类型元素的顺序集合
声明数组:需要指定元素的类型和元素的数量
type arrayName [ arraySize ];
初始化数组:
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
balance[4] = 50.0;
指针与数组名的区别:
指针:也是一个变量,存储的数据是地址。
数组名:代表的是该数组最开始的一个元素的地址。
对数组元素 a[i]的引用也可以写成
(a+i)这种形式。
指针是一个变量,可以进行数值运算。数组名不是变量,不可以进行数值运算。
C 传递数组给函数:
1.void myFunction(int *param)
2.void myFunction(int param[10])
3.void myFunction(int param[])

C enum(枚举)
枚举语法定义格式: enum 枚举名 {枚举元素1,枚举元素2,……};
枚举变量的定义:
1、先定义枚举类型,再定义枚举变量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
2、定义枚举类型的同时定义枚举变量
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
3、省略枚举名称,直接定义枚举变量
enum
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
在C 语言中,枚举类型是被当做 int 或者 unsigned int 类型来处理的,所以按照 C 语言规范是没有办法遍历枚举类型的。不过在一些特殊的情况下,枚举类型必须连续是可以实现有条件的遍历。
C 指针 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。
指针变量声明的一般形式为:type *var-name;
使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。
C 中的 NULL 指针:
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。
C 指向指针的指针:
指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二 个指针的地址,第二个指针指向包含实际值的位置。
一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。
int *var;
函数指针: 函数指针是指向函数的指针变量。
函数指针变量的声明:typedef int (fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型
int max(int x, int y)
int (
p)(int, int) = & max; // &可以省略 即:int (
p)(int, int) = max;
p(a, b) /等价于max(a, b)/
回调函数
函数指针作为某个函数的参数.
函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。简单讲:回调函数是由别人的函数执行时调用你实现的函数。
C 字符串
在 C 语言中,字符串实际上是使用 null 字符 ‘\0’ 终止的一维字符数组。
char greeting[6] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’}; //字符数组的大小比单词 “Hello” 的字符数多一个。
函数:
strcpy(s1, s2); 复制字符串 s2 到字符串 s1。
strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。
strlen(s1); 返回字符串 s1 的长度。
strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。
strchr(s1, ch); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
strstr(s1, s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。
strcmp: string compare
strcat: string catenate
strcpy: string copy
strlen: string length
strlwr: string lowercase
strupr: string upercase
C 结构体
定义结构
struct tag {
member-list
member-list
member-list

} variable-list ;
tag 是结构体标签。
member-list 是标准的变量定义,比如 int i; 或者 float f,或者其他有效的变量定义。
variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。
结构体变量的初始化
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book = {“C 语言”, “RUNOOB”, “编程语言”, 123456};
访问结构成员 为了访问结构的成员,我们使用成员访问运算符(.)
book.title = “C Programming”;
结构作为函数参数
void printBook( struct Books book )
指向结构的指针:
定义指向结构的指针:struct Books *struct_pointer;
struct_pointer = &Book1;
为了使用指向该结构的指针访问结构的成员,您必须使用 -> 运算符:struct_pointer->title;

	void printBook( struct Books *book )
	{
	   printf( "Book title : %s\n", book->title);
	   printf( "Book author : %s\n", book->author);
	   printf( "Book subject : %s\n", book->subject);
	   printf( "Book book_id : %d\n", book->book_id);
	}
	printBook( &Book1 );

C 共用体 共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体占用的内存应 足够存储共用体中最大的成员。
定义共用体:
union [union tag]
{
member definition;
member definition;

member definition;
} [one or more union variables];
union tag 是可选的,每个 member definition 是标准的变量定义,比如 int i; 或者 float f; 或者其他有效的变量定义。在共用体定义的末尾,最后一个分号之前,您可以指定一个或多个共用体变量,这是可选的。
访问共用体成员:
为了访问共用体的成员,我们使用成员访问运算符(.)
结构体与共用体区别: 结构体变量所占内存长度是各成员占的内存长度之和。每个成员分别占有其自己的内存单元。共用体变量所占的内存长度等于最长的成员变量的长度。
C 位域 带有预定义宽度的变量被称为位域。
位域声明:
struct
{
type [member_name] : width ;
};
type 整数类型,决定了如何解释位域的值。member_name 位域的名称。width 位域中位的数量。宽度必须小于或等于指定类型的位宽度。
C typedef 使用它来为类型取一个新的名字
typedef unsigned char BYTE; //在这个类型定义之后,标识符 BYTE 可作为类型 unsigned char 的缩写
typedef vs #define:
typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。
C 输入 & 输出 C 语言中的 I/O (输入/输出) 通常使用 printf() 和 scanf() 两个函数。
scanf() 函数用于从标准输入(键盘)读取并格式化.
printf() 函数发送格式化输出到标准输出(屏幕),printf() 函数在 “stdio.h” 头文件中声明.
printf(“Number = %d”, testInteger); //printf() 函数的引号中使用 “%d” (整型) 来匹配整型变量 testInteger 并输出到屏幕。
// %s、%d、%c、%f 字符串、整数、字符或浮点数
int getchar(void) 函数从屏幕读取下一个可用的字符,并把它返回为一个整数。这个函数在同一个时间内只会读取一个单一的字符。
int putchar(int c) 函数把字符输出到屏幕上,并返回相同的字符。这个函数在同一个时间内只会输出一个单一的字符。
char *gets(char *s) 函数从 stdin 读取一行到 s 所指向的缓冲区,直到一个终止符或 EOF。
int puts(const char *s) 函数把字符串 s 和一个尾随的换行符写入到 stdout。
int scanf(const char *format, …) 函数从标准输入流 stdin 读取输入,并根据提供的 format 来浏览输入。 在读取字符串时,只要遇到一个空格,scanf() 就会停止读取
int printf(const char *format, …) 函数把输出写入到标准输出流 stdout ,并根据提供的格式产生输出。
C 文件读写:
打开文件: 使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件
FILE *fopen( const char * filename, const char * mode );
filename 是字符串,用来命名文件,访问模式 mode 的值可以是下列值中的一个:
r 打开一个已有的文本文件,允许读取文件。
w 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该 会被截断为零长度,重新写入。
a 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。
r+ 打开一个文本文件,允许读写文件。
w+ 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。
a+ 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。
如果处理的是二进制文件,则需使用下面的访问模式来取代上面的访问模式:“rb”, “wb”, “ab”, “rb+”, “r+b”, “wb+”, “w+b”, “ab+”, “a+b”
关闭文件: int fclose( FILE *fp );
如果成功关闭文件,fclose( ) 函数返回零,如果关闭文件时发生错误,函数返回 EOF。
写入文件: int fputc( int c, FILE *fp ); 函数 fputc() 把参数 c 的字符值写入到 fp 所指向的输出流中。如果写入成功,它会返回写入的字符,如果发生错误,则会返回 EOF。
int fputs( const char *s, FILE *fp ); 函数 fputs() 把字符串 s 写入到 fp 所指向的输出流中。如果写入成功,它会返回一个非负值,如果发生错误,则会返回 EOF。
也可以使用 int fprintf(FILE *fp,const char *format, …) 函数来写把一个字符串写入到文件中。
读取文件: 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, …) 函数来从文件中读取字符串,但是在遇到第一个空格字符时,它会停止读取。
注意: 只有用 r+ 模式打开文件才能插入内容,w 或 w+ 模式都会清空掉原来文件的内容再来写,a 或 a+ 模式即总会在文件最尾添加内容,哪怕用 fseek() 移动了 文件指针位置。
C 预处理器: 是编译过程中一个单独的步骤。所有的预处理器命令都是以井号(#)开头。
#define 定义宏
#include 包含一个源代码文件
#undef 取消已定义的宏
#ifdef 如果宏已经定义,则返回真
#ifndef 如果宏没有定义,则返回真
#if 如果给定条件为真,则编译下面代码
#else #if 的替代方案
#elif 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码
#endif 结束一个 #if……#else 条件编译块
#error 当遇到标准错误时,输出错误消息
#pragma 使用标准化方法,向编译器发布特殊的命令到编译器中
预定义宏:
DATE_ 当前日期,一个以 “MMM DD YYYY” 格式表示的字符常量。
TIME 当前时间,一个以 “HH:MM:SS” 格式表示的字符常量。
FILE 这会包含当前文件名,一个字符串常量。
LINE 这会包含当前行号,一个十进制常量。
STDC 当编译器以 ANSI 标准编译时,则定义为 1。
C 头文件: 头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:程序员编写的头文件和编译器自带的头文件。
在程序中要使用头文件,需要使用 C 预处理指令 #include 来引用它。
C 强制类型转换: (type_name) expression
C 递归: 递归指的是在函数的定义中使用函数自身的方法。
void recursion()
{
statements;
… … …
recursion(); /
函数调用自身 */
… … …
}
数的阶乘:
double factorial(unsigned int i)
{
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1);
}
斐波那契数列:
int fibonaci(int i)
{
if(i == 0)
{
return 0;
}
if(i == 1)
{
return 1;
}
return fibonaci(i-1) + fibonaci(i-2);
}
C 可变参数:需要使用 (stdarg.h 头文件)
函数带有可变数量的参数,而不是预定义数量的参数。
int func(int, … ) // func() 最后一个参数写成省略号,即三个点号(…),
{
}
C 内存管理
C 排序算法:
1.冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。
2.选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元 素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
3.插入排序(英语:Insertion Sort)是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到 {\displaystyle O(1)} {\displaystyle O(1)}的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向 后挪位,为最新元素提供插入空间
4.希尔排序 希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
5.归并排序 把数据分为两段,从两段中逐个选最小的元素移入新数据段的末尾。
6.快速排序 在区间中随机挑选一个元素作基准,将小于基准的元素放在基准之前,大于基准的元素放在基准之后,再分别对小数区与大数区进行排序。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值