C语言入门第六章知识点总结.docx

上传人:b****3 文档编号:5520035 上传时间:2023-05-08 格式:DOCX 页数:18 大小:742.37KB
下载 相关 举报
C语言入门第六章知识点总结.docx_第1页
第1页 / 共18页
C语言入门第六章知识点总结.docx_第2页
第2页 / 共18页
C语言入门第六章知识点总结.docx_第3页
第3页 / 共18页
C语言入门第六章知识点总结.docx_第4页
第4页 / 共18页
C语言入门第六章知识点总结.docx_第5页
第5页 / 共18页
C语言入门第六章知识点总结.docx_第6页
第6页 / 共18页
C语言入门第六章知识点总结.docx_第7页
第7页 / 共18页
C语言入门第六章知识点总结.docx_第8页
第8页 / 共18页
C语言入门第六章知识点总结.docx_第9页
第9页 / 共18页
C语言入门第六章知识点总结.docx_第10页
第10页 / 共18页
C语言入门第六章知识点总结.docx_第11页
第11页 / 共18页
C语言入门第六章知识点总结.docx_第12页
第12页 / 共18页
C语言入门第六章知识点总结.docx_第13页
第13页 / 共18页
C语言入门第六章知识点总结.docx_第14页
第14页 / 共18页
C语言入门第六章知识点总结.docx_第15页
第15页 / 共18页
C语言入门第六章知识点总结.docx_第16页
第16页 / 共18页
C语言入门第六章知识点总结.docx_第17页
第17页 / 共18页
C语言入门第六章知识点总结.docx_第18页
第18页 / 共18页
亲,该文档总共18页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

C语言入门第六章知识点总结.docx

《C语言入门第六章知识点总结.docx》由会员分享,可在线阅读,更多相关《C语言入门第六章知识点总结.docx(18页珍藏版)》请在冰点文库上搜索。

C语言入门第六章知识点总结.docx

C语言入门第六章知识点总结

传智播客C/C++课堂笔记C语言入门6

6.1如何节约内存-位运算

内存单元,即1B,我们说char型占1个内存单元(1B),而short型占2个内存单元(2B)。

1B被当成整体来看。

但同时1B=8bits1个字节有8个位,每个位有0、1两个取值。

总体来说,C语言中的位运算符有以下两类:

位逻辑运算符:

(位逻辑运算以位(bit)为单位)

&(位“与”)、^(位“异或”)、|(位“或”)、~(位“取反”)。

移位运算符:

<<(左移)、>>(右移)

位“取反”:

操作符为“~”,如果A为10101010,那么~A返回的结果为01010101,即每位都取反,0变成1,1变成0,需要注意的是,位取反运算并不改变操作数的值

位“与”:

操作符为&,将对两个操作数的每一位进行与运算,位“与”运算的准则如下:

1&1=11&0=00&1=00&0=0

位“或”:

操作符为|,将对两个操作数的每一位进行或运算,位“或”运算的准则如下:

1|1=11|0=10|1=10|0=0

位“异或”:

操作符为^,将对两个操作数的每一位进行异或运算。

通俗地讲,如果两个位相同(同为0或同为1),结果为0,若两个位不同(一个为0,另一个为1),结果为1,对应的准则为:

1^1=01^0=10^1=10^0=0

移位运算表达式的基本形式为:

A<

A>>n;/*右移*/

A称为操作数,其必须为数字型变量或数字型常量,此处的数字型包括整型、浮点型和char型,A中存储的0、1序列向左或右移动n位,移动后的值作为整个表达式的输出,执行移位运算并不改变操作数A的值。

小结:

位运算主要分为位逻辑运算和移位运算两大类,位逻辑运算主要有位取反运算、位或运算、位与运算和位异或运算,使用时应注意和普通变量的逻辑运算区分。

移位运算分为向左移动和向右移动两类,对无符号数或有符号正数来说,编译器会自动为空白位补0,对有符号负数来说,当填充的空白位牵扯到符号位时,编译器会对符号位进行特殊处理。

6.2不局限内存-文件

输入输出都是由printf函数和scanf函数来完成,完成的也只是极其简单的任务,所有的变量和数字什么的都是放在内存中,一旦断电,所有的数据都会丢失,有时,希望能将结果保存起来,下次开机时再使用,这就要用到文件。

文件:

存储在外部介质上数据的集合,是操作系统数据管理的单位。

文件分类

按文件的逻辑结构:

记录文件:

由具有一定结构的记录组成(定长和不定长)

流式文件:

由一个个字符(字节)数据顺序组成

