我使用C语言并不频繁,一般都是用来实现数据结构与算法,因为面向过程的编程方式容易理解算法的原理,但是呢,如果很长时间没写算法,那么就意味着C语言的某些语法就生疏了,但是总有那么一些,在写算法的时候,特别常用的,所以,我就专门写下来,不用再没头没脑的复习C语言了。
在提醒一下,这里只说C语言,不涉及C++。
声明普通变量
#include<stdio.h> int main() { int iVar = 10; float fVar = 10.01; double dVar = 10.001; //bool flag = true;//C语言中没有bool类型 char cVar = 'a'; //字符类型使用单引号括起来 printf("%d ", iVar); printf("%f %f ", fVar, dVar); printf("%c ", cVar); printf("%s ", NAME); return 0; }
声明指针
int *ptr = NULL; //这里请使用大写的NULL,小写的null不对 int a = 10; ptr = &a; printf("%p %d ", ptr, *ptr);
声明数组
//定义整型数组(浮点型是一样的) int arrInt[10] = {1,2,3,4,5,6,7,8,9,10}; //也可不指定数组长度,长度会根据实际的元素个数来设置 int arrInt2[] = {9,8,7,6,5,4,3,2,1}; printf("%d ", sizeof(arrInt) / 4); //10 printf("%d ", sizeof(arrInt2) / 4); //9 int i = 0; //遍历数组——case1 for (i = 0; i < 10; i++) { printf("%d ", arrInt[i]); } //数组名还有另外一层含义:数组首地址(可以加*解引用来访问值) int *ptr = arrInt; printf("%d ", *ptr); //输出了arrInt[0] --> 1 //遍历数组——case2 for (i = 0; i < 10; i++) { printf("%d ", *(ptr++)); printf("%d ", *(arrInt + i)); //printf("%d ", *(arrInt++)); 不要尝试这么做 }
字符与字符串
//务必保证数组长度比字符数量多1,因为结束有一个 char arrCh1[6] = {'h', 'e', 'l', 'l', 'o', ' '}; char arrCh2[] = {'h', 'e', 'l', 'l', 'o', ' '}; char arrCh3[] = "hello"; //自动添加 ,推荐使用这种方法,可以不用指定长度。 char *arrCh4 = "hello world"; //声明一个字符型指针,指向字符串的首地址,推荐使用。 //注意strlen只会返回字符数组中,实际的字符数量(并不是声明的长度) //所以arrCh1的长度是5,并不会将 算在长度中 printf("%d ", strlen(arrCh1)); //5 printf("%d ", strlen(arrCh2)); //5 printf("%d ", strlen(arrCh3)); //5 printf("%d ", strlen(arrCh4)); //11 //遍历字符数组(字符串) int i = 0; while (arrCh1[i] != ' ') { printf("%c ", arrCh1[i++]); } //直接输出字符串。因为数组名是字符串的首地址,那么就可以直接输出了 //注意不用加* printf("%s ", arrCh1); printf("%s ", arrCh2); printf("%s ", arrCh3); printf("%s ", arrCh4);
声明并创建结构体
#include<stdio.h> #include<stdlib.h> struct Person { //int age = 10; 不能设置默认值 int age; char *name; }; //末尾加分号 int main() { //创建结构体变量的时候,前面不止要加结构体名,还要加struct关键字 struct Person p; p.age = 10; p.name = "abcdefg"; printf("%d %s ", p.age, p.name); //结构体指针 struct Person *ptr; ptr = (struct Person*)malloc(sizeof(struct Person)); ptr->age = 20; ptr->name = "xyzdddddd"; printf("%d %s ", ptr->age, ptr->name); free(ptr); return 0; }
共用体
#include<stdio.h> #include<string.h> //这个union只占用10个字节空间 union Info { int age; char name[10]; char addr[10]; }; int main() { //声明共用体实例同样要使用union关键字加上共用体名称 union Info t; t.age = 10; printf("%d ", t.age); //给字符数组赋值可以使用strcpy(dest, source) strcpy(t.name, "hello"); printf("%s ", t.name); //此时age的数据已经被清除了。因为他们共用一段空间 printf("%d ", t.age); return 0; }
typedef和define
#include<stdio.h> //define用来定义常量,语句末尾不加分号 #define ONE "1111111" //define是预编译器处理 //typdef用来声明别名,语句末尾要加分号 typedef int* ptr; //typedef是编译器处理 int main() { int a = 10; ptr b = &a; //使用新定义的类型 printf("%s ", ONE); //输出常量 printf("%d ", *b); return 0; }
隐式类型转换
注意在类型转换的时候,精度丢失的问题。
#include<stdio.h> int main() { double dd = 10.0001; int ii = dd; //隐式转换。 printf("%d ", ii); //10 printf("%f ", dd); //10.0001 //printf("%d ", dd); //错误用法。注意不会发生类型转换 int i = 10; double d = i / 3.0; //隐式转换 printf("%f ", d); //3.333333 return 0; }
强制类型转换
注意在类型转换的时候,精度丢失的问题。
#include<stdio.h> #include<stdlib.h> struct Person { int age; char *name; }; int main() { double dd = 100.0001; int a = dd; //隐式转换 double b = (double)a; //强制类型转换 printf("%d ", a); printf("%f ", b); //强制类型转换 struct Person *p = (struct Person*)malloc(sizeof(struct Person)); return 0; }
函数
函数可以定义为无返回值(void),或者有返回值(int、char.....)
无返回值的函数
#include<stdio.h> //打印数组 void PrintArr(int *a, int length){ int i; for (i = 0; i < length; i++){ printf("%d ",a[i]); } } int main() { int a[] = {9,8,7,6,5,4,3,2,1}; int length = sizeof(a) / 4; PrintArr(a, length); return 0; }
有返回值的函数
#include<stdio.h> int is_odd(int a){ return a&1; } int main() { printf("%d ", is_odd(2)); //0 printf("%d ", is_odd(3)); //1 return 0; }