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)函数使用注意
===========================================
2014.3.11-C语言学习小结的更多相关文章
- 2014.3.5-C语言学习小结
知识点: 1.结构体 struct 2.联合体 union 3.枚举 4.结构.联合与函数 =========================== 结构体 思考:如果现在希望保存一个学生的信息,该如何 ...
- 2014.3.4-C语言学习小结
位操作: 知识点: 1.位运算符 2.位移运算符 1.将指定位设置为12.将指定位设置为03.获取指定位的内容 ==========================复习二进制 1.二进制转换 10-- ...
- 2014.3.6-C语言学习小结
链表基础: 知识点: 1.链表基础 2.节点的创建和添加 llist_append_node 3.链表的遍历 llist_print_each 4.链表的查找与修改 5.链表的插入与删除 6.链表的销 ...
- 12天学好C语言——记录我的C语言学习之路(Day 11)
12天学好C语言--记录我的C语言学习之路 Day 11: 因为指针部分比较的难,所以我们花费的时间也是最长的,希望大家耐的住性子,多多理解,多多打代码.好了,废话不多说,来看第11天的学习. //编 ...
- 18 11 04 初用单片机 c语言学习
---恢复内容开始--- 1 作为单片机使用的的 c 语言学习 ++ 增位运算符 在原有基础上加一 -- 相同 由于单片机只有 ~ 取反 & 两个 参数里有没有 | 两个 参数里有没有 ^ 两 ...
- objective-c基础教程——学习小结
objective-c基础教程——学习小结 提纲: 简介 与C语言相比要注意的地方 objective-c高级特性 开发工具介绍(cocoa 工具包的功能,框架,源文件组织:XCode使用介绍) ...
- 【转】朱兆祺教你如何攻破C语言学习、笔试与机试的难点(连载)
原文网址:http://bbs.elecfans.com/jishu_354666_1_1.html 再过1个月又是一年应届毕业生应聘的高峰期了,为了方便应届毕业生应聘,笔者将大学四年C语言知识及去年 ...
- C语言学习 第八次作业总结
本次作业其实没有新的内容,主要就是复习上一次的一维数组的相关内容.冯老师布置了5道题目,其中涉及到一些比较简单的排序或者是查找的方法.因为数据很少,所以直接使用for循环遍历就可以了. 关于本次作业, ...
- Python 学习小结
python 学习小结 python 简明教程 1.python 文件 #!/etc/bin/python #coding=utf-8 2.main()函数 if __name__ == '__mai ...
随机推荐
- OCP读书笔记(22) - 题库(ExamB)
101.Identify two situations in which you can use Data Recovery Advisor for recovery. (Choose two.) A ...
- Lampda或Linq中的SqlFunctions.StringConvert()
要使用 Lampda或Linq中的SqlFunctions.StringConvert(), 需要引用命名空间using System.Data.Objects.SqlClient, 该函数可进行模拟 ...
- NET 领域驱动设计实战系列总结
NET 领域驱动设计实战系列总结 一.引用 其实在去年本人已经看过很多关于领域驱动设计的书籍了,包括Microsoft .NET企业级应用框架设计.领域驱动设计C# 2008实现.领域驱动设计:软件核 ...
- linux runtime pm在深入了解的机制
一:runtime机构简介 何为runtime机制?也就是系统在非睡眠状态,设备在空暇时能够进入runtime suspend状态同一时候不依赖系统wake_lock机制.非空暇时运行runtime ...
- mysql_自动备份
1 @echo off 2 set errorlevel=0 3 set dump_command="C:\Program Files\MySQL\MySQL Server 5.5\bin\ ...
- Codeforces Round #243 (Div. 1)-A,B,C-D
此CF真是可笑.. . 由于早晨7初始点,因此,要做好CF时间已经17没有休息一小时,加上中午5小时耐力赛. 心里很清楚.是第一个问题的时候,几乎被解读为寻求最大的领域和.然后找到一个水体,快速A降. ...
- linux复制文件命令scp
linux大多数复制我们的递送工具使用,有着ftp,scp等一下. 当中scp命令很easy快捷, 本机到远程:scp (-r) 本地目录或者文件路径 远程ip:目录 远程到本机:scp (-r) 远 ...
- STL慎重选择删除元素的
一.要删除容器中有特定值的全部对象 1.假设容器是vector.string或deque.则使用erase-remove习惯使用方法.比如: vector<int> c; c.era ...
- easyui datagrid 单元格编辑 自动聚焦 、全选
$.extend($.fn.datagrid.methods, { editCell: function (jq, param) { return jq.each(function () { var ...
- c# p2p 穿透(源码加密)
http://blog.oraycn.com/ESFramework_Demo_P2P.aspx 测试,完全OK! 我很喜欢这个.可以源码是加密的!我希望实现 web 版本的p2p视频观看,aehy ...