1. Hello world 例子
#include <stdio.h>
int main()
{
printf("hello world");
return 0;
}
2. 数据类型
char a ='A'; //1个字节
32位机器里 short 2个字节 int 4个字节 long 4个字节 float 4个字节 double 8个字节
另有无符号类型unsigned short, unsigned int; unsigned long
void 空类型
没有bool型
强制转换类型 比如
unsigned short i = 10;
int j = (int) i;
格式化输出
char name[]="kv110";
int id = 100;
float f = 76.5
printf("打印学号 %d 姓名 %s 成绩 %f", id, name, f);
3. 运算符号优先级
算术运算符 + - * / % ++ --
赋值运算符 = += -= *= /= %=
关系运算符 > >= < <= == !=
逻辑运算符 && || ~
三目运算符 表达式? 值1 : 值2
级别1: [], (), .(对象成员) ->(指针)
级别2:-(负号), 强制类型转换,++,--; * (取值), & (取址) ! (逻辑非) ~(按位取反), sizeof
级别3: / 除 * 乘 % 取余
级别4: + 加 - 减
级别5:<<左移 >>右移
级别6: >大于 >= <小于 <=
级别7: == 等于 !=不等于
级别8:&按位与
级别9:^ 按位异或
级别10:| 按位或
级别11:&&逻辑与
级别12: || 逻辑或
级别13: ?:条件运算符
级别14:= 等于 /= *= %= += -= <<= >>= &= ^= |=
级别15: , 逗号
4. 条件语句
条件语句
if (condition) {
} else if {
} else {
}
switch(条件) {
case 值 1: 语句1; break;
case 值 2: 语句2; break;
...
default: 语句n; break;
}
5. 循环语句
for (初始值;终止循环条件; 步进值) {
}
while (条件) {
}
do {
} while (条件)
break语句只跳出当前循环
continue结束本次循环开始执行下一次循环、
goto 跳转到某标号处
6. 数组
数据类型 数组名称[长度];
int temp[5] ={0,1,2,3,4};
数组的下标均以0开始,不要越界
数组的长度 int len = sizeof(temp)/sizeof(temp[0]);
二维数组 行数必须指定
多维数组
7. 字符串
char 字符串名称[长度] = “字符串值”;
char temp[]="abc";
char temp[]={'a','b','c','\0'};
unsigned
int
strlen
(
char
*s);
获取字符串的长度,在字符串长度中是不包括‘\0’
char *strcpy(char* dest, const char *src);
把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间里
char *strncpy(char *destinin, char *source, int maxlen);
复制字符串source中的内容(字符,数字、汉字....)到字符串destinin中,复制多少由maxlen的值决定
char *strcat(char *dest, const char *src);
把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除*dest原来末尾的“\0”)。要保证*dest足够长,以容纳被复制进来的*src。*src中原有的字符不变。返回指向dest的指针。
int
strcmp
(
const
char
*s1,
const
char
*s2);
两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止
int strncmp(const char *str1, const char *str2, size_t n)
用来比较s1和s2字符串的前n个字符。如果两个字符串相等的话,strncmp将返回0。如果s1是s2的一个子串的话,s1小于s2。
char
*
strstr
(
char
*str1,
const
char
*str2);
若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL
8. 函数
类型 函数名(参数类型 参数...)
{
变量声明;
......
return ****;
}
注意形参和实参类型的一致性
定义在函数内部的变量叫作局部变量,局部变量只能在该函数内才能使用;
定义在函数外部的变量叫作全局变量,全局变量可以被整个 C 程序中所有的函数所共用。它的作用范围是从定义的位置开始一直到整个 C 程序结束
自动变量(auto) 局部变量其实都是 auto 型,默认是 auto 型,存储在栈区,函数运行完就结束了
静态变量(static)static 可以用于修饰局部变量,也可以用于修饰全局变量。存储在静态存储区,一直存在于程序的整个运行过程中。用 static 修饰全局变量时,会限定全局变量的作用范围,使它的作用域仅限于本文件中。
寄存器变量(register),CPU 内部也有一些用来存储数据的区域,这就是寄存器,它的存取速度要比内存快很多
外部变量(extern) extern 变量是针对全局变量而言的。它的作用域是从变量的定义处开始
static修饰函数时表示该函数仅可以在当前c文件里调用
extern修饰函数时表示该函数可以在其他c文件里调用
inline 内联函数
内联函数是为了解决C 预处理器宏存在的问题所提出一种解决方案,用来提高函数使用效率
为了解决一些频繁调用的小涵数大量消耗栈空间或者是叫栈内存的问题,特别的引入了inline修饰符,表示为内联涵数
选择inline类型的函数是有条件的
·函数足够简单,并且非常频繁被调用,只有一条程序就可以完成任务
·不能包含复杂的结构控制语句例如while switch
普通函数: 编译器在它的符号表中放入函数类型(包含名字和参数类型的函数原型及函数的返回类型)
内联函数: 函数的代码也被放入符号表,代码是以源程序形式还是以编译过的汇编指令形式存放取决于编译器。
如果不用内联函数,而用普通函数,如果该函数被频繁调用,就会导致栈空间不足所造成的程序出错的问题
宏定义define是会产生副作用的,尤其是不同类型参数所导致的错误,inline有更强的约束性和能够让编译器检查出更多错误的特性。
9. 指针
类型标识符 *变量名;
例: int *p;
表示p指向int类型变量或保存int类型变量的地址; p是地址,地址里存放的是整数值
*p表示p所指向的变量的值
int a =1;
int *p = &a;
printf("a=%d",a); a=1
print("*p=%d",*p); *p=1
&a表示变量a的地址
int arr[10]; int *p=arr;
p和arr都是指向数组arr的首地址
p+i和arr+i都是指向arr[i]的地址
p+i与&array[i]是等价的,而*(p+i)与array[i]是等价的
引用数组元素:
下标法:array[i]
指针法:*(p+i)或*(arr+i)
注意不能用arr++或++arr或arr=arr+1,这几个用法都不对,但可以用p++, ++p
*p++先用p再加1, 即先用p,得到p地址里的值,然后p=p+1(地址加4), *p++等于*(p++),但不等于(*p)++
例:int arr[3]={1,2,3}; int *p=arr;
printf("%p", p); 12345678
printf("%d", *p++); 1
printf("%p",p); 1234567B
printf("%d", *p); 2
10. 文件操作
区分文本文件和二进制文件
Windows的文件路径,比如c:\users\***\Documents\a.txt, 在调用时改成c:\\users\\***\\Documents\\a.txt
在 UNIX 和 Linux 系统中,无论是二进制文件还是文本文件,均是以单字节 LF(0x0A) 即作为文件中的换行符
在 Windows 系统中,文本文件使用 ASCII 值为 13(0x0D) 的回车符 CR(Carriage-Return) 以及 ASCII 值为 10(0x0A) 的换行符 LF(Line-Feed) 这两个符号,即双字节 CR-LF(0x0D 0x0A) 的 'r'、'\n' 作为文本文件的换行符。
FILE *fopen(const char *filename, const char *mode);
r 以只读方式打开文件,该文件必须存在。
r+ 以读/写方式打开文件,该文件必须存在。
rb+ 以读/写方式打开一个二进制文件,只允许读/写数据。
w 打开只写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。
w+ 打开可读/写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。
a 以附加的方式打开只写文件。若文件不存在,则会创建该文件;如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF 符保留)。
a+ 以附加方式打开可读/写的文件。若文件不存在,则会创建该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF符不保留)。
wb 以只写方式打开或新建一个二进制文件,只允许写数据。
wb+ 以读/写方式打开或新建一个二进制文件,允许读和写。
ab+ 以读/写方式打开一个二进制文件,允许读或在文件末追加数据
int fclose(FILE *stream);
size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
int fgetc(FILE *fp); 从文件中读取一个字符
int fputc(int ch,FILE *fp) 写一个字符到文件中去
char *fgets(char *str,int n,FILE *fp) 从文件中读取一个字符串
int fputs(char *str,FILE *fp) 写一个字符串到文件中去
int fprintf(FILE *fp,char *format,arg_list) 往文件中写格式化数据
int getw(FILE *fp) 以二进制形式读取一个整数
int putw(int n,FILE *fp) 以二进制形式存贮一个整数
int feof(FILE *fp) 1:真值,表示文件结束。
int ferror(FILE *fp) 1:真值,表示出错。
void clearerr(FILE *fp) 清除文件错误标志
long ftell(FILE *fp) 文件指针的当前位置,相对于文件开头的位移量来表示
void rewind(FILE *fp) 指定的文件的位置指针重新指向文件的开头位置
int fseek(FILE *fp,long offset,int base)
base 文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))
例:
#include <stdio.h>
struct stud
{ int id;
char name[20];
int score;
};
int main()
{
int n;
struct stud student;
FILE *in,*out;
if((in=fopen("f1.txt","rb"))==NULL)
{
printf("The file f1.txt open error.\n");
return 0;
}
if((out=fopen("f2.txt","wb"))==NULL)
{
printf("The file f2.txt open error\n");
return 0;
}
while(fread(&student,sizeof(struct stud),1,in)==1)
fwrite(&student,sizeof(struct stud),1,out);
fclose(in);
fclose(out);
return 1;
}
11. Linux 文件操作
以上文件操作函数是标准C库函数
Unix/Linux还有一套文件操作函数
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int
open(const char* pathname,int flags);
int
open(const char* pathname,int flags,mode_t mode);
第三个参数仅当创建新文件时(即 使用了O_CREAT 时)才使用,用于指定文件的访问权限位
flags 访问模式,宏定义和含义如下:
O_RDONLY 1 只读打开
O_WRONLY 2 只写打开
O_RDWR 4 读写打开
还可选择以下模式与以上3种基本模式相与:
O_CREAT 0x0100 创建一个文件并打开
O_TRUNC 0x0200 打开一个已存在的文件并将文件长度设置为0,其他属性保持
O_EXCL 0x0400 未使用
O_APPEND 0x0800 追加打开文件
O_TEXT 0x4000 打开文本文件
O_BINARY 0x8000 打开二进制字符
mode 该参数仅在access=O_CREAT方式下使用,其取值如下:
S_IFMT 0xF000 文件类型掩码
S_IFDIR 0x4000 目录
S_IFIFO 0x1000 FIFO 专用
S_IFCHR 0x2000 字符专用
S_IFBLK 0x3000 块专用
S_IFREG 0x8000 只为0x0000
S_IREAD 0x0100 可读
S_IWRITE 0x0080 可写
S_IEXEC 0x0040 可执行
#include <unistd.h>
int close(int fd)
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count)
#include <unistd.h>
ssize_t write(int fd, void *buf, size_t count)
#include <unistd.h>
#include <sys/types.h>
off_t lseek(int fd, off_t offset,int whence)
whence:
SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小
SEEK_CUR:当前位置为指针的位置,新位置为当前位置加上偏移量
SEEK_END:当前位置为文件的结尾,新位置为文件大小加上偏移量的大小
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *file_name, struct stat *buf);
struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //伟建内容对应的块数量
};