首页 sicp03-2

sicp03-2

举报
开通vip

sicp03-2 程序设计技术和方法 裘宗燕,2009-2010 /1 3. 模块化,对象和状态(2) 这本节课讨论: „ 求值的环境模型 „ 环境模型中的求值规则 „ 过程应用 „ 局部状态 „ 内部定义 „ 基于状态的模拟 „ 数字电路模拟 „ 约束传播语言 程序设计技术和方法 裘宗燕,2009-2010 /2 求值的环境模型 „ 代换模型:将复合表达式里的复合过程作用于一组参数:对实参求值, 用这些值代换过程体里的形参,求值代换后的过程体 „ 有赋值后代换模型就失效了。原因:变量不再是简单的代表值的名字, ...

sicp03-2
程序 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 技术和 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 裘宗燕,2009-2010 /1 3. 模块化,对象和状态(2) 这本节课讨论: „ 求值的环境模型 „ 环境模型中的求值规则 „ 过程应用 „ 局部状态 „ 内部定义 „ 基于状态的模拟 „ 数字电路模拟 „ 约束传播语言 程序设计技术和方法 裘宗燕,2009-2010 /2 求值的环境模型 „ 代换模型:将复合表达式里的复合过程作用于一组参数:对实参求值, 用这些值代换过程体里的形参,求值代换后的过程体 „ 有赋值后代换模型就失效了。原因:变量不再是简单的代表值的名字, 而表示某种“存储位置”,其中保存的值可以随计算进展而改变 „ 有了赋值,语言的求值模型就必须反映存储的概 念。下面介绍的新模型称为环境模型,其中以抽 象形式表达了变量存储 „ 环境是框架(frame)的序列。框架是可空的表 格,其中每项表示一个变量的约束。在一个框架 里,每个变量至多有一个约束 „ 每个框架有一个指向其外围框架的指针,全局框 架没有外围框架 „ 一个变量在一个环境里的值,就是环境里第一个 有它的约束的框架里的那个约束值 例:x在环境A中的值, 在环境 B中的值 程序设计技术和方法 裘宗燕,2009-2010 /3 环境模型和求值规则 „ 环境确定了表达式求值的上下文。没有环境,表达式求值就没有意义。 例如,(+ 1 1) 的求值也需要上下文为 + 提供意义 „ 为描述解释器的意义,假定有一个全局环境,其中只有一个全局框架, 框架中包含着所有基本过程名的意义约束 „ 新求值模型中,组合表达式的基本求值规则仍然是: ‰ 求值这一组合式的各子表达式 ‰ 将运算符表达式的值作用于运算对象表达式的值 „ 一个过程对象是一个对 (c, e),其中 c是过程的代码,e是环境指针。求 值一个 lambda 表达式,将创建一个过程对象: ‰ 过程对象的代码由 lambda 表达式的体得到 ‰ 过程对象的环境指针指向求值该 lambda 表达式时的环境 „ 下面用一些例子说明有关情况:环境在求值中的作用,求值过程中框架 的创建,过程对象的创建等等 程序设计技术和方法 裘宗燕,2009-2010 /4 环境模型下的求值 „ 过程对象的建立和约束。在全局环境中求值 (define (square x) (* x x)) 实际上就是求值: (define square (lambda (x) (* x x))) 图:在全局环境里增加了 square 的约束, 它约束于新建的过程对象 ■ 过程应用。在全局环境里求值 表达式 (square 5): ‰ 过程应用表达式创建新环 境 E1,其中 x (形参) 约束到 5(实参的值) ‰ 在环境 E1 中求值过程体 (* x x) 得到结果 25 程序设计技术和方法 裘宗燕,2009-2010 /5 环境模型下的求值规则 „ 环境模型下的求值规则: ‰ 将一个过程对象应用于一组实参:先构造一个新框架,该框架以过 程对象的框架作为外围框架,框架里是过程的形参与对应实参值的 约束;而后在这个新环境中求值过程体 ‰ 在环境 E 里求值一个 lambda 表达式,将建立起一个过程对象。其 代码是该 lambda 表达式的体,其环境指针指向 E „ 用 define 定义一个符号,在当前框架里建立一个约束,将被定义的符 号约束到给定值(如果当前框架里已有这个符号,则改变其已有的约束 【参考书上的注释】) „ (set! <变量> ) 的作用: ‰ 在当前环境中找到<变量>的约束(可能不在当前框架里) ‰ 将该变量的约束值修改为由 计算出的值 ‰ 如果环境中没有<变量>的约束,则报告错误 „ 新求值规则比代换规则复杂得多,但它是 Scheme 解释器工作方式的 真正模型,可以基于这个模型实现 Scheme 解释器(第4章) 程序设计技术和方法 裘宗燕,2009-2010 /6 环境模型:简单过程的应用 假设有定义 (define (square x) (* x x)) (define (sum-of-squares x y) (+ (square x) (square y))) (define (f a) (sum-of-squares (+ a 1) (* a 2))) 三个定义建立起的环境见图 对 (f 5) 的求值 求值时新建一个环境,其中 有一个新约束 ■ 每个调用创建一个新框 架,同一函数的不同调 用的框架相互无关 ■ 这里没有特别关注返回 值的传递问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 程序设计技术和方法 裘宗燕,2009-2010 /7 框架和局部状态 环境模型下有局部状态的对象在计 算过程中的情况 „提款处理器代码: (define (make-withdraw balance) (lambda (amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds"))) 调用 (define W1 (make-withdraw 100)) 新建环境 E1,在其中求值过程体 对过程中 lambda 表达式的求值建 立新过程对象(左),其环境指针 指向 E1,W1 约束于这个过程对象 程序设计技术和方法 裘宗燕,2009-2010 /8 框架和局部状态 考虑过程调用: (w1 50) 这个调用建立起一个新环境( 右)并在其中求值 从环境的不同框架中,可以找 到各变量的值 过程中set! 表达式的求值改 变环境中 balance 的约束, 使其约束值变为 50 ■ 再调用W1 将建立另一个新框 架,与上面建立的框架无关, 但其外围框架仍是 E1 ■ 过程求值中将再次找到包含 balance 的框架 E1 并修改 balance 的约束值 程序设计技术和方法 裘宗燕,2009-2010 /9 框架和局部状态 „ 建立另一个提款处理器 (define W2 (make-withdraw 100)) „ 新提款处理器W2 的局部状态与 W1 的局部状态无关 „ 两个提款处理器(是两个过程对象)将各自独立变化 „ 两个提款处理器(过程对象)的代码相同。究竟是共享同一份代码,还是各有一 份代码,是系统实现的细节问题。具体采用哪种方式并不影响语义 „ 聪明的编译器可能让它们共享代码,以提高内存利用的效率 程序设计技术和方法 裘宗燕,2009-2010 /10 内部定义 „ 考虑带有内部定义的过程: (define (sqrt x) (define (good-enough? guess) (< (abs (- (square guess) x)) 0.001)) (define (improve guess) (average guess (/ x guess))) (define (sqrt-iter guess) (if (good-enough? guess) guess (sqrt-iter (improve guess)))) (sqrt-iter 1.0)) ■ 对 (sqrt 2) 的求值建立一个新 框架 E1,其中包含形参 x 的约 束和各内部过程的约束 ■ 每个内部过程名约束于一个过 程对象(包括代码和一个环境 指针)。内部过程的环境指针 都指向 E1 ■ 首次调用 good-enough? 时的 现场情况如右图 程序设计技术和方法 裘宗燕,2009-2010 /11 内部定义 „ 建立一个过程对象时,内部定义过程的名字与相应过程对象的约束在一 个局部框架里,与其他框架里的同名对象(变量或过程)均无关 „ 内部过程对象的环境指针指向其外围过程调用时建立的环境,因此在这 些内部过程里可以直接使用其外围过程的局部变量(形式参数等) „ 每次调用有着内部过程定义的过程时,都将新建一个框架 ‰ 包括重新建立其中的各内部过程对象 ‰ 不同过程对象是否共享代码是系统的实现细节,不影响语义 程序设计技术和方法 裘宗燕,2009-2010 /12 用变动数据做模拟 „ 下面考虑如何用具有局部状态的对象做模拟 „ 前面提出,在建立数据抽象时,相应数据结构要基于其构造函数和选择 函数描述。现在考虑具有不断变化的状态的对象构成的系统,模拟这种 系统,复合数据对象需要有可随计算进程变化的状态,要有修改状态的 操作。这种操作称为改变函数(mutator) „ 例:模拟银行账户时,表示它的数据结构应有下面操作: (set-balance! ) „ 前面介绍:序对是构造各种复合对象的通用粘合机制。要用序对构造状 态可变的对象,需要有能修改序对内容的操作 „ 序对的改变操作是 set-car! 和 set-cdr!,它们都有两个参数,其作用是 修改第一个参数(应为序对)的 car 或 cdr,使之以第二个参数为值 程序设计技术和方法 裘宗燕,2009-2010 /13 表结构的变动 做 (define z (cons y (cdr x)) 得到 (set-car! x y) 得到: 假设 x 的值为 ((a b) c d),y 的值为 (e f) 程序设计技术和方法 裘宗燕,2009-2010 /14 表结构的变动 在 x 的值为 ((a b) c d),y 值为 (e f) 的情况下执行 (set-cdr! x y): ■ set-car! 和 set-cdr! 修改已有的表结构(破坏性操作) ■ cons 通过建立新序对的方式构建表结构(非破坏性操作) ■ cons 可以通过一个建立新序对的操作 get-new-pair 和两个破坏性操 作 set-car! 和 set-cdr!实现 程序设计技术和方法 裘宗燕,2009-2010 /15 共享和相等 „ 赋值引起“同一个”和“变动”问题。当不同数据 对象共享某些序对时,问题将暴露出来。例: (define x (list 'a 'b)) (define z1 (cons x x)) 得到的状态如右图 ■下面表达式产生另一个结构 (define z2 (cons (list 'a 'b) (list 'a 'b))) Scheme 里的符号是共享的 ■ z1 和 z2 貌似表示“同样”的表。若只能做 car/cdr/cons,不可能察觉是 否存在共享。而如果能修改表结构,就会暴露共享的情况 (set-car! (car z1) 'wow) z1 ((wow b) wow b) (set-car! (car z2) 'wow) z2 ((wow b) a b) 程序设计技术和方法 裘宗燕,2009-2010 /16 共享和相等 „ eq? 检查两个表达式的值是否为共享。例如,(eq? x y) 检查 x 和 y 的 值是不是同一个对象(引用同一个对象) ‰ 由于 Scheme 里符号的唯一性,(eq? 'a 'a) 得真 ‰ cons 总建立新序对,(eq? (cons 'a 'b) (cons 'a 'b)) 得假 ‰ 对于前一页建立的两个情况,(eq? (car z1) (cdr z1)) 得真,而 (eq? (car z2) (cdr z2)) 得假 „ 下面将看到 ‰ 结构共享能极大地扩充序对能表示的数据结构的范围 ‰ 存在共享时,对一部分数据结构的修改可能改变其他数据结构。如 果这种改变不是有意而为,那就很可能造成错误 ‰ 使用改变操作 set-car! 和 set-cdr! 时要特别小心,必须清楚当时的 数据共享情况,否则可能导致严重的程序错误 程序设计技术和方法 裘宗燕,2009-2010 /17 改变也就是赋值 前面介绍过纯粹用过程来表示序对: (define (cons x y) (define (dispatch m) (cond ((eq? m 'car) x) ((eq? m 'cdr) y) (else (error "Undefined operation -- CONS" m)))) dispatch) (define (car z) (z 'car)) (define (cdr z) (z 'cdr)) 有了变动操作,这一框架仍然可以用: (define (cons x y) (define (set-x! v) (set! x v)) (define (set-y! v) (set! y v)) (define (dispatch m) (cond ((eq? m 'car) x) ((eq? m 'cdr) y) ((eq? m 'set-car!) set-x!) ((eq? m 'set-cdr!) set-y!) (else (error "Undefined operation -- CONS" m)))) dispatch) (define (car z) (z 'car)) (define (cdr z) (z 'cdr)) (define (set-car! z new-value) ((z 'set-car!) new-value) z) (define (set-cdr! z new-value) ((z 'set-cdr!) new-value) z) 理论保证:要在语言 里支持变动,只需引 进一个赋值就够了 set-car!/set-cdr! 都 可通过赋值实现 程序设计技术和方法 裘宗燕,2009-2010 /18 队列 „ 用 set-car! 和 set-cdr! 能构造出一些无法基于 car/cdr/cons 实现的数 据结构。问题是:同一个数据结构,需要随着操作改变其内部 „ 考虑构造一个队列。其操作实例: (define q (make-queue)) (insert-queue! q 'a) a (insert-queue! q 'b) a b (delete-queue! q) b (insert-queue! q 'c) b c (insert-queue! q 'd) b c d (delete-queue! q) c d „ 基本操作: ‰ 创建:(make-queue) ‰ 选择:(empty-queue ) 和 (front-queue ) ‰ 改变:(insert-queue ) 和 (delete-queue ) 程序设计技术和方法 裘宗燕,2009-2010 /19 队列 „ 采用如右图的队列表示 ■ 先定义几个辅助过程(为清晰): (define (front-ptr queue) (car queue)) (define (rear-ptr queue) (cdr queue)) (define (set-front-ptr! queue item) (set-car! queue item)) (define (set-rear-ptr! queue item) (set-cdr! queue item)) ■ 前端指针空时认为队列空;空队列是前后端指针均为空的序对: (define (empty-queue? queue) (null? (front-ptr queue))) (define (make-queue) (cons '() '())) ■ 选取表头元素就是取出前端指针所指元素的 car: (define (front-queue queue) (if (empty-queue? queue) (error "FRONT called with an empty queue" queue) (car (front-ptr queue)))) 程序设计技术和方法 裘宗燕,2009-2010 /20 队列 „ 向队列加入元素时创建新序对,并将其连接在最后: (define (insert-queue! queue item) (let ((new-pair (cons item '()))) (cond ((empty-queue? queue) (set-front-ptr! queue new-pair) (set-rear-ptr! queue new-pair) queue) (else (set-cdr! (rear-ptr queue) new-pair) (set-rear-ptr! queue new-pair) queue)))) 设队列 q 有元素 a, b, c (insert-queue! q 'd) 后: 程序设计技术和方法 裘宗燕,2009-2010 /21 队列 „ 删除元素时修改队列前端指针: (define (delete-queue! queue) (cond ((empty-queue? queue) (error "DELETE! called with an empty queue" queue)) (else (set-front-ptr! queue (cdr (front-ptr queue))) queue))) (delete-queue! q) 之后 Scheme 系统的输出功能不理解队列结构,要自己定义输出队列的过程 程序设计技术和方法 裘宗燕,2009-2010 /22 表格 „ 数据导向的编程需要用两维表格 保存各个操作的信息。现在先考 虑一维表格的构造 „ 用序对表示关键码/值关联,特殊 符号 *table* 作为表格头标志 „ 表格: a: 1 b: 2 c: 3 的结构如图 表格查找过程 lookup 返回给定关键码所关联的值: (define (lookup key table) (let ((record (assoc key (cdr table)))) (if record (cdr record) false))) (define (assoc key records) (cond ((null? records) false) ((equal? key (caar records)) (car records)) (else (assoc key (cdr records))))) 程序设计技术和方法 裘宗燕,2009-2010 /23 表格:一维表格 „ 为给定关键码关联新值时,先找到该关键码所在序对,而后修改所关联 的值。找不到时在表格里加一个序对表示这一关联 (define (insert! key value table) (let ((record (assoc key (cdr table)))) (if record (set-cdr! record value) (set-cdr! table (cons (cons key value) (cdr table))))) 'ok) 两种情况都需要修改已有的表格 „ 创建新表格就是构造一个空表格: (define (make-table) (list '*table*)) 程序设计技术和方法 裘宗燕,2009-2010 /24 表格:两维表格 考虑两维索引的表格 „ 两维表格是以第一个关 键码为关键码,以一维 表格为关联值的表格 „ 右图表示的表格 math: +: 43 -: 45 *: 42 letters: a: 97 b: 98 其中有两个子表格 程序设计技术和方法 裘宗燕,2009-2010 /25 表格:两维表格 „ 查找时,用关键码逐层查找 (define (lookup key-1 key-2 table) (let ((subtable (assoc key-1 (cdr table)))) (if subtable (let ((record (assoc key-2 (cdr subtable)))) (if record (cdr record) false)) false))) „ 插入关键码时也逐层查找,可能需要建立新的子表格或表格项: (define (insert! key-1 key-2 value table) (let ((subtable (assoc key-1 (cdr table)))) (if subtable (let ((record (assoc key-2 (cdr subtable)))) (if record (set-cdr! record value) (set-cdr! subtable (cons (cons key-2 value) (cdr subtable))))) (set-cdr! table (cons (list key-1 (cons key-2 value)) (cdr table))))) 'ok) 程序设计技术和方法 裘宗燕,2009-2010 /26 表格:表格生成器 „ 表格操作都以一个表格为参数,允许同时有许多表格。可建立“表格生 成器”生成表格对象,其中数据结构作为所生成对象的局部数据 (define (make-table) (let ((local-table (list '*table*))) (define (lookup key-1 key-2) ... ... ) (define (insert! key-1 key-2 value) ... ... 'ok) (define (dispatch m) (cond ((eq? m 'lookup-proc) lookup) ((eq? m 'insert-proc!) insert!) (else (error "Unknown operation -- TABLE" m)))) dispatch)) 内部 lookup/insert! 不需要 table 参数,直接用 local-table 关联的表格 „ 创建一个操作表格(创建其他表格也一样): (define operation-table (make-table)) (define get (operation-table 'lookup-proc)) (define put (operation-table 'insert-proc!)) 程序设计技术和方法 裘宗燕,2009-2010 /27 数字电路模拟器 „ 本章下面介绍了两个大型实例。一个是数字电路模拟器,另一实例建立 一种有趣的语言,其中的计算可以向任何方向进行 „ 复杂的数字电路在许多领域里越来越重要,其正确设计也愈发重要。数 字电路由一些简单元件构成,通过复杂连接可能形成很复杂的行为。要 理解被设计的电路,需要模拟 „ 数字电路模拟是事件驱动的模拟的代表。这是重要的计算机应用领域, 基本想法:系统活动中发生一些事件,事件又会引发其他事件 „ 电路的计算模型由一些对象构成,对象对应于各种基本电路元件 ‰ 连线在对象间传递数字信号(信号只能是 0 或 1) ‰ 功能块有若干输入信号的端口和输出端口,从输入计算出输出。功 能块的输出信号有一定延迟 „ 基本功能块:反门(inverter),与门(and-gate),或门(or-gate) 等。各 种逻辑门都有若干单位时间的延迟 程序设计技术和方法 裘宗燕,2009-2010 /28 数字电路模拟器:连线 „ 基本功能块按一定方式连接,可得到更复杂的功能块。如半加器,有输 入 A 和 B,输出 S(和)和 C(进位)。A、B 之一为 1 时 S 为 1;A 和 B 均为 1 时 C 为 1。由于延迟,得到输出的时间可能不同 ■ 下面构造模拟数字电路的程序。其中 ‰连线用计算对象表示,它们能保持信号 ‰功能模块用过程模拟,它们产生正确的信号关系 ‰ 构造连线的基本操作是 make-wire。例如,用它构造 6 条连线 (define a (make-wire)) (define b (make-wire)) (define c (make-wire)) (define d (make-wire)) (define e (make-wire)) (define s (make-wire)) 程序设计技术和方法 裘宗燕,2009-2010 /29 数字电路模拟器:组合和抽象 „ 将反门、与门和或门连接起来,可以构成半加器: (or-gate a b d) ok (and-gate a b c) ok (inverter c e) ok (and-gate d e s) ok „ 更好的方式是把这类构造操作定义为过程,取 4 个连线参数: (define (half-adder a b s c) (let ((d (make-wire)) (e (make-wire))) (or-gate a b d) (and-gate a b c) (inverter c e) (and-gate d e s) 'ok)) 程序设计技术和方法 裘宗燕,2009-2010 /30 数字电路模拟器:语言结构 „ 用两个半加器和一个或门可以构造 出全加器。相应过程定义: (define (full-adder a b c-in sum c-out) (let ((s (make-wire)) (c1 (make-wire)) (c2 (make-wire))) (half-adder b c-in s c1) (half-adder a s sum c2) (or-gate c1 c2 c-out) 'ok)) ■ 用构造出的功能块作为部件,可以继续构造更复杂的电路 ■ 这样就建立了一种语言,可用于构造具有任意复杂结构的数字电路 ‰基本功能块是这个语言的基本元素 ‰将功能块用连线连接,是这个语言的组合机制 ‰将复杂连接方式定义为过程,是这里的抽象机制 程序设计技术和方法 裘宗燕,2009-2010 /31 数字电路模拟器:基本功能块 „ 基本功能块实现某种效果,使一条线的信号能影响其他连线。连线基本操作 ‰ (get-signal ) 返回 上的当前信号值 ‰ (set-signal! ) 将 上的信号值设置为新值 ‰ (add-action! ) 断言当 上的 信号值改变时,指定过程必须执行 ‰after-delay 要求在给定时延后执行指定过程(两个参数) ■ 基本功能块基于这些操作定义。反门在给定时间延迟后将输入的逆送给输出 (define (inverter input output) (define (invert-input) (let ((new-value (logical-not (get-signal input)))) (after-delay inverter-delay (lambda () (set-signal! output new-value))))) (add-action! input invert-input) 'ok) (define (logical-not s) (cond ((= s 0) 1) ((= s 1) 0) (else (error "Invalid signal" s)))) ; 在 input 连线对象登记一个无参过程 程序设计技术和方法 裘宗燕,2009-2010 /32 数字电路模拟器:基本功能块 „ 与门有两个输入,在两个输入得到信号后都要执行动作 „ 过程 logical-and 与 logical-not 类似 (define (and-gate a1 a2 output) (define (and-action-procedure) (let ((new-value (logical-and (get-signal a1) (get-signal a2)))) (after-delay and-gate-delay (lambda () (set-signal! output new-value))))) (add-action! a1 and-action-procedure) (add-action! a2 and-action-procedure) 'ok) „ 或门、异或门等可以类似定义 „ inverter-delay 和 and-gate-delay 等是模拟中的常量,需事先定义 程序设计技术和方法 裘宗燕,2009-2010 /33 数字电路模拟器:连线 „ 连线是计算对象,有局部的信号值变量 signal-value 和记录一组过程 的变量 action-procedures,连线信号值改变时执行这些过程: (define (make-wire) (let ((signal-value 0) (action-procedures ‘())) ; 初始值 (define (set-my-signal! new-value) (if (not (= signal-value new-value)) (begin (set! signal-value new-value) (call-each action-procedures)) 'done)) (define (accept-action-procedure! proc) (set! action-procedures (cons proc action-procedures)) (proc)) (define (dispatch m) (cond ((eq? m 'get-signal) signal-value) ((eq? m 'set-signal!) set-my-signal!) ((eq? m 'add-action!) accept-action-procedure!) (else (error "Unknown operation -- WIRE" m)))) dispatch)) 辅助过程 call-each 逐个调用过程表里的过程(都是无参过程) 程序设计技术和方法 裘宗燕,2009-2010 /34 数字电路模拟器:连线 (define (call-each procedures) (if (null? procedures) 'done (begin ((car procedures)) (call-each (cdr procedures))))) „ 使用连线的几个过程: (define (get-signal wire) (wire 'get-signal)) (define (set-signal! wire new-value) ((wire 'set-signal!) new-value)) (define (add-action! wire action-procedure) ((wire 'add-action!) action-procedure)) „ 连线是典型变动对象,保存可变化的信号,用带局部状态的过程模拟。 调用 make-wire 返回新的连线对象,它们局部状态 „ 连线状态被连接上的功能块共享,一个部件的活动通过交互影响连线状 态,进而影响连接在这条线上的其他部件 程序设计技术和方法 裘宗燕,2009-2010 /35 数字电路模拟器:待处理表 „ 为实现 after-delay 操作,采用的想法是维护一个待处理表,记录要处 理的事项。该数据抽象提供如下操作: (make-agenda) 返回新建的空的待处理表 (empty-agenda? ) 判断待处理表是否为空 (first-agenda-item ) 返回待处理表中第一个项 (remove-first-agenda-item! ) 修改待处理表,删除第一项 (add-to-agenda!
本文档为【sicp03-2】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_048883
暂无简介~
格式:pdf
大小:383KB
软件:PDF阅读器
页数:0
分类:互联网
上传时间:2010-11-03
浏览量:6