按存储介质:

普通文件:

存储介质文件(磁盘、磁带等)

设备文件:

非存储介质(键盘、显示器、打印机等)

按数据的组织形式:

文本文件:

ASCII文件,每个字节存放一个字符的ASCII码

二进制文件:

数据按其在内存中的存储形式原样存放

6.2.1二进制文件和文本文件的区别

6.2.2文件标识

⏹每个文件都以文件名为标识,I/O设备的文件名是系统定义的,如:

⏹COM1或AUX——第一串行口,附加设备

⏹COM2——第二串行口,此外,还可能有COM3、COM4等

⏹CON——控制台(console),键盘(输入用)或显示器(输出用)

⏹LPT1或PRN——第一并行口或打印机

⏹LPT2——第二并行口,还可能有LPT3等

⏹NUL——空设备

磁盘文件可以由用户自己命名,但上述被系统(windows和dos下均是如此)保留的设备名字不能用作文件名,如不能把一个文件命名为CON(不带扩展名)或CON.TXT(不带扩展名)

6.2.3流

流是一个动态的概念,可以将一个字节形象地比喻成一滴水,字节在设备、文件和程序之间的传输就是流,类似于水在管道中的传输,可以看出,流是对输入输出源的一种抽象,也是对传输信息的一种抽象。

通过对输入输出源的抽象,屏蔽了设备之间的差异,使程序员能以一种通用的方式进行存储操作,通过对传输信息的抽象,使得所有信息都转化为字节流的形式传输,信息解读的过程与传输过程分离。

C语言中,I/O操作可以简单地看作是从程序移进或移出字节,这种搬运的过程便称为流(stream)。

程序只需要关心是否正确地输出了字节数据,以及是否正确地输入了要读取字节数据,特定I/O设备的细节对程序员是隐藏的。

6.2.4文件的处理方法

缓冲文件系统:

高级文件系统,系统自动为正在使用的文件开辟内存缓冲区

非缓冲文件系统:

低级文件系统,由用户在程序中为每个文件设定缓冲区

6.2.5重定向

重定向是由操作系统来完成的,一般来说,标准的输出和输入设备通常指的是显示器和键盘,在支持重定向的操作系统中,标准输入输出能被替换。

⏹DOS系统为例,看一段代码:

#include/*使用printf要包含的头文件*/

voidmain(void)/*主函数*/

{

printf("本段文字用来测试重定向");/*输出提示信息*/

getchar();/*等待,按任意键继续*/

}

Hello.exe<输入,>输出

6.2.6文件类型指针

指针变量说明:

FILE*fp;

用法:

文件打开时,系统自动建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得文件信息,访问文件

文件关闭后,它的文件结构体被释放

6.2.7文件型结构体

使用printf函数时,输出设备默认为标准输出设备(一般是显示器),因此,不需要告诉printf函数显示器在哪。

但如果想从文件中读取输入,情况就不同了,系统中有不同的磁盘,每个磁盘又有成千上万的文件,到底应该从哪个读呢?

要想对文件进行操作,系统需要很多控制信息,包括文件名,文件当前读写位置,缓冲区位置和大小等,为此,C语言提供了“文件型”结构来标示记录待操作文件的信息,该结构定义于头文件stdio.h中,其形式为:

struct_iobuf

{

char*_ptr;//当前缓冲区内容指针

int_cnt;//缓冲区还有多少个字符

char*_base;//缓冲区的起始地址

int_flag;//文件流的状态,是否错误或者结束

int_file;//文件描述符

int_charbuf;//双字节缓冲,缓冲2个字节

int_bufsiz;//缓冲区大小

char*_tmpfname;//临时文件名

};

typedefstruct_iobufFILE;

6.2.8文件操作步骤

C语言程序在进行文件操作时遵循如下操作步骤:

打开读写操作关闭,通俗地说,打开是获取文件结构、系统为文件分配缓冲区的过程,不打开文件就不能对其进行读写,关闭是释放缓冲区和其他资源的过程,不关闭文件就会慢慢耗光系统资源,。

在进行文件操作时,系统自动与3个标准设备文件联系,这3个文件无需打开和关闭,它们的文件指针分别是:

stdin:

标准输入文件指针,系统分配为键盘。

stdout:

标准输出文件指针,系统分配为显示器。

stderr:

标准错误输出文件指针,系统分配为显示器。

举例来说,从文件输入和向文件输出有两个对应函数fscanf和fprintf,两个函数的原型分别为:

intfprintf(FILE*ofp,控制字符串,参数表);

