01C语言基础(二)

Day07

笔记

指针和函数:

	栈 帧:
		当函数调用时,系统会在 stack 空间上申请一块内存区域,用来供函数调用,主要存放 形参 和 局部变量(定义在函数内部)。

		当函数调用结束,这块内存区域自动被释放(消失)。


	传值和传址:

		传值:函数调用期间,实参将自己的值,拷贝一份给形参。 

		传址:函数调用期间,实参将地址值,拷贝一份给形参。 【重点】

			(地址值 --》 在swap函数栈帧内部,修改了main函数栈帧内部的局部变量值)

	指针做函数参数:

		int swap2(int *a, int *b);

		int swap2(char *a, char *b);

		调用时,传有效的地址值。


	数组做函数参数:

		void BubbleSort(int arr[10]) == void BubbleSort(int arr[])  == void BubbleSort(int *arr) 

		传递不再是整个数组,而是数组的首地址(一个指针)。

		所以,当整型数组做函数参数时,我们通常在函数定义中,封装2个参数。一个表数组首地址,一个表元素个数。

	指针做函数返回值:

		int *test_func(int a, int b);

		指针做函数返回值,不能返回【局部变量的地址值】。


	数组做函数返回值:

		C语言,不允许!!!!  只能写成指针形式。


指针和字符串:

	1)
		char str1[] = {'h', 'i', ''};			变量,可读可写

		char str2[] = "hi";				变量,可读可写

		char *str3 = "hi";				常量,只读

			str3变量中,存储的是字符串常量“hi”中首个字符‘h’的地址值。


			str3[1] = 'H';	// 错误!!

		char *str4 = {'h', 'i', ''};  // 错误!!!

	2)
		当字符串(字符数组), 做函数参数时, 不需要提供2个参数。 因为每个字符串都有 ''。


	练习:比较两个字符串: strcmp();实现

		比较 str1 和 str2, 如果相同返回0, 不同则依次比较ASCII码,str1 > str2 返回1,否则返回-1

数组方式:

int mystrcmp(char *str1, char *str2)
{
	int i = 0;

	while (str1[i] == str2[i])   // *(str1+i) == *(str2+i)
	{
		if (str1[i] == '')
		{
			return 0;			// 2字符串一样。
		}
		i++;
	}
	return str1[i] > str2[i] ? 1 : -1;
}

指针方式:

int mystrcmp2(char *str1, char *str2)
{
	while (*str1 == *str2)   // *(str1+i) == *(str2+i)
	{
		if (*str1 == '')
		{
			return 0;			// 2字符串一样。
		}
		str1++;
		str2++;
	}
	return *str1 > *str2 ? 1 : -1;
}


	练习:字符串拷贝:

//数组版本
void mystrcpy(char *src, char *dst)
{
	int i = 0;
	while (src[i] != 0)  // src[i] == *(src+i)
	{
		dst[i] = src[i];
		i++;
	}
	dst[i] = '';
}

//指针版
void mystrcpy2(char *src, char *dst)
{
	while (*src != '')  // src[i] == *(src+i)
	{
		*dst = *src;
		src++;
		dst++;
	}
	*dst = '';
}

	练习:在字符串中查找字符出现的位置:

char *myStrch(char *str, char ch)
{
	while (*str)
	{
		if (*str == ch)
		{
			return str;
		}
		str++;
	}
	return NULL;
}
// hellowrld --- 'o'
char *myStrch2(char *str, char ch)
{
	int i = 0;
	while (str[i])
	{
		if (str[i] == ch)
		{
			return &str[i];  
		}
		i++;
	}
	return NULL;
}

	练 习:字符串去空格。

void str_no_space(char *src, char *dst)
{
	int i = 0;   // 遍历字符串src
	int j = 0;	 // 记录dst存储位置
	while (src[i] != 0)
	{
		if (src[i] != ' ')
		{
			dst[j] = src[i];
			j++;
		}
		i++;
	}
	dst[j] = '';
}
// 指针版
void str_no_space2(char *src, char *dst)
{
	while (*src != 0)
	{
		if (*src != ' ')
		{
			*dst = *src;
			dst++;
		}
		src++;
	}
	*dst = '';
}


带参数的main函数:

	无参main函数: 	int main(void) == int main()

	带参数的main函数: int main(int argc, char *argv[]) == int main(int argc, char **argv)

		参1:表示给main函数传递的参数的总个数。

		参2:是一个数组!数组的每一个元素都是字符串 char * 

	测试1: 
		命令行中的中,使用gcc编译生成 可执行文件,如: test.exe

		test.exe abc xyz zhangsan nichousha 

		-->

		argc --- 5
		test.exe -- argv[0]
		abc -- argv[1]
		xyz -- argv[2]
		zhangsan -- argv[3]
		nichousha -- argv[4]

	测试2:

		在VS中。项目名称上 --》右键--》属性--》调试--》命令行参数 --》将 test.exe abc xyz zhangsan nichousha 写入。

		-->

		argc --- 5
		test.exe -- argv[0]
		abc -- argv[1]
		xyz -- argv[2]
		zhangsan -- argv[3]
		nichousha -- argv[4]
			

str 中 substr 出现次数:

	strstr函数: 在 str中,找substr出现的位置。

	char *strstr(char *str, char *substr)   -- #include <string.h>

		参1: 原串

		参2: 子串

		返回值: 子串在原串中的位置。(地址值);

			 如果没有: NULL

实 现:
int str_times(char *str, char *substr)
{
	int count = 0;
	char *p = strstr(str, substr);  // "llollollo"

	while (p != NULL)
	{
		count++;
		p += strlen(substr);	// p = p+strlen(substr) --> "llollo"
		p = strstr(p, substr);	// 返回: "llo"
	}
	return count;
}



求非空字符串元素个数:


字符串逆置: str_inverse


判断字符串是回文:



字符串处理函数:


	字符串拷贝:


	字符串拼接:


	字符串比较:


	字符串格式化输入、输出:

		sprintf():

		sscanf():	

	字符串查找字符、子串:

		strchr()

		strrchr()

		strstr()

	字符串分割:

		strtok()

	atoi/atof/atol:

Code

  • 01-传值和传址.c
int swap(int, int);  // 函数声明
int swap2(int *, int *);

