传智播客C提高讲义.docx

上传人:b****1 文档编号:1689664 上传时间:2023-05-01 格式:DOCX 页数:42 大小:1.51MB
下载 相关 举报
传智播客C提高讲义.docx_第1页
第1页 / 共42页
传智播客C提高讲义.docx_第2页
第2页 / 共42页
传智播客C提高讲义.docx_第3页
第3页 / 共42页
传智播客C提高讲义.docx_第4页
第4页 / 共42页
传智播客C提高讲义.docx_第5页
第5页 / 共42页
传智播客C提高讲义.docx_第6页
第6页 / 共42页
传智播客C提高讲义.docx_第7页
第7页 / 共42页
传智播客C提高讲义.docx_第8页
第8页 / 共42页
传智播客C提高讲义.docx_第9页
第9页 / 共42页
传智播客C提高讲义.docx_第10页
第10页 / 共42页
传智播客C提高讲义.docx_第11页
第11页 / 共42页
传智播客C提高讲义.docx_第12页
第12页 / 共42页
传智播客C提高讲义.docx_第13页
第13页 / 共42页
传智播客C提高讲义.docx_第14页
第14页 / 共42页
传智播客C提高讲义.docx_第15页
第15页 / 共42页
传智播客C提高讲义.docx_第16页
第16页 / 共42页
传智播客C提高讲义.docx_第17页
第17页 / 共42页
传智播客C提高讲义.docx_第18页
第18页 / 共42页
传智播客C提高讲义.docx_第19页
第19页 / 共42页
传智播客C提高讲义.docx_第20页
第20页 / 共42页
亲,该文档总共42页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

传智播客C提高讲义.docx

《传智播客C提高讲义.docx》由会员分享,可在线阅读,更多相关《传智播客C提高讲义.docx(42页珍藏版)》请在冰点文库上搜索。

传智播客C提高讲义.docx

传智播客C提高讲义

传智播客C提高讲义

传智扫地僧

1程序内存模型

就业班引言

问题引出

企业需要能干活的人

C学到什么程度可以找工作

对于C/C++初级开发者,怎么达到企业的用人标准

就业问题

问:

老师,有没有一个框框

有没有一个标准啊

我们学什么哪

C工程开发需要什么(培养什么能力)

成熟的、商业化的信息系统在分区、分层

信息系统的技术模型在分层

找出对我们初学者最近的那一层(哪些能力是你入行前,必须要掌握的)

C项目开发的套路(一套接口)

...\n");

getchar();

return0;

}

sizeof是操作符,不是函数;sizeof测量的实体大小为编译期间就已确定

数据类型别名

数据类型可以理解为固定大小内存块的别名,请问数据类型可以起别名吗

intmain()

{

...\n");

getchar();

return0;

}

数据类型的封装

1、void的字面意思是“无类型”,void*则为“无类型指针”,void*可以指向任何类型的数据。

2、用法1:

数据类型的封装

intInitHardEnv(void**handle);

典型的如内存操作函数memcpy和memset的函数原型分别为

 void*memcpy(void*dest,constvoid*src,size_tlen);

 void*memset(void*buffer,intc,size_tnum);

3、用法2:

void修饰函数返回值和参数,仅表示无。

如果函数没有返回值,那么应该将其声明为void型

如果函数没有参数,应该声明其参数为void

intfunction(void)

{return1;}

4、void指针的意义

C语言规定只有相同类型的指针才可以相互赋值

void*指针作为左值用于“接收”任意类型的指针

void*指针作为右值赋值给其它指针时需要强制类型转换

int*p1=NULL;

char*p2=(char*)malloc(sizoeof(char)*20);

5、不存在void类型的变量

C语言没有定义void究竟是多大内存的别名

6、扩展阅读《void类型详解.doc》

数据类型总结与扩展

1、数据类型本质是固定内存大小的别名;是个模具,c语言规定:

通过数据类型定义变量。

2、数据类型大小计算(sizeof)

