版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第一章:C 语言入门一)基础实验:1C 语言的历史和发展1)语言à汇编语言à高级语言(结构化语言à面向对象语言)C 语言由早期的编程语言 BCPL(Basic Combined Programming Language)发展演变而来C 语言之父:Dennis Ritchie ( 2)C 语言标准的发展:.)ANSI C()àISO98991990(1990 年)à ISO/IEC9899:1999(1999 年)àISO/IEC 9899:2011(2011 年) (即从 ANSI CàC99àC11)最新 C 语
2、言标准:2011 年 12 月 8 日,ISO 正式公布 C 语言新的国际标准草案:ISO/IEC 9899:2011,即 C113)gcc -std=选择 C 语言编译标准2C 语言的特点:1)优点:语法简单代码量小 执行速度快功能强大缺点:性高 开发周期长可移植性不好(相对) c 语言的应用:操作系统的开发驱动开发2)3)单片机和系统开发引擎/数据库引擎等3面向过程的程序设计=数据结构+算法数据结构:数据结构是计算机、组织数据的方式。数据结构是指相互之间一种或多种特定的数据元素的集合。算法的五大特点:)有穷性)确定性)输入)输出)可行性4伪代码和流程图的作用。流程图各符号的意义和画法5C
3、语言程序以函数6GNU/Linux,以 main 函数为Linux 操作系统除了内核之外,还需要很多其他的工具,比如 GNU 工具链, GNU 工具链 (GNU Toolchain) 是一组用于开发应用程序和操作系统的编程工具的集合,这些工具了一个完整的系统。GNU 工具链主要GCC(gcc/g+等)、GNU Binutils(比如:ar、objdump 等)、GNU make 等部分。7C 语言程序的编译和运行的五个步骤编译工具:gcc1)预处理 (展开头文件、替换符号和宏定义、条件编译处理、删除注释等)gccEoexample.iexample.c2)编译(进行词法、语法检查,编译成汇编代
4、码等)gccS汇编oexample.s(汇编成进行反汇编)oexample.oexample.i不的二进制代码,可以用 objdump d example.o3)gcccexample.s4)gcco运行./exampleexampleexample.o5)gccoESc常用选项:指定文件输出名 预处理结束即停止编译结束即停止 汇编结束即停止Wall 打开所有警告On 对可执行程序进行优化L 指定库搜索目录l 指定库文件名I 指定头文件搜索路径8交叉编译1)交叉编译(cross-compilation)是指,在某个主机平台上(比如 PC 上)用交叉编译器编译出可在其他平台上(比如 ARM 上)
5、运行的代码的过程。简单地说, 就是在一个平台上生成另一个平台上的可执行代码2)宿主机(host) :编辑和编译程序的平台,一般是基于 X86 的 PC 机,通常也被称为主机。目标机(target):用户开发的系统,通常都是非 X86 平台。host 编译得到的可执行代码在 target 上运行。3): “既然我们已经有了主机编译器,那为什么还要交叉编译呢?”有时是因为目的平台上不或不能够安装我们所需要的编译器,而我们又需要这个编译器的某些特征;有时是因为目的平台上的要编译器9C/C+头文件和源文件为什么要贫乏,无法运行我们所需c 语言中头文件中一般定义了函数的局变量最好放到源文件中)、结构体的
6、定义、宏定义。(常量和全1) 从业务扩展性上看:头文件提供接口,头文件中放函数的,函数由源文件实现,接口和实现,这在面对业务变更频繁的需求中技术实现的好处是显而易见的:只要定义出良好地、扩展性高的接口,实现是可以很方便的更换。2) 从程序架构上看:代码在在大型需要分成不同的模块,单一模块中又可能分为不同的业务功能单元,他们间有很多相互的调用。头文件中的、结构体定义、宏就都可以充当这部分的模块与模块间、业务功能间的接口调用。模块与模块间,功能单元与功能单元间都是面向接口的调用,耦合性低,这正是基于组件编程的思想。3) 从某些技术角度实现上看:头文件可通过宏定义来保证类定义、结构体定义、宏定义的唯
7、一性。方便,不容易出错。二)扩展实验:1静态库和共享库的制作在当前目录下有 include/sum.h 和 src/sum.c 程序源文件静态库:$gcc Iinclude c src/sum.c o obj/sum.o$ar rc ./lib/libsum.a obj/sum.o$gcc Iinclude src/main.c lib/libsum.a o bin/main$./bin/main静态库的特点:1)优点:库代码和源代码都在一起装入内连续的内存空间中,则运行时寻址范围变小,运行速度较快。2)缺点:代码总体积大,库每次装入内存需要消耗效率,每次发布新的库版本都要做重新编译共享库:$
8、gcc Iinclude fPIC shared o ./lib/libsum.sosrc/sum.c$gcc Iinclude src/main.c L./lib lsum o bin/main$./bin/main注意:1)也可以通过 C_INCLUDE_PATH 变量设置头 C 语言程序文件路径如: export C_INCLUDE_PATH=./include (与 Iinclude 2)可以通过 ldd 命令分析某执行程序所依赖的库文件。效果一样)要到动态库则需要找到该库的路径,有三种方式设置:1: export LD_LIBRARY_PATH=./lib2: sudo cp./li
9、b/libsum.so/lib3:cd /etc/ld.so.conf.d/ vi libc.conf 或 touch的绝对路径名添加上去mylib.conf 把应用程序使用库然后用 ldconfig 命令使配置文件生效(当然也可以重启)共享库的特点:不管程序有多个地方使用该库,程序运行的时候库只装入内存一次,程序要调用库中的功能,则都会跳到该库的执行再返回。每次发布新的库版本,更新替换后,不需要重新编译,只要动态库:动态库的使用相关接口 API:void *dlopen(const char *filename, int flag); char *dlerror(void);void *dl
10、sym(void *handle, const char *symbol);即可。int dlclose(void *handle);2Makefile 的作用?简单Makefile 文件的的编写,通过make 命令执行Makefile。makefile 带来的好处就是“自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了开发的效率。make 是一个命令工具,是一个解释 makefile 中指令本一样,其中也可以执行操作系统令工具。因为 makefile 就像一 shell 脚令。make 工具最主要也是最基本的功能就是通过 makefile 文件来描述源程序
11、之并自动维护编译工作。而 makefile 文件需要按照某种语法进行编间的相互写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖。3gdb 的使用:使用 gdb 调试程序,需要在用 gcc 编译执行文件。gdb 的常用选项:查看帮助: help指定要调试程序: file: quit查看源代码:list设置命令行参数:set args查看命令行参数:show args设置断点:break查看断点:info breakpoints删除断点:delete 运行程序:run执行到下一断点处:continueg 选项,然后 gdb(遇到函数调用,进入到被调函数):nex
12、t(遇到函数调用,进入到被调函数): step打印变量值:print设置变量值:set variable count=50跳到指定行:until 跳出函数: finish反汇编:disassemble下向下三)作业:1. 练习静态库和共享库的制作以及使用2. 编写 Makefile 文件,通过 make 命令自动化编译执行程序3. gdb 调试工具的使用第二章:数据类型和作用域一)基础实验:1基本数据类型 4 中:整型、浮点型、指针类型、聚合类型(数组和结构体)整型 4 种:字符型、短整型、整型、长整型整型按有符号无符号 9 种:字符型、有符号字符型、无符号字符型、无符号短整型、有符号短整型、
13、无符号整型、有符号整型、无符号长整型、有符号长整型C 标准规定:长整型至少和整型一样长,整型至少和短整型一样长long double 至少和 double 一样长,double 至少和 float 一样长2宽字符类型 wchar_t:wchar_t 是 C/C+的字据类型,是一种扩展的字符方式,wchar_t 类型主要用在程序的实现中,wchar_t 数据类型一般为 16 位或 32 位,但不同的 C 或 C+库有不同的规定, wchar_t 所能表示的字远超 char 型。3常用进制的字母表示:2 进制 :10 进制:16 进制: 或者:8 进制:16 进制:以 B(Binary)结尾如 2
14、3 可以以 D(Decimal)结尾:23D以 H(Hex)结尾以 0 开头以 0x 开头如 012 表示十进制 104整型数在计算机中的二进制表示:如整数:2:2:二进制表示为:0010二进制表示为: 1110注意:负整数用补码表示:即对应的正整数的二进反加 1 5关于无符号整数最大值和最小值,很明显无符号整数最大值:所有的二进制位都是 1无符号整数最小值:所有的二进制位都是 0,即为 0 6关于有符号整数的最大值和最小值因为此时最为符号位,正数符号位为 0,负数符号位为 1,所以有符号整数最大值:最为 0,其它位都是 1有符号整数最小值:最为 1,其它位都是 0所以:其实 有符号最小值=有
15、符号最大值+1 7浮点数在计算机中的表示。IEEE 标准用规定 float格式为: V=(-1)S * 1.M * 2E符号位:s 表示符号位,当 s=0,V 为正数;当 s=1,V 为负数。尾数:M 表示有效数字,大于等于 1,小于 2。(尾数)指数: 2E 表示指数位。(E 的作用是对浮点数次幂)对于 float:,这个是2的E SEM1 位符号位8 位指数23 位尾数转成数值即为:V=(-1)S * 1.M * 2(E-127) (双精度 double 转成数值即为:V=(-1)S * 1.M * 所以:2(E-1023) )对于 16.5 转成二进制为 00010000.1=>1
16、.00001*24,(注意:小数的二进制表示规定为点左边的位权是 2 的非负幂,点右边的位的权是 2 的负数幂,例如二进制小数 101.11 表示数字则是: 1*22+0*21+1*20+1*2-1+1*2-2=5.75 所 以 16.5 的 二 进 制 为00010000.1)那么在内存的表示为:符号位0指数 4+127 =数00001 000000000000000000在转换过程中由于需要往右移位,可见对于 float 数整数部分越大,小数部分的精度就越低 ,对 float 数来说有效数字约为 7 位(223 约等于107),所以整数部分占的位数越多,小数部分
17、的精度就越低。为了方便理解下面是 float 和 double 的位表示图:对于 64 为的浮点数,最高的 1 为是符号位 s,接着的 11 位是指数 E,剩下的 52 位为有效数字 M8. 指针类型变量的和定义,以及取地址符的使用。1) 指针和地址其实是不同的,指针有类型,而且比如 linux 操作系统下不能把任意的地址直接赋给一个指针,比如 int *p = (int*)(0x0fffff2c)是不可以的)2) 指针的大小,本机地址线的大小3 )指针变量一般涉及到两个值: 指针变量本身和指针所指向的变量(types/src/point_test.c)9. 指针类型变量字节数的大小指针类型无
18、关,只与地址线有关。(types/src/point_size.c)10. 指针常量和常量指针的区别:const int *pa(int const *pa)、int *const pa、const int *const pa 的区别 (types/src/const_test.c)11. 无类型指针和空指针无类型指针: void*p空指针: int *p = NULL;不能对空指针进行间接(解)操作。(注意:NULL 此时的含义与*p = NULL 中 NULL 的区别,NULL 其实就是一个宏定义符号,可以查看/usr/include/linux/stddef.h 中的宏定义)int *p
19、 = NULL; (此时 NULL 表示空指针, #define NULL (void *)0) )*p = NULL;(此时 NULL 表示 0, #define NULL 0)所以说 NULL 和 0 并不等价,得看具体情况12. 枚举类型 enum 的使用和注意(types/src/enum_test.c)13. typedef 和#define 的区别1). typedef 相当于一个语句,注意要以 ; 2).宏定义是在预处理阶段替换typedef 取的别名是在编译的时候做类型检查结尾3).当多个变量的时候:比如:#definePCHARchar*typedef则:char*CHARP
20、;PCHAR a, b, c;相当于 char*a, b, c;即 char*a; char b; char c;相当于 char*a; char*b; char*c;CHARP a, b, c;14.#define N 5 和 const int n = 5 的区别1) #define 是在预处理阶段做符号或宏定义的替换const 变量是在编译执行时使用2) #define 的宏或符号没有类型,不做类型检查const 变量在编译阶段做类型检查3)#define 定义的符号和宏常数符号一般情况下会为 const 变量分配内存空间,可能在栈区也可能在堆区。于程序的代码段,在实际使用中只是一个的
21、const 变量分配但是编译器为了提高效率,通常不给全局空间,而是将它保符号表中,则在使用时没有了与读内存的操作,使得他的效率也提高1)一些集成的调试工具比如 gdb 能对 const 变量调试而不能对#define 的宏或符号调试const 一般修饰函数的参数,可以防止被意外的修改,提高程序的健壮性。2)15.作用域(scope):编译期确定1)文件作用域:(在本文件中任何地方都可以使用)全局的变量或函数2)函数作用域:(只能在函数体)候的形参(形式参数),函数函数体内的局部变量3)代码块作用域:大括号 . 中4)原型作用域:函数只有原型的的变量则不能在外面使用但是没有定义的时候的形参具有原
22、型作用域的属性属性(linkage)16在不同的文件代码一起阶段,所有的识符(特别是不同文件中相同的标识符)的处理方式1)无属性(none):函数体内的局部变量 无(任何)属性2)外部属性: (extern)extern int sum(int, int);extern inta;全局的标识符默认都具有外部属性(可以在其他文件中使用)比如:如果在本文件中要使用其他地方定义的变量 int a = 10;在其它本文件中使用,则需要做:externinta; (表示该变量 a 是在其他地方定义过,本文件只要拿过来使用即可。即:使用其它地方定义过的变量)3)内部属性:在默认具有外部属性的标识符(变量或
23、函数)前面加上 static 关键字, 则该标识符 只能在本文件使用17.属性(store 程序运行时变量栈区(stack):局部变量(自动变量) 堆区(heap):在什么地方)程序员进行动态内存分配获得的内存空间( malloc/calloc/realloc ), 注意使用完手动(free)全局数据区/静态数据区: 全局变量和静态变量文本区:放的是编译好的二进制指令寄存器变量(register):类型为 register 也不一定存放在寄存器中的变量,即使什么变量存放到寄存器中,因为寄存器个数有限二)扩展实验:1.编写简单的 c 程序,属性(通过 gdb 调试打印作用域、属性、各变量的地址,
24、清楚栈区、堆区、全局数据区、文本区的大致地址空间分布)注意:static 用于代码块内部的变量时,static 用于修改变量的但变量的属性和作用域不受影响比如: 某函数体内voidfun()static int a = 10;类型 。则变量 a 为静态变量,但在该函数体外无法在全局数据区,从程序装入内存开始就到该变量。2. 自增/自减运算符的操作测试:int a = 1; int b = a+; int c = +a;三 )作业1 编写 c 语言程序,获取本机 int 型数据(以及其他各类整型)的总字节数。(type/src/int_bits.c)2. 编写 c 语言程序,通过移位操作计算无符
25、号整型的最大值(uint_max) (type/src/int_bits.c)3. 编写 c 语言程序,通过移位操作计算有符号整型的最大值(int_max)和有符号整型的最小值(int_min) (type/src/int_bits.c)4. 查看/usr/include/limits.h 中的符号定义打印本机规定的各数据类型的最大值和最小值。(参考 type/src/float_double_limits.c)5. 定义如下 a 和 b 两个变量: unsigned char a = 0xA5; unsigned char b = a*2;请问 b 的值是多少?unsigned char 能
26、表示的最大数是 255,而 a*2 = 160 * 2 为 330,会溢出 所以 b 的值为 330256 = 74很明显最(330 的二进制表示:101001010 最溢出后则为 01001010 即 74) 6浮点型比较常见1)c 程序,float 和 0 的大小if(x<0.000001 && x>-0.000001)2)编写 c 语言程序,有 float f=0.1,f 是否与 0.1 相等根据 1)可得: if(fabs(x-0.1)<=0.000001) 则表示与 0.1 相等7有如下 c 语言程序:int main(void)int a=2,x=
27、2,p,q;p = (a+)+(a+);q = (+x)+(+x);return 0;请问程序执行后 a、x、p、q 的值分别是多少?值分别如下: 4448一般情况下: a+(后+)无论多少项相加,是计算完表+x(前+)都是先自加 1,之后再计算表后,再自加 1当然: 不同的编译器可能有不同的词法分析规则,所以不同的编译器执行结果可能不同。比如下面的程序:int i = 2;printf("%dn", (+i)+(+i)+(+i);/ 查看本机上的执行结果,可以通过查看反汇编代码(objdump dexample.o),查看本机结果形成的过程。8. 字节序:(types/s
28、rc/byte_order.c)编写 c 语言程序,利用指针操作关于字节序的相关概念:本机字节序。小端字节序:低字节大端字节序:低字节于内存的低地址,高字节于内存的高地址,高字节于内存的高地址。于内存的低地址。字节序上传输的数据节流,对于一个多字节数值,在进行传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它将这个字节作为字节还是低位字节处理。UDP/TCP/IP 协议规定:把接收到的第一个字节当作字节,这就要求发的第一个字送端的第一个字节是字节;而在端数据时,节是该数值在内存中的起始地址处对应的那个字节,也就是说,该数值在内存中的起始地址处对应的那个字节就是要的第一个字节
29、(即:字节存放在低地址处);由此可见,多字节数值在之前,在内存中应该是以大端法存放的,所以说,字节序就是是大端字节序。第三章:语句一)基础实验:1输字符,分别统计出其中英文字母、空格、数字和其它字符的个数2. 输入两个正整数 m 和 n,求其最大公约数和最小公倍数3. 编写函数 out_bin(int),利用 while 循环输出某 int 型数的二进制形式4. 编写函数 out_bin_any(void*p,size_tn)输出任何类型数的二进制形式(对于浮点型:查看输出二进制表示是否与第二章说明的 IEEE 标准规定的计算方式 得出的浮点数二进制结果一致:比如 floata = 16.5二
30、进制表示为:00000000000000)5. 将以上 while 循环的基础练习题均改用 for 循环和 dowhile 循环实现6. 有 1、2、3、4 个数字,能组成多少个互不相同且无重复数字的三位数?并打印出来。7一球从 100 米高度落下,每次落地后反跳高度的一半;再落下,求它在第 10 次落地时,共经过多少米?第 10 次反弹多高?8. 从键盘输入年份和月份,编写程序计算并打印该年的该月是多少天?9. 逻辑右移动和算术右移左移:(右边)低位补 0左移的时候没有逻辑左移和算术左移之分, 右移:当有符号数右移的时候:1)逻辑右移:不管正负数,往(左边)补 02)算术右移:正数还是一样,
31、符号位是 0,往(左边)补 0负数由于符号位是 1,往(左边) 10continue 和 break 关键字的作用补 111循环应该注意,在逻辑的情况下,如果可能,将最长的循环放在最内层,最短的循环放在最外层,减少 cpu 跨切循环层的次数,提高运行效率。12goto 关键字的使用goto 语句也称为无条件转移语句,goto 语句通常与条件语句配合使用。可用来实现条件转移,循环,跳出循环体等功能。一般情况下,在结构化程序设计中一般不主张使用 goto 语句, 以免造成程序流程的,使理解和调试程序都产生。goto 语句会跳过goto 语句,要先指定一个有的一段代码并转到一个预先指定的位置。为了使
32、用的位置作为跳转位置,这个位置必须与 goto 在同一个函数内,在不同的函数之间无法实现 goto 跳转。13当 if-else 分支比较多的时候,最好用 switch-case 能够提高运行效率和代码的可读性。但是注意:switch-case 后跟的条件整型、整型、长整型)。只能是整型(字符型,短二)扩展实验:1. 从键盘输入一个整型数,计算它的阶乘(如果超出 long int 的最大范围则打印越界信息:”out of range”)2. 利用死循环计算出 int 型数据的最大值和最小值第四章:操作符和表一)基础实验:1sizeof 操作符的作用:C 语言中长度符,sizeof 不是一个函数
33、,字节数的计数据类型或者表算在程序编译2逻辑操作符(&&。和 |)的短路规则测试。 (operator/src/logic_test.c)3注意操作符的优先级。(最好多用括号) 如: 0x0001 << 2 + 3结果是多少?3. 逗号操作符的使用例如:int a = (1, 2, 3); /a = 3 int i = 2;int c = (i+, +i, i+10); /c = 144. 三目运算符如:int c = (a>b?a:b) 即:if(a>b)c = a; elsec = b; 5怎么样在不使用其他中间变量让两个数交换?a = b;b =
34、a;a = b; 5隐式类型转换和显示类型转换(强制类型转换)隐式类型转换:1)2)在赋值符号同一边的,低精度向高精度转换在赋值符号两边的,右边的向左边转换如下表:inta = 10; a = a + 3.14以上此表 经过两次隐式类型转换,赋值符号右边的 a+3.14,a 是int 型,而 3.14 默认是 double 型,所以 int 向 double 转换。然后给左边赋值的时候,左边是 a 是 int 型,则右边的 double 又会向 int 转换。所以:注意在赋值操作是,当赋值符号左边的数据类型范围比右边小的时候,注意隐式类型转换可能会发生数据截断,注意数据类型范围。比如: cha
35、rc= 256;printf(“%dn”, c); / 被截断输出 0显示类型转换:即程序员手动用括号指定类型 比如:inta = 10;a = a +(int) 3.14/则此时只做了一次显示类型转换二)作业:1编写 c 语言程序,用户输入 10 进制格式表示的文件权限三位数,请位数表示的读、写、执行权限。(operator/src/permission.c)例如:执行:./bin/permission输入十进制权限数字: 755该三user: rwx group:rx other: rx输出:2.位操作符的使用测试 (operator/src/out_bin.c)1)编写函数 set_bi
36、n(int *p, size_tn),将某 int 型数的第 n 位置 1 2)编写函数 clr_bin(int *p, size_t n),将某 int 型数的第 n 为清 0第五章:数组一)基础实验:1C 语言中有两种聚合数据类型,数组和结构体,数组中所有元素类型一致, 并且所有元素连续存放。2. 对数组名 sizeof 操作,取的是数组中所有元素的总字节数之和。C 语言中数组大小是在编译时就可知并确定的,编译器会为数组预留内存空间。所以数组大小不要做动态定义。3. 数组名可以用下标方式,也可以用指针方式。数组的下标从 0 开始,到n1。注意数组时不要越界。将数组 a 赋值给数组 b,需要
37、每个元素都进行赋值。关于数组越界int main(void)int i;int array10;,请执行如下程序,查看结果,并分析:for(i = 0; i<= 10; i+)arrayi = 0; printf("i = %dn", i);return 0;该程序执行结果是一个死循环,因为数组越界,array10会把 i 的值覆盖掉,所以 i 加到最后总会是 0,则循环会不断执行。(array/src/ out_rangle.c)和右值的(赋值符号的左右两边):能够表示内存中一个确切特定的内存地址位置4右值:能够表示某内存地址上确切的值某变量能放在赋值符号左边,则能
38、作为某变量能放在赋值符号右边,则能做为右值例如:a = b + 25;a 就是一个,因为它标识了一个可以结果值的地点,b + 25 是个右值,因为它指定了一个值。但是它们可以互换吗? b + 25 = a; 原先用作的 a 此时也可以当作右值,因为每个位置都包含一个值。,b + 25 不能作为,因为它并未标识一个特定的位置。因此,这条赋值语句是的。注意当计算机计算 b + 25 时,它的结果必然保存于的某个地方。但是,程序员并没有办法该结果会在什么地方,也无法保证这个表的值下次还会于那个地方。其结果是,这个表不是一个。基于同样的理由,字面值常量也都不是比如:int a = 10; int *p
39、 = &a;*p = 20; int b = *p;。/此时 p 是此时 p 是此时 p 是右值5 有数组 inta10 ,则 a 和 &a0 和 &a 到底有什么区别? (array/src/array_name.c)以上三个值打印结果一致,但是具体表达的含义是不同的。 数组名 a,是一个指针常量,不能改变它的值。故 a 一般不能做作为数组名本身之外)。(即除了a 可以作为右值:即利用指针的间接(即等价于 e=a0,e=a1)。但是本质上:&a0表示数组首元素的地址方式数组时如 int e; e=*(a+0);a 既是数组名,也是 a 表示数组首元素的地址(此
40、时即等价于&a0) &a 表示整个数组的首地址所以会造成用 a 和&a 去进行元素偏移时偏移大小不同如下程序:int a5 = 1, 3, 4, 29, 20;int *p = (int*)(&a+1); printf("%d, %d", *(a+1), *(p1);结果是: 3和 20二)作业:1给出一个含有 n 个元素的整型数组 a,其中只有一个元素出现奇数次,找出这个元素。(array/exercise/test1.c)2给定一个 n 个元素的数组,其中一个元素次数超过 n/2,求这个元素。(array/exercise/test2.c
41、)3 求两个含有 n 个整型元素的有序( 非降序) 数组的共同元素。 (array/exercise/test3.c)4利用数组,使用除 2 取余的方式将某整形数转换成二进制的形式输出。(array/src/ array_outbin.c) 5利用数组,实现栈(先进后出)的数据结构。(array/include/stack.h , array/src/ stack.c)栈的基本操作有:/*往栈中放入一个元素,返回该元素*/ElementType push(ElementType e);ElementType pop(void); ElementType top(void); size_t si
42、ze(void);int is_empty(void); int is_full(void);/*弹出栈顶元素*/获取栈顶元素*/*栈中元素的个数*/栈是否为空 */是否栈满*/6. 利用 2 中实现的栈结构提供的接口,使用除 2 取余的方式将某整形数转换成二进制的形式并输出。7. 利用数组实现队列(先进先出)的数据结构(array/include/queue.h , array/src/ queue.c)队列的基本操作有:ElementType enqueue(ElementType e); ElementType dequeue(void); ElementType cpqueue(voi
43、d);size_t size(void); int is_empty(void); int is_full(void);/*元素入队*/*元素出队列*/队首元素*/*队列的长度*/队空*/ 队满*/8对以上 7 中的队列进行改进,实现循环队列,提供的接口与 7 中的一致(array/include/queue.h , array/src/ loop_queue.c) 9思考:如何用两个栈实现一个队列10 对数组中的元素进行排序,分别用以下不同的排序实现:1)冒泡排序(array/src/ bubble_sort.c) (array/src/ insert_sort.c) (array/src/
44、 shell_sort.c) (array/src/ bubble_sort.c) (array/src/ binary_searh.c)2)3)排序排序4)选择排序11二分查找12. 找出一个数组中的最大数和第二大的数。(array/exercise/src/test11.c)13. 找 出 一 个 非 递 减 序 列 中 绝 对 值 最 小 的 数(array/exercise/src/abs_maxmin.c) 14求数组中两个元素差的最大值。(array/exercise/src/test14.c) 15关于算法的时间复杂度和空间复杂度。(参考 时间复杂度空间复杂度.pdf)二维数组:
45、一)基础实验:1. 二维数组的初始化:以下三种语法格式都支持int a34 = 1, 2, 3, 4,5, 6, 7, 8,9, 10, 11, 12;int b34 = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;int c4 = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12;/注意:列数不能省略2. 二维数组实际的方式是线性了,通常为了方便理解和运算,我们解为逻辑上的行和列的二维形式。即:二维数组在内存中实际上是以一维的线性方式。所以:二维数组实际上就是有多个一维数组的一维数组。3. 二维数组的通常的方式直接利用下标,比如一个有
46、 n 行 m 列的二维数组,行和列的下标则分别从 0>n1 和 0>m1,如 a02。关于二维数组名 a 的真实含义,可以类比一维数组:比二维数组:int a34 = 1, 2, 3, 4,5, 6, 7, 8,9, 10, 11, 12;a:表示第 0 行整个这一行的一维数组的首地址&a:表示整个二维数组的首地址&a00: 表示二维数组第 0 行第 0 列该元素的地址故有:a+1 的值与&a10值相等&a+1 的值与&a24值相等&a00+1 的值与&a01值相等所以综合以上分析所得:到 a11可以有以下三种方式: 直接利用
47、下标: a11利用二维数组本质上在内存中以一维数组线性方式要1)2)的原理:*(int*)(a+1)+1)/注意:这里第一次 a+1 后必须要通过指针的显示类型转换,否则再用 a 直接偏移会每次都偏掉一整行3)利用用指针*(*(a+1)+1)二维数组的:4.二维数组作为参数传递给函数的时候,函数的方式1)根据二维数组实际线性的原理,可以直接传二维数组第一个元素的地址 p,以及元素总个数:void out(int *p, int n); int i;for(i = 0; i < n; i+)printf("%dn", *(p+i);2)根据二维数组实际线性的原理,可以直
48、接传二维数组第一个元素的地址 p,以及行数 row 和列数 col: void out(int *p, int row, int col);则第 i 行第 j 列的时候则为如下方式:for(i=0; i < row; i+)for(j=0; j<col; j+)printf("p%d%d=%dn",i,j,3) 传入二维数组包含列的原型和行数void out(int p4, int row)则第 i 行和第 j 列的时候则:*(p+i*col+j);for(i = 0; i < row; i+)for(j = 0; j < 4; j+)/下面三种方式
49、都可以(即以上 3 中总结的三种方式)/*printf("a%d%d=%d/*printf("a%d%d=%d printf("a%d%d=%d", i, j, pij);*/",i, j, *(int*)(p+i)+j);*/",i, j, *(*(p+i)+j);printf("n");以上 void out(int p4, int row)等价于 void out(int (*p) 4, int row)数组指针:int (*p)4/ 有四个元素的数组的指针指针数组:int*p4/ 元素类型为 int*类型的
50、数组,该数组有 4 个元素二)作业:1有如下二维数组:int a23 = (1, 2), (3, 4), (5, 6);则int *p = (int*)a0; printf("%dn", *p);注意:以上二维数组初始化时用的是小括号,所以根据逗号表int a23 = 2,4,6;所以结果为: 2 2有如下代码:int a55;int (*p)4; p = a;&a42&p42 等于多少?计算过程:&a42 =&a00 + 4*5*sizeof(int) + 2*sizeof(int)等价于&p42 =&a00 + 4*4*s
51、izeof(int) + 2*sizeof(int)该题考查对二维数组跨列偏移的运算,由于指针直接的减法运算是得出它们之间相隔了多少个元素,所以最后结果是: 43打印杨辉三角(array/src/yh_trigle.c) 1111211010516152015611.4在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,数组中是否含有该整数。(exercise/src/test2-4.c)5. 螺旋式打印一个二维数组。如要求打印后顺序为:1 ,16 ,3 ,2 ,17 ,23 ,12 ,13 ,6 ,4 ,
52、2 ,21 , 2 ,8 ,6 ,4 ,3 ,8 ,7, 5(exercise/src/test2-5.c)6利用二维数组实现表(散列表)typedef int ElementType; typedef unsigned int size_t;extern int entable(ElementType e);/*往表中放入一个元素*/extern int checktable(ElementType e); /*查找某个元素在表中是否extern void remove_element(ElementType e); /*删除某个元素*/*/extern size_t size(); ext
53、ern int is_empty(); extern int is_full(); extern void out_table(); (array/include/hash.h字符串: 一)基础练习/*表的总的元素个数*/是否为空*/ 表是否满*/表中所有元素*/array/src/hash.c)1.字符串:(引号” ”括起来)由于 c 语言中没有字符串类型,所以表示字符串可以用字量:(c 语言中规定字符串以0结尾)字组:char str = 'h','e','l','l','o''组或字符串常表示真正字符串的字组:char str1 = 'h','e','l','l','o','0' 或char str2 = "hello"字符串常量:char *str3 = "hello"/字符串以0结尾/字符串以0结尾注意:分别用 sizeof 操作符和 strlen 函数去取得 str、str1、str2、st
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年度城市供水供应合同完整版下载3篇
- 2024年度停薪留职员工职业发展支持与就业援助合同范本3篇
- 2024年标准化物流服务协议模板版B版
- 2024年度物业公司物业代理销售合同3篇
- 2024年度教材印刷环保认证服务合同范本3篇
- 2024年度学校教学楼维修改造合同7篇
- 2024年度企业信息化项目私人承包合同范本3篇
- 2024年旅游大巴班车承包合同范本2篇
- 2024年特定产品三方销售协议模板版B版
- 2024年度智慧城市系统集成与运维委托合同2篇
- 新时代大学生劳动教育智慧树知到期末考试答案章节答案2024年江西中医药大学
- 西安市艺术教育示范校评估验收标准
- 鸡西730煤机电器图册
- 电力电子-降压斩波电路设计
- 小学音乐课件-选唱歌曲《旋转的童年》-西师大版(共8张PPT)ppt课件
- 轴类零件加工工艺设计毕业论文.doc
- 60Si2Mn汽车板簧热处理工艺设计
- 信息工建学院项目项目实施方案
- 《背向大地的爱》阅读练习及答案
- 色彩构成7色彩秩序
- 创新管理出亮点安全生产见成效
评论
0/150
提交评论