Presentation is loading. Please wait.

Presentation is loading. Please wait.

C语言程序设计 北京工业大学计算机学院 软件学科部 宋凯 学时40:课堂24+上机16

Similar presentations


Presentation on theme: "C语言程序设计 北京工业大学计算机学院 软件学科部 宋凯 学时40:课堂24+上机16"— Presentation transcript:

1 C语言程序设计 北京工业大学计算机学院 软件学科部 宋凯 学时40:课堂24+上机16
软件学科部 宋凯 学时40:课堂24+上机16 教案下载:

2 教学安排 总学时: 40 上课:24学时 星期二 7-8节(1,10周) 1-316 星期四 5-6节(1-10周) 1-316
星期二 7-8节(1,10周) 星期四 5-6节(1-10周) 上机:16学时 星期二 7-8节(2-9周) 信南206 (微机1室)

3 计算机与算法初步总结 教学效果 存在问题 初步的程序设计基础知识 初步的程序编程和调试能力 工程能力:设计规范、算法描述等 分析问题能力
动手能力 考试要求低,不反映实际水平

4 本学期的教学内容调整 教学内容 作业要求 增加软件工程初步、程序文档编制 编程体要求提供数据说明和程序流程图 上机题
预先完成算法设计(数据说明和程序流程图) 上交实验报告(功能简介、数据说明和流程图)

5 一、什么是地址? 计算机内存是以字节为单位的一片连续的存储空间,每个字节都有一个编号,这个编号就称为内存地址。 内存地址的特点:
地址是连续的; 通常用二进制表示。为直观起见,在高级语言中,可以用十进制表示。

6 二、变量与地址的关系 每个变量在内存中都占有一定字节数的存储单元。 int a, b; float x;
... a b x 变量的地址是指该变量所占存储单元的首字节地址。 可以使用运算符&获取变量的地址: &a、 &b、&x。 变量的内容是指在内存的存储单元中存放的数据。

7 第六章 指针 6.1 指针的概念 什么是指针 指针变量的声明 保存内存单元地址的变量 为内存中的数据提供了直接访问手段
第六章 指针 指针的概念 什么是指针 保存内存单元地址的变量 为内存中的数据提供了直接访问手段 指针变量的声明 int *p; 声明p 用于保存整型数据的地址 double *q; 声明q 用于保存双精度数据的地址 变量p, q本身各占用4个字节(地址需用的空间) 指针变量本身的数据长度是由系统决定的。

8 指针变量示意图 1012 a ptr 2002 a ptr 2002 a ptr

9 操作方式 a a=123 123 直接操作 ptr *ptr=123 间接操作 ptr = &a 间接访问提供了另一种访问内存数据的手段

10 指针变量的特性有2点: (1)变量的值为地址值; (2)变量的类型为该指针所指向的实体的类型。 指针的名字与一般变量名相同。

11 通过指针的引用与赋值 注意: 定义后的指针在没有赋初值或赋值之前是不能使用的. x 3.02 double x, y; double *q;
q = &x; /* 取 x 的地址 */ *q = /* 等效于 x = 3.02 */ y = *q; /* 等效于 y = x */ 变量的地址 = 所占用单元的首地址 3.02 注意: 定义后的指针在没有赋初值或赋值之前是不能使用的.

12 &和*是 指针操作中两个特殊的单目运算符。
指针相关运算符 &和*是 指针操作中两个特殊的单目运算符。 取地址运算符: & 指针运算符(间接访问运算符): * (简称:取内容) 它们优先级与结合方式同其他单目运算符。

13 不同指针类型操作示意图: int data1 = 12 , *ptr1; float data2 = 56.8, *ptr2; data1
1000 1002 2001 2003 1000 • 1002 • ptr1 ptr2 ptr1=&data1 ptr2=&data2 data1 data2

