• 2014.3.11-C语言学习小结


    文件操作:

    知识点:		持久化
    	1.文本文件的读写
    	2.二进制文件的读写
    	3.缓冲文件系统
    
    		1.打开文件
    		2.读写文件
    		3.保存
    		4.关闭文件		
    
    
    
    ======================================
    文本文件的读写
    	1.文件的打开
    	  1)打开模式
    	      r(read)		读文件,不存在,打开失败
    	      w(write)  	写文件,如果文件不存在,创建文件,存在则清空文件内容  
    	      a(append)		以追加方式写文件
    
    	      a+		读写方式打开,以追加方式写文件
    	      r+		读写方式打开,文件存在打开
    	      w+		读写方式打开,文件不存在创建,存在打开并清空
    	  2)函数原型
    		FILE *fopen(const char *path, 
    			    const char *mode)
    		思考:如果打开的文件不存在会如何
    	2.文件的关闭
    	  1)函数原型
    		int fclose(FILE *file);
    	3.读写文件内容
    	  1)按字符读文本文件,从文件读取一个字符
    	    1>函数原型
    		int fgetc(FILE *file);
    		函数返回值:读取成功返回该字符的ascii码,失败返回-1
    			1.如果读到文件末尾,返回-1
    			2.如果打开方式不对,返回-1
    
    		思考:如何判断读到文件末尾
    	  2)按字符写文本文件,向文件写入一个字符
    		int fputc(int c, FILE *fp);
    		函数返回值:写入成功返回写入字符对应的ascii码,失败返回-1
    			1.打开方式不对,返回-1
    			2.磁盘空间不足,返回-1
    			3.对文件没有写权限,返回-1
    
    		练习:
    		    1.通过循环将字符数组中的内容写入到文件中
    		    2.读取文件中的文件内容
    	  3)按行读文本文件,从文本读取一行字符
    	     1>函数原型
    		char *fgets(char *buf, int size, FILE *fp);
    		stdin  stdout  stderr
    			fgets(buf, 100, stdin);
    	
    		函数返回值:读取成功返回读取和参数buf相同的地址,失败返回NULL
    	  4)按行写文本文件,向文本写入一行字符
    	     1>函数原型
    		int fputs(char *s, FILE *fp);
    		函数返回值:返回成功写如的字符数,失败返回-1
    	  5)格式化读写文本文件
    	     1>格式化输出函数原型,按照指定格式将内容写入文本文件	
    		%s|%d|%d|%d|%d|%c
    		
    		%s	角色名		char *name
    		%d	级别		int level	
    		%d	血		int boold
    		%d	攻		int act
    		%d	防		int def
    		%c	y/n		char boss
    
    		int fprintf(FILE *fp, const char *fmt, …);
    		函数返回值:成功返回写入的字符数,失败返回-1
    
    	     2>格式化输入函数原型,按照指定格式从文本文件读取内容	
    		int fscanf(FILE *fp, const char *fmt, …);	
    			%[^'|']
    		函数返回值:成功返回对应读取的变量个数,失败返回-1
    		练习:1.按照指定格式保存自身的基本信息
    		     2.按照指定格式读取自身的基本信息并且输出
    =============================================
    二进制文件的读写
    	需求:
    	    1.现在需要保存班级中的所有学生的身高信息
    			int height[10]
    		%s|%d|%d
    		a|9|100
    		a|100|9
    			double  score[10]
    	    2.保存学生的完整信息
    	1.文件的打开
    	  1)读写模式
    	     同上
    	2.读写文件内容
    	  1)读取函数,从文件读取数据到内存中
    	    size_t fread(void *ptr, size_t size, 
    		         size_t n, FILE *stream);
    		参数:1.要保存数据的首地址
    		    2.每次读取的数据大小
    		    3.读取次数,每次读取都会在首地址后+对应的数据大小
    		    4.读取的文件
    		返回值:成功返回读取的次数,失败返回0
    	  2)写入函数,把内存的一块数据写入到文件
    	    size_t fwrite(void *ptr, size_t size, 
    		          size_t n,  FILE *stream);
    		参数:1.要写入数据的首地址
    		    2.每次写入的数据大小
    		    3.写入次数
    		    4.写入的文件
    		返回值:成功返回写入的次数,失败返回0
    	  3)文件定位函数,文件随机读写
    	    1>ftell,读取文件当前读写位置
    		long ftell(FILE *stream);
    	    2>设置当前文件读写位置
    		int fseek(FILE *stream, long offset, int whence);
    		whence:
    		       SEEK_SET		相对与文件开头
    		       SEEK_CUR		相对于当前位置
    		       SEEK_END		相对于文件末尾
    		 练习:将文件位置指针向后移动n个位置
    			   然后写入数据,查看最后的结果=============================================
    缓冲文件系统
    	思考:printf的内容一定会马上输出到屏幕吗
    	1.缓冲系统的作用
    	2.缓冲的过程
    	  printf->fprintf->缓冲区->write
    		行缓冲
    		全缓冲		fflush(fp)
    		无缓冲		stderr
    			
    		
    	3.手动刷新缓冲
    	  fflush
    	4.系统的标准输输入,输出,错误输出
    			stdin,   stdout,  stderr
    =============================================
    作业:
    	1.文件十六进制显示工具
    	
    	fp1 %c —> fp2 %x
    	fprintf(fp2, “%x”, var);
    	
    

      

    链表:

    知识点:
    	1.链表基础
    	2.节点的创建和添加		llist_append_node
    	3.链表的遍历		llist_print_each
    	4.链表的查找与修改
    	5.链表的插入与删除
    	6.链表的销毁
    	7.链表逆序
    
    
    ==========================
    回顾数组
    	1.数组的常用操作
    	  1)插入
    	  2)修改
    	  3)遍历
    	  4)删除
    	  5)逆序
    	2.数组操作的问题
    	  1)插入和删除的效率低
    			1 2 3 5 6 0 0
    			1 2 3 4 9 5 6
    			1 2 3 4 9 5 6 0
    	  2)当数组空间不足时需要重新申请内存空间
    	  3)但是遍历速度快
    ==========================
    链表基础
    	1.什么是链表
    	   链表(Linked list)是一种常见的基础数据结构,是一种线性表
    	2.链表的作用
    	  一种数据结构,保存数据
    	3.如何创建链表
    ==========================
    链表节点的创建和添加
    	1.如何创建和添加一个节点
    	2.如何插入一个节点
    	4.处理链表的框架
    void llist_append_node
    			(struct node *head, 
    		          struct node *new)
    void llist_change_node(struct node *head, 
    			             int id, 
    			             char *name)
    		append	*
    		insert  *
    		search	*
    		change
    		delete
    		destory
    		print_all  *
    		print_node
    
    	5.添加节点模块append
    	练习:添加一个节点到头结点后面
    ==========================
    链表的遍历
    	1. llist_print_each函数
    	void llist_print_each(struct node *head);
    	 练习:
    	      1.遍历输出链表内容
    	      2.向链表添中加多个节点
    ==========================
    链表的查找与修改
    	1. llist_search_node函数
    struct node *llist_search_node(struct node *head, int id)
    void llist_print_node(struct node *nd)
    	  1)遍历链表
    	  2)比较要搜索的内容是否和节点数据内容匹配
    	  3)返回节点地址
    	  练习:
    		1.查找指定id的学生信息,并输出该信息
    	2.change函数
    	  1)搜索要修改的节点空间
    	  2)修改节点内的数据
    		1.修改指定id的学生性别
    ==========================
    链表的插入和删除
    	1. llist_insert_node函数
    void llist_insert_node(struct node *head,
    			            struct node *nd, int id)
    	  1)创建一个新节点
    	  2)插入到指定位值
    	  练习:
    			链表包含10个节点
    			id=3,id=4 <== tmp
    			       id=1
    	       1.创建一个新节点并且插入到第一个节点的前面
    	       2.创建一个节点并且插入到第三和第四个节点之间
    	2.delete函数
    void llist_delete_node(struct node *head, int id);
    	  1)修改该节点上一个节点的指向
    	  2)释放当前节点
    	  练习:
    		1.删除id为1节点
    		2.删除id为10节点
    		3.删除id为5节点
    ==========================
    链表销毁
    	1.destory函数
    	int llist_destory(struct node *head);
    	 1)销毁和清空是两种不同的操作
    	   例如:倒空杯子的水和砸碎杯子两个操作
    	 练习:
    	     销毁上面创建的链表
    ==========================
    链表逆序
    	H->A->B->C->D->E
    	   ^  ^	 ^  
    	   p  pp  t
    	1.inverse函数
    void llist_inverse(struct node *head);
    	 练习:
    	     1.按照上述顺序实现一个链表的逆序,并输出逆序的结果
    ==========================
    多文件封装
    	1.头文件
    	2.实现文件
    ==========================
    创建一个班级链表,该链表包含10个学生信息
    1.每个学生包含信息有
    		姓名,年龄,身高,性别,语数英三门成绩
    2.实现:
    	1)添加学生信息
    	2)输出所有的学生信息
    	3)搜索指定学生的信息,并且输出
    	4)将指定学生插入到指定学生的前面
    	5)删除指定学生信息
    	6)销毁班级链表
    	========================
    	enume menu{
    			EXIT, ADD, SONE, SALL, 
    		         INSERT, DEL, DELALL};
    	1.添加学生
    	2.查询指定学生信息
    	3.查询所有学生信息
    	4.学生插队
    	5.删除指定学生信息
    	6.删除班级
    	0.退出系统
    

      

    预处理:

    知识点:
    	1.宏的定义		#define    #undef
    	2.宏与函数的区别
    	3.文件包含和多文件编译	#include <> “”	#import
    	3.条件编译		#if  #elif #else #endif
    				#ifdef  #ifndef
    	4.typedef关键字
    
    > gcc -E  源代码文件.c -o 预处理结果文件.i //预处理
    > gcc -S   预处理结果文件.i -o 汇编结果文件.s //编译  翻译为汇编   
    > gcc -c 汇编结果文件.s -o 目标文件.o //汇编
    > gcc 目标文件.o -o a.out         //链接	ld
    =================================
    宏定义
    	0.什么是宏定义
    	  1)宏定义是C提供的三种预处理功能中的一种,预处理包括宏定义、文件包含、条件编译
    	1.宏定义的作用
    	  1)使用标识符来替换一些常用的代码
    		for (i = 0; i < 100; ++i)
      
    		LOOP100
    		{
    			printf(“i”);
    		}
    		WALK  小明---nickname 别名
    	2.宏定义的本质
    	  1)一种占位符,用来代替一些常用代码
    	  2)一切以转换为前提,做任何事情之前先要替换
    	2.基本的宏定义
    	  0)#define指令语法!!!!
    		宏指令	  宏名		宏体
    	  1)标识符
    	  2)大写,不加分号结束
    	  3)使用
    	  示例:定义常量PI的宏
    	  练习:
    		  定义数组大小的宏
    	      	  定义重力加速度宏	9.8	G
    	3.带有参数的宏定义
    	  1)示例:计算两数最大值的宏
    	    练习:
    		 1.计算两数最小值的宏	?:
    		 2.计算两数之和的宏,两数之积
    
    
    	思考:ADD(1,2)*ADD(1,2)结果
    	  
           
    
    
    	4.宏替换的问题
    	  1)宏替换作用的演示,gcc编译参数	
    	  2)思考:能否嵌套定义或调用
    
    
    
    
    	5.常用宏  
    	  2)字母大小写转换
    		TOLOWER		ch + 32
    		TOUPPER		ch - 32
    	
    	  4)设置指定数某位为1或0
    		SET1, SET0
    
    	  5)获取某一位的值
    		GETBITS
    	  6)取得一个short的高1个字节和低1个字节
    		SLOW
    		SHIGH
    	  7)将short的高字节和低字节互换	
    	  8) 交换两数宏  
    	  9)安全释放内存宏  SAFTY_FREE
    		
    	6.宏和函数的区别
    	  1)思考:宏的本质和函数的本质
    	  2)思考:宏和函数调用的速度,安全性和空间	
    	  3)回忆函数调用的过程
    		函数调用需要开辟栈空间,保存参数和局部变量
    	  4)本质:宏只是替换,并不会产生函数调用
    	  5)速度:宏不占运行时间,只占编译时间,函数调用占运行时间
    	  6)安全:宏不会检查参数类型,函数会检查参数类型
    	  7)空间:宏的参数不占用空间,函数的用空间
    	  8)能否调用自身:宏不能进行递归调用,函数可以
    	   思考:如何结合宏与函数的优势
    		1.代码非常简单而又十分常用的时候使用宏
    		2.代码非常复杂,一般使用函数
    ==================================
    文件包含和多文件编译
    	1.思考:如何实现多人合作项目
    		接口---->函数原型	.h	//head
    		实现---->函数定义	.c
    		
    	cvs	git	svn
    		
    	2.回忆函数定义和声明
    	3.头文件和源文件
    	4.#include指令语法!!!!
    	  1)本质:头文件包含实际是替换文件内容
    	  2)作用:实现声明和实现相分离,进一步使程序更加的模块化	
    
    		#include <stdio.h>  尖括号表示系统标准目录		
    	    双引号表示自定义路径		
    	  		add,  sub, mut, div
    	5.示例:链表的实现的声明相分离
    	  练习:
    		1.实现加减乘除四则运算,并将函数的声明与实现相分离
    		  并编写测试函数测试该些函数
    
    		A B C D		200		100
    
    		
    ===================================
    条件预编译
    	需求:现在用户只购买系统中的某些模块
    	1.思考:如何可以简单快速的在编译的过程中满足用户的需求
    	2.#ifdef 条件编译语法!!!!
    	     #ifndef
    		1)作用:模块选择
    	  示例:判断是否定义过PI宏
    	  练习:判断是否有定义上述的常用宏
    	思考:
    	   1.如何可以安全,快速的注释代码
    	   2.// 和 /**/注释是否可以嵌套使用
    	3.#if 条件编译语法!!!!
    	  1)作用
    	     快速安全的注释代码
    	4.安全注释
    	思考:如果重复包含头文件会如何
    	5.防止头文件重复包含
    ===================================
    调试宏
    		NSLog
    	思考:如何使用printf调试代码,是否方便移出
    	1.调试宏定义
    	  INFO, WARN, ERROR, DEBUG
    	2.调试开关
    	3.预定义宏
    		printf("line = %d, file = %s, DATA = %s, TIME = %s", 
    				__LINE__, __FILE__, __DATE__, __TIME__);
    	  __LINE__:行号
    	  __FILE__:文件名
    	  __DATE__:日期		%s
    	  __TIME__:时间
    	  __FUNCTION__, __func__:函数名
    ===================================
    typedef关键字				int4		int32		int64
    	思考:程序的跨平台性		64	32	16	8
    					int    int     int2
    					long  long	   long 
    
    			size_t
    
    			long long	int64
    			long
    
    	1.typedef作用
    	   1)typedef常用来定义一个标识符和及关键字的别名,并不分配实际的内存
    	   2)typedef可以增强程序的可读性
    	   3)typedef可以增强标识符的灵活性
    	2.typedef本质
    	   typedef本质为类型的别名
    	3.typedef语法使用!!!!
    	4.重定义结构体
    	5.重定义类型
    	6.typedef与define的区别
    	  1)typedef是为了程序的可读性而为标识符另起的别名,而
    	    define在c语言中是为了定义常量,常用代码替换
    	  2)define可以使用#ifdef和#ifndef来进行逻辑判断
    

      

    动态内存分配:

    知识点:	
    	动态内存管理
    	1.数据在内存中的存储
    	2.内存分配malloc和realloc和calloc函数使用和注意事项
    	3.free函数使用
    	4.堆和栈的区别      .heap  .stack	 .bss	.data	.rodata
    	5.常用内存操作函数  
    ==============================
    内存使用
    	1.回顾函数在使用时候所开辟的内存栈
    	2.变量所在的内存空间
    	3.栈空间的限制	stack  
    	  1)栈大小:一般在2M左右
    	4.栈数据的特点
    	  1)回顾局部变量的生命周期
    	  2)每个变量的内存大小均在编译时候确定,空间由操作系统分配
    	  3)数据由系统自动释放
    	  4)数据分配在栈段
    	思考:	
    			int var;
    			return &var;
    20000 / 1000 == 20
    		0.是否可以返回函数执行过程中局部变量的内存地址
    		1.如果需要的内存栈无法提供足够的内存容纳我们的数据怎么办
    		2.如果需要将函数内的数据保存到程序结束再销毁,是否可以
    	5.堆空间的使用		heap
    	  1)堆空间的特点
    	    1>大小由程序员决定,空间由程序员分配
    	    2>大小在运行时候确定
    	    3>由程序员手动释放
    	    4>数据分配在堆段
    ==============================
    动态内存分配函数
    	1.malloc  内存分配 
    	  1)函数原型
    		void *malloc(size_t size) 
    		void *calloc(int n, size_t size) 
    	        申请size个字节的内存
    	  2)函数使用
    	      void *p = malloc(4096 * 1024 * 1024);
    	  3)分配内存注意	
    	     1)函数执行完后如果成功,返回该size大小内存的首地址
    	     2)函数执行失败返回NULL
    	     3)malloc会在堆上寻找一块size个字节的内存返回给用户
    	     4)使用之前一定要判断是否分配成功,因为malloc函数执行有可能会失败(内存不足)
    			1.内存不足
    			2.没有足够大的连续内存空间
    	
    			
    		练习:
    		1.分配一能足够保存double			  数据的内存空间,并且赋值输出
    	        2.分配一个足够保存n个double类型数据		  的内存空间,并且赋值输出
    
    
    	思考:如果现在所使用的内存空间不足,想要重新分配一块内存,但是又不想丢失原来的数据,么办
    	2.realloc  重新分配内存
    	  1)函数原型
    	      void *realloc(void *ptr, size_t size)
    	      在ptr指针后再分配size个字节的内存空间
    	  2)函数使用
    		realloc(ptr, 40);
    	  3)函数使用注意
    	    1)思考:如果ptr执行NULL会如何
    	    2)思考:如果在ptr后没有size个字节的内存会如何
    	    3)思考:函数返回值是什么
    	 	练习:使用realloc函数为malloc分配的内存向后扩展40个字节的空间
    		    0.比较返回地址是否为原理的内存地址
    		    1.输出新空间中的所有内容
    		    2.对新的内存空间进行赋值
    		   
    ================================
    内存释放函数
    	思考:申请的内存是否需要释放,不释放是否可以,会造成怎样的结果
    	1.free 内存释放
    	  1)函数原型
    	     void free(void *ptr)
    	  2)函数使用
    	    free(ptr)
    	  3)函数使用注意
    		思考:释放后的内存是否可以继续使用
    	    1>只能对有效分配的内存进行释放
    		思考: 被释放的内存还可以引用吗
    	    2>思考:如果对一个指针连续释放两次会如何
    	         3>不能释放栈上的空间
    	    3>如何避免上述情况
    		练习:释放malloc和realloc申请的内存空间
    ================================
    堆和栈的区别
    	1.分配大小
    		栈	不能超过2M
    		堆	可以任意分配,只要系统有内存
    	2.分配速度
    		栈	快
    		堆	慢
    ===============================
    数据在内存中的存储与分布
    	1.数据区:栈,堆,数据段
    	2.栈
    	  1)进入函数时分配空间,函数结束时释放空间
    	  2)局部变量,函数参数均在此段中
    	  3)此段中的初始值均为随机数
    	3.堆
    	  1)malloc申请,free释放
    	  2)初始值
    	4.数据段
    	  1)全局变量    bss 没有初始化的全局变量
    	  2)static静态变量
    	  3)字符串常量(只读静态存储取)   rodata
    ================================
    常用内存处理函数
    
    	1.memset 将指定地址指定大小设置为指定内容
    	  1)函数原型
    		void *memset(void *ptr, int c, size_t len)
    	  2)函数使用
    	  3)函数使用注意
    	    练习:分配10个字节的内存空间
    		1.输出该空间中的内容
    		2.将该内存空间上的内容全部设置为1	
    	2.memmove  内存拷贝,从s2拷贝len的字节内容到s1中
    	   1)函数原型
    		void *memmove(void *dst, const void *src, size_t  len)
    		void *memcpy(void *dst, const void *src, size_t  len)
    	   2)函数使用
    	   3)函数使用注意
    ===========================================
    
    
    

      

  • 相关阅读:
    解决页面报错: GEThttp://localhost:8080/favicon.ico 404 (Not Found)
    vs2019快捷键整理
    js保存图片至本地
    PHP输出方式的区别
    js运算精度问题
    Hadoop相关问题
    2015年10月5日 12:49:07
    Hive数据倾斜
    Hadoop错误日志
    使用maven开发MR
  • 原文地址:https://www.cnblogs.com/firstrate/p/3593180.html
Copyright © 2020-2023  润新知