======================== 2022-7-27 ========================
一.温故知新 1.求10000-11000中所有的质数
2.冒泡法排序
3.实现strcat
char *mystrcat(char *dest, const char *src);
字符数组和字符指针
在C语言中是没有字符串类型的,
想要存储字符串数据可以使用字符数组
数组越界的问题
----------------------------------
char *p = "Hello";
字符串的操作
strcpy strcat strcmp strlen
mystrcpy mystrcat mystrcmp mystrlen
----------------------------------
mystrncpy mystrncat mystrncmp
----------------------------------
char dest[2];
char *src = "Hello World";
strcpy(dest, src);
strncpy
用多文件的形式实现一下冒泡法排序
main.c sort.c sort.h makefile
vim * -p(以标签页的形式打开多文件)
切换文件 ctrl + alt + pgup/pgdn
1 2 3 4 5 6 7 #ifndef __SORT_H #define __SORT_H #endif
==========================
作业:
1.把今天讲过的内容完完整整的复习一遍
2.把之前讲过的功能函数都拆成多文件的形式写一遍
1)子弹的程序
2)排序(冒泡法 选择法 ...)
3)字符串操作函数(mystrcpy mystrcat mystrcmp mystrlen)
4)atoi函数功能
3.把五子棋游戏拆成多文件的形式实现
==========================
一.写C语言程序的四个阶段 第一阶段 只写一个.c文件,在.c文件中只写一个main函数
把所有功能都堆到main函数中
第二阶段 只写一个.c文件,在.c文件中除了main函数以外
封装了其他的功能函数
函数的声明
函数的返回值类型 函数名(参数列表);//该处的参数指的是形参
函数的实现
函数的返回值类型 函数名(参数列表)//该处的参数指的是形参
{
功能实现的代码
}
函数的调用
函数名(参数);//该处的参数指的是实际参数
第三阶段 以项目工程的形式编写程序,以多文件的形式
main.c 存放主函数和功能函数的调用
func.c 存放功能函数的实现
func.h 存放功能函数的声明以及各种定义
makefile 存放的是编译规则
第四阶段 把功能函数的实现封装成库文件
静态库和动态库
二.makefile文件的简介 一个项目工程中源文件不计其数,这些源文件按照文件类型,
功能,模块,分别存放在不同的目录中,makefile文件定义了
一系列的规则来指定哪些文件需要先编译,
哪些文件需要后编译,哪些文件需要重新编译
包括更复杂的一些编译操作
三.内存空间的分布 C语言会把内存分为5个区域
(栈区 堆区 常量区 全局区 代码区)
./a.out执行程序时,是由一个进程来执行程序的
进程的空间大小是4Gb,是由真实内存4Kb虚拟出来的
1Gb Kernel(内核)
----------------------------
3Gb 命令行参数以及环境变量
栈区(从上往下分配空间)
空白
堆区(从下往上分配空间)
静态区(全局区)未初始化的(系统会初始化成0)
静态区(全局区)已初始化的
常量区(只读区)Read Only
代码区
栈区 不需要程序员管理,自己开辟,自己释放
堆区 需要程序员管理,需要手动开辟,需要手动释放
(malloc calloc realloc free)
全局区 全局变量/static关键字修饰的变量
常量区 Read Only
char *p = "Hello";
字符串常量"Hello"存储在常量区中
代码区 程序员没有办法管理
四.全局变量和局部变量 局部变量
在某个函数内部定义或者块内定义的变量叫做局部变量
局部变量只能在函数内部或者块内使用
局部变量在函数之外是不可知的
全局变量
全局变量是定义在函数之外的,通常写到程序开头的位置
全局变量在整个程序中生命周期都是有效的
在任意函数内部都可以访问全局变量
注意:
全局变量和局部变量可以同名
如果出现了同名情况,那么在执行该函数时,优先使用局部变量
在该函数中全局变量被屏蔽
全局变量和局部变量在定义时的区别
当定义局部变量时,系统不会帮助初始化,
局部变量存储的是垃圾值
当定义全局变量时,系统会帮助初始化
int -> 0;
char -> '\0';
pointer -> NULL;
全局变量和局部变量存储空间的区别
全局变量 : 保存在内存的静态全局区,
占用的是静态的存储单元
当程序运行时就被创建了,
当程序结束时才被销毁
局部变量 : 保存在栈区中,
只有在局部变量所在的函数被调用时,
系统才会帮助分配存储单元,
当局部变量所在的函数调用结束时被释放
/*
全局变量和局部变量
其实在查看一个变量可以通过3个属性进行查看
存储区域 生命周期 作用域
*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #include <stdio.h> #include <stdlib.h> int a = 9527 ;void func (void ) { int a = 100 ; printf ("func().a = %d\n" , a); } void func1 (void ) { printf ("func1().a = %d\n" , a); } int main (int argc, char *argv[]) { int a = 200 ; func(); printf ("main.a = %d\n" , a); func1(); { int a = -900 ; printf ("块.a = %d\n" , a); } printf ("main.a = %d\n" , a); return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <stdio.h> #include <stdlib.h> int myatoi (const char *nptr) ;int myatoi (const char *nptr) { int i = 0 ; int num = 0 ; int flag = 1 ; for (i = 0 ; nptr[i] == ' ' ; i++); if (nptr[i] == '-' || nptr[i] == '+' ) { flag = nptr[i] == '+' ? 1 : -1 ; i++; } for (; nptr[i] != '\0' ; i++) { switch (nptr[i]) { case '0' ... '9' : num *= 10 ; num += nptr[i] - '0' ; break ; default : return num * flag; } } return num * flag; } int main (int argc, char *argv[]) { int num = 0 ; num = myatoi("- 9527" ); printf ("myatoi = %d\n" , num); return 0 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #ifndef __ADD_H #define __ADD_H int add (int , int ) ;#endif ---------------------------------------------------------- #include "add.h" int add (int a, int b) { return a + b; } ---------------------------------------------------------- #include <stdio.h> #include "add.h" int main (void ) { int a = 0 , b = 0 ; int sum = 0 ; scanf ("%d-%d" , &a, &b); sum = add(a, b); printf ("sum = %d\n" , sum); return 0 ; } ---------------------------------------------------------- # 注意:makefile文件是脚本文件,所以想要注释需要用 # # 注意:makefile文件是非常注重格式的,空格是空格,tab是tab # 生成的文件 : 依赖的文件(:以左是生成文件,:以右是依赖文件) main : main.o add.o gcc main.o add.o -o main # 注意:使用的工具和上边生成文件的内容要差一个tab main.o : main.s gcc -c main.s -o main.o main.s : main.i gcc -S main.i -o main.s main.i : main.c gcc -E main.c -o main.i add.o : add.s gcc -c add.s -o add.o add.s : add.i gcc -S add.i -o add.s add.i : add.c gcc -E add.c -o add.i clean : rm -rf *.i *.s *.o main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #ifndef __MAX_H #define __MAX_H int max (int a, int b) ;#endif ---------------------------------------------------------- #include "max.h" int max (int a, int b) { return a > b ? a : b; } ---------------------------------------------------------- #include <stdio.h> #include "max.h" int main (void ) { int a = 0 , b = 0 ; int sum = 0 ; scanf ("%d-%d" , &a, &b); sum = max(a, b); printf ("sum = %d\n" , sum); return 0 ; } ---------------------------------------------------------- main : main.o max.o gcc -o main main.o max.o clean : rm -rf *.o main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #ifndef __SWAP_H #define __SWAP_H void swap (int *, int *) ;#endif ---------------------------------------------------------- #include "swap.h" void swap (int *a, int *b) { int tmp = 0 ; tmp = *a; *a = *b; *b = tmp; } ---------------------------------------------------------- #include <stdio.h> #include "swap.h" int main (void ) { int a = 0 , b = 0 ; scanf ("%d-%d" , &a, &b); printf ("a = %d b = %d\n" , a, b); swap(&a, &b); printf ("a = %d b = %d\n" , a, b); return 0 ; } ---------------------------------------------------------- # 注意:在makefile文件中 $ 就是用来引用变量的 # 注意:$@指的是引用上一条语句的 : 以左的内容 # 注意:$^指的是引用上一条语句的 : 以右的内容 main : main.o swap.o gcc -o $@ $^ #等价于 gcc -o main main.o swap.o clean : rm -rf *.o main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 #ifndef __INC_H #define __INC_H int arr[15 ][15 ];int x, y;int flag;void init (void ) ;void draw (void ) ;void print_infor (void ) ;void check (void ) ;int win (void ) ;#endif ---------------------------------------------------------- #include "inc.h" void init (void ) { int i = 0 , j = 0 ; for (i = 0 ; i < 15 ; i++) { for (j = 0 ; j < 15 ; j++) { arr[i][j] = 0 ; } } x = y = 0 ; flag = 1 ; } ---------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include "inc.h" void draw (void ) { int i = 0 , j = 0 ; system("clear" ); printf (" 1 2 3 4 5 6 7 8 9 A B C D E F\n" ); for (i = 0 ; i < 15 ; i++) { printf ("%X " , i + 1 ); for (j = 0 ; j < 15 ; j++) { switch (arr[i][j]) { case 0 : printf ("+ " ); break ; case 1 : printf ("O " ); break ; case 2 : printf ("X " ); break ; } } printf ("\n" ); } } ---------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include "inc.h" void print_infor (void ) { printf ("Player %d > " , flag); } #include <stdio.h> #include "inc.h" void check (void ) { if (x < 1 || x > 15 || y < 1 || y > 15 ) printf ("下出了棋盘边界,请重新下棋!\n" ); else if (arr[x - 1 ][y - 1 ] != 0 ) printf ("下到了重复位置,请重新下棋!\n" ); else { arr[x-1 ][y-1 ] = flag; flag ^= 3 ; } } ---------------------------------------------------------- #include "inc.h" int win (void ) { return 1 ; } ---------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include "inc.h" int main (int argc, char *argv[]) { init(); do { draw(); print_infor(); scanf ("%d-%d" , &x, &y); check(); }while (win()); return 0 ; } ---------------------------------------------------------- five : main.o init.o draw.o print.o check.o win.o gcc -o $@ $^ clean : rm -rf *.o five