C语言整理(待更新)
C语言整理(待更新)
Note:根据 CSDN C语言技能树 整理的题目;初衷是因为C语言相对于Java,Python更加简洁,没有那么多花里胡哨的语言特性,用来练习算法题再合适不过了。
文章目录
- C语言整理(待更新)
- 一、C语言的发展
- 二、数据类型
- 三、运算符与表达式
- 四、语句与控制流
- 五、函数与程序结构
- 六、数组(派生数据类型)
- 七、指针(派生数据类型,用地址初始化,用*解析地址中的值)
- 八、字符串
- 九、结构体(用户自定义数据类型)
- 十、联合体与枚举类型(用户自定义类型)
- 十一、位运算
- 十二、预处理器
- 十三、文件
- 十四、存储管理
- 十五、标准函数库
一、C语言的发展
- C语言特点
- C语言标准,可参考C语言标准, ANSI C, ISO C, GNU C
- C语言编译过程(预处理,编译(汇编码),汇编(机器码),链接),可参考C语言的编译过程详解
二、数据类型
- 变量类型, 生命周期 和 作用域
- 常量2种类型(数值和字符) 和 定义(#define和const)
Note:常量也可以是函数表达式,比如#define MAX(a,b) ((a > b) ? a : b)
,参考关系运算符(判断区间是否重叠) - 数据类型分类(原生,派生,用户自定义)
- 结构体内存对齐1,结构体内存对齐2,可参考c语言数据类型字节大小 和 精度,结构体内存对齐(如何计算结构体的大小),内存管理:固定分区与可变分区,操作系统: 动态(可变)分区分配,内存分配 & C++类对象内存对齐 -------保姆级解释
Note:
- C语言没有bool,string类型;基本类型包括字符型,浮点型,整型 和 空类型;派生类型包括数组,指针和函数类型;用户自定义类型包括枚举,结构体和联合体类型。
- 不同位数的操作系统,基本类型所占内存大小也是不同的。比如64位(机器字为8字节)系统
int
类型可能为4 或 8,16位系统int
类型为2字节。 - C++的基本类型则在C语言基本类型基础上,增加了bool类型。
- C语言规定,结构体中各成员列表占用连续内存空间,但结构体的大小并不是简单地将每个结构体成员的大小相加就能得到,需要进行内存对齐,不同编译器默认对齐数不同(VS为8),而对齐倍数由编译器默认对齐数(8) 和 变量类型的字节数(
int
4,char
1)中的最小值(4,1)决定,而对齐数由结构体(int
4,char
1)中最大字节数(4)决定,比如下面结构体中对齐数为4。struct S1 {char a; //1 bytechar b; //1 byteint c; //4 byte };
即使是64位系统的
long long
,也只有最多的8 byte
,占一个字长。
数据对齐意味着将数据放在小于或等于字长的倍数的内存偏移处,这由于CPU处理内存的方式而提高了系统的性能。大多数CPU只能访问内存对齐的地址。
操作系统在数据读取的时候,并不是一个字节一个字节进行读取的,而是一段一段进行读取,如果没有对齐约束,代码可能最终不得不跨越机器字边界进行两次或多次访问(有些硬件架构直接报错)。因此考虑平台和性能原因,数据结构(尤其是栈),结构体应该尽可能的在自然边界上对齐,这样访问一个变量只需访问1次内存即可,结构体的内存对齐是拿空间来换取时间的做法。struct S1 {char a; //1 bytechar b; //1 byteint c; //4 byte };//结构体1 struct S2 {char a; //1 byteint c; //4 bytechar b; //1 byte };//结构体2
结构体1和结构体2的成员变量一模一样,可是当我们按照内存对齐规则来计算两个结构体的大小的时候,会发现两个结构体的大小不一样,在VS编译器下(通过对上面结构体的计算,对齐数为4)第一个结构体大小为8(变量起始地址依次为0,1,4,4 + 4 = 8),第二个结构体大小为12(不是9,也不是16,变量起始地址依次为0,4,8,8 + 4 = 12)。解释见结构体中的对齐数到底是什么
内存对齐更多知识可参考详聊内存对齐(Memory alignment),结构体内存对齐(如何计算结构体的大小),失传的C结构体打包技艺 - 内存连续分配方式包括:单一连续分配,固定分区分配(预先划分分区大小,大小可以不等),动态分区分配(首次适应,最佳适应,最坏适应,邻近适应)。为结构体分配内存空间时采用动态分配 + 内存对齐。
三、运算符与表达式
- 赋值运算符(注意多个变量同时赋值的问题)
- 算数运算符(++i < 100 和 i++ < 100 的区别)
- 关系运算符
- 逻辑运算符(判断是否为闰年,||和&&的使用)
- 逗号运算符,运算符优先级与求值顺序(逗号运算符),可参考C语言逗号表达式在for循环语句中的使用
Note:逗号运算符常用在for循环头部初始化或递增多个变量- 注意变量的处理顺序
- 从左往右开始算
- 整个逗号表达式的值为其中最后一个子表达式的值。
- sizeof运算符(输出 操作数所占空间 的 字节大小),可参考c语言数据类型字节大小 和 精度
Note:sizeof在使用的时候看上去像是一个函数(因为其后面有一对小括号),但他却是一个运算符。他的使用方法有以下3种:- a)
sizeof(变量名)
。 - b)
sizeof(数据类型名)
。 - c)
sizeof 变量名
。
- a)
- 结构体内存对齐1,结构体内存对齐2,可参考c语言数据类型字节大小 和 精度,结构体内存对齐(如何计算结构体的大小),内存管理:固定分区与可变分区,操作系统: 动态(可变)分区分配,内存分配 & C++类对象内存对齐 -------保姆级解释
四、语句与控制流
- 三个数从小到大排序输出(swap原地交换)
- 判断三角形的类型(注意判断条件的先后次序)
- switch-case分数评级
- 九九乘法表打印(9行9列)
- 最大公约数(m)和最小公倍数(q)(ab = mq),可参考辗转相除法求最大公约数
五、函数与程序结构
- 函数的声明和定义(C语言 关注方法的定义相对于调用语句的位置)
Note:其实 python 也一样关注方法的定义相对于调用语句的位置,只不过没有函数声明,只有函数定义。 - 形参与实参(注意swap时实参是引用类型,即传入地址,而形参是指针类型)
- 打印函数调用顺序(C语言(编译)必须通过main函数入口才可以执行程序,python(解释)则不需要)
- 上楼梯问题(C语言模块化设计),可参考C语言模块化编程
- 内部函数(static)和外部函数(extern),可参考C语言中 static 和 extern 的用法详解,C语言关键字static与extern的详细解释
Note:- 头文件(
.h
)需通过#define
和#endif
定义变量和函数 - 源文件可以分成多个
.c
文件,每个.c
文件可以对应一个.h
文件,该.h
文件包含.c
文件的变量或函数声明。 - 全局变量默认是带
extern
,即在整个源程序中 所有 源文件 里都可以访问和修改 static
如果修饰全局变量,则会 对其他源文件隐藏该全局变量
- 头文件(
六、数组(派生数据类型)
- 数组初始化
- 冒泡排序
- 二维数组传参(使用指针,见题解)
Note:
- 数组名,即数组地址,数组元素首地址。 参考C语言:用指针访问数组元素
- 二维数组的存储方式其实在内存中是用一个连续的存储空间存起来的,而二维数组的表示是通过行地址和列地址构成的,第
i
行的地址和第i
行第0列地址的是相同的;参考二维数组的行地址、列地址,与元素的存储int arr[2][5] = {1,2,3,4,5,6,7,8,9,10}; cout << "arr首行地址:" << arr << " ,arr首行首列地址" << &arr[0][0] << endl; cout << "arr第二行地址:" << arr[1] << " ,arr第二行首列地址" << &arr[1][0] << endl; --- arr首行地址:0x40d67ff8f0 ,arr首行首列地址0x40d67ff8f0 arr第二行地址:0x40d67ff904 ,arr第二行首列地址0x40d67ff904
七、指针(派生数据类型,用地址初始化,用*解析地址中的值)
使用指针变量交换变量值(区分指针(地址)交换 还是 指针指向的内容的交换,见题解),可参考深入理解C语言指针,C语言指针详解(区分指针数组和数组指针)
指针与数组(指针变量通过自增,访问数组的连续地址空间;而数组地址是个常量,不能自增)
利用指针变量遍历二维数组元素,参考二维数组的行地址、列地址,与元素的存储
指针数组的使用(一定要弄清楚二维数组的存储结构,见题解),可参考数组指针和指针数组
函数指针的定义,可参考C语言指针详解(区分函数指针和指针函数)
字符串输入与输出
Note:
对于指针变量,我们可以把它类比看做是计算机指令,我们从指针变量中取出已存放变量(操作数,操作数组等)的地址(操作数寻址),接着使用
*
对地址进行解析(取操作数);如果是操作数组,则可以通过++
操作实现连续地址空间的访问(获取下一个操作数的地址),但是这样容易出现访问越界问题。假设
a
是一个整型变量,p
为指针变量,指向a
的地址,q
为指针变量,指向p
指针的地址://写法1 int a = 10; //整型变量 int *p = &a; //指针变量,指向整型变量地址 int **q = &p; //二级指针变量,指向指针变量地址 cout << "a值为:" << a << ", a的地址为:" << &a << endl; cout << "p值为:" << p << ", *p为:" << *p << ", *p的地址为:" << &p << endl; cout << "q值为:" << q << ", *q为:" << *q << ", **q为:" << **q << ", q的地址为:" << &q << endl; --- a值为:10, a的地址为:0x4dff1ffbec p值为:0x4dff1ffbec, *p为:10, *p的地址为:0x4dff1ffbe0 q值为:0x4dff1ffbe0, *q为:0x4dff1ffbec, **q为:10, q的地址为:0x4dff1ffbd8
//写法2 int a = 10; //整型变量 int *p; //指针变量 p = &a; int **q; //二级指针变量 q = &p; cout << "a值为:" << a << ", a的地址为:" << &a << endl; cout << "p值为:" << p << ", *p为:" << *p << ", *p的地址为:" << &p << endl; cout << "q值为:" << q << ", *q为:" << *q << ", **q为:" << **q << ", q的地址为:" << &q << endl; --- a值为:10, a的地址为:0x1c577ff97c p值为:0x1c577ff97c, *p为:10, *p的地址为:0x1c577ff970 q值为:0x1c577ff970, *q为:0x1c577ff97c, **q为:10, q的地址为:0x1c577ff968
假设
b
是二维数组,p
为指针变量,指向b
的首地址:int row = 2, col = 5; int arr[row][col] = {{1,2,3,4,5},{6,7,8,9,10}};int *p; p = &arr[0][0]; int num = row * col; int i; for(p = &arr[0][0], i = 1; i <= num; p++, i++){cout << *p << ",";if(i % col == 0){cout << endl;} } --- 1,2,3,4,5, 6,7,8,9,10,
数组指针是一个指针变量,占有内存中一个指针的存储空间;
int arr[5]={1,2,3,4,5}; int (*p1)[5] = &arr; /*下面是错误的*/ int (*p2)[5] = arr;
指针数组是多个指针变量,以数组的形式存储在内存中,占有多个指针的存储空间。
char *fruits[LEN] = {"apple","cherry","grape","peach","watermelon"};
假设
arr1
为数组1,arr2
为数组2,arr
为指向arr1
,arr2
的指针数组(arr1
和arr2
长度可以不等)://指针数组(有点像邻接表) int arr1[5] = {1,2,3,4,5}; int arr2[3] = {1,2,3}; int *arr[2] = {arr1, arr2}; int *p = arr[0]; //数组首行指针元素指向的字符串首地址 cout << "arr1数组地址为:" << arr1 << ", arr1数组首元素地址为:" << &arr1 << ", arr1数组首元素值为:" << arr1[0] << endl; cout << "arr[0]值为:" << arr[0] << ", arr数组首地址为:" << arr << ", arr数组首指针元素地址为:" << &arr[0] << ", arr[0]解析的值为" << *arr[0] << endl; cout << "p值为:" << p << ", *p为:" << *p << ", p的地址为:" << &p << endl;int i = 0; for(p = arr[0]; i < 2; i++, p = arr[i]){cout << "第" << i + 1 << "行: " << endl;do{cout << "p的地址为:" << p << ", p值为:" << *p << endl;if(*(p + 1) == 0){break;} //没办法,还是无法解决指针访问地址下标越界}while(p++); } --- arr1数组地址为:0x52cbfff8a0, arr1数组首元素地址为:0x52cbfff8a0, arr1数组首元素值为:1 arr[0]值为:0x52cbfff8a0, arr数组首地址为:0x52cbfff880, arr数组首指针元素地址为:0x52cbfff880, arr[0]解析的值为1 p值为:0x52cbfff8a0, *p为:1, p的地址为:0x52cbfff878 第1行: p的地址为:0xd32d9ffde0, p值为:1 p的地址为:0xd32d9ffde4, p值为:2 p的地址为:0xd32d9ffde8, p值为:3 p的地址为:0xd32d9ffdec, p值为:4 p的地址为:0xd32d9ffdf0, p值为:5 p的地址为:0xd32d9ffdf4, p值为:565 p的地址为:0xd32d9ffdf8, p值为:16 第2行: p的地址为:0xd32d9ffdd4, p值为:1 p的地址为:0xd32d9ffdd8, p值为:2 p的地址为:0xd32d9ffddc, p值为:3 p的地址为:0xd32d9ffde0, p值为:1 p的地址为:0xd32d9ffde4, p值为:2 p的地址为:0xd32d9ffde8, p值为:3 p的地址为:0xd32d9ffdec, p值为:4 p的地址为:0xd32d9ffdf0, p值为:5 p的地址为:0xd32d9ffdf4, p值为:565 p的地址为:0xd32d9ffdf8, p值为:16 p的地址为:0xd32d9ffdfc, p值为:1 p的地址为:0xd32d9ffe00, p值为:1
指针数组中的每一个元素(
arr[0]
,arr[1]
),其实是各个一维数组的首地址(可以初始化,也可以malloc
),不是指针变量的地址,指针变量地址应为&arr[0]
,&arr[1]
,指针变量只是指向了这些数组的首地址,避免了空指针问题。
字符指针数组 的使用参考【C语言】字符串数组按字典升序,C语言指针数组初始化*
和&
是相反操作:ptr = &fruits[0]; *ptr = fruits[0]
,这里要注意指针数组也是数组,依然满足指针数组的数组名(fruits
)为第一个指针元素的首地址(&fruits[0]
),但不等于fruits[0]
。参考交换变量值2(我的题解)//定义指针数组 char *fruits[LEN] = {"apple","cherry","grape","peach","watermelon" }; //等价于 char **ptr = fruits; 也等价于 char **ptr = &fruits[0]; char **ptr; ptr = &fruits[0]; //指针地址,而*ptr为指针地址中存储的值,首行第一个字符串的首地址 for (int i = 0; i < LEN; ++i, ptr++) { printf("%s\n",*ptr); //ptr表示fruits首行第一个指针元素的地址, *ptr表示fruits首行第一个指针元素的值,即首行第一个字符串的首地址。 } --- apple cherry grape peach watermelon
*p++
、*(p++)
、(*p)++
、*++p
、++*p
的运算规则 参考指针&指针值的自增与自减(结合自增运算符 A = i++, B = ++i 理解)原则上指针变量可以从地址的角度,访问所有变量(基本类型变量,数组,函数),操作所有变量;但是实际上对于指针的使用,还是得结合特定场景(链表实现等),不要一味追求指针,否则很容易弄巧成拙。因为任何变量类型可以转换成指针类型,但是指针类型不能转化成指定的变量类型,比如字符串等价于字符数组,而不等于字符指针(下一条有说明)。
数组和指针是不同的数据类型,有本质的区别:
char str[] = "abcd"; //sizeof(str) == 5 * sizeof(char)
,而char *str = "abcd"; //sizeof(str) == 4(x86) or 8(x64)
。
char *str = "xxxxx"
,str指向该常量地址(静态存储区);char str[] = "xxxxx"
,str在栈上申请空间,将常量内容复制进来,所以是局部变量,允许字符串strcpy
操作;参考char str[] 和 char *str 的区别,C 语言 strcpy 报 segmentation fault,动态存储区、静态存储区、堆和栈的区别指针比较难理解,在了解基础概念之后一定要多加练习,不然很容易整迷糊。
八、字符串
- 字符串输入与输出(gets和puts),参考C++的gets和puts
Note:char *tail = str; while(*tail++)
; 当地址溢出时,地址中的值为负值,跳出循环;tail -= 2;
即回到字符串倒数第二个地址的位置(倒数第一个是'\0'
)
- 字符串函数的使用(strcat,strcmp,strcpy),参考strcat、strcpy、strcmp三种函数用法,C 语言 strcpy 报 segmentation fault,动态存储区、静态存储区、堆和栈的区别
Note:char *src
和char src[]
虽然都可以表示字符串,但是数据存储地方不一样,char *src = "abcd"
等价于const char *src = "abcd"
,指针数组存放在静态存储区,即常量区,该区只许读不许写,因此字符指针不能使用strcpy
方法,虽然在编译时没有问题,但是在运行时会报错。
- 字符串的输入输出可参考C语言:字符串数组与字符串指针数组,C语言:字符数组的输入输出,C语言字符串输入及输出的几种方式,【c语言】malloc函数详解
九、结构体(用户自定义数据类型)
- 结构体的定义与使用,参考结构体定义 typedef struct 用法详解和用法小结
- 结构体数组,结构体与函数(打印结构体数组对象),参考结构体&结构体数组
- 结构体指针访问(‘.‘优先级高于’*’),参考C语言运算符优先级
- 结构体指针类型:用链表保存一个班级所有学生的基本信息,参考如何定义结构体指针
Note:
- 声明和初始化结构体的几种方式:注意结构体声明时末尾带
;
//声明结构体方法1:只能创建一个实例stu;struct为结构体类型符,Student是结构体的类型名;最后的分号一定要写 struct Student {char *name;int id;unsigned int age;char group;float score; } stu = {"张三", 1001, 16, 'A', 95.50};
//声明结构体方法2:typedef将结构体`struct Student`重命名为student或者Stu,其中`struct Student`可以简写为`struct`; typedef struct Student {char *name;int id;unsigned int age;char group;float score; }student,Stu;//初始化方法1(struct关键字可省略) Student stu = {"张三", 1001, 16, 'A', 95.50}; //初始化方法2 Stu stu1 = {"张三", 1001, 16, 'A', 95.50}; //初始化方法3(在main函数中为结构体成员赋值) struct Stu stu2;int main(int argc, char** argv) { stu2.name = "张三";stu2.id = 1001;stu2.age = 16;stu2.group = 'A';stu2.score = 95.50;printf("========== 学生基本信息 ==========\n");printf("姓名:%s\n学号:%d\n年龄:%d\n所在小组:%c\n成绩:%.2f\n",stu2.name, stu2.id, stu2.age, stu2.group, stu2.score);printf("==================================\n");return 0; }
- 如果使用结构体声明方法1来定义结构体数组,而不是通过结构体名定义结构体数组时,只能在结构体定义时同时对数组初始化:
错误做法如下,会报编译错误:error: assigning to an array from an initializer list
#include <stdio.h> #define NUM_STR 3struct Student {char *name;int id;unsigned int age;char group;float score; } cls[NUM_STR];int main(int argc, char** argv) {cls = {{"张三", 1001, 16, 'A', 95.50},{"李四", 1002, 15, 'A', 90.00},{"王五", 1003, 16, 'B', 80.50}};return 0; }
正确做法如下
#include <stdio.h> #define NUM_STR 3struct Student {char *name;int id;unsigned int age;char group;float score; } cls[] = {"张三", 1001, 16, 'A', 95.50,"李四", 1002, 15, 'A', 90.00,"王五", 1003, 16, 'B', 80.50 };int main(int argc, char** argv) {return 0; }
- 指针访问对象 :
student->name
或(*student).name
,不能是student++
。 - 想要定义结构体类型的指针一定要用
typedef
十、联合体与枚举类型(用户自定义类型)
- 枚举类型,参考C语言枚举类型(enum)的各种用法
Note:
- 定义枚举类型:
1)格式:enum 枚举类型 {枚举值列表}
;
2)枚举值列表可以手动设置,也可以默认从0递增;
3)如果在全局下定义枚举类型,则枚举类型中所有的枚举值均为全局变量//1、定义枚举类型: //枚举颜色(red, orange, yellow, green, ching, blue, purple为枚举类型变量,如果在全局下定义枚举类型,则枚举类型中所有的枚举值均为全局变量,值为整型;如果有指定enum值,则将指定的enum值赋予enum变量) enum color{red=1, orange=2, yellow=3, green=4, ching=5, blue=6, purple=7};//枚举一个星期的每一天(默认从0开始递增得到enum值) enum week {Su, Mo, Tu, We, Th, Fr, Sa };//枚举每一个月 enum month {January, February, March, April, May, June, July, August, September, October, November, December };int main(int argc, char const *argv[]) {printf("%-3d %-3d %-3d %-3d %-3d %-3d %-3d\n", red, oreange, yellow, green, ching, blue, purple); printf("%-3d %-3d %-3d %-3d %-3d %-3d %-3d\n", Su, Mo, Tu, We, Th, Fr, Sa); printf("%-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d\n", January, February, March, April, May, June, July, August, September, October, November, December); return 0; } --- 1 2 3 4 5 6 7 0 1 2 3 4 5 6 0 1 2 3 4 5 6 7 8 9 10 11
- 定义枚举类型变量:
//枚举一个星期的每一天(默认从0开始递增得到enum值) enum week {Su, Mo, Tu, We, Th, Fr, Sa }; //定义枚举类型的变量 enum week a = Su; enum week b = Mo; enum week c = Fr; int main(int argc, char const *argv[]) {printf("%-3d %-3d %-3d\n", a, b, c); return 0; } --- 0 1 5
十一、位运算
- 尾数加一(利用位运算>>和 & 将十进制打印成二进制,利用 原十进制数 和 加1的十进制数 按位与 得到问题的解),可参考位运算(a << b 左移,末尾添b个0;a >> b 右移,去掉末b位;&按位与)
- 整数 x 是否是 2 的正整次幂(按位与)
- 计算整数的二进制位数(右移1位)
- 正数转八进制(右移3位)
- 结构体内存对齐1,结构体内存对齐2,可参考c语言数据类型字节大小 和 精度,结构体内存对齐(如何计算结构体的大小),内存管理:固定分区与可变分区,操作系统: 动态(可变)分区分配,内存分配 & C++类对象内存对齐 -------保姆级解释
- 位字段(bit filed),可参考位域的使用详解(内存对齐)
十二、预处理器
十三、文件
十四、存储管理
十五、标准函数库
C语言整理(待更新)相关推荐
- Java自学视频整理(持续更新中...)
1.Java基础视频 <张孝祥JAVA视频教程>完整版[RMVB](东西网) 历经5年锤炼(史上最适合初学者入门的Java基础视频)(传智播客) 张孝祥2010年贺岁视频:Java高新技术 ...
- C语言(持续更新中)
根据以下学习视频,个人整理的笔记 https://www.bilibili.com/video/BV1jS4y1x7Gf/?spm_id_from=333.999.0.0&vd_source= ...
- android qq毛玻璃,腾讯电脑管家桌面整理重磅更新!支持毛玻璃效果!
原标题:腾讯电脑管家桌面整理重磅更新!支持毛玻璃效果! 桌面杂乱不但影响工作效率,还会影响工作心情.在年初腾讯电脑管家发布12.0后正式推出了桌面整理工具,从而取代了停更近两年的小Q桌面. 对于有强迫 ...
- java支持库 易语言_易语言支持库|易语言支持库更新集合包下载233个 - 欧普软件下载...
易语言支持库更新集合包是目前比较齐全的集合包,包含233个,有EXCEL2000支持库2.0.Java支持库2.0.PowerPoint2000支持库2.0.DirectX2D支持库2.0.位图操作支 ...
- 易语言 软件 升级 c,易语言做软件更新的方法
易语言做软件更新源码,利用QQ空间名称做更新,简单方便快速. 1.首先打开易语言,新建一个窗口. 2.分别在窗口添加3个编辑框,一个按钮. 编辑框2写入内容.注明:编辑框1带取网页源码内容,编辑框3是 ...
- R语言时间序列函数整理[不断更新]
来自:http://www.xiaowanxue.com/up_files/2012919161514.html [资料] 文档1:<R与金融时间序列分析常见问题集> [包] librar ...
- Redis4.0、5.0、6.0、7.0特性整理(持续更新)
最近研究研究新版本redis的新特性,网上查了查资料,这里记录一下. 0. Redis的版本迭代和里程碑 Redis从发布至今,已经有十余年的时光了,一直遵循着自己的命名规则: 版本号第二位如果是奇数 ...
- iOS 知识点整理 (持续更新...)
整理了些iOS相关的基础问题,每个问题可能会再写些扩展,需要具体了解可以看题目下方的链接 如有错漏,欢迎指出,谢谢 一.Swift 1.给一个数组,要求写一个函数,交换数组中的两个元素(swift可用 ...
- 前端面试知识自己的一些整理 ---持续更新中
- title: 自己整理的面试复习资料 date: 2019-03-20 12:27:51 tags: 面试 前端 CSS3+H5 [CSS3.0 帮助文档.chm](CSS3.0 帮助文档.chm ...
最新文章
- 建议转变编程时的思维习惯改为:忽略细节关扰,直指问题核心,追寻问题关键。...
- 从一个servlet转发到另一个servlet_javaweb02-创建第一个Servlet
- jq.validate.js
- 扩容是元素还是数组_数组是如何随机访问元素?数组下标为什么从0开始,而不是1?...
- Flash Alter v1.0 个性化Flash轮播图文播放器
- java 人脸识别 demo_java引用Arcface,实现人脸识别(demo)
- JDK 8中的流驱动的集合功能
- 【2019牛客暑期多校训练营(第八场)- G】Gemstones(栈,模拟)
- vue 右边跳转 实现左侧栏_Vue 后台管理项目8-侧边菜单的实现
- java中为final变量赋值的几种方式
- javasript模块化
- lintcode-135-数字组合
- 推荐:免费万能视音频转换软件--格式工厂
- python架构师是做什么的_架构师的工作都干些什么?!想做架构师必看!
- python逻辑运算优先级_测试误区《二》 python逻辑运算和关系运算优先级
- 《图解数据结构》.pdf
- 基于arduino的oled显示屏的使用
- EXCEL的COUNTIF和COUNTIFS函数的区别和联系
- java 动态代理相关记录
- linux微信卡,在UOS个人版中运行Wine QQ/微信/TIM很慢,很卡的处理
热门文章
- UI5-文档-4.5-Controllers
- Warning: .config does not exists一生一芯
- 一步步教你搭建Android开发环境(有图有真相)--“自吹自擂:史上最详细、最啰嗦、最新的搭建教程”
- JINI学习笔记2-HelloWorld
- python批量移动文件到指定文件夹_使用python批量将文件夹中的文件移动到某个文件夹下...
- 用javascript自定义SharePoint文档库/列表项菜单
- php把搜索的结果导出,excel表格查找数据之后导出-如何将Excel查找全部后得到的内容Copy出来...
- Java刷题面试系列习题(一)
- StoneTab标签页CAD插件 2.6.0
- 肖申克的救赎 经典语录