intfscanf(FILE*ifp,控制字符串,参数表);

参数表中参数的个数同样是任意的,fprintf函数用于将转换后的控制字符串写出到ofp指向的文件中,fscanf用于从ifp指向的文件中读取字节信息为参数表中的参数赋值。

前面章节中用到的标准输入输出函数printf和scanf实际上等价于:

fprintf(stdout,控制字符串,参数表)

fscanf(stdin,控制字符串,参数表)

6.2.9文件打开与关闭

C文件操作用库函数实现,包含在stdio.h

打开文件

函数原型:

FILE*fopen(char*name,char*mode)

功能:

按指定方式打开文件

返值:

正常打开,为指向文件结构体的指针;打开失败,为NULL

关闭文件

作用:

使文件指针变量与文件“脱钩”,释放文件结构体和文件指针

函数原型:

intfclose(FILE*fp)

v功能:

关闭fp指向的文件

v返值:

正常关闭为0;出错时,非0

不关闭文件可能丢失数据

6.2.10字符读写函数fgetc和fputc

fgetc(fp)fp为文件句柄,函数值为得到的字符。

fputc(ch,fp)ch为字符变量,fp为句柄。

成功函数返回相应字符;失败返回EOF。

按照文本的方式读取字符,以及写入字符。

feof

函数原型:

intfeof(FILE*fp)

功能:

判断文件是否结束

返值:

文件结束,返回真(非0);文件未结束,返回0

函数原型:

char*fgets(char*s,intn,FILE*fp)

intfputs(char*s,FILE*fp)

(fputs把s指向的字符串写入fp指向的文件)

v从fp指向的文件读/写一个字符串

v返值:

●fgets正常时返回读取字符串的首地址;出错或文件尾,返回NULL

fputs正常时返回写入的最后一个字符;出错f

gets从fp所指文件读n-1个字符送入s指向的内存区,

并在最后加一个‘\0’

(若读入n-1个字符前遇换行符或文件尾(EOF)即结束)

fputs把s指向的字符串写入fp指向的文件

6.2.11数据块I/O:

fread与fwrite

数据块I/O:

fread与fwrite

函数原型:

size_tfread(void*buffer,size_tsize,size_tcount,FILE*fp)

size_tfwrite(void*buffer,size_tsize,size_tcount,FILE*fp)

功能:

读/写数据块

返值:

成功,返回读/写的块数;出错或文件尾,返回0

说明:

typedefunsignedsize_t;

buffer:

指向要输入/输出数据块的首地址的指针

size:

每个要读/写的数据块的大小(字节数)

count:

要读/写的数据块的个数

fp:

要读/写的文件指针

fread与fwrite一般用于二进制文件的输入/输出

6.2.12格式化I/O:

fprintf与fscanf

格式化I/O:

fprintf与fscanf

函数原型:

intfprintf(FILE*fp,constchar*format[,argument,…])

intfscanf(FILE*fp,constchar*format[,address,…])

v功能:

按格式对文件进行I/O操作

v返值:

成功,返回I/O的个数;出错或文件尾,返回EOF

v例fprintf(fp,“%d,%6.2f”,i,t);//将i和t按%d,%6.2f格式输出到fp文件

vfscanf(fp,“%d,%f”,&i,&t);//若文件中有3,4.5,则将3送入i,4.5送入t

6.2.13如何检测错误

出错的检测

ferror函数

函数原型:

intferror(FILE*fp)

功能:

测试文件是否出现错误

返值:

未出错,0;出错,非0

说明

每次调用文件输入输出函数,均产生一个新的ferror函数值,所以应及时测试

fopen打开文件时,ferror函数初值自动置为0

6.2.14文件定位

前面介绍的文件读写是针对顺序读写的情况,实际上,文件的读写方式有两种,一是顺序读写,位置指针按字节顺序从头到尾移动,另一种是随机读写,位置指针按需要移动到任意位置,随机形式多用于二进制文件的读写。

如果要对文件进行随机读写,就需要控制文件位置指针的值,这就是文件定位,与文件定位有关的函数是rewind函数,fseek函数和ftell函数

文件定位移动到开头rewind

⏹rewind函数没有返回值,其调用形式为;

⏹rewind(FILE*fp);

⏹该函数使得文件位置指针返回文件开头。

得到当前位置—ftell

⏹随机形式允许文件位置指针跳来跳去,为得到文件指针的当前位置,C语言标准库提供了ftell函数,其原型为:

⏹longftell(FILE*);