3、可以给已存在的数据类型起别名typedef

4、数据类型封装概念(void万能类型)

思考1:

C一维数组、二维数组有数据类型吗intarray[10]。

若有,数组类型又如何表达又如定义

若没有,也请说明原因。

抛砖:

数组类型,压死初学者的三座大山

1、数组类型

2、数组指针

3、数组类型和数组指针的关系

思考2:

C语言中,函数是可以看做一种数据类型吗

a)若是,请说明原因

并进一步思考:

函数这种数据类型,能再重定义吗

b)若不是,也请说明原因。

抛砖:

变量本质分析

变量概念

概念:

既能读又能写的内存对象,称为变量;若一旦初始化后不能修改的对象则称为常量。

变量定义形式:

类型标识符,标识符,…,标识符;

例如:

intx;

intwordCut,Radius,Height;

doubleFlightTime,Mileage,Speed;

变量本质

1、程序通过变量来申请和命名内存空间inta=0

2、通过变量名访问内存空间

(一段连续)内存空间的别名(是一个门牌号)

3、修改变量有几种方法

1、直接

2、间接。

内存有地址编号,拿到地址编号也可以修改内存;于是横空出世了!

(编程案例)

3、内存空间可以再取给别名吗

4、数据类型和变量的关系

通过数据类型定义变量

5、总结及思考题

1对内存,可读可写;2通过变量往内存读写数据;3不是向变量读写数据,而是向变量所代表的内存空间中写数据。

问:

变量跑哪去了

思考1:

变量三要素(名称、大小、作用域),变量的生命周期

思考2:

C++编译器是如何管理函数1,函数2变量之间的关系的

====》引出两个重要话题:

内存四区模型

函数调用模型

重要实验:

intmain333()

{

..\n");

getchar();

return0;

}

程序的内存四区模型

内存四区的建立流程

流程说明

1、操作系统把物理硬盘代码load到内存

2、操作系统把c代码分成四个区

3、操作系统找到main函数入口执行

各区元素分析

函数调用模型

基本原理

内存四区模型和函数调用模型变量传递分析

1、一个主程序有n函数组成,c++编译器会建立有几个堆区有几个栈区

2、函数嵌套调用时,实参地址传给形参后,C++编译器如何管理变量的生命周期

分析:

函数A,调用函数B,通过参数传递的变量(内存空间能用吗)

提示学好C语言的关键

如何建立正确的程序运行内存布局图

内存四区模型&函数调用模型

函数内元素

深入理解数据类型和变量“内存”属性

一级指针内存布局图(int*,char*)

二级指针内存布局图(int**char**)

函数间

主调函数分配内存,还是被调用函数分配内存

主调函数如何使用被调用函数分配的内存(技术关键点:

指针做函数参数)

======》学习指针的技术路线图

内存四区强化训练

01全局区训练

char*p1=“abcdefg”;

02堆栈区生命周期训练

Charp1[]=“abcdefg”;

返回基本类型

返回非基本类型

03堆栈属性训练

测试heap生长方向

测试stack生长方向

Heap、stack生长方向和内存存放方向是两个不同概念

野指针

Malloc得到指针释放问题测试

free(p)

free(p+1),深入理解

作业强化

训练1划出内存四区

voidmain26()

{

charbuf[100];

(from==NULL||to==NULL)\n");

return-1;

}

while((*to++=*from++)!

='\0')

{

;

}

return0;

}

典型错误知多少

char*str_cnct(char*x,char*y)/*简化算法*/

{

charstr3[80];

char*z=str3;/*指针z指向数组str3*/

while(*z++=*x++);

z--;/*去掉串尾结束标志*/

while(*z++=*y++);

z=str3;/*将str3地址赋给指针变量z*/

return(z);

}

修改字符常量结果会如何

Char*p=“abcdefg”;

Modifyp[1]=‘1’;

04字符串操作易错

1、

结构体变量的指针->

02、结构体做函数参数