int main0101(void)
{
	int m = 23;
	int n = 57;

	printf("--before-- m = %d, n = %d
", m, n);
	// 函数调用
	//swap(m, n);  // m/n 实参

	swap2(&m, &n);

	printf("--after-- m = %d, n = %d
", m, n);

	system("pause");
	return EXIT_SUCCESS;
}

int swap2(int *a, int *b)	// 形参a、b, 需传地址值
{
	int tmp = 0;
	tmp = *a;
	*a = *b;
	*b = tmp;
	return 0;
}

// 函数定义
int swap(int a, int b)	// a/b 形参
{
	int tmp = 0;

	tmp = a;
	a = b;
	b = tmp;

	return 0;
}
  • 02-数组做函数参数.c
//void BubbleSort(int arr[])  // void BubbleSort(int *arr)

void BubbleSort(int *arr, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}


int main0202(void)
{
	int arr[] = {5, 89, 3, 22, 40, 31, 9, 22, 67, 28, 45, 78};

	printf("main: sizeof(arr) = %d
", sizeof(arr));

	int n = sizeof(arr) / sizeof(arr[0]);

	BubbleSort(arr, n);

	for (size_t i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("
");

	system("pause");
	return EXIT_SUCCESS;
}
  • 03-数组做函数参数测试.c
void test_func(int arr[])
{
	printf("size 2 = %u
", sizeof(arr));  // 整个数组大小

	printf("%d
", arr[0]);
}

int main0301(void)
{
	int arr[] = { 4, 5, 5, 6, 7 };

	printf("size 1 = %u
", sizeof(arr));  // 整个数组大小

	test_func(arr);

	system("pause");
	return EXIT_SUCCESS;
}
  • 04-指针做函数返回值.c
int m = 100;   // 全局变量 对应空间消失 ==> 程序结束。

int *test_func2(int a, int b)
{
	int p = 1234;  // 局部变量
	//return &m;

	return &p;
}

int main0401(void)
{
	int *ret = NULL;  // NULL == 0

	ret = test_func2(10, 20);

	printf("ret = %d
", *ret);

	system("pause");
	return EXIT_SUCCESS;
}
  • 05-指针和字符串.c
int main(void)
{
	char str1[] = "hello";		// {'h',, 'e', 'l', 'l', 'o', ''}
	char m[] = "hello";

	char *str2 = "hello";		// "hello" 是一个字符串常量, 不能修改。
	char *n = "hello";

	str1[0] = 'R';
	str2[0] = 'R';

	printf("str1 = %p
", str1);
	printf("m = %p
", m);

	printf("str2 = %p
", str2);
	printf("n = %p
", n);

	system("pause");
	return EXIT_SUCCESS;
}
  • 06-字符串比较.c
// str1 和 str2  == -->0  str1 > str2 --> 1, str1<str2 --> -1
int mystrcmp(char *str1, char *str2)
{
	int i = 0;

	while (str1[i] == str2[i])   // *(str1+i) == *(str2+i)
	{
		if (str1[i] == '')
		{
			return 0;			// 2字符串一样。
		}
		i++;
	}
	return str1[i] > str2[i] ? 1 : -1;
}

int mystrcmp2(char *str1, char *str2)
{
	while (*str1 == *str2)   // *(str1+i) == *(str2+i)
	{
		if (*str1 == '')
		{
			return 0;			// 2字符串一样。
		}
		str1++;
		str2++;
	}
	return *str1 > *str2 ? 1 : -1;
}

int main0601(void)
{
	char *str1 = "helloz";
	char *str2 = "helloz";

	//int ret = mystrcmp(str1, str2);
	int ret = mystrcmp2(str1, str2);

	if (ret == 0)
		printf("相同
");
	else if (ret == 1)
		printf("str1 > str2
");
	else if (ret == -1)
		printf("str1 < str2
");
	else
		printf("异常
");

	system("pause");
	return EXIT_SUCCESS;
}
  • 07-字符串拷贝.c
// src: 源  dst: 目标
//数组版本
void mystrcpy(char *src, char *dst)
{
	int i = 0;
	while (src[i] != 0)  // src[i] == *(src+i)
	{
		dst[i] = src[i];
		i++;
	}
	dst[i] = '';
}
//指针版
void mystrcpy2(char *src, char *dst)
{
	while (*src != '')  // src[i] == *(src+i)
	{
		*dst = *src;
		src++;
		dst++;
	}
	*dst = '';
}

int main0701(void)
{
	char *src = "helloworldfuoie11ll";

	char dst[100];

	mystrcpy2(src, dst);

	printf("dst = %s
", dst);

	system("pause");
	return EXIT_SUCCESS;
}
  • 08-在字符串中找字符.c
// hellowrld --- 'm'
char *myStrch(char *str, char ch)
{
	while (*str)
	{
		if (*str == ch)
		{
			return str;
		}
		str++;
	}
	return NULL;
}

// hellowrld --- 'o'
char *myStrch2(char *str, char ch)
{
	int i = 0;
	while (str[i])
	{
		if (str[i] == ch)
		{
			return &str[i];  
		}
		i++;
	}
	return NULL;
}

int main0801(void)
{
	char str[] = "hello world";
	char ch = ' ';

	char *ret = NULL; 

	ret = myStrch2(str, ch);

	printf("ret = %s
", ret);

	system("pause");
	return EXIT_SUCCESS;
}
  • 09-字符串去空格.c
// src : 有空格字符串, dst:没有空格的字符串
void str_no_space(char *src, char *dst)
{
	int i = 0;   // 遍历字符串src
	int j = 0;	 // 记录dst存储位置
	while (src[i] != 0)
	{
		if (src[i] != ' ')
		{
			dst[j] = src[i];
			j++;
		}
		i++;
	}
	dst[j] = '';
}
// 指针版
void str_no_space2(char *src, char *dst)
{
	while (*src != 0)
	{
		if (*src != ' ')
		{
			*dst = *src;
			dst++;
		}
		src++;
	}
	*dst = '';
}

int main0901(void)
{
	char str[] = "ni chou sha chou ni za di";
	char dst[100] = {0};

	str_no_space2(str, dst);

	printf("dst = %s
", dst);

	system("pause");
	return EXIT_SUCCESS;
}
  • 10-带参数的main.c
int main1001(int argc, char *argv[])
{
	int i;

	for (i = 0; i < argc; i++)
	{
		printf("argv[%d] = %s
", i, argv[i]);
	}

	system("pause");
	return EXIT_SUCCESS;
}
  • 11-字符串中找子串.c
//strstr函数测试
int main1101(void)
{
	char *ret = strstr("hellollollo", "llo");

	printf("ret = %s
", ret);

	system("pause");
	return EXIT_SUCCESS;
}


int str_times(char *str, char *substr)
{
	int count = 0;
	char *p = strstr(str, substr);  // "llollollo"

	while (p != NULL)
	{
		count++;
		p += strlen(substr);	// p = p+strlen(substr) --> "llollo"
		p = strstr(p, substr);	// 返回: "llo"
	}
	return count;
}
// 统计字符串中,子串出现的次数。
int main1102(void)
{
	char str[] = "helloabclloxyzllo";
	char substr[] = "llo";

	int ret = str_times(str, substr);

	printf("出现%d次
", ret);

	system("pause");
	return EXIT_SUCCESS;
}

Day08

笔记

求非空字符串元素个数:

	“ni chou sha chou ni za di”  

字符串逆置: str_inverse

	hello -- olleh 

void str_inserse(char *str)
{
	char *start = str;			// 记录首元素地址
	char *end = str + strlen(str) - 1;	// 记录最后一个元素地址。

	while (start < end)			// 首元素地址是否 < 最后一个元素地址
	{
		char tmp = *start;		// 三杯水 char 元素交换
		*start = *end;
		*end = tmp;
		start++;			// 首元素对应指针后移
		end--;				// 尾元素对应指针前移
	}
}

判断字符串是回文:

int str_abcbb(char *str)
{
	char *start = str;			// 记录首元素地址
	char *end = str + strlen(str) - 1;	// 记录最后一个元素地址。

	while (start < end)			// 首元素地址是否 < 最后一个元素地址
	{
		if (*start != *end)		// 判断字符是否一致。
		{
			return 0; 		// 0 表示非 回文
		}
		start++;
		end--;
	}
	return 1;				// 1 表示 回文
}


字符串处理函数:   #include <string.h>

	字符串拷贝: 

		strcpy: 

			将 src 的内容,拷贝给 dest。 返回 dest。 保证dest空间足够大。【不安全】

			char *strcpy(char *dest, const char *src);

			函数调用结束 返回值和 dest参数结果一致。

		strncpy:

			将 src 的内容,拷贝给 dest。只拷贝 n 个字节。 通常 n 与dest对应的空间一致。 

			默认 不添加 ‘’

			char *strncpy(char *dest, const char *src, size_t n);	

			特性: n > src: 只拷贝 src 的大小

			       n < src: 只拷贝 n 字节大小。 不添加 ‘’

	字符串拼接:

		strcat:

			将 src 的内容,拼接到 dest 后。 返回拼接后的字符串。	保证 dest 空间足够大。

			char *strcat(char *dest, const char *src);

		strncat:

			将 src 的前 n 个字符,拼接到 dest 后。 形成一个新的字符串。保证 dest 空间足够大。

			char *strncat(char *dest, const char *src, size_t n);

			函数调用结束 返回值和 dest 参数结果一致。


	字符串比较:	不能使用 > < >= <= == != 

		strcmp:

			比较s1和s2两个字符串,如果相等 返回0.如果不相等,进一步表 s1 和 s2 对应位 ASCII码值。

			s1 > s2 返回1

			s1 < s2 返回-1

			int strcmp(const char *s1, const char *s2);

		strncmp:

			int strncmp(const char *s1, const char *s2, size_t n);

			比较s1和s2两个字符串的前n个字符,

			如果相等 返回0。如果不相等,进一步表 s1 和 s2 对应位 ASCII码值。(不比字符串ASCII码的和)

			s1 > s2 返回1

			s1 < s2 返回-1
			


	字符串格式化输入、输出:

		sprintf():  s -- string

			int sprintf(char *str, const char *format, ...);

			对应printf,将原来写到屏幕的“格式化字符串”,写到 参数1 str中。

			printf("%d+%d=%d
", 10, 24, 10+24);

			---》 
			char str[100];

			sprintf(str, "%d+%d=%d
", 10, 24, 10+24);  格式串写入str数组中。

		
		sscanf():

			int sscanf(const char *str, const char *format, ...);

			对应scanf, 将原来从屏幕获取的“格式化字符串”, 从 参数1 str中 获取。

			scanf("%d+%d=%d", &a, &b, &c);

			---》

			char str[]= "10+24=45";

			sscanf(str, "%d+%d=%d", &a, &b, &c);  a --> 10, b --> 24, c --> 45
			

	字符串查找字符、子串:

		strchr():

			在字符串str中 找一个字符出现的位置。 返回字符在字符串中的地址。

			char *strchr(const char *s, int c);

			printf("%s
" strchr("hehehahahoho", 'a'));  --> "ahahoho"

		strrchr():

			自右向左,在字符串str中 找一个字符出现的位置。 返回字符在字符串中的地址。

			char *strrchr(const char *s, int c);

			printf("%s
" strrchr("hehehahahoho", 'a'));  --> "ahoho"

		strstr():

			在字符串str中,找子串substr第一次出现的位置。返回地址。

			char *strstr(const char *str, const char *substr);

			在字符串中找子串的位置。 

			printf("%s
" strrchr("hehehahahoho", "ho"));  --> "hoho"

			printf("%s
" strrchr("hehehahahoho", "xixi"));  --> NULL

scanf("%s", str);

scanf("%[^
]", str);

	字符串分割:

		strtok(): 按照既定的分割符,来拆分字符串。“www.baidu.com”  --> "wwwbaidu.com"

		char *strtok(char *str, const char *delim);

			参1: 待拆分字符串

			参2: 分割符组成的“分割串”

		返回:字符串拆分后的首地址。 “拆分”:将分割字符用 ''替换。

	特性:
		1)strtok拆分字符串是直接在 原串 上操作,所以要求参1必须,可读可写(char *str = "www.baidu.com" 不行!!!)

		2)第一次拆分,参1 传待拆分的原串。	第1+ 次拆分时,参1传 NULL.


	练习: 拆分 ".itcast.cn$This is a strtok$test"

		char str[] = "www.itcast.cn$This is a strtok$test";

		char *p = strtok(str, "$ .");

		while (p != NULL)
		{	
			p = strtok(NULL, " .$");
			printf("p = %s
", p);
		}

	atoi/atof/atol:
		
		使用这类函数进行转换,要求,原串必须是可转换的字符串。

		错误使用:"abc123" --> 0;	"12abc345" ---> 12;  "123xyz" -->123
 		
		atoi:字符串 转 整数。

		int atoi(const char *nptr);

		atof:字符串 转 浮点数

		atol:字符串 转 长整数

----------------------------------------------------------------------------------------------

局部变量:

	概念:定义在函数 内 部的变量。

	作用域:从定义位置开始,到包裹该变量的第一个右大括号结束。

全局变量:

	概念:定义在函数 外 部的变量。

	作用域:从定义位置开始,默认到本文件内部。 其他文件如果想使用,可以通过声明方式将作用域导出。


static全局变量:

	定义语法: 在全局变量定义之前添加 static 关键字。		static int a = 10;

	作用域:被限制在本文件内部,不允许通过声明导出到其他文件。


static局部变量:

	定义语法: 在局部变量定义之前添加 static 关键字。

	特性: 静态局部变量只定义一次。在全局位置。 通常用来做计数器。

	作用域:从定义位置开始,到包裹该变量的第一个右大括号结束。


全局函数:  函数

	定义语法: 函数原型 + 函数体
	

static函数:

	定义语法:static + 函数原型 + 函数体

	static 函数 只能在 本文件内部使用。 其他文件即使声明也无效。

生命周期:

	局部变量:从变量定义开始,函数调用完成。 --- 函数内部。

	全局变量:程序启动开始,程序终止结束。  --- 程序执行期间。

	static局部变量:程序启动开始,程序终止结束。  --- 程序执行期间。

	static全局变量:程序启动开始,程序终止结束。  --- 程序执行期间。

	全局函数:程序启动开始,程序终止结束。  --- 程序执行期间。

	static函数:程序启动开始,程序终止结束。  --- 程序执行期间。


内存4区模型:
	
	代码段:.text段。 程序源代码(二进制形式)。

	数据段:只读数据段 .rodata段。初始化数据段 .data段。 未初始化数据段 .bss 段。

	stack:栈。 在其之上开辟 栈帧。	windows 1M --- 10M	Linux: 8M --- 16M

	heap:堆。 给用户自定义数据提供空间。 约 1.3G+

	
开辟释放 heap 空间:

	void *malloc(size_t size);  申请 size 大小的空间

		返回实际申请到的内存空间首地址。 【我们通常拿来当数组用】

	void free(void *ptr);	释放申请的空间

		参数: malloc返回的地址值。


使用 heap 空间:

	空间时连续。 当成数组使用。

	free后的空间,不会立即失效。 通常将free后的 地址置为NULL。

	free 地址必须 是 malloc申请地址。否则出错。

	如果malloc之后的地址一定会变化,那么使用临时变量tmp 保存。


二级指针对应的 heap空间:

	申请外层指针: char **p = (char **)malloc(sizeof(char *) * 5);

	申请内层指针: for(i = 0; i < 5; i++)
			{
				p[i] = (char *)malloc(sizeof(char) *10);
			}

	使用: 不能修改 p 的值。

		 for(i = 0; i < 5; i++)
		{
			strcpy(p[i], "helloheap");
		}

	释放内层:

		 for(i = 0; i < 5; i++)
		{
			free(p[i]);
		}

	释放外层:

		free(p);



栈的存储特性:

	局部变量:

	形参:	

内存操作函数:

	memset:

	memmove:

	memcmp:

内存常见问题:

	1) 申请 0 字节空间

	2)free空指针

	3)越界访问

	4)free ++后的地址

	5)子函数malloc空间,main中用

Code

  • 01-非空字符串元素个数.c
int no_space_str(char *str)
{
	int count = 0;

	char *p = str;

	while (*p)
	{
		if (*p != ' ')
		{
			count++;
		}
		p++;
	}
	return count;
}

int main0101(void)
{
	char str[] = "ni chou sha";

	int ret = no_space_str(str);

	printf("%d
", ret);

	system("pause");
	return EXIT_SUCCESS;
}
  • 02-字符串逆序.c
// o e l l h

// 字符串逆序
void str_inserse(char *str)
{
	//int i, j;  // str[i] *(str+i)
	char *start = str;					// 记录首元素地址
	char *end = str + strlen(str) - 1;	// 记录最后一个元素地址。

	while (start < end)			// 首元素地址是否 < 最后一个元素地址
	{
		char tmp = *start;		// 三杯水 char 元素交换
		*start = *end;
		*end = tmp;
		start++;			// 首元素对应指针后移
		end--;				// 尾元素对应指针前移
	}
}
// 判断回文字符串   abcddpba
int str_abcbb(char *str)
{
	char *start = str;		// 记录首元素地址
	char *end = str + strlen(str) - 1;// 记录最后一个元素地址。

	while (start < end)		// 首元素地址是否 < 最后一个元素地址
	{
		if (*start != *end)	// 判断字符是否一致。
		{
			return 0; // 0 表示非 回文
		}
		start++;
		end--;
	}
	return 1;		// 1 表示 回文
}

int main0201(void)
{
	char str[] = "this is a test";

	str_inserse(str);

	printf("str=%s
 ---------------------
", str);

	char s2[] = "abcmncba";

	int ret = str_abcbb(s2);

	if (ret == 0)
		printf("不是回文
");
	else if (ret == 1)
		printf("是回文
");

	system("pause");
	return EXIT_SUCCESS;
}
  • 03-字符串拷贝strcpy和strncpy.c
// strcpy
int main0301(void)
{
	char src[] = "abc efg  zhansan wangwu ";
	char dest[10] = {0};

	char *p = strcpy(dest, src); ;// 字符串src 拷贝给dest

	printf("p= %s
", p);
	printf("dest = %s
", dest);

	system("pause");
	return EXIT_SUCCESS;
}
// strncpy
int main0302(void)
{
	char src[] = "hello world";
	char dest[100] = { 0 };

	char *p = strncpy(dest, src, 100); ;// 字符串src 拷贝给dest
	for (size_t i = 0; i < 10; i++)
	{
		printf("%c
", p[i]);
	}

	printf("p= %s
", p);
	printf("dest = %s
", dest);

	system("pause");
	return EXIT_SUCCESS;
}
  • 04-字符串拼接 strcat和strncat.c
int main0401(void)
{
	char src[] = "world";
	char dest[] = "hello";

	char *p = strcat(dest, src);

	printf("p = %s
", p);
	printf("dest = %s
", dest);

	system("pause");
	return EXIT_SUCCESS;
}

int main0402(void)
{
	char src[] = "world";
	char dest[6] = "hello";

	char *p = strncat(dest, src, 3);

	printf("p = %s
", p);
	printf("dest = %s
", dest);

	printf("%d
", strlen(dest));

	system("pause");
	return EXIT_SUCCESS;
}
  • 05-strcmp和strncmp字符串比较.c
int main0501(void)
{
	char *str1 = "helloworld";
	char *str2 = "helloz";

	printf("ret = %d
", strcmp(str1, str2));

	system("pause");
	return EXIT_SUCCESS;
}

int main0502(void)
{
	char *str1 = "helloworld";
	char *str2 = "helloz";

	printf("ret = %d
", strncmp(str1, str2, 8));

	system("pause");
	return EXIT_SUCCESS;
}
  • 06-格式化读入和写出 sprintf、sscanf.c
// sprintf
int main0601(void)
{
	char buf[100] = {0}; //buffer  string str  source src
	 
	sprintf(buf, "%d%c%d=%d
", 10, '+', 34, 10+34);

	puts(buf);

	system("pause");
	return EXIT_SUCCESS;
}

// sscanf
int main0602(void)
{
	char buf[100] = { 0 }; //buffer  string str  source src

	int a, b, c;

	char str[] = "13+56=89";

	sscanf(str, "%d+%d=%d", &a, &b, &c);

	printf("a = %d
", a);
	printf("b = %d
", b);
	printf("c = %d
", c);

	system("pause");
	return EXIT_SUCCESS;
}
  • 07-字符串分割strtok.c
int main0701(void)
{
	char str[] = "www.itcast.cn.com.net";  // www itcast cn

	char *p = strtok(str, ".");  // 第一次拆分,参1 传 待拆分的原串。

	while (p != NULL)
	{
		p = strtok(NULL, ".");  // 第1+ 次拆分是,参1传 NULL.

		printf("%s
", p);
	}
	system("pause");
	return EXIT_SUCCESS;
}


int main0702(void)
{
	char str[] = "www.itcast.cn$This is a strtok$test";

	char *p = strtok(str, "$ .");

	while (p != NULL)
	{
		p = strtok(NULL, ". $");
		printf("p = %s
", p);
	}

	system("pause");
	return EXIT_SUCCESS;
}
  • 08-atoi_atof_atol.c
static int a = 1034673;

void test1(void)
{
	static int b = 0;

	printf("b = %d
", b++);
}


int main0801(void)
{
	char str[] = "abc345";
	int num = atoi(str);
	printf("num = %d
", num);

	char str1[] = "     -10";
	int num1 = atoi(str1);
	printf("num1 = %d
", num1);

	char str2[] = "0.123f";
	double num2 = atof(str2);
	printf("num2 = %.2lf
", num2);

	char str3[] = "123L";
	long num3 = atol(str3);
	printf("num3 = %ld
", num3);

	system("pause");
	return EXIT_SUCCESS;
}
  • 09-局部变量.c
void test1(void);  // 全局函数声明

int m = 4456;

int main0901(void)
{
	int i = 10903;

	for (size_t j = 0; j < 10; j++)
	{
		printf("j = %d
", j);
		//test1();
	}	
	printf("i 2 = %d
", i);

	system("pause");
	return EXIT_SUCCESS;
}
  • 10-申请堆空间.c
int main1001(void)
{
	//int arr[1000000] = {10, 20, 40};
	int *p = (int *)malloc(sizeof(int) * 10);
	//char *str = (char *)malloc(sizeof(char)*10);
	if (p == NULL)
	{
		printf("malloc error
");
		return -1;
	}
	char *tmp = p;  // 记录malloc返回的地址值。用于free

	// 写数据到 malloc 空间。
	for (size_t i = 0; i < 10; i++)
	{
		p[i] = i + 10;
	}
	// 读出malloc空间中的数据
	//for (size_t i = 0; i < 10; i++)
	//{
	//	printf("%d ", *(p+i));
	//}
	for (size_t i = 0; i < 10; i++)
	{
		printf("%d ", *p);
		p++;
	}

	// 释放申请的内存。
	free(tmp);
	p = NULL;

	system("pause");
	return EXIT_SUCCESS;
}
  • 11-二级指针malloc空间.c
int main(void)
{
	int **p = malloc(sizeof(int *) * 3);	// int **p ==> int *p[10]; ==> [ int *, int *, int * ]

	for (size_t i = 0; i < 3; i++)
	{
		p[i] = malloc(sizeof(int) * 5);
	}

	// 使用空间 -- 写
	for (size_t i = 0; i < 3; i++)
	{
		for (size_t j = 0; j < 5; j++)
		{
			p[i][j] = i + j;
		}
	}

	// 使用空间 -- 读
	for (size_t i = 0; i < 3; i++)
	{
		for (size_t j = 0; j < 5; j++)
		{
			printf("%d ", *(*(p+i)+j));  // p[i][j] == *(p+i)[j] == *(*(p+i)+j)
		}
		printf("
");
	}

	// 释放空间时,应先释放内层空间。
	for (size_t i = 0; i < 3; i++)
	{
		free(p[i]); //*(p+i)
		p[i] = NULL;
	}
	// 释放外层空间
	free(p);
	p = NULL;

	system("pause");
	return EXIT_SUCCESS;
}

Day09

Code

  • 01-结构体定义及初始化.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct student {
	int age;
	char name[10];
	int num;
}obj1, obj2;

struct {
	int age;
	char name[10];
	int num;
}obj, *obj4, obj5 = { 100, "abc", 666 };


int main0102(void)
{
	obj4 = &obj5;
	printf("%x
", obj5.name[0]);

	(*obj4).age = 200;//obj4->age = 200;
	strcpy((*obj4).name,"200");
	(*obj4).num = 200;

	printf("age=%d, name=%s, num=%d
", obj4->age, obj4->name, obj4->num);

	printf("age=%d, |%s|, num=%d
", (&obj5)->age, (&obj5)->name, (&obj5)->num);

	system("pause");
	return EXIT_SUCCESS;
}

int main0101(void)
{
	struct student stu = { 18, "afei", 97 };
	struct student stu2;

	stu2.age = 17;
	strcpy(stu2.name, "andy");//stu2.name = "andy";
	stu2.num = 99;

	printf("age = %d, name=%s, num= %d
", stu2.age, stu2.name, stu2.num);
	printf("age = %d, name=%s, num= %d
", stu.age, stu.name, stu.num);

	system("pause");
	return EXIT_SUCCESS;
}
  • 02-结构体数组.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct student {
	int age;
	char name[10];
	int num;
};

int main02(void)
{
	struct student arr[5] = { 10, "andy", 10 ,11, "lucy", 11 ,12, "lily", 12 ,13, "mike", 13 ,14, "marry", 14 };

	int n = sizeof(arr) / sizeof(arr[0]);
	int sum = 0;

	for (size_t i = 0; i < n; i++)
	{
		sum += arr[i].age;
	}
	printf("avg age = %d
", sum / n);

	system("pause");
	return EXIT_SUCCESS;
}


int main0201(void)
{
	struct student arr[5] = {
		{ 10, "andy", 10 },
		{ 11, "lucy", 11 },
		{ 12, "lily", 12 },
		{ 13, "mike", 13 },
		{ 14, "marry", 14 }
	};

	int n = sizeof(arr) / sizeof(arr[0]);
	for (size_t i = 0; i < n; i++)
	{
		printf("age=%d, name=%s, num=%d
", arr[i].age, arr[i].name, arr[i].num);
	}
	printf("
");

	system("pause");
	return EXIT_SUCCESS;
}

int main0203(void)
{
	struct student arr2[5] = {
		10, "andy", 10 ,
		11, "lucy", 11 ,
		12, "lily", 12 ,
		13, "mike", 13 ,
		14, "marry", 14 
	};

	struct student arr[5] = {10, "andy", 10 ,11, "lucy", 11 ,12, "lily", 12 ,13, "mike", 13 ,14, "marry", 14};

	int n = sizeof(arr) / sizeof(arr[0]);

	for (size_t i = 0; i < n; i++)
	{
		printf("age=%d, name=%s, num=%d
", arr[i].age, arr[i].name, arr[i].num);
	}
	printf("
");

	system("pause");
	return EXIT_SUCCESS;
}

int main0202(void)
{
	struct student arr[5];

	arr[0].age = 19;
	strcpy(arr[0].name, "1111");
	arr[0].num = 19;

	(*(arr+1)).age = 191;
	strcpy((*(arr + 1)).name, "2222");
	(*(arr + 1)).num = 192;

	(arr + 2)->age = 193;
	strcpy((arr + 2)->name, "333");
	(arr + 2)->num = 192;

	struct student *p = arr;

	(*(p + 3)).age = 194;
	strcpy((*(p + 3)).name, "444");
	(*(p + 3)).num = 192;

	(p + 4)->age = 196;
	strcpy((p + 4)->name, "444");
	(p + 4)->num = 192;

	int n = sizeof(arr) / sizeof(arr[0]);

	for (size_t i = 0; i < n; i++)
	{
		printf("age=%d, name=%s, num=%d
", arr[i].age, arr[i].name, arr[i].num);
	}
	printf("
");

	system("pause");
	return EXIT_SUCCESS;
}
  • 03-结构体嵌套.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct person {
	int age;
	char name[10];
};

struct student {
	struct person man;
	int score;
};

int main0302(void)
{
	struct student stu = { 18, 21, "BBB" };

	printf("age = %d
", (&stu)->man.age);
	printf("name = %s
", (&stu)->man.name);
	printf("score = %d
", (&stu)->score);


	system("pause");
	return EXIT_SUCCESS;
}

int main0301(void)
{
	struct student stu;

	stu.man.age = 16;
	strcpy(stu.man.name, "zhangsan");
	stu.score = 61;

	printf("age = %d
", (&stu)->man.age);
	printf("name = %s
", (&stu)->man.name);
	printf("score = %d
", (&stu)->score);

	struct student *p = &stu;

	p->man.age = 18;

	strcpy(p->man.name, "AAA");
	p->score = 100;

	printf("age = %d
", (*p).man.age);
	printf("name = %s
", (&(p->man))->name);
	printf("score = %d
", p->score);

	system("pause");
	return EXIT_SUCCESS;
}
  • 04-结构体做函数参数.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct student
{
	int age;
	char name[10];
	int score;
	short num;
};

void func(struct student stu)
{
	printf("func stu: age = %d, name= %s
", stu.age, stu.name);
	printf("func stu: score = %d, num= %d
", stu.score, stu.num);

	stu.age = 100;
	strcpy(stu.name, "super man");
	stu.num = 666;
	stu.score = 101;

	printf("2 func stu: age = %d, name= %s
", stu.age, stu.name);
	printf("2 func stu: score = %d, num= %d
", stu.score, stu.num);
}

void func2(struct student *stu)
{
	printf("func stu: age = %d, name= %s
", stu->age, stu->name);
	printf("func stu: score = %d, num= %d
", stu->score, stu->num);

	stu->age = 100;
	strcpy(stu->name, "super man");
	stu->num = 666;
	stu->score = 101;

	printf("2 func stu: age = %d, name= %s
", stu->age, stu->name);
	printf("2 func stu: score = %d, num= %d
", stu->score, stu->num);
}

struct student func3(struct student stu)
{
	printf("func stu: age = %d, name= %s
", stu.age, stu.name);
	printf("func stu: score = %d, num= %d
", stu.score, stu.num);

	stu.age = 100;
	strcpy(stu.name, "super man");
	stu.num = 666;
	stu.score = 101;

	printf("2 func stu: age = %d, name= %s
", stu.age, stu.name);
	printf("2 func stu: score = %d, num= %d
", stu.score, stu.num);

	return stu;
}

int main0401(void)
{
	struct student stu1 = {15, "ABC", 67, 99};
	struct student stu2 = stu1;

	//func(stu2);		// 实参 给 形参 赋值
	//func2(&stu2);

	stu2 = func3(stu2);

	printf("stu2: age = %d, name= %s
", stu2.age, stu2.name);
	printf("stu2: score = %d, num= %d
", stu2.score, stu2.num);

	system("pause");
	return EXIT_SUCCESS;
}
  • 05-含有指针成员的结构体.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct student {
	int age;
	char *name;  // char name[10];  // 栈
	int num;
};

void init_struct(struct student **p)
{
	*p = malloc(sizeof(struct student));	// 先申请外层
	if (*p == NULL) {
		printf("malloc error");
		return ;
	}
	(*p)->age = 10;
	(*p)->name = malloc(sizeof(char)*10);	// 再申请内层
	strcpy((*p)->name, "hello");
	(*p)->num = 100;
}

int main0503(void)
{
	struct student *p = NULL;
	p = malloc(sizeof(struct student));		// 先申请外层空间

	p->age = 100;
	p->name = malloc(sizeof(char)*10);		// 再申请内层空间
	strcpy(p->name, "world");
	p->num = 20;

	printf("age = %d, name=%s, num = %d
", p->age, p->name, p->num);

	free(p->name);  // 先释放内层
	free(p);		// 再释放外层

	system("pause");
	return EXIT_SUCCESS;
}

int main0502(void)
{
	struct student *p = NULL;

	init_struct(&p);
	printf("age = %d, name=%s, num = %d
", p->age, p->name, p->num);

	free(p->name);  // 先释放内层
	free(p);		// 再释放外层

	system("pause");
	return EXIT_SUCCESS;
}

int main0501(void)
{
	struct student stu;
	stu.age = 19;

	stu.name = malloc(sizeof(char) * 10);  // 堆

	strcpy(stu.name, "andy");  // stu.name  是 野指针。

	stu.num = 10;

	printf("age = %d, name= %s, num= %d
", stu.age, stu.name, stu.num);

	free(stu.name);
	stu.name = NULL;

	system("pause");
	return EXIT_SUCCESS;
}
  • 06-结构体数组作为函数参数.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

struct student {
	int age;
	char *name;  // char name[10];  // ջ
	int num;
};

//void init_arr(struct student stu[5])
//void init_arr(struct student stu[])
void init_arr(struct student *stu, int n)
{
	for (size_t i = 0; i < n; i++)
	{
		stu[i].age = i + 10;
		stu[i].name = malloc(10);
		strcpy(stu[i].name, "ABC");
		stu[i].num = i * 10;
	}
}

void print_arr(struct student *stu, int n)
{
	for (size_t i = 0; i < n; i++)
	{
		printf("age = %d
", stu[i].age);
		printf("name = %s
", stu[i].name);
		printf("num = %d
", stu[i].num);
	}
}

int main0601(void)
{
	struct student stu[5];

	int n = sizeof(stu) / sizeof(stu[0]);

	init_arr(stu, n);
	print_arr(stu, n);

	for (size_t i = 0; i < n; i++)
	{
		free(stu[i].name);
	}

	system("pause");
	return EXIT_SUCCESS;
}
  • 07-联合体.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

union test {
	char a;
	short b;
	int c;
	char str[13];
};

int main0701(void)
{
	union test t1;

	t1.c = 0x87654321;

	printf("&t1 = %p
", &t1);
	printf("&t1.a = %p
", &(t1.a));
	printf("&t1.b = %p
", &(t1.b));
	printf("&t1.c = %p
", &(t1.c));

	printf("a = %x
", t1.a);
	printf("b = %x
", t1.b);
	printf("c = %x
", t1.c);

	t1.b = 0x3A;

	printf("----------------
a = %x
", t1.a);
	printf("b = %x
", t1.b);
	printf("c = %x
", t1.c);

	printf("sizeof(t1) = %u
", sizeof(t1));

	system("pause");
	return EXIT_SUCCESS;
}
  • 08-枚举.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

enum color { red, black, blue = 10, yellow, pink, green };

int main08(void)
{
	int flg = yellow;

	if (flg == 3)
		printf("flg = yellow
");

	system("pause");
	return EXIT_SUCCESS;
}
  • 09-typedef.c
typedef long long int32;

typedef struct student {
	int32 a;
	int32 b;
	int32 c;
	int32 d;
	int32 e;
	int32 f;
}stu_t;		// 给 struct student 类型起了一个别名: stu_t;

int main09(void)
{
	struct student stu;
	stu_t s1;

	s1.a = 10;
	s1.b = 20;

	system("pause");
	return EXIT_SUCCESS;
}

Day10

笔记

共用体和联合体:

	union test {

		char ch;

		short sh;

		int var;
	};

	联合体,内部所有成员变量地址一致。等同于整个联合体的地址。

		联合体的大小,是内部成员变量中,最大的那个成员变量的大小。(对齐)

		修改其中任意一个成员变量的值,其他成员变量会随之修改。

枚  举:

	enum  color { 枚举常量 };

	enum  color { red, green, blue, black, pink, yellow };

		 枚举常量: 是整型常量。不能是浮点数。可以是负值。 默认初值从 0 开始,后续常量较前一个常量 +1.

			   可以给任意一个常量赋任意初值。后续常量较前一个常量 +1

-----------------------

读写文件与printf、scanf关联

	printf -- 屏幕 -- 标准输出

	scanf -- 键盘 -- 标准输入

	perror -- 屏幕 -- 标准错误

系统文件:

	标准输入 -- stdin -- 0

	标准输出 -- stdout -- 1

	标准错误 -- stderr -- 2

	应用程序启动时,自动被打开,程序执行结束时,自动被关闭。 ---- 隐式回收。

	1s = 1000ms 

	1ms = 1000us

	1us == 1000ns

文件指针和普通指针区别:

	FILE *fp = NULL;

	借助文件操作函数来改变 fp 为空、野指针的状况。	fopen();  --> 相当于 fp = malloc();

	操作文件, 使用文件读写函数来完成。 fputc、fgetc、fputs、fgets、fread、fwrite
	
文件分类:

	设备文件:

		屏幕、键盘、磁盘、网卡、声卡、显卡、扬声器...

	磁盘文件:

		文本文件: 	ASCII

		二进制文件:	0101 二进制编码

文件操作一般步骤:

	1. 打开文件 fopen()  --》 FILE *fp;

	2. 读写文件 fputc、fgetc、fputs、fgets、fread、fwrite

	3. 关闭文件 fclose()  


打开、关闭文件函数:

	FILE * fopen(const char * filename, const char * mode);

		参1:待打开文件的文件名(访问路径)

		参2:文件打开权限:

			"r": 只读方式打开文件, 文件不存在,报错。存在,以只读方式打开。

			"w": 只写方式打开文件, 文件不存在,创建一个空文件。文件如果存在,清空并打开。

			"w+":读、写方式打开文件,文件不存在,创建一个空文件。文件如果存在,清空并打开。

			"r+":读、写方式打开文件, 文件不存在,报错。存在,以读写方式打开。

			"a": 以追加的方式打开文件。

			"b": 操作的文件是一个二进制文件(Windows)

		返回值:成功:返回打开文件的文件指针

			失败:NULL


	int fclose(FILE * stream);

		参1:打开文件的fp(fopen的返回值)

		返回值:成功 :0, 失败: -1;

文件访问路径:

	绝对路径:

		从系统磁盘的 根盘符开始,找到待访问的文件路径

		Windows书写方法:

			1)C:\Users\afei\Desktop\06-文件分类.avi

			2)C:/Users/afei/Desktop/06-文件分类.avi  --- 也使用于Linux。

	相对路径:

		1)如果在VS环境下,编译执行(Ctrl+F5),文件相对路径是指相对于 day10.vcxproj 所在目录位置。

		2)如果是双击 xxx.exe 文件执行,文件的相对路径是相对于 xxx.exe 所在目录位置。 

		
按字符写文件 fputc:

	int fputc(int ch, FILE * stream);

		参1:待写入的 字符

		参2:打开文件的fp(fopen的返回值)

		返回值: 成功: 写入文件中的字符对应的ASCII码

			 失败: -1


	练习:写26个英文字符到文件中。


按字符读文件 fgetc

	int fgetc(FILE * stream);

		参1:待读取的文件fp(fopen的返回值)

		返回值: 成功:读到的字符对应的ASCII码

			 失败: -1

	文本文件的结束标记: EOF ---》 -1 
	
	
feof()函数:

	int feof(FILE * stream);

		参1: fopen的返回值

		返回值: 到达文件结尾--》非0【真】
				
			 没到达文件结尾--》0【假】

	作用:	
		用来判断到达文件结尾。 既可以判断文本文件。也可以判断 二进制文件。

	特性:

		要想使用feof()检测文件结束标记,必须在该函数调用之前,使用读文件函数。

		feof()调用之前,必须有读文件函数调用。

fgets()函数:
	
	获取一个字符串, 以
作为结束标记。自动添加 . 空间足够大 读
, 空间不足舍弃
, 必须有。

	char * fgets(char * str, int size, FILE * stream);

		char buf[10];  	hello --> hello


		返回值: 成功: 读到的字符串

			 失败: NULL

fputs()函数:

	写出一个字符串,如果字符串中没有
, 不会写
。

	int fputs(const char * str, FILE * stream);

		返回值: 成功: 0

			 失败: -1


练习: 获取用户键盘输入,写入文件。

	假定:用户写入“:wq”终止接收用户输入,将之前的数据保存成一个文件。

	FILE *fp = fopen("test07.txt", "w");
	if (fp == NULL)
	{
		perror("fopen error");
		return -1;
	}
	char buf[4096] = {0};

	while (1)
	{
		fgets(buf, 4096, stdin);
		if (strcmp(buf, ":wq
") == 0)	 // 实际 fgets 读到的是“:wq
”
		{
			break;
		}
		fputs(buf, fp);
	}

	fclose(fp);


练习: 文件版四则运算:


	1. 封装 write_file 函数,将4则运算表达式写入。

		FILE * fp = fopen("w");

		fputs("10/4=
", fp);

		fputs("10+4=
", fp);
		....

		fputs("10*4=
", fp);

	2. 封装 read_file 函数, 将4则运算表达式读出,拆分,运算,写回。

		1) 读出:

			FILE * fp = fopen("r");

			while (1) {

				fgets(buf, sizeof(buf), fp);	// buf中存储的 4则运算表达式
			}

		2) 拆分:

			sscanf(buf, "%d%c%c=
", &a, &ch, &b);	// 得到运算数, 运算符

		3) 根据运算符,得到运算结果

			switch(ch) {

				case '+':
					a+b;
			}

		4) 拼接 结果到  运算式 上

			char result[1024];

			sprintf(reuslt, "%d%c%d=%d
", a, ch, b, a+b);		// reuslt 中包含带有结果的 运算式。

		5)将 多个带有结果的运算 拼接成一个字符串。

			char sum_ses[4096];	// 存总的字符串  -- "10/2=5
10*3=30
4+3=7
8-6=2
"

			strcat(sum_ses,reuslt);  // 在while中循环拼接

		6) 重新打开文件, 清空原有 4则运算表达式

			fclose(fp);

			fp = fopen("w");

		7) 将 拼接成一个字符串。写入到空的文件中

			fputs(sum_res);

			

10/2=	fgets(buf, 4096, 文件fp) --->"10/2=
" --> 10   /   2   sscanf(buf, "%d%c%d=
", &a, &c, &b);  -> a=10, b=2, c='/'
10*3=
4+3=
8-6=
		switch (c) {

			case '/':

				a / b;
				break;

			case '+':
				a + b;

				break;

			....
		}

		fopen("", "w");

		char result[];   sprintf()/strcat()  --> "10/2=5
10*3=30
4+3=7
8-6=2
"  --> fputs(result, fp)
=====>

10/2=5
10*3=30
4+3=7
8-6=2

Code

  • 01-联合体和枚举.c
typedef union test {
	char ch;
	short sh;
	int a;
}test_t;

int main0101(void)
{
	test_t obj;	

	obj.a = 0x87654321;

	printf("&obj    = %p
", &obj);
	printf("&obj.ch = %p
", &obj.ch);
	printf("&obj.sh = %p
", &obj.sh);
	printf("&obj.a  = %p
", &obj.a);

	printf("sizeof(test_t) = %u
", sizeof(test_t));

	printf("a  = 0x%x
", obj.a);
	printf("sh = 0x%x
", obj.sh);
	printf("ch = 0x%x
", obj.ch);

	obj.ch = 0xFF;

	printf("a  = 0x%x
", obj.a);
	printf("sh = 0x%x
", obj.sh);
	printf("ch = 0x%x
", obj.ch);

	system("pause");
	return EXIT_SUCCESS;
}

enum  color { red, green = -5, blue, black, pink = 18, yellow };

int main0102(void)
{
	int flg = 2;

	// ......

	if (flg == blue)
	{
		printf("blue is 2
");
	}
	else
	{
		printf("blue is not 2, blue = %d
", blue);
	}	
	printf("yellow = %d
", yellow);

	system("pause");
	return EXIT_SUCCESS;
}
  • 02-系统文件.c
int main0201(void)
{
	//fclose(stdout);

	printf("hello file
");

	system("pause");
	return EXIT_SUCCESS;
}
  • 03-文件的打开和关闭.c
int main0301(void)
{
	FILE *fp = NULL;

	fp = fopen("test2.txt", "w");
	if (fp == NULL)
	{
		perror("fopen error");  //printf("fopen error
");  :xxxxxxx
		getchar();
		return -1;
	}

	fclose(fp);
	printf("------------finish
");

	system("pause");
	return EXIT_SUCCESS;
}
  • 04-fputc.c
int main0401(void)
{
	char *filename = "test04.txt";

	FILE *fp = fopen(filename, "w");
	if (fp == NULL)
	{
		perror("fopen error");
		return -1;
	}

	int ret = fputc('A', fp);

	printf("ret = %d
", ret);

	fclose(fp);
	printf("---------------finish
");

	system("pause");
	return EXIT_SUCCESS;
}

int main0402(void)
{
	char *filename = "test04.txt";
	int ret = 0;

	FILE *fp = fopen(filename, "w");
	if (fp == NULL)
	{
		perror("fopen error");
		return -1;
	}
	char ch = 'a';

	while (ch <= 'z')
	{
		ret = fputc(ch, fp);
		if (ret == -1)
		{
			perror("fputc eror");
			return -1;
		}
		ch++;
	}

	system("pause");
	return EXIT_SUCCESS;
}


int main0403(void)
{
	char *buf = "abcdefghijklmnopqrstuvwxyz";

	char *filename = "test04.txt";
	int ret = 0;

	FILE *fp = fopen(filename, "w");
	if (fp == NULL)
	{
		perror("fopen error");
		return -1;
	}
	int n = strlen(buf);
	for (size_t i = 0; i < n; i++)
	{
		ret = fputc(buf[i], fp);
		if (ret == -1)
		{
			perror("fputc eror");
			return -1;
		}
	}
	fclose(fp);

	system("pause");
	return EXIT_SUCCESS;
}
  • 05-fgetc.c
void write_file()
{
	FILE *fp = fopen("05test.txt", "w");
	if (fp == NULL)
	{
		perror("fopen error");
		return ;
	}

	fputc('a', fp);
	fputc('b', fp);
	fputc('c', fp);
	fputc('d', fp);

	fclose(fp);
}

void read_file()
{
	char ch = 0;

	FILE *fp = fopen("05test.txt", "r");
	if (fp == NULL)
	{
		perror("fopen error");
		return;
	}

	while (1)
	{
		ch = fgetc(fp);	
		if (ch == EOF)
		{
			break;
		}
		printf("%d
", ch);
	}

	fclose(fp);
}

int main0501(void)
{
	//write_file();
	read_file();

	system("pause");
	return EXIT_SUCCESS;
}
  • 06-feof函数.c
void read_file06()
{
	char ch = 0;

	FILE *fp = fopen("06test.txt", "r");
	if (fp == NULL)
	{
		perror("fopen error");
		return;
	}

	while (1)
	{
		ch = fgetc(fp);

		if (feof(fp))
		{
			break;
		}
		printf("%d
", ch);
	}

	fclose(fp);
}

void test_feof()
{
	FILE *fp = fopen("06test.txt", "r");
	if (fp == NULL)
	{
		perror("fopen error");
		return ;
	}
	while (1)
	{
		printf("没有到达文件结尾
");
		fgetc(fp);				// 一次读一个字符,读到字符直接丢弃。
		if (feof(fp))
		{
			break;
		}
	}
	fclose(fp);
}
void write_file06()
{
	FILE *fp = fopen("06test.txt", "w");
	if (fp == NULL)
	{
		perror("fopen error");
		return;
	}
	fputc('a', fp);
	fputc('b', fp);
	fputc(-1, fp);
	fputc('c', fp);
	fputc('d', fp);
	fputc('
', fp);

	fclose(fp);
}

int main0601(void)
{
	//write_file06();
	//read_file06();
	test_feof();

	system("pause");
	return EXIT_SUCCESS;
}
  • 07-fgets和fputs.c
int main0701(void)
{
	FILE *fp = fopen("test07.txt", "w");
	if (fp == NULL)
	{
		perror("fopen error");
		return -1;
	}
	char buf[4096] = {0};

	while (1)
	{
		fgets(buf, 4096, stdin);
		if (strcmp(buf, ":wq
") == 0)
		{
			break;
		}
		fputs(buf, fp);
	}

	fclose(fp);

	system("pause");
	return EXIT_SUCCESS;
}
  • 08-文件版4则运算.c
void write_file08()
{
	FILE *fp = fopen("test08.txt", "w");
	if (fp == NULL)
	{
		perror("fopen error");
		return;
	}

	fputs("10/2=
", fp);
	fputs("10*3=
", fp);
	fputs("4-2=
", fp);
	fputs("10+2=
", fp);

	fclose(fp);
}

int calc(char ch, int a, int b)
{	
	switch (ch)
	{
	case '/':
		return a / b;
		
	case '+':
		return a + b;
		
	case '-':
		return a - b;
		
	case '*':
		return a *b;	
	default:
		break;
	}
}

void read_file08()
{
	char buf[4096] = {0};
	char result[4096] = {0};

	char sum_res[4096] = {0};

	int a, b, ret;
	char ch;

	FILE *fp = fopen("test08.txt", "r");
	if (fp == NULL)
	{
		perror("fopen error");
		return;
	}

	while (1)
	{
		fgets(buf, 4096, fp);  //buf = "10/2=
";
		if (feof(fp))
		{
			break;
		}
		sscanf(buf, "%d%c%d=
", &a, &ch, &b);	// a:10, ch:'/' b: 2

		sprintf(result, "%d%c%d=%d
", a, ch, b, calc(ch, a, b));  // 10 / 2 = 5;

		strcat(sum_res, result); 
	}
	fclose(fp);  // 将 只有表达式没有结果的文件关闭。

	fp = fopen("test08.txt", "w");	// 清空 只有表达式没有结果的文件
	if (fp == NULL)
	{
		perror("fopen error");
		return;
	}
	fputs(sum_res, fp);	// 将 既有表达式又有结果的字符串写到文件中。

	fclose(fp);
}


int main(void)
{
	write_file08();
	getchar();
	read_file08();

	system("pause");
	return EXIT_SUCCESS;
}

Day11

笔记

printf --- sprintf --- fprintf: 

	变参函数:参数形参中 有“...”, 最后一个固参通常是格式描述串(包含格式匹配符), 函数的参数个数、类型、顺序由这个固参决定。

	printf("hello");
		
	printf("%s", "hello");

	printf("ret = %d+%d
", 10, 5);

	printf("%d = %d%c%d
", 10+5, 10, '+', 5);			--> 屏幕


	char buf[1024];   //缓冲区  

	sprintf(buf, "%d = %d%c%d
", 10+5, 10, '+', 5);		--> buf 中

	FILE * fp = fopen();

	fprintf(fp, "%d = %d%c%d
", 10+5, 10, '+', 5);			--> fp 对应的文件中

scanf --- sscanf --- fscanf

	scanf("%d", &m);		键盘 --> m


	char str[] = "98";

	sscanf(str, "%d", &m);		str --> m


	FILE * fp = fopen("r");

	fscanf(fp, "%d", &m);		fp指向的文件中 --> m


fprintf()函数:   ---> 将数据按指定的格式写进文件中

	写

	int fprintf(FILE * stream, const char * format, ...);

fscanf()函数:--->  从文件中读取指定格式的数据到内存中

	读

	int fscanf(FILE * stream, const char * format, ...);

		成功:正确匹配的个数。

		失败: -1

	1) 边界溢出。 存储读取的数据空间。在使用之前清空。

	2)fscanf函数,每次在调用时都会判断下一次调用是否匹配参数2, 如果不匹配提前结束读文件。(feof(fp) 为真)。


练习:文件版排序

	生成随机数,写入文件。将文件内乱序随机数读出,排好序再写回文件。


fgetc --- fputc

fgets --- fputs

fprintf -- fscanf		默认处理文本文件。


fwrite()函数:			既可处理以文本文件。也处理二进制文件。

	写出数据到文件中。

	stu_t stu[4] = { ...... };

	size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

		参1:待写出的数据的地址

		参2:待写出数据的大小

		参3:写出的个数				-- 参2 x 参3 = 写出数据的总大小。

		参4:文件

		返回值: 成功:永远是 参3 的值。 --- 通常将参2 传 1. 将参3传实际写出字节数。

			 失败:0 

fread()函数:

	从文件fp中读出数据。

	size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

		参1:读取到的数据存储的位置

		参2:一次读取的字节数

		参3:读取的次数				-- 参2 x 参3 = 读出数据的总大小

		参4:文件

		返回值: 成功:参数3.	--- 通常将参2 传 1. 将参3传欲读出的字节数。				

			 0:读失败 -- 到达文件结尾 -- feof(fp)为真。 

练习:大文件拷贝

	已知一个任意类型的文件,对该文件复制,产生一个相同的新文件。

	1. 打开两个文件, 一个“r”, 另一“w”

	2. 从r中 fread , fwrite到 w 文件中。

	3. 判断到达文件结尾 终止。  

	4. 关闭。

	注意: 在windows下,打开二进制文件(mp3、mp4、avi、jpg...)时需要使用“b”。如:“rb”、“wb”
	

随机位置 读:

	文件读写指针。在一个文件内只有一个。

	fseek():

		int fseek(FILE *stream, long offset, int whence);

			参1:文件

			参2:偏移量(矢量: + 向后, - 向前)

			参3:	SEEK_SET:文件开头位置

				SEEK_CUR:当前位置

				SEEK_END:文件结尾位置

		返回值: 成功:0, 失败: -1

	ftell():

		获取文件读写指针位置。

		long ftell(FILE *stream);

		返回:从文件当前读写位置到起始位置的偏移量。

		
		借助 ftell(fp) + fseek(fp, 0, SEEK_END); 来获取文件大小。

	rewind():

		回卷文件读写指针。 将读写指针移动到起始位置。

		void rewind(FILE *stream);


Linux和windows文件区别:

	1)对于二进制文件操作, Windows 使用“b”, Linux下二进制和文本没区别。

	2)windows下,回车 
, 换行 
。 
  , Linux下 回车换行


	3) 对文件指针,先写后读。windows和Linux效果一致。

		       先读后写。Linux无需修改。windows下需要在写操作之前添加 fseek(fp, 0, SEEK_CUR); 来获取文件读写指针,使之生效。

获取文件状态:

	打开文件,对于系统而言,系统资源消耗较大。

	int stat(const char *path, struct stat *buf);

		参1: 访问文件的路径

		参2: 文件属性结构体

		返回值: 成功: 0, 失败: -1;


删除、重命名文件:

	int remove(const char *pathname); 删除文件。

	int rename(const char *oldpath, const char *newpath);  重名文件

缓冲区刷新:

	标准输出-- stdout -- 标准输出缓冲区。   写给屏幕的数据,都是先存缓冲区中,由缓冲区一次性刷新到物理设备(屏幕)

	标准输入 -- stdin -- 标准输入缓冲区。	从键盘读取的数据,直接读到 缓冲区中, 由缓冲区给程序提供数据。

	预读入、缓输出。

	行缓冲:printf(); 遇到
就会将缓冲区中的数据刷新到物理设备上。

	全缓冲:文件。 缓冲区存满, 数据刷新到物理设备上。

	无缓冲:perror。 缓冲区中只要有数据,就立即刷新到物理设备。

	

	文件关闭时, 缓冲区会被自动刷新。  隐式回收:关闭文件、刷新缓冲区、释放malloc

	手动刷新缓冲区: 实时刷新。

		int fflush(FILE *stream);

			成功:0

			失败:-1

Code

  • 01-sprintf 和 sscanf.c
void write_file()
{
	FILE *fp = fopen("abc.c", "w");
	if (!fp)  // fp == NULL
	{
		perror("fopen error");
		return -1;
	}

	fprintf(fp, "%d
", 10);
	fprintf(fp, "%d
", 8);
	fprintf(fp, "%d
", 6);

	fclose(fp);
}

void read_file()
{
	int a;

	FILE *fp = fopen("abc.c", "r");
	if (!fp)  // fp == NULL
	{
		perror("fopen error");
		return -1;
	}

	fscanf(fp, "%d
", &a);
	printf("%d
" , a);

	fscanf(fp, "%d
", &a);
	printf("%d
", a);

	fscanf(fp, "%d
", &a);
	printf("%d
", a);

	a = 0;
	fscanf(fp, "%d
", &a);
	printf("%d
", a);

	fclose(fp);
}

// fscanf 循环读文件
void read_file2()
{
	int a;

	FILE *fp = fopen("abc.c", "r");
	if (!fp)  // fp == NULL
	{
		perror("fopen error");
		return -1;
	}
	while (1)
	{
		fscanf(fp, "%d
", &a);  // 读
		printf("%d
", a);
		if (feof(fp))		// 真-- 文件结尾
			break;
	}

	fclose(fp);
}

// fgets 循环读文件
void read_file3()
{
	char buf[1024];
	FILE *fp = fopen("abc.c", "r");
	if (!fp)  // fp == NULL
	{
		perror("fopen error");
		return -1;
	}
	while (1)
	{
		memset(buf , 0, 1024);
		fgets(buf, 1024, fp);// 读 

		if (feof(fp))		// 真-- 文件结尾
			break;
		printf("%d
", buf[0]);
	}

	fclose(fp);
}

int main0101(void)
{
	//write_file();
	read_file3();

	system("pause");
	return EXIT_SUCCESS;
}


int main(void)
{
	FILE *fp = fopen("test0101.txt", "r");
	if (!fp)  // fp == NULL
	{
		perror("fopen error");
		return -1;
	}

	int a;
	char ch;
	char str[10];

	int ret = fscanf(fp, "%d %c %s", &a, &ch, str);
	printf("ret = %d
", ret);

	fclose(fp);

	system("pause");
	return EXIT_SUCCESS;
}
  • 02-文件版排序.c
#include <stdlib.h>
#include <math.h>
#include <time.h>

void write_rand()
{
	FILE *fp = fopen("test02.txt", "w");
	if (!fp)  // fp == NULL
	{
		perror("fopen error");
		return -1;
	}

	srand(time(NULL)); // 随机数种子

	for (size_t i = 0; i < 10; i++)
	{
		fprintf(fp, "%d
", rand() % 100);  // 将生成的随机数写入文件
	}
	
	fclose(fp);
}


void BubbleSort(int * src, int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - 1 - i; j++)
		{
			if (src[j] > src[j + 1])
			{
				int temp = src[j];
				src[j] = src[j + 1];
				src[j + 1] = temp;
			}
		}
	}
}

void read_rand02()
{
	int arr[10], i = 0;

	FILE *fp = fopen("test02.txt", "r");
	if (!fp)  // fp == NULL
	{
		perror("fopen error");
		return -1;
	}

	while (1)
	{
		fscanf(fp, "%d
", &arr[i]);// 从文件中读取一个随机数,存入数组arr
		i++;
		if (feof(fp))				// 先存储,后判断,防止最后一个元素丢失
			break;
	}
	BubbleSort(arr, sizeof(arr)/sizeof(arr[0]));  // 对读取到的乱序数组排序

	fclose(fp);							// 关闭文件
	fp = fopen("test02.txt", "w");		// 重新w方式打开文件, 清空原未排序文件。
	if (!fp)  // fp == NULL
	{
		perror("fopen error");
		return -1;
	}
	for (size_t i = 0; i < 10; i++)
		fprintf(fp, "%d
", arr[i]);	// 写排好序的数组到文件

	fclose(fp);
}

int main0201(void)
{
	write_rand();

	getchar();

	read_rand02();

	system("pause");
	return EXIT_SUCCESS;
}
  • 03-fwrite 和 fread.c
typedef struct student {
	int age;
	char name[10];
	int num;
} stu_t;

void write_struct()
{
	stu_t stu[4] = {
		18, "afei", 10,
		20, "andy", 20,
		30, "lily", 30,
		16, "james", 40
	};

	FILE *fp = fopen("test03.txt", "w");
	if (!fp)
	{
		perror("fopen error");
		return -1;
	}

	int ret = fwrite(&stu[0], 1, sizeof(stu_t) * 4, fp);
	if (ret == 0)
	{
		perror("fwrite error");
		return -1;
	}

	printf("ret = %d
", ret);

	fclose(fp);
}

// 一次读一个元素。
void read_struct()
{
	FILE *fp = fopen("test03.txt", "r");
	if (!fp)
	{
		perror("fopen error");
		return -1;
	}
	stu_t s1;

	int ret = fread(&s1, 1, sizeof(stu_t), fp);
	printf("ret = %d
", ret);

	printf("age = %d, name=%s, num = %d
", s1.age, s1.name, s1.num);

	fclose(fp);
}

// 读所有元素
void read_struct2()
{
	FILE *fp = fopen("test03.txt", "r");
	if (!fp)
	{
		perror("fopen error");
		return -1;
	}
	stu_t s1[10];  // stu_t *s1 = malloc(sizeof(stu_t) * 1024);
	int i = 0;
	while (1)
	{
		int ret = fread(&s1[i], 1, sizeof(stu_t), fp);
		//if (ret == 0)		// 替代feof()函数来判断读到文件结尾。
		if (feof(fp))
		{
			break;
		}
		i++;
		printf("age = %d, name=%s, num = %d
", s1[i].age, s1[i].name, s1[i].num);
	}
	fclose(fp);
}


int main0301(void)
{
	//write_struct();
	read_struct2();

	system("pause");
	return EXIT_SUCCESS;
}
  • 04-大文件拷贝.c
void myfile_cp()
{
	FILE *rfp = fopen("C:\itcast\08-fread函数.avi", "rb");
	FILE *wfp = fopen("C:\itcast\mycopy.avi", "wb");

	char buf[4096] = {0};  // 缓冲区。

	int ret = 0;

	while (1)
	{
		memset(buf, 0, sizeof(buf));
		ret = fread(buf, 1, sizeof(buf), rfp);
		if (ret == 0)
		{
			break;
		}
		printf("ret = %d
", ret);
		fwrite(buf, 1, ret, wfp);
	}

	fclose(wfp);
	fclose(rfp);
}

int main0401(void)
{
	myfile_cp();

	printf("---------------------finish
");

	system("pause");
	return EXIT_SUCCESS;
}
  • 05-随机读文件.c
typedef struct student {
	int age;
	char name[10];
	int num;
} stu_t;

int main0501(void)
{
	stu_t stu[4] = {
		18, "afei", 10,
		20, "andy", 20,
		30, "lily", 30,
		16, "james", 40
	};
	stu_t s1;

	FILE *fp = fopen("test05.txt", "wb+");
	if (!fp)  // fp == NULL
	{
		perror("fopen error");
		return -1;
	}
	int ret = fwrite(&stu[0], 1, sizeof(stu), fp);  // 以二进制形式写入,
	printf("ret = %d
", ret);

	fseek(fp, sizeof(stu_t)*2, SEEK_SET);		// 从文件起始位置,向后偏移一个stu结构体

	ret = fread(&s1, 1, sizeof(s1), fp);
	printf("ret = %d
", ret);

	printf("1 age= %d, name=%s, num=%d
", s1.age, s1.name, s1.num);

	int len = ftell(fp); // 获取文件当前读写指针位置,到文件起始位置的偏移量。

	printf("len = %d
", len);

	rewind(fp);	// 将文件读写指针回卷到起始。

	ret = fread(&s1, 1, sizeof(s1), fp);

	printf("2 age= %d, name=%s, num=%d
", s1.age, s1.name, s1.num);

	// 获取文件大小。
	fseek(fp, 0, SEEK_END);	// 将文件读写指针放到文件结尾。
	len = ftell(fp);
	printf("文件大小为:%d
", len);

	fclose(fp);

	system("pause");
	return EXIT_SUCCESS;
}

int main0502(void)
{
	FILE *fp = fopen("test0501.txt", "w+");  // "r+"

	int ret = fputs("11111", fp);
	printf("ret 1 = %d
", ret);		// 0 表示成功。

	ret = fputs("22222", fp);
	printf("ret 2 = %d
", ret);

	ret = fputs("33333", fp);
	printf("ret 3 = %d
", ret);

	char buf[1024] = { 0 };

	//fseek(fp, 5 * 2, SEEK_SET);  // 改变读写指针位置。
	rewind(fp); // 起始位置。
	char *ptr = fgets(buf, 1024, fp);
	if (ptr == NULL)
		printf("ptr == NULL 
");

	printf("fgets ptr = %s
", ptr);
	printf("buf = %s
", buf);

	fclose(fp);
	system("pause");
	return EXIT_SUCCESS;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main0503(int argc, char *argv[])
{
	FILE *fp = fopen("test1.txt", "r+");

	char buf[6] = { 0 };
	char *ptr = fgets(buf, 6, fp);

	printf("buf=%s, ptr=%s
", ptr, buf);

	fseek(fp, 0, SEEK_CUR);
	int ret = fputs("AAAAA", fp);
	printf("ret = %d
", ret);

	fclose(fp);

	system("pause");
	return 0;
}
  • 06-获取文件属性-大小.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#include <sys/types.h>
#include <sys/stat.h>

/*
FILE *fp = fopen("test05.txt", "r");

fseek(fp, 0, SEEK_END);

int len = ftell(fp);

printf("文件大小:%d
", len);

fclose(fp);
*/

int main0602(void)
{
	struct stat buf;

	int ret = stat("test05.txt", &buf);  // 传出参数:在函数调用结束时,充当函数返回值。

	printf("文件大小:%d
", buf.st_size); // 不打开文件,获取文件大小。

	system("pause");
	return EXIT_SUCCESS;
}
  • 07-刷新缓冲区.c
int main0701(void)
{
	FILE *fp = fopen("test07.txt", "w+");
	if (!fp)
	{
		perror("fopen error");
		return -1;
	}
	char m = 0;

	while (1) 
	{
		scanf("%c", &m);
		if (m == ':')
		{
			break;
		}
		fputc(m, fp);
		fflush(fp);  // 手动刷新文件缓冲到物理磁盘。
	}
	// 当文件关闭时,会自动刷新缓冲区。
	fclose(fp);

	system("pause");
	return EXIT_SUCCESS;
}

Day12 -- 贪吃蛇游戏

Code

  • 源文件 -- main.c
 #define _CRT_SECURE_NO_WARNINGS

#include "snake.h"		// 引入自定义头文件

int main(void)
{
	// 去除光标。
	CONSOLE_CURSOR_INFO cci;
	cci.dwSize = sizeof(cci);
	cci.bVisible = FALSE;  // TRUE :
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);

	srand(time(NULL));  // 播种随机数种子。

	initSnake();	// 初始化蛇
	initFood();		// 初始化食物

	initWall();		// 画墙
	initUI();		// 画蛇和食物

	playGame();		// 启动游戏

	showScore();	// 打印分数

	system("pause");
	return EXIT_SUCCESS;
}

void showScore(void)
{
	// 将光标默认位置移动至 不干扰游戏的任意位置。
	COORD coord;

	coord.X = 0;
	coord.Y = HIGH + 2;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

	printf("Game Over!!!
");
	printf("成绩为:%d


", score);
}

void initWall(void)
{
	for (size_t i = 0; i <= HIGH; i++)	// 多行
	{
		for (size_t j = 0; j <= WIDE; j++)			// 一行中的多列
		{
			if (j == WIDE)
			{
				printf("|");
			}
			else if (i == HIGH)
			{
				printf("_");
			}
			else
			{
				printf(" ");
			}
		}
		printf("
");
	}
}

void playGame(void)
{
	char key = 'd';

	// 判断蛇撞墙
	while (snake.body[0].X >= 0 && snake.body[0].X < WIDE
		&& snake.body[0].Y >= 0 && snake.body[0].Y < HIGH)
	{
		// 更新蛇
		initUI();

		// 接收用户按键输入  asdw 
		if (_kbhit()) {				// 为真时,说明用户按下按键。
			key = _getch();
		}
		switch (key)
		{
		case 'w': kx = 0; ky = -1; break;
		case 's': kx = 0; ky = +1; break;
		case 'd': kx = +1; ky = 0; break;
		case 'a': kx = -1; ky = 0; break;
		default:
			break;
		}

		// 蛇头撞身体: 蛇头 == 任意一节身体
		for (size_t i = 1; i < snake.size; i++)
		{
			if (snake.body[0].X == snake.body[i].X
				&& snake.body[0].Y == snake.body[i].Y)
			{
				return;		// 游戏结束。
			}
		}

		// 蛇头撞食物
		if (snake.body[0].X == food.X && snake.body[0].Y == food.Y)
		{
			initFood();		// 食物消失
			snake.size++;	// 身体增长
			score += 10;	// 加分

			sleepSecond -= 100;	// 加速
		}

		// 存储蛇尾坐标
		lastX = snake.body[snake.size - 1].X;
		lastY = snake.body[snake.size - 1].Y;

		// 蛇移动,前一节身体给后一节身体赋值。
		for (size_t i = snake.size - 1; i > 0; i--)
		{
			snake.body[i].X = snake.body[i - 1].X;
			snake.body[i].Y = snake.body[i - 1].Y;
		}
		snake.body[0].X += kx;		// 蛇头坐标根据用户按键,修改。
		snake.body[0].Y += ky;

		Sleep(sleepSecond);
		// 清屏
		//system("cls");	
	}

	return;
}

// 定义初始化蛇函数
void initSnake(void)
{
	snake.size = 2;

	snake.body[0].X = WIDE / 2;		//蛇头初始化
	snake.body[0].Y = HIGH / 2;

	snake.body[1].X = WIDE / 2 - 1;	// 蛇一节身体初始化
	snake.body[1].Y = HIGH / 2;

	return;
}

// 初始化界面控件
void initUI(void)
{
	COORD coord = {0};					// 光标移动的位置。

	// 画蛇
	for (size_t i = 0; i < snake.size; i++)
	{
		coord.X = snake.body[i].X;
		coord.Y = snake.body[i].Y;
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

		if (i == 0)
			putchar('@');
		else
			putchar('*');
	}
	// 去除蛇尾
	coord.X = lastX;
	coord.Y = lastY;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
	putchar(' ');

	// 画食物
	coord.X = food.X;
	coord.Y = food.Y;

	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
	putchar('#');
}

// 食物的初始化函数
void initFood(void)
{
	food.X = rand() % WIDE;  // 0-59
	food.Y = rand() % HIGH;  // 0-59
	return;
}
  • 头文件 -- snake.h
#ifndef __SNAKE_H__
#define __SNAKE_H__

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <conio.h>
#include <Windows.h>


#define WIDE 60			// 宽度
#define HIGH 20			// 高度

// 一个身体的对象
struct BODY {
	int X;
	int Y;
};

// 定义蛇对象
struct SNAKE {
	struct BODY body[WIDE*HIGH];
	int size;
}snake;			// 一个蛇对象

				// 定义食物对象
struct FOOD {
	int X;
	int Y;
}food1;			// 一个食物对象

int score = 0;	// 分数

int kx = 0;			// 用户按下 asdw 任意一个按键所得到的 坐标值。
int ky = 0;

int lastX = 0;		// 蛇尾的坐标。
int lastY = 0;

int sleepSecond = 400;

// 声明函数
void initSnake(void);
void initFood(void);
void initUI(void);
void playGame(void);
void initWall(void);
void showScore(void);

#endif

Day13

笔记


vim 3 种工作模式:

	命令模式:

		使用所有输入都被vim当成命令看。

		i、a、o、s -- I、A、O、S

	文本模式(编辑模式):

		在该模式下编辑代码。

	末行模式:

		“:” 切换为末行模式。 

		w:保存。 q:退出。
原文地址:https://www.cnblogs.com/zranguai/p/14998997.html