⏹执行成功时,返回当前文件指针到文件头有多少个字节,否则,返回-1。

移动指针—fseek

⏹文件定位中最重要的一个函数是fseek,用以控制、调整文件指针的值,从而改变下一次读写操作的位置,其函数原型为;

⏹intfseek(FILE*fp,longoffset,intstartPos);

⏹其中,fp是文件指针,startPos是起始点,offset是目标位置相对起始点的偏移量,可以为负数,如果函数操作执行成功,文件位置指针将被设定为“起始点+offset”,起始点并不是任意设定的,C语言给出了3中起始点方式,如所示:

6.2.15文件小结

函数名

功能

fopen()

打开文件

fclose()

关闭文件

fputc()

将字符写入文件中

fgetc()

从文件中读取字符

fread()

将数据从文件中读到缓冲区

fwrite()

将数据从缓冲区写入文件

fseek()

在文件中搜索指定位置

fprintf()

操作类似于printf(),但是用于文件

fscanf()

操作类似于scanf(),但是用于文件

feof()

如果到达文件结尾,返回true

ferror()

如果出错,返回true

rewind()

将文件位置指示器重新置于文件开头

remove()

删除文件

fflush()

将内部缓冲区的数据写入指定文件

6.3指针高级进阶

6.3.1指针与数组名

数组名是一种常指针(不能修改),其值等于数组占据内存单元的首地址,但其类型取决于数组的维数。

二维数组a[i][j]

大家认为&a,*a,a区别在哪里

作为指针存储的地址都是一样,是否意味着指针都一样呢

指针不仅仅有大小,也也有数据类型,类型决定了大小

6.3.2指针访问三维数组

数组与指针关系密切,数组元素除了可以使用下标来访问,还可用指针形式表示。

数组元素可以很方便地用数组名常指针来表示,以3维int型数组A举例,其中的元素A[i][j][k]可用下述形式表示:

(1)*(A[i][j]+k)

A[i][j]是int型指针,其值为&A[i][j][0],因此,A[i][j][k]可表述为*(A[i][j]+k)。

(2)*(*(A[i]+j)+k)

和第一种形式比较,不难发现A[i][j]=*(A[i]+j),A[i]是二级指针,其值为&A[i][0]。

(3)*(*(*(A+i)+j)+k)

将第2种形式的A[i]替换成了*(A+i),此处A是三级指针,其值为&A[0]。

此处以3维数组举例,还可进一步推广到更高维的情况。

6.3.3指针数组

指针也可作为数组中的元素,将一个个指针用数组形式组织起来,就构成了指针数组。

一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。

定义一维指针数组的一般形式为

类型名*数组名[数组长度];

int*p[4];

例1:

有一个指针数组,其元素分别指向一个整型数组的元素,用指向指针数据的指针变量,输出整型数组各元素的值。

然后从小到大显示。

例2:

将若干字符串按字母顺序(由小到大)输出。

解题思路:

定义一个指针数组,用各字符串对它进行初始化,然后排序,但不是移动字符串,而是改变指针数组的各元素的指向。

指针数组的一个重要应用是作为main函数的形参。

在以往的程序中,main函数的第一行一般写成以下形式:

intmain()或intmain(void)

表示main函数没有参数,调用main函数时不必给出实参。

这是一般程序常采用的形式。

6.3.4指向指针数据的指针

在了解了指针数组的基础上,需要了解指向指针数据的指针变量,简称为指向指针的指针。

char*name[]={“Follow”,“Great”,“FORTRAN”,“Computer”};

char**p;inti;

for(i=0;i<5;i++)

{

p=name+i;

printf("%s\n",*p);

}

6.3.5命令行

实际上,在某些情况下,main函数可以有参数,例如:

intmain(intargc,char*argv[])

其中,argc和argv就是main函数的形参,它们是程序的“命令行参数”。

argv是*char指针数组,数组中每一个元素(其值为指针)指向命令行中的一个字符串。

通常main函数和其他函数组成一个文件模块,有一个文件名。

对这个文件进行编译和连接,得到可执行文件(后缀为.exe)。

用户执行这个可执行文件,操作系统就调用main函数,然后由main函数调用其他函数,从而完成程序的功能。

#include

intmain(intargc,char*argv[])

{while(argc>1)

{++argv;

printf(“%s\n”,*argv);

--argc;

}

return0;

}

6.3.6指向数组结构的指针

普通数组名可以看成是“指向数组元素首地址的常指针”,结构体数组名同样可以看成是指向结构体数组元素首地址的常指针,也可以声明一个结构指针变量,使其指向数组元素首地址,这两种方式都能实现通过指针访问数组元素,我们来亲自动手实践一下。