结构体赋值编译器行为研究

结构体变量做函数参数PK结构体指针做函数参数

结构体做函数参数(

..\n");

getchar();

return0;

}

结构体做函数参数及结构体数组

ame,"aaaaa");

ame);

tmp=&teaArray[i];

printf("%s",tmp->name);

}

getchar();

return0;

}

例子

从键盘接受数据。

并排序

intprintfArray(struct_MyTeacher*teaArray,intcount)

{

inti=0;

ame);

printf("\n教师年龄:

");

printf("%d",teaArray[i].age);

}

}

intmain23()

{

inti=0,j=0;

struct_MyTeacherteaArray[3];

struct_MyTeachertmp;

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

{

printf("\n请键入教师名字:

");

scanf("%s",teaArray[i].name);

printf("\n请键入教师年龄:

");

scanf("%d",&teaArray[i].age);

}

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

{

for(j=i+1;j<3;j++)

{

if(teaArray[i].age>teaArray[j].age)

{

tmp=teaArray[i];

teaArray[i]=teaArray[j];

teaArray[j]=tmp;

}

}

}

ame);

printf("\n教师年龄:

");

printf("%d",teaArray[i].age);

}

printf("ddddd\n");

printfArray(teaArray,3);

system("pause");

}

结构体在工程开发中的应用

ame,"aaaaa");

ame);

tmp=&teaArray[i];

printf("%s",tmp->name);

}

getchar();

return0;

}

件的打开fopen()

文件的打开操作表示将给用户指定的文件在内存分配一个FILE结构区,并将该结构的指针返回给用户程序,以后用户程序就可用此FILE指针来实现对指定文件的存取操作了。

当使用打开函数时,必须给出文件名、文件操作方式(读、写或读写),如果该文件名不存在,就意味着建立(只对写文件而言,对读文件则出错),并将文件指针指向文件开头。

若已有一个同名文件存在,则删除该文件,若无同名文件,则建立该文件,并将文件指针指向文件开头。

fopen(char*filename,char*type);

其中*filename是要打开文件的文件名指针,一般用双引号括起来的文件名表示,也可使用双反斜杠隔开的路径名。

而*type参数表示了对打开文件的操作方式。

其可采用的操作方式如下:

方式含义

"r"打开,只读

"w"打开,文件指针指到头,只写

"a"打开,指向文件尾,在已存在文件中追加

"rb"打开一个二进制文件,只读

"wb"打开一个二进制文件,只写

"ab"打开一个二进制文件,进行追加

"r+"以读/写方式打开一个已存在的文件

"w+"以读/写方式建立一个新的文本文件

"a+"以读/写方式打开一个文件文件进行追加

"rb+"以读/写方式打开一个二进制文件

"wb+"以读/写方式建立一个新的二进制文件

"ab+"以读/写方式打开一个二进制文件进行追加

