最新C语言讲义第12章
c语言学习c语言课件第12章
1. 读字符串函数fgets
C提供读字符串的函数原型在stdio.h头文件中,其函数形式为 :
char *fgets(char *str,int num,FILE *fp)
unsigned char *curp; /*文件读写位置*/
unsigned istemp;
/*临时文件,指示器*/
short token;
/*用于有效性的检查*/
} FILE;
在操作文件以前,应先定义文件类型的指针,定义 的一般格式:
FILE *指针变量标识符
例如:
FILE *fp1,*fp2;
例如:
ch=fgetc(fp);/*从fp指向的文件中读取一个字符送入ch 变量中*/
2. 写字符函数fputc
fputc()函数的原型为:
int fputc(int ch,FILE *fp)
功能:将字符ch的值写入所指定文件的当前位置处,并将文件 指针后移一位。fputc()函数的返回值是所写入字符的值,出 错时返回EOF。
2)标准输出文件——stdout:指向终端输出(一 般为显示器)。
3)标准错误文件——stderr:指向终端标准错误 输出(一般为显示器)。
12.2.2 文件的关闭──fclose()函数 1.用法: int fclose(FILE *文件指针); 2.功能:关闭“文件指针”所指向的文件。如果 正常关闭了文件,则函数返回值为0;否则,返回值 为非0。 例如,fclose(fp);/*关闭fp所指向的文件*/
文件命名规则,遵循操作系统的约定。 2.文件分类 可以从不同的角度对文件进行分类: (1)根据文件的内容,可分为程序文件和数据文 件,程序文件又可分为源文件、目标文件和可执行文件 。 (2)根据文件的组织形式,可分为顺序存取文件 和随机存取文件。
第12章 c语言位运算.ppt
unsigned half_carry: 1; /*半进位标志*/
unsigned negative: 1; /*减标志*/
} flags;
显然,对CPU的状态寄存器而言,使用位段类型(仅需1 个字节),比使用结构类型(需要6个字节)节省了5个 字节。
定义位段的一般格式 struct [结构类型名]
76543210
图11-1 1个字节各二进制位的编号 2.数值的原码表示 数值的原码表示是指,将最高位用作符号位(0表示正 数,1表示负数),其余各位代表数值本身的绝对值(以二 进制形式表示)的表示形式。为简化描述起见,本节约定
用1个字节表示1个整数。
例如,+9的原码是00001001
└→符号位上的0表示正数 -9的原码是10001001。
main()
{ int num, mask, i;
printf("Input a integer number: ");
scanf("%d",&num);
mask = 1<<15; /*构造1个最高位为1、其余各位为0的整数(屏蔽字)*/
printf("%d=" , num);
for(i=1; i<=16; i++)
/*案例代码文件名:AL12_1.C*/ /*程序功能:输出一个整数中由8~11位构成的 数*/ main()
{ int num, mask; printf("Input a integer number: "); scanf("%d",&num); num >>= 8; /*右移8位,将8~11位移到低4位上*/ mask = ~ ( ~0 << 4); /*间接构造1个低4位为1、其
C语言讲义第12章.ppt
fwrite(内存地址,长度,次数,文件指针);
float x;
fread ( &x , sizeof(float), 1, fp);
fwrite( &x , 4 , 1 , fp);
19
若有以下的定义和说明
#include”stdio.h” struct std { char num[6];
char name[8]; float mark[4]; } a[30]; FILE *fp;
文件尾部,此时可以进行追加或读操作。
10
如果是二进制文件,则在方式后加“b”。
如果不能正确完成文件的打开操作,函数fopen将返 回错误信息,即返回空指针值NULL。
if ( (fp=fopen (“file1.C”, “r” ) )= =NULL) { printf(“cannot open this file\n”);
main( )
printf(“%d,%f\n” ,_r_.n_u_m__,_r_.t_o_t_a_l _);
{ FILE *f;
f=fopen( “bin.dat”, “rb”); }
reout(f);
}
fanf 函数 是格式化的读写函数,与printf和scanf相仿,但 其读写对象不是终端而是磁盘文件。 fprintf(文件指针,格式字符串,输出列表); fscanf(文件指针,格式字符串,输入列表);
设文件中以二进制形式存有10个班的学生 数据, 且已正确打开,文件指针定位于文件 开头,若要从文件中读30个学生的数据放入 ss数组中,以下不能实现此功能的语句是
A) for (i=0;i<30;i++) fread(&a[i], sizeof(struct std), 1L, fp);
C语言第十二章
说明:高位左移后溢出,舍弃不起作用。
左移后被溢出舍弃的高位中若不包含1, 则左移1位相当于该数乘以2,则左移n位相当 于该数乘以2n。
右 移 运 算 符 ( >> )
右移运算符“>>”是双目运算符。其功能是把 “>> ”左边的运算数的各二进位全部右移若干位, “>>”运算符右边的数指定移动的位数。
即: 0&0=0; 0&1=0; 1&0=0; 1&1=1
例如:9&5可写算式如下: 00001001 &00000101 00000001 (9的二进制补码) (5的二进制补码) (1的二进制补码)
可见9&5=1。
(1)清零。
按位与的用途:
(2)取一个数中某些指定位。 (3)保留某些位。
如果想将一个单元清零,即使其全部二进制位 为0,只要找一个二进制数,让原来的数中为1的 位,新数中相应位为0,然后使二者进行&运算, 即可达到清零目的。若想取指定的某些位或保留某 些位,只要让这些位与1进行与运算即可。
例如:设 a=15,则 a>>2 表示把000001111右移为00000011(十进制3)。如图: 00 00 00 00 00 00 11 11 00 00 00 00 00 00 00 11
说明:右移有两种:逻辑右移和算术右移,
逻辑右移:不论高位是0还是1,右移时高位补0。 算术右移:对于有符号数,在右移时,符号位将随同移动。当为正 数时,最高位补0,而为负数时,符号位为1,最高位补1。 右移时是算术右移还是逻辑右移,取决于编译系统的规定。 Turbo C和很多系统规定为补1。
——————————
(9的二进制补码) (5的二进制补码) (1的二进制补码)
C语言新教材PPT课堂课件第12章位运算
1011=11 (3)主要用途:将1个数的某(些)位置1,其余各位不变。
3.按位异或── ^ (1)格式:x^y (2)规则:对应位相同时为0,不同时为1:3^9=10。 例如,3^9=1: 0011
^ 1001
────
1010=10 (3)主要用途:使1个数的某(些)位翻转(即原来为1的位变为0,为0 的变为1),其余各位不变。 4.按位取反── ~ (1)格式:~x (2)规则:各位翻转,即原来为1的位变成0,原来为0的位变成1: 在IBM-PC机中,~0=0xffff,~9=0xfff6。 (3)主要用途:间接地构造一个数,以增强程序的可移植性。 5.按位左移── << (1)格式:x<< 位数 (2)规则:使操作数的各位左移,低位补0,高位溢出:5<<2=20。
程序运行情况:
Input a integer number:1000 ←┘
result=0x3
程序说明:~ ( ~0 << 4)按位取0的反,为全1;左移4位后,其低4位为0,其 余各位为1;再按位取反,则其低4位为1,其余各位为0。这个整数正是我们 所需要的。
[例12.2] 从键盘上输入1个正整数给int变量num,按二进制位输 出该数。
printf("Input a integer number: ");
scanf("%d",&num);
num >>= 8;
/*右移8位,将8~15位移到低8位上*/
mask = ~ ( ~0 << 4);/*间接构造1个低4位为1、其余各位为0的整数*/
printf("result=0x%x\n", num & mask); }
Chapter12
12.1 位运算符和位运算
按位或的用途: 1) 用1相或可以臵1 2) 用0相或保留原样 如: main( ) { unsigned a=128; a=a|7; printf("%xH", a); } 87H
00000000 10000000 | 00000000 00000111 00000000 10000111
C Programming
11
12.1 位运算符和位运算
2. “按位或”运算 运算符:| 双目、10级 运算规则:两个操作数的相应位只要有一个为1, 结果相应位为1;两个相应位全0,结 果相应位为0。 如:060|027 00110000 060 | 00010111 027 00110111
C Programming 12
C Programming 28
12.1 位运算符和位运算
8. 不同长度数据的位运算 两个不同长度的数据进行位运算时,系统自 动将两数按低位对齐,并且将较短数高位视情况 补0或补1,使两数长度一致再进行运算。 补0补1规则: 补0——无符号整数、有符号正整数 补1——有符号负整数 如: long a=0xAAAAAAAA; int b=-1; printf("%d,%lX\n", sizeof(a&b), a&b); 4,AAAAAAAA
C Programming 6
12.1 位运算符和位运算
1. “按位与”运算 运算符:& 双目、8级 运算规则:两个操作数的相应位都为1,结果相 应位为1,否则为0。 如: 11000001 带有奇校验位的字符'A' & 01111111 二进制的127 01000001 还原为字符'A'
计算机二级C语言第12章 编译预处理与动态存储分配
正确答案:D 【解析】ANSI C标准规定malloc函数的返回值类型为void *,要是p指向double类型的动态存储单 元,需要使用强制类型转换double *,本题答案为D。
假设short int型数据占2字节、float型数据占4字节存储单元,则以下程序段将使Pi指向一个short int类型的存 储单元,使pf指向一个float类型的存储单元: short int *pi; float * pf; pi = ( short * ) malloc ( 2 ); pf = ( float * ) malloc(4); malloc函数返回的指针为void *(无值型),在调用函数时,必须利用强制类型转换将其转成所需的类型。上面的 程序段中,调用malloc函数时括号中的*号不可少,否则就转换成普通变量类型而不是指针类型了。
C语言中还有一种称作“动态存储分配”的内存空间分配方式:在程序执行期间需要空间来 存储数据时, 通过“申请”得到指定的内存空间;当有闲置不用的空间时,可以随时将其释放,由系统另作他用。
malloc函数
函数的调用形式为:malloc ( size)。
该函数包含在头文件stdlib.h里,返回值的类型为void *, malloc函数用来分配size个字节的存储区,返回一 个指向存储区首地址的基类型为void的地址。若没有足够的内存单元供分配,函数返回空(null)。
目录页
CONTENTS PAGE
计算机二级C语言 第12章 编译预处理与动态存储分配
所谓“编译预处理”就是在C编译程序对C源程序进行编译前,由编译预处理程序对这些编译预处理命 令行进行处理的过程。 预处理命令行必须在一行的开头以“#”号开始,每行的末尾不得用“;”号结束。 这些命令行的语法与C语言中其他部分的语法无关。根据需要,命令行可以出现在程序的任何一行的开 始部位,其作用一直持续到源文件的末尾。 重点是:#define 和 #include 命令行
C语言与程序设计ppt-第12章递归
第12章 递 归
华中科技大学计算机学院 卢萍
华中科技大学计算机学院C语言课
2021/4/25
程组
1
本章讲授内容
递归(recursion)是一项非常重要的编 程技巧,可以使程序变得简洁和清晰,是 许多复杂算法的基础。本章介绍 递归、递归函数的概念; 递归的执行过程; 典型问题的递归函数设计; 分治法与快速排序; 回溯法; 递归在动态规划等算法中的应用。
12
【例12.3】 设计一个求解汉诺塔问题的算法。
这是一个典型的用递归方法求解的问题。要移动n个 盘子,可先考虑如何移动n 1个盘子。分解为以下3 个步骤:
(1)把A上的n-1个盘子借助C移到B。 (2)把A上剩下的盘子(即最大的那个)移到C。 (3)把B上的n-1个盘子借助A移到C。 其中,第(1)步和第(3)步又可用同样的3步继
2021/4/25
华中科技大学计算机学院C语言课程组
2
12.1 递归概述
递归是一种函数在其定义中直接或间接调用 自己的编程技巧。递归策略只需少量代码就 可描述出解题过程所需要的多次重复计算, 十分简单且易于理解。
递归调用:函数直接调用自己或通过另一函 数间接调用自己的函数调用方式
递归函数:在函数定义中含有递归调用的函 数
续分解,依次分解下去,盘子数目n每次减少1,直 至n为1结束。这显然是一个递归过程,递归结束条 件是n为1。
2021/4/25
华中科技大学计算机学院C语言课程组
13
函数move(n,a,b,c)
为了更清楚地描述算法,可以定义一个函数 move(n,a,b,c)。该函数的功能是:将n个盘 子从木桩a上借助木桩b移动到木桩c上。算法 的第(1)步和第(3)步的实现都是递归调 用,分别为move(n-1,a,c,b)和move(n1,b,a,c)。
c语言从入门到精通__第12章
12.1.1 指针与数组
&grade[3]=&grade[0] + 3 * 4 上面表达式的含义是gradep[3]的地址等于grade[0]地址加上12。写成以下 的通式: 数组中下标为N元素的地址 = 数组的首地址 + N * sizeof(DataType) 例如: int grade[5]; /*定义array为包含5个整型数据的数组*/ int *p; /*定义p为指向整型变量的指针变量*/ p=&grade[0];
12.1.2 数组名作为指针
每个创建的数组,数组名就成为编译器为这 个数组所创建的指针常量名称,存储的是数 组第一个元素的起始地址,也是我们所说的 数组首地址。这样,我们就有多了一种获取 数组元素地址的手段。如【范例12-1】中 代码“p=&grade[0];”就可以改写为 “p=grade;”。
例如:输入字符串“abcdefgabcdeabc”,输出的 结果应该是“3 3 3 2 2 2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0”
12.2 指针与字符串
12.2.1 12.2.2 12.2.3 12.2.4 使用指针创建字符串 使用指针处理字符串 指针的指针 指针数组和数组指针
指针与数组 指针与字符串 综合应用——报数游戏 跟我上机
第12章
指针的深入研究——指针进阶
指针与数组 指针与字符串 综合应用——报数游戏 跟我上机
12.1 指针与数组
12.1.1 12.1.2 12.1.3 12.1.4 指针与数组 数组名作为指针 指针与多维数组 指针与数组参数
12.1.1 指针与数组
12.2.1 使用指针创建字符串
C语言第12章PPT教学课件
printf("input a to creat(########.###):"); gets(); if ((fp=fopen(,"wb"))==NULL)
如果正常关闭了文件,则函数返回值为0; 否则,返回值为非0(-1)。
2020/12/09
9
12.3 文件的读写操作
文件打开之后,就可以对它进行读与写的操作了。
12.3.1 读/写一个字符 12.3.3 读/写一个数据块 12.3.2 读/写一个字符串 12.3.4 格式化读/写 12.3.5 读/写函数的选用原则
第12章 文 件
程序运行时,数据一般都存放在内存中。当程序运行结 束后,存放在内存中的数据被释放。
如需长期保存程序运行所需的原始数据,或程序运行产 生的结果,就必须将数据以文件形式存储到外部存储介质上。
12.1 C语言文件概述 12.2 文件的操作步骤 12.3 文件的读写操作 12.4 位置指针与文件定位 12.5 出错检测
p.310
二、打开文件──fopen()函数 以某种使用方式打开文件
p.311
if( (fp=fopen(“文件名”,“使用方式”)) ==NULL)
{ printf("can not open this file\n");
exit(0);
}
正常返回DOS
2020/12/09
7
文件的使用方式: “r” 以只读方式打开已有文本文件 “w” 以只写方式打开新文本文件 “a” 以只写方式打开已有文本文件,追加数据到末尾 “r+”、”w+”、”a+” 以读写方式打开ASCII文件
2020/12/09
1
c语言12
struct numST { int num; struct numST *next; };
// 结构声明
// 整型数 // numST结构指针
4
// 被调用函数insert(),两个形参分别表示链表和待插入的结点 void insert (struct numST **phead, struct numST *p) { // 函数体开始 struct numST *q,*r; // 定义结构指针q,r if ((*phead)==null) // 第一种情况,链表为空 { *phead = p; // 链表头指向p return; // 完成插入操作,返回 } else // 链表不为空 { // 第二种情况,p结点num值小于链表头结点的num值 if ( (*phead)->num > p->num ) { // 将p结点插到链表头部 p->next = *phead;// 将p的next指针指向链表头(*phead) *phead = p; // 将链表头赋值为p return; // 返回 5 }
head
5
10 15 null
该链表的头结点由head所指向。
10
3、构造一个结点p,在p结点的数据域放12,再插入 链表 (1)p=(struct numST*) malloc(LEN); (2)p->num=12;; (3)p->next=null; 4、调用insert函数来插入p结点。 语句为 insert(&head,p); 意思是以将p插入到以head为队头的链表中。但这 里在调用时,不是用head作为实参,而是用&head 作为实参,属于传址调用,而非传值调用。
也就是说如果从键盘输入数据来建立二叉树第一个数据就是这棵树的根的数据之后再输入的数据每一个都要与根中的数据作比较以便确定该数据所在接点的插入位置
C语言第12章
Turbo C提供了一个自动检测显示器硬件的函数, 其调用格式 为: void far detectgraph(int *gdriver, *gmode); 其中gdriver和gmode的意义见表12.5。
【例12-3】自动进行硬件测试后进行图形初始化。 - #include <graphics.h> main() { int gdriver, gmode; detectgraph(&gdriver, &gmode); /*自动测试硬件*/ printf("the graphics driver is %d, mode is %d\n", gdriver, gmode); /*输出测试结果*/ getch(); initgraph(&gdriver, &gmode, "c:\\tc"); /* 根据测试结果初始化 图形*/ bar3d(10, 10, 130, 250, 20, 1); getch(); closegraph(); return 0; }
但某位为1时 表示相应的键已按,或相应的控制功能已有效, 但某位为 时,表示相应的键已按,或相应的控制功能已有效,如选参数 CMD为2,则有:key=bioskey(2)。 若key 值为 值为0x09,则表示右边的 为 ,则有: 。 ,则表示右边的Shift键 键 被按,同时又按Alt键 被按,同时又按 键。
第12章 C语言图形介绍 12章
Turbo C 提供了非常丰富的图形函数以实现图形程序设 计,所有图形函数的原型均在graphics.h中,本章主要介绍 键盘、鼠标、光标等的控制,主要的图形函数的功能、使 用方法,并用实例加以解释。本章的内容供有志于编写实 用系统的读者参考,在实际编写此类程序时可能还需要查 阅相关手册
第12章C语言
第12章运算符重载12.1 什么是运算符重载在第10章中曾介绍过函数重载,已经接触到重载(overloading)这个名词。
所谓重载,就是重新赋予新的含义。
函数重载就是对一个已有的函数赋予新的含义,使之实现新的功能。
因此,同一个函数名就可以代表多个不同功能的函数,也就是一名多用。
运算符也可以重载。
运算符重载的概念,其实并不陌生,只是此前没有做进一步的讲解。
如“+”加法运算符,在C语言中已经用的很多了。
在C++中,若对数值型数据进行“+、-、*、/”等操作,可写出如下程序int a,b,c;c=a+b; //对整型变量执行算术的加法运算。
float f1,f2,f3;f3=f1+f2; //对实型变量执行算术的加法运算。
从中可以看出,运算符“+”既可以实现整型变量的加法,又可以实现实型变量的加法。
这说明运算符“+”具有双重功能,它能够根据表达式中运算符两侧的数据类型自动调整该类型所需的数据操作方法。
这样,就可以将同一运算符用于不同的数据类型上实现功能相同的操作。
这就是C++中的运算符重载。
编译系统已经为基本数据类型定义(重载)了一些运算符。
如为数值型数据,定义有“+、-、*、/”等运算符;为关系运算定义了“>、>=、<、<=、!=、==”等运算符;为系统输入输出定义了“>>、<<”操作符。
但对于用户自定义的结构体及类只定义了赋值运算符“=”、成员访问运算符“.”和指针运算符“->”这三种运算符。
换句话说,编译系统在语法中赋予了这些运算符或操作符相应的功能。
编译源程序时,系统遇到什么操作符就执行什么操作。
若用户要对自定义类型数据进行算术、关系、或其他运算,就不能使用这些未加定义(重载)的运算符或操作符,如以下自定义类型数据的“+”运算。
struct fraction //定义表示分数(fraction)的结构体,为完成如(1/2)+(2/3)+(1/3)的加法{int numerator; //分子int denominator; //分母};fraction num1,num2,num3;num3= num1+ num2; //试图执行两个分数的加法运算,编译错误error C2676:num1= num3- num2; //试图执行两个分数的减法运算,编译错误error C2676:编译时提示error C2676:binary '+' : 'struct main::fraction' does not define this operator or a con- version to a type acceptable to the predefined operator错误。
C语言第十二章.ppt
int endangle, int xradius,int yradius);
12.1.5 封闭图形的填充
❖填充模式设置 void far setfillstyle(int pattern, int color); void far setfillpattern(char * upattern,int color); void far getfillpattern(char * upattern); void far getfillsetings(struct fillsettingstype far * fillinfo);
void far moverel(int dx, int dy); 移动游标从当前位置(x, y)移动到 (x+dx, y+dy)的位置, 移动过程中不画点。
❖画点函数 void far putpixel(int x, int y, int color); int far getpixel(int x, int y);
void far initgraph(int far *gdriver,
int far *gmode, char *path); 其中,gdriver和gmode分别表示图形驱动器和模式, path是指图形驱动程序所在的目录路径。其值参见 表12-1
void far detectgraph(int *gdriver, *gmode); 自动检测显示器硬件的函数, 用gdriver= DETECT 语句 进行初始化。
返回当前背景颜色值。
int far getcolor(void);
VC++讲义 第12章
第12章进程间的通讯在上一章中已经简单的介绍过进程,进程是一个可执行的程序,由私有虚拟地址空间、代码、数据和其他操作系统资源(如进程创建的文件、管道、同步对象等)组成。
当启动一个进程时,操作系统会为此进程建立一个4GB的地址空间。
一个应用程序可以有一个或多个进程,一个进程可以有一个或多个线程,其中一个是主线程。
本章将介绍进程的创建、终止以及进程间的几种通讯方式。
12.1 进程控制12.1.1 进程的创建进程控制的意义在于可以创建一个进程,并可以通过进程句柄结束进程。
因为MFC没有提供类处理进程,所以直接使用了Win32 API函数。
创建进程的函数为CreateProcess,原形如下:BOOL CreateProcess(LPCTSTR lpApplicationName,LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCWSTR lpCurrentDirectory,LPSTARTUPINFO lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation);该函数用于创建一个新的进程和其主线程,因为进程是惰性的,要想完成什么事情,就必须拥有一个以上的线程,主线程是万万不能缺少的。
若函数调用成功返回非0值;若调用失败返回0。
第一个参数lpApplicationName,表示执行的程序文件名。
该参数可以是完整的路径和文件名,也可以是相对路径,但一定要给出文件名。
如果在创建进程时要使用参数,则该参数可以为NULL。
第二个参数lpCommandLine,表示命令参数行。