6.3.7函数指针内存原理

函数被载入内存,函数必然有一个地址是函数的入口,我们用这个地址来调用,函数名也是指向函数入口点的指针,我们可以通过函数名找到函数的执行入口。

同时C语言的编译器(无论VC或者GCC)都有这样的规则。

针对函数voidrun(),函数名run解析为函数的地址,run,&run,*run都解析为run的入口地址,即为&run函数的首地址。

而且函数名不可以用sizeof操作符。

6.3.8函数指针数组

先复习下指针数组的概念,当数组元素都是同种类型的指针时,该数组称为指针数组,如“int*A[3];”即声明了一个指针数组A,大小为3,其中每个元素都是int型指针。

如果数组元素都是指向同型函数(返回值类型相同,参数类型相同)的指针,该数组称为函数指针数组,来看一个例子:

double(*f[5])();

f是一个数组,有5个元素,元素都是函数指针,指向的函数类型是没有参数且返回double类型的函数。

函数指针数组的使用方式和普通数组完全一致,我们来亲自演练一下。

double(*f[5])();

已经知道,数组名可作为指向数组首元素起始地址的常指针,那函数指针数组的数组名是什么呢?

类推得出,函数指针数组名,对应上面语句中的f,是指向函数指针的常指针,下述代码声明了一个指向函数指针的指针变量p,并用f为其初始化:

double(**p)()=f;

6.3.9对比define与typedef

C语言中,内置类型,如int型,其指针(int*)可以看成种新的类型,那有没有函数指针类型呢?

借助前面介绍的typedef,能容易地将函数指针类型化。

在结构体和共用体一节中介绍了typedef和#define的基本用法,对比了以下两个语句:

typedefdouble*DP;

DPpDouble1,pDouble2;

#defineDPdouble*

DPpDouble1,pDouble2;

不知大家是否还记得两者的不同,通俗地说,#define是种字面替换,而typedef却是引入一个新的助记符号,这么说稍显枯燥,下面给出一个简单的理解方式:

试着将上面语句中的typedef和#define去掉试试看。

对typedef语句“typedefdouble*DP;”来说,去掉typedef后,其仍然是条完整的C语句“double*DP;”,该语句用以声明一个double类型的指针变量DP。

由此可以理解:

typedef的作用是将变量名作为(或说定义为)该变量所属类型的别名(或说助记符)。

#define不具备这种特点,去掉#define后,“DPdouble*”并不是一条合法的C语句。

如何用define与typedef定义函数指针?

6.3.10

6.4函数进阶

本节从更深层次帮助大家理解函数。

主要是函数的参数的传递两种形式,传值与传地址。

函数的输入-参数,函数的输出-返回值不仅可以是int,double等等也可以是数组,结构体等等。

6.4.1参数传递的副本机制

如果将函数比作剧本,那形参和实参的关系相当于角色和演员的关系,函数的参数传递有传值和传地址两种方式。

传值调用时,在函数内对形参的改变都不会影响实参,要想在函数内对实参进行操作,必须采用传地址调用的方式。

这是形象化的理解,从本质上说,这是由参数传递的副本机制决定的。

所谓副本机制,是指copy(拷贝)的思想,不论是传值调用还是传址调用,编译器都要为每个参数制作临时副本,或称拷贝,函数体中对参数的修改都是对副本的修改,下面具体分析之。

6.4.2传址调用的副本机制

⏹相比传值调用,传址调用似乎要复杂一点,但只要知道,传址调用也是通过副本机制,便能很好地理解传址调用的机理.

6.4.3return局部变量为什么合法

函数返回的副本机制很好地解释了为什么return一个局部变量是合法的,来看一段简单的求和函数代码:

intsum(inta,intb)/*函数定义*/

{

intc=a+b;/*局部变量c*/

returnc;/*返回*/

}

……

intd=sum(1,2);/*函数调用*/

来看语句“intd=sum(1,2);”,该语句先执行函数sum,sum函数执行完毕后将结果赋值给int型变量d,如果从字面上理解,是将c赋值给d,但实际上,在执行赋值操作时,由于函数sum已经执行完毕返回,函数中的局部变量c已被撤销,不存在了。

实际上,在c被撤销前,函数已经为返回值c创建了副本,保存在特定的位置上,赋值操作是由该位置处的副本完成的,形象的示意如所示。

6.4.4函数返回值的副本机制

6.5

6.6

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 表格模板 > 调查报告

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2