当用fopen(0成功的打开一个文件时,该函数将返回一个FILE指针,如果文件打开失败,将返回一个NULL指针。

如想打开test文件,进行写:

FILE*fp;

if((fp=fopen("test","w"))==NULL)

{

printf("Filecannotbeopened\n");

exit();

}

else

printf("Fileopenedforwriting\n");

……

fclose(fp);

DOS操作系统对同时打开的文件数目是有限制的,缺省值为5,可以通过修改文件改变这个设置。

2.关闭文件函数fclose()

文件操作完成后,必须要用fclose()函数进行关闭,这是因为对打开的文件进行写入时,若文件缓冲区的空间未被写入的内容填满,这些内容不会写到打开的文件中去而丢失。

只有对打开的文件进行关闭操作时,停留在文件缓冲区的内容才能写到该文件中去,从而使文件完整。

再者一旦关闭了文件,该文件对应的FILE结构将被释放,从而使关闭的文件得到保护,因为这时对该文件的存取操作将不会进行。

文件的关闭也意味着释放了该文件的缓冲区。

intfclose(FILE*stream);

它表示该函数将关闭FILE指针对应的文件,并返回一个整数值。

若成功地关闭了文件,则返回一个0值,否则返回一个非0值。

常用以下方法进行测试:

if(fclose(fp)!

=0)

{

printf("Filecannotbeclosed\n");

exit

(1);

}

else

printf("Fileisnowclosed\n");

当打开多个文件进行操作,而又要同时关闭时,可采用fcloseall()函数,它将关闭所有在程序中打开的文件。

intfcloseall();

该函数将关闭所有已打开的文件,将各文件缓冲区未装满的内容写到相应的文件中去,接着释放这些缓冲区,并返回关闭文件的数目。

如关闭了4个文件,则当执行:

n=fcloseall();时,n应为4。

3.文件的读写

(1).读写文件中字符的函数(一次只读写文件中的一个字符):

intfgetc(FILE*stream);

intfgetchar(void);

intfputc(intch,FILE*stream);

intfputchar(intch);

intgetc(FILE*stream);

intputc(intch,FILE*stream);

其中fgetc()函数将把由流指针指向的文件中的一个字符读出,例如:

ch=fgetc(fp);

将把流指针fp指向的文件中的一个字符读出,并赋给ch,当执行fgetc()函数时,若当时文件指针指到文件尾,即遇到文件结束标志EOF(其对应值为-1),该函数返回一个-1给ch,在程序中常用检查该函数返回值是否为-1来判断是否已读到文件尾,从而决定是否继续。

#include""

main()

{

FILE*fp;

chch;

if((fp=fopen("","r"))==NULL)

{

printf("filecannotbeopened\n");

exit

(1);

}

while((ch=fgetc(fp))!

=EOF)fputc(ch,stdout);

fclose(fp);

}

该程序以只读方式打开文件,在执行while循环时,文件指针每循环一次后移一个字符位置。

用fgetc()函数将文件指针指定的字符读到ch变量中,然后用fputc()函数在屏幕上显示,当读到文件结束标志EOF时,变关闭该文件。

上面的程序用到了fputc()函数,该函数将字符变量ch的值写到流指针指定的文件中去,由于流指针用的是标准输出(显示器)的FILE指针stdout,故读出的字符将在显示器上显示。

又比如:

putc(ch,fp);

该函数执行结构,将把ch表示的字符送到流指针fp指向的文件中去。

在TC中,putc()等价于fput(),getc()等价于fgetc()。

putchar(c)相当于fputc(c,stdout);getchar()相当于fgetc(stdin)。

注意,这里使用charch,其实是不科学的,因为最后判断结束标志时,是看ch!

=EOF,而EOF的值为-1,这显然和char是不能比较的。

所以,某些使用,我们都定义成intch。

(2).读写文件中字符串的函数

char*fgets(char*string,intn,FILE*stream);

char*gets(char*s);

intfprintf(FILE*stream,char*format,variable-list);

intfputs(char*string,FILE*stream);

intfscanf(FILE*stream,char*format,variable-list);

其中fgets()函数将把由流指针指定的文件中n-1个字符,读到由指针stream指向的字符数组中去,例如:

fgets(buffer,9,fp);

将把fp指向的文件中的8个字符读到buffer内存区,buffer可以是定义的字符数组,也可以是动态分配的内存区。

注意,fgets()函数读到'\n'就停止,而不管是否达到数目要求。

同时在读取字符串的最后加上'\0'。

fgets()函数执行完以后,返回一个指向该串的指针。

如果读到文件尾或出错,则均返回一个空指针NULL,所以长用feof()函数来测定是否到了文件尾或者是ferror()函数来测试是否出错,例如下面的程序用fgets()函数读文件中的第一行并显示出来:

#include""

main()

{

FILE*fp;

charstr[128];

if((fp=fopen("","r"))==NULL)

{

printf("cannotopenfile\n");

exit

(1);

}

while(!

feof(fp))

{

if(fgets(str,128,fp)!

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

}

fclose(fp);

}

gets()函数执行时,只要未遇到换行符或文件结束标志,将一直读下去。

因此读到什么时候为止,需要用户进行控制,否则可能造成存储区的溢出。

fputs()函数想指定文件写入一个由string指向的字符串,'\0'不写入文件。

fprintf()和fscanf()同printf()和scanf()函数类似,不同之处就是printf()函数是想显示器输出,fprintf()则是向流指针指向的文件输出;fscanf()是从文件输入。

下面程序是向文件里输入一些字符:

#include<>

main()

{

char*s="That'sgoodnews";

inti=617;

FILE*fp;

fp=fopne("","w");

fputs("YourscoreofTOEFLis",fp);

fputc(':

',fp);

fprintf(fp,"%d\n",i);

fprintf(fp,"%s",s);

fclose(fp);

}

用DOS的TYPE命令显示的内容如下所示:

屏幕显示

YourscoreofTOEFLis:

617

That'sgoodnews

下面的程序是把上面的文件里的内容在屏幕上显示出来:

#include<>

main()

{

char*s,m[20];

inti;

FILE*fp;

fp=fopen("","r");

fgets(s,24,fp);

printf("%s",s);

fscanf(fp,"%d",&i);

printf("%d",i);

putchar(fgetc(fp));

fgets(m,17,fp);

puts(m);

fclose(fp);

getch();

}

运行后屏幕显示:

YourscoreofTOEFLis:

617

That'sgoodnews

4.清除和设置文件缓冲区

(1).清除文件缓冲区函数:

intfflush(FILE*stream);

intflushall();

fflush()函数将清除由stream指向的文件缓冲区里的内容,常用于写完一些数据后,立即用该函数清除缓冲区,以免误操作时,破坏原来的数据。

flushall()将清除所有打开文件所对应的文件缓冲区。

(2).设置文件缓冲区函数

voidsetbuf(FILE*stream,char*buf);

voidsetvbuf(FILE*stream,char*buf,inttype,unsignedsize);

这两个函数将使得打开文件后,用户可建立自己的文件缓冲区,而不使用fopen()函数打开文件设定的默认缓冲区。

对于setbuf()函数,buf指出的缓冲区长度由头文件中定义的宏BUFSIZE的值决定,缺省值为512字节。

当选定buf为空时,setbuf函数将使的文件I/O不带缓冲。

而对setvbuf函数,则由malloc函数来分配缓冲区。

参数size指明了缓冲区的长度(必须大于0),而参数type则表示了缓冲的类型,其值可以取如下值:

type值含义

_IOFBF文件全部缓冲,即缓冲区装满后,才能对文件读写

_IOLBF文件行缓冲,即缓冲区接收到一个换行符时,才能对文件读写

_IONBF文件不缓冲,此时忽略buf,size的值,直接读写文件,不再经过文件缓冲区缓冲

5.文件的随机读写函数

前面介绍的文件的字符/字符串读写,均是进行文件的顺序读写,即总是从文件的开头开始进行读写。

这显然不能满足我们的要求,C语言提供了移动文件指针和随机读写的函数,它们是:

(1).移动文件指针函数:

longftell(FILE*stream);

intrewind(FILE*stream);

fseek(FILE*stream,longoffset,intorigin);

函数ftell()用来得到文件指针离文件开头的偏移量。

当返回值是-1时表示出错。

rewind()函数用于文件指针移到文件的开头,当移动成功时,返回0,否则返回一个非0值。

fseek()函数用于把文件指针以origin为起点移动offset个字节,其中origin指出的位置可有以下几种:

origin数值代表的具体位置

SEEK_SET0文件开头

SEEK_CUR1文件指针当前位置

SEEK_END2文件尾

例如:

fseek(fp,10L,0);

把文件指针从文件开头移到第10字节处,由于offset参数要求是长整型数,故其数后带L。

fseek(fp,-15L,2);

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

当前位置:首页 > 初中教育 > 语文

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

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