14 数组与指针运算 数组名 = 数组占用的内存单元的首地址 int arr[ 32 ], x;
int *p = arr; /* 将数组首地址保存在 p */ x = *(p + 2); /* 取数组中的第 3 个元素 */ p++; /* 使指针指向第 2 个元素 */ p = p + 5; /* 使指针指向第 7 个元素 */ *p = 308; /* 改变第 7 个元素 */ x = p – arr; /* 得到 6 */ /* 计算两个地址之间有几个整数的空间 */

15 注意: 在指针加、减运算中,数字“1”不是指一个字节,而是以一个数据(基类型)为基本单位。 地址计算与地址中存放的数据长度有关。

16 对于不同的数据类型的指针p,p  n表示的实际位置的地址是: (p)  n * 数据长度(含几个字节)
计算后的指针地址值的变化取决于它指向的数据类型。 见例pointsz2.c pointsz3.c

17 例6-1: 设计一个函数,用于交换两个变量中的整数
#include <stdio.h> void swap(int *p, int *q) { int t; t = *p; *p = *q; *q = t; } main( ) { int x, y; scanf( “%d%d”, &x, &y ); swap( &x, &y ); printf( “%d %d\n”, x, y );

18 下面的函数能否实现两个变量中的整数交换吗?
#include <stdio.h> void swap(int x, int y) { int t; t = x; y = x; y = x; } main( ) { int x, y; scanf( “%d%d”, &x, &y ); swap( x, y ); printf( “%d %d\n”, x, y );

19 程序分析 作为参数的是指针类型变量 参数传递(按单向值调用) 函数体内 分析方法的特点 参数变量有自己的内存单元(存地址)
将变量 x 的地址值传到参数 p 中 用 *p 访问 x 函数体内 以间接访问方式操作 分析方法的特点 利用内存单元的图示 表示所有变量的变化(包括指针)

20 例6-2:设计一个函数,用于将字符串中的小写字母改为大写字母
#include <stdio.h> void toUpper( char p[ ] ) { for( ; *p != ‘\0’; p++ ) if( ‘a’ <= *p && *p <= ‘z’ ) *p = *p – ‘a’ + ‘A’; } main( ) { char *buf = “characters.”; toUpper( buf ); printf( “%s\n”, buf );

21 程序分析 数组与指针 空间分配 字符串 char p[ ] 等价于 char *p p[ i ] 等价于 *( p + i )
指针代替了下标变量 空间分配 数组:数组大小 * 元素占用空间 数组名 = 首元素地址 (本身无空间) 指针:4个字节保存地址 字符串 以‘\0’结束的字符数组 用首字符地址参加运算

22 例 6.3 求两个向量之和的函数 double *addVector( double a[ ], double b[ ], int n )
例 6.3 求两个向量之和的函数 double *addVector( double a[ ], double b[ ], int n ) { int i; double *p; p = (double *)malloc( n * sizeof(double) ); for( i=0; p != NULL && i<n; i++ ) p[ i ] = *a++ + *b++; return p; } /* 用指针代替下标变量 */

