#include
int main()
{
printf("Hello, world!\n");
}
宏定义, 定义常量, 定义宏函数
文件引用, 引用系统文件, 引用用户文件
外部变量
函数向前引用声明
主函数 (带命令行参数)
{
函数向前引用说明
局部变量
调用函数
分配动态内存
调用宏定义函数
文件操作
输入输出
}
int
long
long long
float
double
char
void
(空类型)
以字母或下划线开头, 后面可以跟若干个字母、数字和下划线, 区分大小写
十六进制:0x
开头
八进制:0
开头
长整型: 后面加 l
超长整型: 后面加 ll
\n
\t
\'
\"
\\
\0
\ddd
1~3 位八进制数所代表的 ASCII 码字符
\xhh
1~2 位十六进制数所代表的 ASCII 码字符
GB
TB
PB
输入输出函数中, 键盘是标准输入设备 stdin
, 显示器是标准输出设备 stdout
头文件 #include
printf("格式控制", 输出列表);
返回值为本次调用输出字符的个数, 包括回车等控制符
十进制: %d
%ld
八进制: %o
%lo
十六进制: %x
%lx
小数: %f
(普通) %e
(指数) %g
(自动选择)
字符:%c
字符串: %s
变量的内存地址:%p
%:%%
在 %
和说明符之间加入整数以限制宽度, 加入小数以限制精度, 加入 -
左对齐, 加入 0
补零而不是空格, 加入 +
显示正号
变场宽输出 printf("%*.*f", m, n, f)
(类型名)(表达式)
在数据前加 (int/float 等数据类型)
scanf("格式控制", 内存地址表);
返回值为本次 scanf() 调用正确输入的数据项的个数
整型、字符、字符串与输出控制相同
float: %f
double: %lf
跳过读入:scanf("%d%*d%d%d", &x, &y, &z);
&
putchar(c);
getchar();
头文件 #include
_getch();
头文件 #include
在按下相应键的同时接收从键盘输入的 一个字符。
_getche();
由键盘输入的字符不在屏幕上显示
_ungetch(c);
将字符放回输入流
+=
-=
*=
/=
%=
7/6==1
(1/2+1/2)==0
<
<=
>
>=
==
!=
&&
||
!
1
1
书写时需要注意运算符优先级, 不确定带括号; 最好直接带括号
若已经能够判断则逻辑运算符后面的语句不执行
自增自减运算符 ++i
i++
--i
i--
sizeof()
逗号运算符: 从左到右计算表达式的值, 最右边表达式的值就是整个逗号表达式的值
#include
#include
#include
#include
#define 符号常量名 字符串
不过这样的宏定义只是做简单的字符串替换
一行写不下可以在杭为加 \
在下一行继续写
** 带参数的宏定义 **
#define 宏名 (参数表) 字符串
如 #define P(x) printf ("%d\n", x)
一般需要将参数用括号括起来
在宏定义中使用 #
#define PR(x) printf("%s=%d\n", #x, x)
#define MP(x) printf("%d",a##x)
if(值为真或假的表达式){
语句}
else if(){
...}
else {
...}
else
只与同层最近的 if
配对
注意小数确定是否相等时用差值小于一个精度而不是直接用 ==
表达式 1 ? 表达式 2 : 表达式 3
switch(int/char)
{
case 1: ...; break;
case 2: ...; break;
case 3: ...;
case 4: ...; break;
default: ...;
}
#include < 文件名 >
#include "文件名"
一般不用 #include
命令引用 .c
文件 (C++
模版文件可能要这么做)
#ifdef
...
#else
...
#endif
#if ...
...
#elif ...
...
#else
...
#endif
文件 item.h
#ifndef ITEM_H
#define ITEM_H
......
#endif // ITEM_H
#undef
将已经定义的标志服变为未定义
一般形式 #pragma token-string
, 这指导编译器如何进行编译
如 #pragma once
, 让编译器把指定的文件只包含一次, 防止此文件被多次引用出现的重复定义等错误.
如 #pragma warning(disable:4996)
将 4996 类警报置为失效,让编译器不再显示这类警告
#line 数字 num ["文件名"]
从该行之后, 编译信息的行数将从第 num
行开始计算, 而不是原先代码的行数
while(){...}
do {...} while ();
for(i=0; i<=n; i++) {...}
i=0
和 i++
可以省略
i<=n
也可以省略, 但是需要 break;
否则无法跳出循环
结束本次循环的执行,但不退出循环结构
C 语言中, 函数分以下两种: 标准库函数, 用户自己定义的函数
类型标志符 函数名 (形参列表)
{
说明部分
语句部分
}
void
类型的函数不返回函数值, 只是完成某个任务
函数中的返回语句 return 表达式;
C 程序其中必须有且只能有一个主函数 int main()
C 程序总是从主函数开始执行 (不管它在程序中的什么位置), 而其他函数只能被调用
类型标志符 函数名 (形参列表);
这里形参列表可以是 形参 1 类型, 形参 2 类型, ...
, 也可以是 形参 1 类型 形参名 1, 形参 2 类型 形参名 2, ...
.
这种对被调用函数的说明称为函数原型 / 函数向前引用说明
C 语言函数传参为值传递
可以通过定义全局变量的方法实现各函数之间的参数传递, 全局变量的有效范围是从定义变量的位置开始到 本源文件结束
全局变量的引用说明 entern 类型名 变量名;
extern
全局变量的用途
extern
加以说明.int
float
char
double
auto
(函数中局部变量默认为 auto
类型), 静态类型 static
, 寄存器类型 register
, 外部类型 extern
.用 static
说明的局部变量或外部变量在函数调用结束后其内存不会消失而保留原值, 即其占用的存储单元不释放, 在下一次调用时仍为上次调用结束时的值.
对局部静态变量赋初值是在编译时进行的
在函数定义前加 static
使函数成为只能在本文件的其他函数中调用的函数, 这种函数被称为内部函数
在函数定义前加 extern
使函数成为外部函数 (也即一般定义的函数)
定义 类型名 数组名 [常量表达式];
注意 [ ]
中必须是常量
在 C 语言中, 只能逐个引用数组元素, 不能一次引用数组中的全部元素
定义 类型名 数组名 [常量表达式 1][常量表达式 2];
字符串常量以结束符 \0
结尾
以下写法等价
char a[15]={
"how do you do?"};
char a[15]="how do you do?";
char a[ ]="how do you do?";
char a[]={
'h', 'o', 'w', '','d','o',' ','y','o','u',' ','d','o','?','\0'};
char a[]={
104,111,119,32,100,111,32,121,111,117,32,100,111,63, 0};
#include
puts(s)
输出字符串
gets(s)
读入字符串
strcat(s1, s2)
将 s2 连接到 s1 后面, 并返回 s1 地址
strcpy(s1, s2)
将 s2 复制到 s1 中
strncpy(s1, s2)
将 s2 的前 n 个字符复制到 s1 中
strcmp(s1, s2)
前大返回大于 0 的数
strlen(s)
求字符串长度 (不包括 \0
)
strstr(s1, s2)
确认 s2 是否在 s1 中出现过, 是则返回第一次出现的位置, 否则返回 NULL
strlwr(s)
strupr(s)
sprintf(字符数组名, "输出格式", 变量列表)
sscanf(字符数组名, "输入格式", 变量列表)
int function(int a[], int n){...}
一般需要另外一个参数传递数组长度
二维传递可以强制转为一维数组
二维数组下标 i*n+j
int *p = &x;
定义了整型指针 p
, 指向整型变量 x
的内存地址
*p = 3;
现在 *p
指的是指针 p
所指的值, 此语句使得变量 x
的值被更改为 3
char *p, *q;// 定义了两个字符指针 p 和 q, 其分别可以指向一个字符
int *a[10];// 定义了含有十个整型指针的指针数组, 数组中的每一个元素是一个指针, 可以指向一个整数
float **r;// 定义了指向浮点型指针的指针
double (*s)[100];// 定义了一个指针 s, 这个指针指向一个 double 数组, 这个 double 数组有 100 个元素
int *f();// 返回值为整型指针的函数
void (*g)();// 定义了一个函数指针 g, 它可以用来指向一个 void 类的函数
double (*h[10])();// 定义了 void 类型的函数指针数组 h[10], 如 h[1] 可以用来指向一个返回值为 double 的函数
*r++
和 (*r)++
:
*r++
: 指针加, 指向下一个单元
(*r)++
: 指针所指的内容加
指针作为函数参数可以实现地址传递
malloc
函数的原型 void *malloc(申请内存的字节数)
使用, 如
p=(char *)malloc(sizeof(char)*20);
q=(double **)malloc(sizeof(double *)*10);
a=(int (*)[4])malloc(sizeof(int)*4*5);
一般用 malloc()
申请内存需要判断是否申请成功
if (p == NULL)
{
printf("Can’t get memory!\n");
exit(1); /* 强制终止当前程序的执行 */ }
使用 malloc()
可以先读入数组长度然后定义一个数组
函数原型 void free(void *ptr);
用 malloc()
申请的动态内存块, 需要用 free()
按照与申请顺序时向量的顺序释放回内存堆, 防止内存泄漏
char s[] = "...";
char *s = "...";
char *s = "..."; printf("%c", s[4]); printf("%c", *(s+4))
; 如 "..."+4
"..."[4]
char *str[]={"abc", "de", "fghij", "k"};
也可以用字符型二维数组来存放字符串数组, 例如: char str[][6]={"abc", "de", "fghij", "k"};
sizeof
操作符求字符串所占内存的大小指向函数的指针指向函数的入口地址
函数指针的定义:类型标识符 (* 指针变量名)(参数类型);
给函数指针变量赋值时, 只需给出函数名
调用方式:(* 函数指针变量名)(实参表)
函数指针变量名 (实参表)
类型标识符 * 函数名 (形参表){...}
int main(int argc, char *argv[])
{
...}
其中: argc
的值是命令行参数个数 +1
, argv
是字符型指针数组, 指向每一个参数字符串
字符串转 int 和 float
#include
atoi()
atof()
定义: struct 结构体类型名 {成员表};
注: 分号别掉了
用大括号和逗号进行赋值
用 .
取结构体中变量的值
在定义结构体类型变量时, 需要使用结构体类型的全称. 如 struct date birthday;
也可以同时定义结构体类型和变量:
struct date
{
int year;
int month;
int day;
}birthday1, birthday2;
也可以定义无名结构体
结构体可以嵌套
结构体变量可以作为函数参数
结构体变量也可以定义数组
当结构体类型的指针变量 p
指向一个同类型的结构体类型变量 a
后, 下列四种表示是等价的:
a. 成员
(*p). 成员
p-> 成员
p[0]. 成员
在程序开头加上 #pragma pack(4)
则其中结构体采用 4 字节对齐
也可以通过调整结构体内部变量顺序的方式来节省空间
一般形式
union 联合体名
{
成员表};
联合体 union
和 struct
的定义和使用是相同的. 但 union
中的各个数据之间共享同一个单元的, 所占内存单元的大小是几个数据项中长度最大的一个
enum 枚举类型名 {枚举元素列表};
如 enum WEEK {SUN, MON, TUE, WED, THU, FRI, SAT};
, 第一个值从 0 开始自动赋值. 也可以在常量名后面加等号自己赋值
typedef 原类型名 新类型名;
typedef
也可以用来声明数组类型, 如 typedef int NUM[100];
用一般的编辑器能编辑、人能直接读懂的文件是文本文件, 是由 ASCII 字节流组成的 (也可能是其他编码)
如 .txt
.c
.h
. 除了这些文件基本上都是二进制文件
FILE * 指针变量名;
fp = fopen("文件", "文件打开方式");
** 打开方式 **
r 只读
为读打开一个文件. 若指定的文件不存在, 则返回空指针值 NULL.
w 只写
为写打开一个新文件. 若指定的文件已存在, 则其中原有内容被删去; 否则创建一个新文件.
a 追加写
向文件尾增加数据. 若指定的文件不存在, 则创建一个新文件.
r+ 读写
为读写打开一个文件若指定的文件不存在, 则返回空指针值 NULL.
w+ 读写
为读写打开一个新文件. 若指定的文件已存在, 则其中原有内容被删去; 否则创建一个新文件.
a+ 读与追加写
为读写向文件尾增加数据打开一个文件, 若指定的文件不存在, 则创建一个新文件.
在后面附加 b
表示打开二进制文件
** 打开文件时的判断 **
FILE *fp;
if ((fp=fopen("文件", "文件打开方式")) == NULL){
printf("Cannot open this file !\n");
exit(0); /* 终止调用过程 */ }
fclose(fp);
fgetc(fp);
读字符
fputc(c, fp);
写字符
fgets(char *s, int n, FILE *fp);
从 fp
中读 n
个字符作为一个字符串放到 s
中
fputs(const char *s, FILE *fp);
写字符串
feof(fp)
遇到文件尾返回非 0, 否则返回 0
fread(buffer, size, count, fp);
从 fp
中读 count
个字节数为 size
的数据放到 buffer
中
fwrite(buffer, size, count, fp);
从 buffer
中写 count
个字节数为 size
的文件到 fp
中
fscanf(文件指针, 格式控制, 地址表);
fprintf(文件指针, 格式控制, 输出表);
可以替换文件指针的量: 标准输入的设备名 stdin
, 标准输出的设备名 stdout
rewind(fp);
(倒带) 将读写指针移动到文件开头
fseek(FILE *fp, long offset, int origin);
offset
为 ** 偏移量 **
origin
为 ** 起始位置 **:
SEEK_SET
或 0
SEEK_CUR
或 1
SEEK_END
或 2
long ftell(FILE *fp);
返回文件当前读写指针的位置
fflush(fp);
清空文件的输入输出缓冲区
clearerr(fp);
清除由于读写等操作失败引起文件输入输出缓冲区处于的错误状态
clearerr(stdin/fp);
应该和 fflush(stdin/fp);
配对使用
&
按位与
|
按位或
^
按位异或
~
按位取反
<<
左移
>>
右移
!(逻辑非)
--> 按位取反 ~
-->算术运算符
--> 左移运算符 <<
右移运算符 >>
--> 关系运算符
--> 按位与 &
按位异或 ^
按位或 |
–> 逻辑与 &&
-->逻辑或 ||
--> 赋值运算符
struct 位段结构类型名 {成员表};
struct packed_d
{
unsigned short f1:2;
unsigned short f2:1;
//unsigned char :2;
};
定义了一个位段结构类型,名为packed_d
,共包含2个成员(又称为位段),每个成员均为无符号short
类型,其中成员f1占2个二进制位,f2占1个二进制位
注意:
unsigned型
;sizeof()
求段位成员的大小