23 主函数 free(p); main() { double x[3], y[3]; double *p;
x[0] = x[1] = x[2] = 4; y[0] = y[1] = y[2] = 5; p = addVector( x, y, 3 ); printf(“%lf”, *p); printf(“%lf”, *(p+1); printf(“%lf”, p[2]); } free(p);

24 动态空间分配 申请存储单元的函数 释放该空间 存储单元大小的计算 void *malloc( long size );
给定所需字节数,取得系统分配的存储单元,返回首地址 如果分配失败,返回空指针 NULL 释放该空间 void free( void *p ); 给定malloc获得的存储单元首地址 存储单元大小的计算 sizeof( 类型 ) sizeof( 变量 )

25 6.2 字符串处理 常用字符串处理函数 int strlen( char *s ); 求字符串中字符个数
6.2 字符串处理 常用字符串处理函数 int strlen( char *s ); 求字符串中字符个数 int strcmp( char *s1, char *s2 ); 按照字母顺序比较, 0 表示相等 char *strcpy( char *dec, char *src ) 字符串从 src 复制到 dec,返回 dec char *strcat( char *dec, char *src ) 将字符串 src 连接到 dec 后面,返回 dec

26 例6-4:字符串连接 使用前提:dec字符数组中必须有足够的空间
char *strcat( char *dec, char *src ) { char *p ; p = dec; while( *p != ‘\0’ ) p++; while( *src != ‘\0’ ) *p++ = *src++; *p = ‘\0’; return dec; } 使用前提:dec字符数组中必须有足够的空间

27 使用合法的内存单元 main( ) { int n; char *p = “abc”, *q = “xyz”, *s;
strcat( p, q ); /* 非法 */ n = strlen(p) + strlen(q); s = (char *)malloc( n+1 ); /* 分配空间 */ strcpy( s, p ); strcat( s, q ); printf( “%s\n”, s ); free( s ); /* 释放空间 */ }

28 例6-5:子字符串的查找 要求:实现函数 char *strstr( char *s1, char *s2 )
用于在 s1 中找出子串 s2,返回首元素地址;若 s2 不存在,则返回 NULL s1比s2短 返回NULL s2是s1的 前缀 返回 s1 在s1首字符之 后的字符串中 查找,返回 结果 Y N

29 函数实现(递归法) char *strstr( char *s1, char *s2 ) {
if( strlen(s1) < strlen(s2 ) return NULL; if( 0 == strncmp( s1, s2, strlen(s2) ) ) return s1; /* 前n个字符相等 */ return strstr( s1+1, s2 ); /* 递归查找 */ }

30 strncmp 的设计 int strncmp( char *s1, char *s2, int n ) 比较2个字符串,返回字符的差
返回 0 n=0? 首字符相等? 首字符=\0? 返回首字 符之差 比较其余字符 返回比较结果 Y N strncmp 的设计 int strncmp( char *s1, char *s2, int n ) 比较2个字符串,返回字符的差 非结构化 控制流图

31 strncpy 的实现(递归法) int strncmp( char *s1, char *s2, int n ) {
if( 0 == n ) return 0; /* 前 n 个相同 */ if( *s1 != *s2 ) return *s1 - *s2; /* 首元素之差 */ if( *s1 == ‘\0’ ) /* 2个字符串都结束 */ return 0; return strncmp( s1+1, s2+1, n-1 ); } /* 比较其余字符 */

32 6.3 指针应用 例6-6:排序函数(按照字符顺序) 要求:对n个字符串进行排序 基本算法:(冒泡排序)
6.3 指针应用 例6-6:排序函数(按照字符顺序) 要求:对n个字符串进行排序 基本算法:(冒泡排序) 逐个比较相邻元素,交换前大后小的元素 重复以上处理(n-1次) void bSort( int n, char *a[ ] ); 采用指针数组指示 n 个字符串

33 程序实现 void bSort( int n, char *a[ ] ) { char **p, *tmp; int i;
for( i=0; i<n-1; i++ ) /* 重复n-1次 */ for( p=a; p<a+n-1; p++ ) /* 逐个检查 */ if( strcmp(*p, *(p+1)) > 0 ) { /* 比较相邻元素 */ tmp = *p; /* 交换 */ *p = *(p+1); *( p+1 ) = tmp; }

34 程序分析 char **p = a; a 是数组名(首元素地址),数组元素是字符指针 因此 a 是保存字符地址的内存单元的地址,
tmp = *p; 将变量 p 中保存的字符指针地址赋给 tmp

35 例6-7:将命令行参数排序后输出 程序处理过程的回顾 myProc.c  myProc.obj  myProc.exe 编译 连接
编译 连接 myProc.exe 可执行文件 鼠标双击 (如:TC.exe) 在DOS环境:myProc 回车 命令行(命令 + 若干个参数) C:\ myProc arg1 arg2 程序启动时指定;而不是运行中输入 也可以在资源管理器中文件属性中指定 或 TC 菜单Option/arguments中指定(调试中用)

36 命令行参数的组织 例:myProc arg1 arg2 空间已分配 m y P r o c ‘\0’ a r g 1 ‘\0’
void main( int ac, char *av[ ] ) m y P r o c ‘\0’ a r g ‘\0’ a r g ‘\0’ 3

37 程序实现 void main(int ac, char *av[ ]) { /* 给定命令行参数个数 ac */
bSort( ac-1, av+1 ); while( --ac ) /* 循环ac-1次 */ printf( “%s\n”, *(++av) ); } /* 指针位移后,取元素 */ av 是变量,保存字符指针的指针 系统负责统计命令行参数个数传递给 ac 同时构造命令行参数的指针数组,传递给 av

38 例6-8:单词统计 要求 数据对象 从键盘输入一篇英文文章,统计各单词的出现次数,以<单词:出现次数>的格式列表输出
单词表:字符串数组 wdTab 出现次数表:整数表 nmTab 用下标联系单词及其出现次数

39 读入一单词 读成功? 在wdTab中 查找该单词 找到? 添加到 wdTab 出现次数 加一 输出wdTab 和nmTab N Y 算法描述

40 模块设计(函数抽象) int wdRead( char buf[ ] ) 从键盘读入一单词(字母和数字组成),
读入失败时,返回0。 int wdLook( char buf[ ], char *tab[ ], int n ) 在单词表 tab 中查找单词 buf, (n 是 tab 中的单词个数) 如果找到,返回下标;未找到返回 –1。 void wdPrint( int n, char *wtab[ ], int ntab[ ] ) 输出单词表 wtab 和出现次数表 ntab 中的 n 个单词及其出现次数

41 主程序的实现 #include <stdio.h> #include <string.h> main( ) {
char *wdTab[ 1024 ], p; /* 最多1024个 */ int nmTab[ 1024 ], num = 0, idx, n; char buf[ 256 ]; /* 当前单词 */ while( 0 != (n = wdRead( buf )) ) { idx = wdLook( buf, wdTab, num ); if( idx >= 0 ) nmTab[ idx ] += 1; /* 出现次数加一 */ else { p = (char *)malloc( n+1 ); /* 分配空间 */ wdTab[ num ] = strcpy( p, buf ); nmTab[ num++ ] = 1; } } /* 保存复制后的单词 */ wdPrint( num, wdTab, nmTab ); } 主程序的实现

42 单词的读入 int wdRead( char buf[ ] ) { int ch, i=0;
do ch = getchar( ); /* 跳过其他字符 */ while( !isalnum(ch) && ch != EOF ); while( ch != EOF && isalnum(ch) ) { buf[ i++ ] = ch; /* 保存字符 */ ch = getchar( ); } buf[ i ] = ‘\0’; /* 字符串结尾 */ return i;

43 单词查找和输出 int wdLook( char buf[ ], char *tab[ ], int n ) { char **p;
for( p=tab; p<tab+n; p++ ) if( strcmp( *p, buf ) == 0 ) return p-tab; return -1; } void wdPrint( int n, char *ws[ ], int ns[ ] ) { int i; for( i=0; i<n; i++ ) printf( “<%s:%d>\n”, ws[ i ], ns[ i ] );

44 程序分析 结构化设计 实现技术 存在问题 功能分解、逐步求精 模块化函数抽象 数据处理局部化 指针数组、字符输入输出、指针索引
数组大小(1024)的限制 数组下标的关联作用(有限)

45 指针小结 指针: 指针运算: 用途: 安全性 保存地址,提供高效访问手段 以基类型数据单元为单位,不等于地址运算
函数参数、数组元素遍历、字符串处理 指针数组(含字符串数组)、命令行 安全性 可访问外部函数申请的内存单元 始终指向申请到的内存单元

46 本章作业 阅读教科书第七章和第八章 程序设计练习 上机题 完成自我测验练习 7.3 7.4 7.6 完成自我测验练习 8.3 8.4
完成自我测验练习 完成自我测验练习 程序设计练习 上机题


Download ppt "C语言程序设计 北京工业大学计算机学院 软件学科部 宋凯 学时40:课堂24+上机16"

Similar presentations


Ads by Google