文档库 最新最全的文档下载
当前位置:文档库 › 函数、函数调用、不定参数、多返回值、延迟调用

函数、函数调用、不定参数、多返回值、延迟调用

函数、函数调用、不定参数、多返回值、延迟调用
函数、函数调用、不定参数、多返回值、延迟调用

1.函数定义

2018年7月4日

11:18

Go 语言函数定义格式如下:

func function_name( [parameter list] ) [return_types] {

函数体

}

函数定义解析:

func:函数由 func 开始声明

function_name:函数名称,函数名和参数列表一起构成了函数签名。parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。

return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。

函数体:函数定义的代码集合。

当有多个相同类型的连续参数时,可以省略类型参数的类型名称,直到声明该类型的最后一个参数。例如:

func plusPlus(a, b, c int) int {

return a + b + c

}

示例:

以下实例为 max() 函数的代码,该函数传入两个整型参数 num1 和 num2,并返回这两个参数的最大值:

/* 函数返回两个数的最大值 */

func max(num1, num2 int) int {

/* 声明局部变量 */

var result int

if (num1 > num2) {

result = num1

} else {

result = num2

}

return result

}

2.函数调用

2018年7月9日

16:47

当创建函数时,你定义了函数需要做什么,通过调用该函数来执行指定任务。调用函数,向函数传递参数,并返回值,例如:

package main

import "fmt"

func main() {

/* 定义局部变量 */

var a int = 100

var b int = 200

var ret int

/* 调用函数并返回最大值 */

ret = max(a, b)

fmt.Printf( "maxNum= : %d\n", ret )

}

/* 函数返回两个数的最大值 */

func max(num1, num2 int) int {

/* 定义局部变量 */

var result int

if (num1 > num2) {

result = num1

} else {

result = num2

}

return result

}

以上实例在 main() 函数中调用 max()函数,执行结果为:

最大值是 : 200

3.不定参数

2018年7月9日

16:48

在C语言时代大家一般都用过printf()函数,从那个时候开始其实已经在感受不

定参数的魅力和价值。如同C语言中的printf()函数,Go语言标准库中的

fmt.Println()等函数的实现也严重依赖于语言的不定参数功能。

(1). 不定参数类型

不定参数是指函数传入的参数个数为不定数量。为了做到这点,首先需要将函数

定义为接受不定参数类型:

func myfunc(args ...int) {

for _, arg := range args {

fmt.Println(arg)

}

}

这段代码的意思是,函数myfunc()接受不定数量的参数,这些参数的类型全部是int,所以它可以用如下方式调用:

myfunc(2, 3, 4)

myfunc(1, 3, 7, 13)

形如...type格式的类型只能作为函数的参数类型存在,并且必须是最后一个参数。从内部实现机理上来说,类型...type本质上是一个数组切片,也就是[]type,这也是

为什么上面的参数args可以用for循环来获得每个传入的参数。

假如没有...type这样的语法,开发者将不得不这么写:

func myfunc2(args []int) {

for _, arg := range args {

fmt.Println(arg)

}

}

从函数的实现角度来看,这没有任何影响,该怎么写就怎么写。但从调用方来说,情形则完全不同:

myfunc2([]int{1, 3, 7, 13}…)

你会发现,我们不得不加上[]int{}来构造一个数组切片实例。但是有了...type这个语法糖我们就不用自己来处理了。

(2). 不定参数的传递

假设有另一个变参函数叫做myfunc3(args ...int),下面的例子演示了如何向其传

递变参:

func myfunc(args ...int) {

// 按原样传递

myfunc3(args...)

// 传递片段,实际上任意的int slice都可以传进去

myfunc3(args[1:]...)

}

(3). 任意类型的不定参数

之前的例子中将不定参数类型约束为int,如果你希望传任意类型,可以指定类型为interface{}。下面是Go语言标准库中fmt.Printf()的函数原型:

func Printf(format string, args ...interface{}) {

// ...

}

用interface{}传递任意类型数据是Go语言的惯例用法。使用interface{}仍然是类型安全的,这和 C/C++ 不太一样。以下代码示范了如何分派传入interface{}类型的数据。

package main

import "fmt"

func MyPrintf(args ...interface{}) {

for _, arg := range args {

switch arg.(type) {

case int:

fmt.Println(arg, "is an int value.")

case string:

fmt.Println(arg, "is a string value.")

case int64:

fmt.Println(arg, "is an int64 value.")

default:

fmt.Println(arg, "is an unknown type.")

}

}

}

func main() {

var v1 int = 1

var v2 int64 = 234

var v3 string = "hello"

var v4 float32 = 1.234

MyPrintf(v1, v2, v3, v4)

}

该程序的输出结果为:

1 is an int value.

234 is an int64 value.

hello is a string value.

1.234 is an unknown type.

4.多返回值

2018年7月9日

16:48

与C、C++和Java等开发语言的一个极大不同在于,Go语言的函数或者成员的方法可以有多个返回值,这个特性能够使我们写出比其他语言更优雅、更简洁的代码,比如File.Read()函数就可以同时返回读取的字节数和错误信息。如果读取文件成功,

则返回值中的n为读取的字节数,err为nil,否则err为具体的出错信息:func (file *File) Read(b []byte) (n int, err Error)

同样,从上面的方法原型可以看到,我们还可以给返回值命名,就像函数的输入

参数一样。返回值被命名之后,它们的值在函数开始的时候被自动初始化为空。在函

数中执行不带任何参数的return语句时,会返回对应的返回值变量的值。

Go语言并不需要强制命名返回值,但是命名后的返回值可以让代码更清晰,可读性更强,同时也可以用于文档。如果调用方调用了一个具有多返回值的方法,但是却

不想关心其中的某个返回值,可以简单地用一个下划线“_”来跳过这个返回值,比如下面的代码表示调用者在读文件的时候不想关心Read()函数返回的错误码:n, _ := f.Read(buf)

实例:

package main

import "fmt"

func swap(x, y string) (string, string) {

return y, x

}

func main() {

a, b := swap("Mahesh", "Kumar")

fmt.Println(a, b)

}

以上实例执行结果为:

Kumar Mahesh

5.匿名函数与闭包

2018年7月9日

16:49

(1). 匿名函数

在Go里面,函数可以像普通变量一样被传递或使用,这与C语言的回调函数比

较类似。不同的是,Go语言支持随时在代码里定义匿名函数。

匿名函数由一个不带函数名的函数声明和函数体组成,如下所示:

func(a, b int, z float64) bool {

return a*b

}

匿名函数可以直接赋值给一个变量或者直接执行:

f := func(x, y int) int {

return x + y

}

x := 10

y := 20

fmt.Println("和 = ", f(x, y))

(2). 闭包

Go的匿名函数是一个闭包,下面我们先来了解一下闭包的概念、价值和应用场景。

*基本概念

闭包是可以包含自由(未绑定到特定对象)变量的代码块,这些变量不在这个代码块

内或者任何全局上下文中定义,而是在定义代码块的环境中定义。要执行的代码块(由于自由变量包含在代码块中,所以这些自由变量以及它们引用的对象没有被释放)为自由变量提供绑定的计算环境(作用域)。

*闭包的价值

闭包的价值在于可以作为函数对象或者匿名函数,对于类型系统而言,这意味着不仅

要表示数据还要表示代码。支持闭包的多数语言都将函数作为第一级对象,就是说这

些函数可以存储到变量中作为参数传递给其他函数,最重要的是能够被函数动态创建

和返回。

*Go语言中的闭包

Go语言中的闭包同样也会引用到函数外的变量。闭包的实现确保只要闭包还被使用,那么被闭包引用的变量会一直存在,如代码清单2-5所示。

代码清单2-5 closure.go

package main

import (

"fmt"

)

func main() {

var j int = 5

a := func()(func()) {

var i int = 10

return func() {

fmt.Printf("i, j: %d, %d\n", i, j)

}

}()

a()

j *= 2

a()

}

上述例子的执行结果是:

i, j: 10, 5

i, j: 10, 10

在上面的例子中,变量a指向的闭包函数引用了局部变量i和j,i的值被隔离,

在闭包外不能被修改,改变j的值以后,再次调用a,发现结果是修改过的值。

在变量a指向的闭包函数中,只有内部的匿名函数才能访问变量i,而无法通过其他途径访问到,因此保证了i的安全性。

6.延迟调用

2018年7月9日

16:49

(1).defer作用

关键字defer用于延迟一个函数或者方法(或者当前所创建的匿名函数)的执行。注意,defer语句只能出现在函数或方法的内部。

func main(){

fmt.Println(“this is a test”)

defer fmt.Println(“this is a defer”)//main结束前调用

/*

运行结果:

This is a test

This is a defer

*/

}

defer语句经常被用于处理成对的操作,如打开,关闭,连接,断开连接,加锁,释放锁,通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源

被释放。释放资源的defer应该直接跟在请求资源的语句后。

(2).多个defer执行顺序

如果一个函数中有多个defer语句,它们会以LIFO(后进先出)的顺序执行。哪怕

函数或者某个延迟调用发生错误,这些调用依旧会执行。

func test(x int){

fmt.Println(100 / x)//x为0时,产生异常

}

func main(){

defer fmt.Println(“aaaaa”)

defer fmt.Println(“bbbbb”)

defer test(0)

defer fmt.Println(“ccccc”)

/*

运行结果:

ccccc

bbbbb

aaaaa

*/

}

(3).defer和匿名函数结合使用

func main() {

a, b := 10, 20

defer func(x int) {//a以值传递方式传给x

fmt.Println("defer:", x, b)//b闭包引用}(a)

a += 10

b += 100

fmt.Println("a = %d, b = %d\n", a, b)

/*

运行结果:

a = 20,

b = 120

defer: 10, 120

*/

}

7.获取命令行参数

2018年7月9日

16:50

(1).os库获取命令行参数

package main

import (

"fmt"

"os"

)

func main() {

fmt.Println(os.Args)

}

(2).flag获取命令行参数

package main

import (

"flag"

"fmt"

)

func main() {

ok := flag.Bool("ok", false, "is ok")

id := flag.Int("id", 0, "id")

port := flag.String("port", ":8080", "http listen port")

var name string

flag.StringVar(&name, "name", "123", "name")

flag.Parse()

fmt.Println("ok:", *ok)

fmt.Println("id:", *id)

fmt.Println("port:", *port)

fmt.Println("name:", name)

}

像flag.Int、flag.Bool、flag.String这样的函数格式都是一样的,第一个参数表示参数名称,第二个参数表示默认值,第三个参数表示使用说明和描述。

flag.StringVar这样的函数第一个参数换成了变量地址,后面的参数和flag.String是一样的。

8.作用域(局部变量,全局变量)

2018年7月9日

16:50

(1).局部变量

在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。

以下实例中 main() 函数使用了局部变量 a, b, c:

package main

import "fmt"

func main() {

/* 声明局部变量 */

var a, b, c int

/* 初始化参数 */

a = 10

b = 20

c = a + b

fmt.Printf ("结果: a = %d, b = %d and c = %d\n", a, b, c)

}

以上实例执行输出结果为:

结果: a = 10, b = 20 and c = 30

(2).全局变量

在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。

全局变量可以在任何函数中使用,以下实例演示了如何使用全局变量:package main

import "fmt"

/* 声明全局变量 */

var g int

func main() {

/* 声明局部变量 */

var a, b int

/* 初始化参数 */

a = 10

b = 20

g = a + b

fmt.Printf("结果: a = %d, b = %d and g = %d\n", a, b, g)

}

以上实例执行输出结果为:

结果: a = 10, b = 20 and g = 30

9.递归函数

2018年7月9日

16:51

递归指函数可以直接或间接的调用自身。递归函数通常有相同的结构:一个跳出条件和一个递归条件。所谓跳出条件就是根据传入的参数判断是否需要停止递归,而递归体则是函数自身所做的一些处理。

递归是算法中特别是树、图等结构中常用的方法,理解递归的运行原理是写出高效代码的关键。针对效率要求比较高的场景,可以尝试写出非递归的版本。总体上而言,递归写法的代码体积小、易维护,非递归写法代码维护稍显困难,但执行效率相对较高。

//通过循环实现1+2+3…+100

func add1() int {

i := 0

sum := 0

for i = 1; i <= 100; i++{

sum += i

}

return sum

}

//通过递归实现1+2+3…+100

func add2(num int) int {

if num == 1 {

return num

}

return num + add2(num-1)

}

实例1:

//求算数列1,1,2,3,5,。。。。第n个数的值

package main

Import "fmt"

func getNum(n int) int {

If n==1 || n==2 {

return1

}

return getNum(n-1) + getNum(n-2)

}

func main(){

num := getNum(4)

fmt.Println("num=", num)

}

实例2:

/*

猴子第一天摘下N个桃子,当时就吃了一半,还不过瘾,就又多吃了一个。

第二天又将剩下的桃子吃掉一半,又多吃了一个。

以后每天都吃前一天剩下的一半零一个。

到第10天在想吃的时候就剩一个桃子了,问第一天共摘下来多少个桃子?

*/

package main

Import (

"fmt"

)

func getPeachNum(n int)int{

If n==10 {

return 1

}

return getPeachNum(n+1) * 2 + 1

}

func main(){

sum := getPeachNum(1)

fmt.Println("sum = ", sum)

}

实例3:

判断用户输入的字符串是否是回文字符串

package main

import "fmt"

func isString(start,end int,str string) bool {

if start == end {

return true

}else if end - start == 1 {

If str[end] == str[start]{

return true

}

return false

}else if str[end] != str[start]{

return false

}

return isString(start+1,end-1,str)

}

func main(){

var str string

fmt.Print("请输入字符串:")

fmt.Scanln(&str)

flag := isString(0, len(str)-1, str)

if flag{

fmt.Println("是回文字符串!") }else{

fmt.Println("不是回文字符串!") }

}

!函数返回值

函数返回值 int Count() { int i,j; i=100; j=200; return i+j; } 测试函数: void Test() { int k=Count(); printf("\n k[%d]\n"); } C/C++的函数返回值一般是放在寄存器eax里的,而不是在栈里。 你的这一句int k = Count()的汇编语句就是这样: mov [esp - 4], eax //eax里是300,esp - 4是局部变量k的位置 你可以在vc里做个实验: int add(int a, int b) { __asm { mov eax,a // 把参数1存入eax add eax,b // eax += 参数2, 结果在eax里 } } int main() { printf("%d\n", add(3, 4)); return 0; } 楼主需要了解下寄存器这一概念,我就不把C/C++函数的汇编代码给发出来了。 还有在汇编层面来看,函数的返回值根本就没有定论,函数可以通过多种方式返回。保存返回值在eax里只是C/C++的一个约定而已。

返回值可以放在栈里,但你在C的语言层面上可能做不到,其实随着函数的结束,mov esp, ebp这条指令过后,函数内部的局部变量就报废了。如果你之后没改变过栈的内容,你可以用栈来存返回值,但比起用寄存器来存储,存储和读取要慢的多。 自己突发奇想在vc下试了下用栈“返回”值,写了段代码: #include void __declspec(naked) __stdcall return_a_value() { int local; local = 1990; // 栈空间 __asm ret } int main() { int local = 1; return_a_value(); // 用栈返回值 printf("%d\n", local); return 0; } 汇编看c之一,简单函数调用 简单的函数调用,通过简单的函数调用反汇编可以清楚了解如下 1.栈到底是什么,如何操纵栈的? 2.参数和临时变量是以什么形式在哪存放? 3.如何传递返回值? 举例: #include

关于引用

引用就是某个目标变量的“别名”(alias),对引用的操作与对变量直接操作效果完全相同。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。 将“引用”作为函数返回值类型 格式:类型标识符&函数名(形参列表及类型说明){ //函数体} 好处:在内存中不产生被返回值的副本 A a(){...;return *this;}//会调用拷贝构造函数和析构函数 A& a(){...;return *this;}//不会调用拷贝构造函数和析构函数 关键:当想要返回一个引用而不是一个拷贝时,要确保这个引用的有效性,比如: int & fun() { int a; a=10; return a; } 这样是不行的,因为a会在fun退出时被销毁,这时返回的a的引用是无效的。 这种情况下,如果fun的返回类型不是int & 而是int就没有问题了。 注意事项: (1)不能返回局部变量的引用。这条可以参照Effective C++的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。 (2)不能返回函数内部new分配的内存的引用。这条可以参照Effective C++的Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。(3)可以返回类成员的引用,但最好是const。这条原则可以参照Effective C++的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。 (4)流操作符重载返回值申明为“引用”的作用:流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << "hello" << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因。赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。 例 #include int &put(int n); int vals[10]; int error=-1;

函数返回值

函数返回值 1.不带返回值的函数:return; 不带返回值的函数的返回类型为void,这样的函数会在函数的最后一个语句完成时隐式调用return;也可以在函数的结尾显式地调用return; 对于任意一个函数,只要执行了return语句,函数就强制结束了。 对于返回类型为void的函数,如果不显式地调用return;则只有在函数结束时才会隐式调用。可以在函数执行的某一阶段,显式地调用return;来结束函数,不再执行return语句之后的函数部分。 由于break语句只能用于循环和switch语句中,因此,想要结束if语句直接退出函数,可用return; 只有一种情况下,返回类型为void的函数可以使用return expression这一形式,那就是返回另一个返回类型同样是void的函数的调用结果。 如: void A() void B() { { .... .... .... .... return; return A(); } }//因为A返回类型为void,所以可以这样调用。 2.具有返回值的函数:return expression; 代码: int max(int x,int y) #include { int main() int z; { if(x>=y) int a,b,c; z=x; scanf("%d%d",&a,&b); else c=max(a,b); z=y; printf("%d\n",c); return z; return 0; } } 在main函数中调用max函数,函数调用语句为max(a,b); 仔细研究一下max(a,b)。 对于一个表达式来说,它要完成一定的功能,还要返回一个操作结果(即表达式的值)。如i++,它的功能是使变量i的值加1,它的值是i自增前的值。同样的,函数调用也同样如此:max(a,b)的功能是把实参a,b的值传递给形参并执行函数中的各个语句;max(a,b)的值是一个int类型的值。 ++i的值是i自增后的值,相当于i=i+1,return i;对于i++来说,它的值是i自增前的值,那么如何获得这个值呢?编译器是这样做的:编译器自动创建一个临时变量并用i自增前的值来初始化这个临时变量。用这个临时变量的值来作为i++这个表达式的值。 同样的,执行max(a,b)后,首先完成参数传递并执行函数max中的各条语句。接着创建一个int型的临时变量并用return expression中expression的值来初始化这个临时变量。临时变量的类型为函数的返回值类型,即函数名之前的类型名。对max()函数来说就是int。

C#多线程函数如何传参数和返回值

C#多线程函数如何传参数和返回值 提起多线程,不得不提起委托(delegates)这个概念. 我理解的委托就是具有同样参数和返回值的函数的集合. 比如 public delegate void MyDelegate(int arg); 就是这种形式的函数 void Myfuntion(int i); 的集合. 如何将一个函数加入委托的集合? MyDelegate dele = new MyDelegate(Myfuntion1); 再增加一个 dele += new MyDelegate(Myfuntion2); ... 委托函数 dele 就是具有整数参数和空返回值的函数 Myfuntion1,2的集合. 调用这个委托函数 dele(1); 就是逐个调用 Myfuntion1,2,... 一般线程函数的声明和启动 Thread t = new Thread(new ThreadStart(MyFunction)); t.Start(); 正是调用了没有参数和返回值的委托函数 ThreadStart 其中的参数MyFunction 是这个委托函数中的一员. 很明显这样无法传参数和返回值,那我们该怎么办? 答案就在委托的BeginInvoke() 方法上, BeginInvoke() 也是(异步)启动一个新线程. 例如 MyDelegate dele = new MyDelegate (MyFunction); dele.BeginInvoke(10,"abcd"); void MyFunction(int count, string str); 可以实现参数的传递. 如何收集线程函数的返回值? 与BeginInvoke 对应有个 EndInvoke 方法,而且运行完毕返回 IAsyncResult 类型的返回值.这样我们可以这样收集线程函数的返回值 MyDelegate dele = new MyDelegate (MyFunction); IAsyncResult ref = dele.BeginInvoke(10,"abcd"); ...

逻辑函数的化简方法

一、公式法化简:是利用逻辑代数的基本公式,对函数进行消项、消 因子。常用方法有: ①并项法利用公式AB+AB’=A 将两个与项合并为一个,消去其 中的一个变量。 ②吸收法利用公式A+AB=A 吸收多余的与项。 ③消因子法利用公式A+A’B=A+B 消去与项多余的因子 ④消项法利用公式AB+A’C=AB+A’C+BC 进行配项,以消去更多 的与项。 ⑤配项法利用公式A+A=A,A+A’=1配项,简化表达式。 二、卡诺图化简法 逻辑函数的卡诺图表示法 将n变量的全部最小项各用一个小方块表示,并使具有逻辑相邻性的最小项在几何位置上相邻排列,得到的图形叫做n变量最小项的卡诺图。 逻辑相邻项:仅有一个变量不同其余变量均相同的两个最小项,称为逻辑相邻项。 1.表示最小项的卡诺图 将逻辑变量分成两组,分别在两个方向用循环码形式排列出各组变量的所有取值组合,构成一个有2n个方格的图形,每一个方格对应变量的一个取值组合。具有逻辑相邻性的最小项在位置上也相邻地排列。

用卡诺图表示逻辑函数: 方法一:1、把已知逻辑函数式化为最小项之和形式。 2、将函数式中包含的最小项在卡诺图对应的方格中填 1,其余方格中填 0。 方法二:根据函数式直接填卡诺图。 用卡诺图化简逻辑函数: 化简依据:逻辑相邻性的最小项可以合并,并消去因子。 化简规则:能够合并在一起的最小项是2n个。 如何最简:圈数越少越简;圈内的最小项越多越简。 注意:卡诺图中所有的 1 都必须圈到,不能合并的 1 单独画圈。说明,一逻辑函数的化简结果可能不唯一。 合并最小项的原则: 1)任何两个相邻最小项,可以合并为一项,并消去一个变量。2)任何4个相邻的最小项,可以合并为一项,并消去2个变量。3)任何8个相邻最小项,可以合并为一项,并消去3个变量。 卡诺图化简法的步骤: 画出函数的卡诺图; 画圈(先圈孤立1格;再圈只有一个方向的最小项(1格)组合);画圈的原则:合并个数为2n;圈尽可能大(乘积项中含因子数最少);圈尽可能少(乘积项个数最少);每个圈中至少有一个最小

C++第四章习题解答

第四章类与对象习题 一.基本概念与基础知识自测题 填空题 引入类定义的关键字是(1)。类的成员函数通常指定为(2),类的数据成员通常指定为(3)。指定为(4)的类成员可以在类对象所在域中的任何位置访问它们。通常用类的(5)成员表示类的属性,用类的(6)成员表示类的操作。 答案: (1)class (2)公有的public (3)私有的private (4)公有的public (5)数据 (6)$ (7)函数 类的访问限定符包括(1)、(2)和(3)。私有数据通常由(4)函数来访问(读和写)。这些函数统称为(5)。 答案: (1)public(公有的) (2)private(私有的) (3)protected(保护的) (4)公有的成员函数 (5)类的接口 通常在逻辑上,同一类的每个对象都有(1)代码区,用以存储成员函数。而在物理上通常只有(2)代码区。只有在(3)定义,并(4)的函数和加了关键字(5)的函数例外。 答案: (1)| (2)独立的 (3)共用的 (4)在类说明中 (5)不包括循环等复杂结构 (6)inline C++中支持三种域:(1)、(2)、(3)。函数域被包括在(4)中,全局域被包括在(5)中。using指示符以关键字using开头,后面是关键字(6),最后是(7)。这样表示以后在该名字空间中所有成员都(8)。 如不使用using指示符则在使用时要加::,称为(9)运算符。 答案: (1)局部域(local scope) (2)名字空间域(namespace scope) (3)类域(class scope) (4)/ (5)局部域

(6)名字空间域 (7)namespace (8)名字空间名 (9)可以直接被使用 (10)域 引用通常用作函数的(1)和(2)。对数组只能引用(3)不能引用(4)。 答案: (1)参数 (2)返回值 (3)~ (4)数组元素 (5)数组名本身 构造函数的任务是(1)。构造函数无(2)。类中可以有(3)个构造函数,它们由(4)区分。如果类说明中没有给出构造函数,则C++编译器会(5)。拷贝构造函数的参数是(6),当程序没有给出复制构造函数时,系统会自动提供(7)支持,这样的复制构造函数中每个类成员(8)。 答案: (1)初始化数据成员 (2)函数返回类型说明 (3)多 (4)不同的参数表 (5)自动给出一个默认的构造函数 (6)同一类对象的引用 (7): (8)默认的的复制构造函,称为默认的按成员语义支持。 (9)被依次复制 一个类有(1)个析构函数。(2)时,系统会自动调用析构函数。 答案: (1)一 (2)对象注销时 运算符重载时,其函数名由(1)构成。成员函数重载双目运算符时,左操作数是(2),右操作数是(3)。 答案: (1)关键字operator和该运算符 (2)对象 (3)… (4)该函数的参数 面向过程的程序设计中程序模型描述为(1),面向对象程序设计的程序模型可描述为(2)。 答案: (1)“程序=算法+数据结构”。其数据与数据处理是分离的。 (2)程序=(对象+对象+……+对象)+消息;对象=(算法+数据结构)。面向对象设计将数据和对数据的操作方法放在一起,形成一个相对独立的整体——对象(Object),并通过

C++中函数调用时的三种参数传递方式

在C++中,参数传递的方式是“实虚结合”。 ?按值传递(pass by value) ?地址传递(pass by pointer) ?引用传递(pass by reference) 按值传递的过程为:首先计算出实参表达式的值,接着给对应的形参变量分配一个存储空间,该空间的大小等于该形参类型的,然后把以求出的实参表达式的值一一存入到形参变量分配的存储空间中,成为形参变量的初值,供被调用函数执行时使用。这种传递是把实参表达式的值传送给对应的形参变量,故称这种传递方式为“按值传递”。 使用这种方式,调用函数本省不对实参进行操作,也就是说,即使形参的值在函数中发生了变化,实参的值也完全不会受到影响,仍为调用前的值。 [cpp]view plaincopy 1./* 2. pass By value 3.*/ 4.#include https://www.wendangku.net/doc/9f10864178.html,ing namespace std; 6.void swap(int,int); 7.int main() 8.{ 9.int a = 3, b = 4; 10. cout << "a = " << a << ", b = " 11. << b << endl; 12. swap(a,b); 13. cout << "a = " << a << ", b = " 14. << b << endl; 15.return 0; 16.} 17.void swap(int x, int y) 18.{ 19.int t = x; 20. x = y; 21. y = t; 22.}

如果在函数定义时将形参说明成指针,对这样的函数进行调用时就需要指定地址值形式的实参。这时的参数传递方式就是地址传递方式。 地址传递与按值传递的不同在于,它把实参的存储地址传送给对应的形参,从而使得形参指针和实参指针指向同一个地址。因此,被调用函数中对形参指针所指向的地址中内容的任何改变都会影响到实参。 [cpp]view plaincopy 1.#include https://www.wendangku.net/doc/9f10864178.html,ing namespace std; 3.void swap(int*,int*); 4.int main() 5.{ 6.int a = 3, b = 4; 7. cout << "a = " << a << ", b = " 8. << b << endl; 9. swap(&a,&b); 10. cout << "a = " << a << ", b = " 11. << b << endl; 12. system("pause"); 13.return 0; 14.} 15.void swap(int *x,int *y) 16.{ 17.int t = *x; 18. *x = *y; 19. *y = t; 20.} 按值传递方式容易理解,但形参值的改变不能对实参产生影响。 地址传递方式虽然可以使得形参的改变对相应的实参有效,但如果在函数中反复利用指针进行间接访问,会使程序容易产生错误且难以阅读。

函数参数返回值总结

函数的参数、返回值总结 (一)参数 ◆函数分: 有参函数:函数名(实参列表) 无参函数:函数名() ◆有参函数调用语句中的实参应与被调函数中的形参在个数、类型、顺序上一致。 ◆参数传递时,实参向形参一一对应进行单向的值传递。值:可是数值(变量或数 组元素)或数值的地址值(指针或数组名)。 (二)返回值 函数的返回值即为函数调用后的结果,可有如下返回结果的方法: (1)通过return语句返回一个值; (2)利用地址做参数返回一个或多个值; (3)利用全局变量返回一个或多个值。 (三)例 1、170页实验内容(1):打印由正三角和倒三角组成的图形。 有一个参数,无返回值。实参向形参传递一个数值。 #include /* 有一个参数,无返回值的函数,打印正三角 */ void f1(int n) /* 形参只能是变量,用来接收实参传来的数值 */ { int i,j,k; for(k=1;k<=n;k++) {for(i=1;i<=10-k;i++) printf(" "); for(j=1;j<=k;j++) printf(" *"); printf("\n");} } /* 有一个参数,无返回值的函数,打印倒三角*/ void f2(int n) {int i,j,k; for(k=n;k>=1;k--) {for(i=1;i<=10-k;i++) printf(" "); for(j=1;j<=k;j++) printf(" *"); /*双引号内应为“空格加半角星号”*/ printf("\n");} } main() { int n; scanf("%d",&n);

函数的参数

如果把函数比喻成一台机器,那么参数就是原材料,返回值就是最终产品;函数的作用就是根据不同的参数产生不同的返回值。 函数的参数 在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数,简称形参。 函数被调用时给出的参数包含了实实在在的数据,会被函数内部的代码使用,所以称为实际参数,简称实参。 形参和实参的功能是作数据传送,发生函数调用时,实参的值会传送给形参。 形参和实参有以下几个特点: 1) 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。 2) 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。 3) 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。

函数调用中发生的数据传送是单向的,只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。 【示例】计算1+2+3+...+(n-1)+n 的值。 1.#include 2.int sum(int n){ // 有参函数 3.int i; 4.for(i=n-1; i>=1; i--){ 5. n+=i; 6.} 7.printf("The inner n = %d\n",n); 8.return n; 9.} 10.int main(){ // 无参函数 11.int m, total; 12.printf("Input a number: "); 13.scanf("%d",&m); 14. total =sum(m); 15.printf("The outer m = %d \n", m); 16.printf("1+2+3+...+%d+%d = %d\n", m-1, m, total); 17.return0; 18.} 运行结果: Input a number: 100↙ The inner n = 5050 The outer m = 100

c++复习题及答案(完整版)

一填空题() 1、派生类的生成过程经历了三个步骤:吸收基类成员、改造基类成员、添加新成员。 2、多态分为:专用多态和通用多态。 二、选择题(10分) 1在一个函数中,要求通过函数来实现一种不太复杂的功能,并且要求加快执行速度,选用(A )比较合适。 A 内联函数 B 重载函数 C 递归调用 D 嵌套调用 2下面对构造函数的描述不正确的是(C ) A 可以重载 B 其名字与类名相同 C 可以显式调用构造函数 D 构造函数是成员函数 E 构造函数不能是虚函数 3、判断题(正确的请写T,错误的请写F)(20分) 静态成员函数可以直接调用类中说明的非静态成员。(F) windows应用程序采用基于消息的事件驱动运行机制。(T) 4、找出程序中的错误并改正(10分) class student() { private: public: display(){} } }; //----------------------------------------------- void g() student g() { student s; return s; } //------------------------------------------------ mian()void main() { student s1; s1->display(); s1.display(); } 5、读程序,在语句后的括号中填入相应的选项,并写出程序运行结果结果(8个小题)(共40分结果30分选择10分)选项:A、复制构造函数 B、构造函数 C、内联成员函数 D、对象成员 E、对象作为函数的参数 F、调用复制构造函数 G、对象调用成员函数 1、 #include #include class Point { public: Point(int xx=0,int yy=0){X=xx;Y=yy;} //1、( B ) Point(const Point& p); //2、( A ) int GetX(){return X;} int GetY(){return Y;} //3、( C ) private:

函数参数传递的原理

函数参数传递的原理 参数传递,是在程序运行过程中,实际参数就会将参数值传递给相应的形式参数,然后在函数中实现对数据处理和返回的过程,方法有按值传递参数,按地址传递参数和按数组传递参数。 形参:指出现在Sub 和Function过程形参表中的变量名、数组名,该过程在被调用前,没有为它们分配内存,其作用是说明自变量的类型和形态以及在过程中的作用。形参可以是除定长字符串变量之外的合法变量名,也可以带括号的数组名。 实参:实参就是在调用Sub 和Function过程时,从主调过程传递给被调用过程的参数值。实参可以是变量名、数组名、常数或表达式。在过程调用传递参数时,形参与实参是按位置结合的,形参表和实参表中对应的变量名可以不必相同,但它们的数据类型、参数个数及位置必须一一对应。 等号、函数名称、括弧和参数,是函数的四个组成部分。 函数“=SUM(1,2,3)”,1、2和3就是SUM函数的参数,没有参数1、2、3,函数SUM 则无从求值。 函数“=VLOOKUP(2,A:C,3,)”,没有参数2、A:C和3,函数VLOOKUP如何在A:C 区域查找A列中是2那一行第3列的数值? 当然,也有不需要参数的函数,如“=PI()”、“=NOW()”、“TODAY()”等。 函数参数传递的原理C语言中参数的传递方式一般存在两种方式:一种是通过栈的形式传递,另一种是通过寄存器的方式传递的。这次,我们只是详细描述一下第一种参数传递方式,另外一种方式在这里不做详细介绍。 首先,我们看一下,下面一个简单的调用例程: int Add (int a,int b,int c) { return a+b+c; }

C语言函数说明与返回值

C语言函数说明与返回值 在学习C语言函数以前,我们需要了解什么是模块化程序设计方法。 人们在求解一个复杂问题时,通常采用的是逐步分解、分而治之的方法,也就是把一个大问题分解成若干个比较容易求解的小问题,然后分别求解。程序员在设计一个复杂的应用程序时,往往也是把整个程序划分为若干功能较为单一的程序模块,然后分别予以实现,最后再把所有的程序模块像搭积木一样装配起来,这种在程序设计中分而治之的策略,被称为模块化程序设计方法。 在C语言中,函数是程序的基本组成单位,因此可以很方便地用函数作为程序模块来实现C语言程序。 利用函数,不仅可以实现程序的模块化,程序设计得简单和直观,提高了程序的易读性和可维护性,而且还可以把程序中普通用到的一些计算或操作编成通用的函数,以供随时调用,这样可以大大地减轻程序员的代码工作量。 函数是C语言的基本构件,是所有程序活动的舞台。函数的一般形式是: type-specifier function_name(parameter list) parameter declarations { body of the function } 类型说明符定义了函数中return语句返回值的类型,该返回值可以是任何有效类型。如果没有类型说明符出现,函数返回一个整型值。参数表是一个用逗号分隔的变量表,当函数被调用时这些变量接收调用参数的值。一个函数可以没有参数,这时函数表是空的。但即使没有参数,括号仍然是必须要有的。参数说明段定义了其中参数的类型。

当一个函数没有明确说明类型时, C语言的编译程序自动将整型( i n t)作为这个函数的缺省类型,缺省类型适用于很大一部分函数。当有必要返回其它类型数据时,需要分两步处理: 首先,必须给函数以明确的类型说明符;其次,函数类型的说明必须处于对它的首次调用之前。只有这样,C编译程序才能为返回非整型的值的函数生成正确代码。 4.1.1 函数的类型说明 可将函数说明为返回任何一种合法的C语言数据类型。 类型说明符告诉编译程序它返回什么类型的数据。这个信息对于程序能否正确运行关系极大,因为不同的数据有不同的长度和内部表示。 返回非整型数据的函数被使用之前,必须把它的类型向程序的其余部分说明。若不这样做,C语言的编译程序就认为函数是返回整型数据的函数,调用点又在函数类型说明之前,编译程序就会对调用生成错误代码。为了防止上述问题的出现,必须使用一个特别的说明语句,通知编译程序这个函数返回什么值。下例示出了这种方法。 第一个函数的类型说明sum()函数返回浮点类型的数据。这个说明使编译程序能够对sum( ) 的调用产生正确代码。 函数类型说明语句的一般形式是: type_specifier function_name (; ) 即使函数使用形参,也不要将其写入说明句。若未使用类型说明语句,函数返回的数据类型可能与调用者所要求的不一致,其结果是难以预料的。如果两者同处于一个文件中,编译程序可以发现该错误并停止编译。如果不在同一个文件中,编译程序无法发现这种错误。类型检查仅在编译中进行,链接和运行时均不检查。因此,必须十分细心以确保绝不发生上

逻辑函数及其化简

第2章逻辑函数及其化简 内容提要 本章是数字逻辑电路的基础,主要内容包含: (1)基本逻辑概念,逻辑代数中的三种基本运算(与、或、非)及其复合运算(与非、或非、与或非、同或、异或等)。 (2)逻辑代数运算的基本规律(变量和常量的关系、交换律、结合律、分配律、重叠律、反演律、调换律等)。 (3)逻辑代数基本运算公式及三个规则(代入规则、反演规则和对偶规则)。 (4)逻辑函数的五种表示方法(真值表法、表达式法、卡诺图法、逻辑图法及硬件描述语言)及其之间关系。本章主要讲述了前三种。(5)逻辑函数的三种化简方法(公式化简法、卡诺图法和Q–M法)。教学基本要求 要求掌握: (1)逻辑代数的基本定律和定理。 (2)逻辑问题的描述方法。 (3)逻辑函数的化简方法。 重点与难点 本章重点: (1)逻辑代数中的基本公式、基本定理和基本定律。 (2)常用公式。 (3)逻辑函数的真值表、表达式、卡诺图表示方法及其相互转换。

(4)最小项和最大项概念。 (5)逻辑函数公式化简法和卡诺图化简法。主要教学内容 2.1 逻辑代数中的三种基本运算和复合运算2.1.1 三种基本运算 2.1.2 复合运算 2.2 逻辑代数运算的基本规律 2.3 逻辑代数的常用运算公式和三个规则2. 3.1 逻辑代数的常用运算公式 2.3.2 逻辑代数的三个规则 2.4 逻辑函数及其描述方法 2.4.1 逻辑函数 2.4.2 逻辑函数及其描述方法 2.4.3 逻辑函数的标准形式 2.4.4 逻辑函数的同或、异或表达式 2.5 逻辑函数化简 2.5.1 公式法化简 2.5.2 卡诺图化简

2.1 逻辑代数中的三种基本运算和复合运算 2.1.1 三种基本运算 1. 与运算(逻辑乘) 2. 或运算(逻辑加) 3. 非运算(逻辑非) 2.1.2 复合运算 1. 与非运算 与非运算是与运算和非运算的组合,先进行与运算,再进行非运算。 2. 或非运算

C笔试题目:将"引用"作为函数返回值类型的格式、好处和需要.doc

C++笔试题目:将”引用”作为函数返回值类型的格式、好处和需要格式:类型标识符函数名(形参列表及类型说明){//函数体} 好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的因为随着该局部变量生存期的结束,相应的引用也会失效产生runtimeerror! 注意事项: (1)不能返回局部变量的引用。这条可以参照EffectiveC++[l]的Item31。主要原因是局部变量会在函 返回后被销毁,因此被返回的引用就成为了”无所指”的引用,程序会进入未知状态。 (2 )不能返回函数内部ne w分配的内存的引用。这条可以参照Effect i veC++[l]的I tem31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由n ew分配)就无法释放,造成memoryl eak。 (3)可以返回类成员的引用,但最好是const。这条原则可以参照Eff ect iveC++[l]的I tem30。主要原因是当对

象的属性是与某种业务规则(busines sru le)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。 如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。 (4)流操作符重载返回值申明为“引用”的作用: 流操作符〉,这两个操作符常常希望被连续使用,例如: cout对于返回一个流指针则不能连续使用这个操作符象流操作符一样,是可以连续使用的,例如:x=j=10;或者(x=10)=100 :赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。 例3 ^include in tp ut (intn); in tvals [10]: i nter ror=-l; voi dmain() { put (0)=10 ://以put (0)函数值作为左值,等价于V als[0]二10 ; put (9) =20;//以put (9)函数值作为左值,等价于va ls[9]=20;

VBA函数返回值

VBA之函数返回值 1.返回一个值 Function define_yy(ByVal names As String, ByVal workbooks As String) As String Dim str_return As String '返回值 Dim i, t As Integer ........ ........ ........ ........ ........ define_yy = str_return End Function 对于函数返回值的要点已经用粗体表示出来了.调用此函数的格式为: call modle_connection.define_yy() (这个是不需要返回值的调用方法) bb=modle_connection.define_yy(a,b) (这是需要返回值的方法) 注:modle_connection为程序块名 2.返回值为多个值,可以采用返回数组的类型 Function return_data(ByVal strSEL As String, ByRef x As Integer) As String() '需要有括号,代表数组 Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim bb(1000, 20) As String Dim i As Integer, j As Integer cn.Open strCN rs.Open strSEL, cn i = 1 Do While Not rs.EOF If x = 1 Then bb(i, 1) = rs(0) Else For j = 1 To x bb(i, j) = rs(j - 1) Next j End If i = i + 1 rs.MoveNext Loop x = i - 1 return_data = bb() 'BB()本身也需要定义为数组

函数练习题(C语言)带答案

C语言函数练习题 一、选择题 1. 一个完整的C源程序是【】。 A)要由一个主函数或一个以上的非主函数构成 B)由一个且仅由一个主函数和零个以上的非主函数构成 C)要由一个主函数和一个以上的非主函数构成 D)由一个且只有一个主函数或多个非主函数构成 2. 以下关于函数的叙述中正确的是【】。 A)C语言程序将从源程序中第一个函数开始执行 B)可以在程序中由用户指定任意一个函数作为主函数,程序将从此开始执行 C)C语言规定必须用main作为主函数名,程序将从此开始执行,在此结束 D)main可作为用户标识符,用以定义任意一个函数 3. 以下关于函数的叙述中不正确的是【】。 A)C程序是函数的集合,包括标准库函数和用户自定义函数 B)在C语言程序中,被调用的函数必须在main函数中定义 C)在C语言程序中,函数的定义不能嵌套 D)在C语言程序中,函数的调用可以嵌套 4. 在一个C程序中,【】。 A)main函数必须出现在所有函数之前 B)main函数可以在任何地方出现 C)main函数必须出现在所有函数之后 D)main函数必须出现在固定位置 5. 若在C语言中未说明函数的类型,则系统默认该函数的数据类型是【】 A)float B)long C)int D)double 6. 以下关于函数叙述中,错误的是【】。 A)函数未被调用时,系统将不为形参分配内存单元 B)实参与形参的个数应相等,且实参与形参的类型必须对应一致 C)当形参是变量时,实参可以是常量、变量或表达式 D)形参可以是常量、变量或表达式 7. C程序中各函数之间可以通过多种方式传递数据,下列不能用于实现数据传递的方式是 【】。 A)参数的形实结合 B)函数返回值 C)全局变量 D)同名的局部变量 8. 若函数调用时参数为基本数据类型的变量,以下叙述正确的是【】。 A)实参与其对应的形参共占存储单元 B)只有当实参与其对应的形参同名时才共占存储单元 C)实参与对应的形参分别占用不同的存储单元 D)实参将数据传递给形参后,立即释放原先占用的存储单元

事件处理函数中返回值

事件处理函数中返回值 事件处理函数返回值其实指当事件发生时,浏览器会执行默认的操作,而当事件处理函数会返回一个结果,而当这个结果为true时,浏览器会继续执行默认操作,否则会停止执行。如果还是不懂的话,我们看一下下面这个实例: 当点击超链接标签时,如果check()的值为true,那么浏览器会跳转到abc.html页面中去,如果check()的值为false,点击超链接标签就不会跳转 这里return其实是对事件对象中的returnValue属性值的设置,而该属性就决定了该事件操作是否继续操作,当retrunValue为true时则继续操作,为false时则中断操作。 然而直接执行函数check,不使用return返回将不会对eturnvalue进行设置所以会默认地继续执行操作,比如如下实例 上面的实例就是不管check()的结果是true还是fasle,浏览器都会跳转到abc.html 页面中去。所以必须使用return返回。 事件处理函数返回值在表单中也存在这种情况,如下图

判断用户名是否为空,如果为空就不提交表单,否则就提交表单...跟上面理解是一样的。 讲到这里有很多同学在这里还能理解,但是呢,换个地方,换个事件绑定方式就不能理解了。 比如:在DOM对象上绑定事件: 很多人不能理解的是:在html元素上绑定事件时,return用了两次,才能阻止表单的提交,为什么在DOM对象上绑定事件时只用了一次return就能阻止表单提交,这里我们就要看看为什么了。 我们看看直接打印btn.onclick的结果,发现我们在html元素上绑定的事件处理函数fn是出现在DOM对象上事件处理函数的里面。 所以onclick=”return fn()”等价于 btn.onclick=function(){ return fn() },而fn()的结果true/false就决定表单是否提交。 总结:事件函数返回值; 如果返回true或者不返回,浏览器执行默认操作; 如果返回false,阻止浏览器默认操作。

逻辑函数的卡诺图化简法

逻辑函数的卡诺图化简法 逻辑函数的卡诺图化简法 由前面的学习得知,利用代数法可以使逻辑函数变成较简单的形式。但要求熟练掌握逻辑代数的基本定律,而且需要一些技巧,特别是经化简后得到的逻辑表达式是否是最简式较难确定。运用卡诺图法可以较简便的方法得到最简表达式。但首先需要了解最小项的概念。 一、最小项的定义及其性质 1.最小项的基本概念 由A、B、C三个逻辑变量构成的许多乘积项中有八个 被称为A、B、C的最小项的乘积项,它们的特点是 1. 每项都只有三个因子 2. 每个变量都是它的一个因子 3. 每一变量或以原变量(A、B、C)的形式出现,或以反(非)变量(A、B、C)的形式出现,各出现一次 一般情况下,对n个变量来说,最小项共有2n个,如n=3 时,最小项有23=8个

2.最小项的性质 为了分析最小项的性质,以下列出3个变量的所有最 小项的真值表。 由此可见,最小项具有下列性质: (1)对于任意一个最小项,只有一组变量取值使得它的值为1,而在变量取其他各组值时,这个最小项的值都是0。 (2)不同的最小项,使它的值为1的那一组变量取值也不同。 (3)对于变量的任一组取值,任意两个最小项的乘积为0。 (4)对于变量的任一组取值,全体最小项之和为1。 3.最小项的编号 最小项通常用mi表示,下标i即最小项编号,用十进制数表示。以ABC为例,因为它和011相对应,所以就称ABC 是和变量取值011相对应的最小项,而011相当于十进制中的3,所以把ABC记为m3 按此原则,3个变量的最小项

二、逻辑函数的最小项表达式 利用逻辑代数的基本公式,可以把任一个逻辑函数化成一种典型的表达式,这种典型的表达式是一组最小项之和,称为最小项表达式 。下面举例说明把逻辑表达式展开为最小项表达式的方法。例如,要将化成最小项表达式,这时可利用的基本运算关系, 将逻辑函数中的每一项都化成包含所有变量A、B、C的项,然后再用最小项下标编号来代表最小项,即 又如,要将化成最小项表达式,可经下列几步: (1)多次利用摩根定律去掉非号,直至最后得到一个只在单个变量上有非号的表达式; (2)利用分配律除去括号,直至得到一个与或表达式; (3)在以上第5个等式中,有一项AB不是最小项(缺少变量C),可用乘此项,正如第6个等式所示。 由此可见,任一个逻辑函数都可化成为唯一的最小项表达式。

逻辑函数化简

一、章节名称: 3.2逻辑函数的卡诺图化简法 二、教学目的与要求: 1. 掌握卡诺图基本概念及基本知识 2. 掌握逻辑函数卡诺化简法 3. 掌握具有约束条件的逻辑函数化简法 三、教学重点与难点: 重点:卡诺图化简法。 难点:合并最小项规律,具有约束条件的逻辑函数化简法。 四、教学手段: 板书与多媒体课件演示结合 五、教学方法: 课堂讲授、提问和讨论 六、教学过程: (一)复习与导入: 1、逻辑代数的三个规则。 2、逻辑代数的化简。 (二)新课讲授: 3.2逻辑函数的卡诺图化简法 一、逻辑函数的最小项及其性质 1、最小项的定义 对于N个变量,如果P是一个含有N个因子的乘积项,而在P中每一个变量都以原变量或反变量的形式出现一次,且仅出现一次,那么就称P是N个变量的一个最小项。 2个最因为每个变量都有以原变量和反变量两种可能的形式出现,所以N个变量有N 小项。 2、最小项的性质 P24表-16列出了三个变量的全部最小项真值表。由表可以看出最小项具有下列性质:性质1:每个最小项仅有一组变量的取值会使它的值为“1”,而其他变量取值都使它的值为“0”。 性质2:任意两个不同的最小项的乘积恒为“0”。 性质3:全部最小项之和恒为“1”。 由函数的真值可以很容易地写出函数的标准与或式,此外,利用逻辑代数的定律、公式,可以将任何逻辑函数式展开或变换成标准与或式。

例: C B A B C A C AB ABC B B AC A A BC C C AB AC BC AB Y +++=+++++=++=) ()()( 例: C AB ABC C B A C B A C C AB C B A C B A AB C B A B A AB C B A AB AB C B A AB AB C B A AB Y +++=+++=+++=+??=+++=++=)())(()( 3、 最小项编号及表达式 为便于表示,要对最小项进行编号。编号的方法是:把与最小项对应的那一组变量取值组合当成二进制数,与其对应的十进制数,就是该最小项的编号。 在标准与或式中,常用最小项的编号来表示最小项。如: ABC C AB C B A BC A Y +++=常写成7653),,(m m m m C B A F Y +++==或∑=m Y )7,6,5,3( 二、逻辑函数的卡诺图表达法 1、 逻辑变量卡诺图 卡诺图也叫最小项方格图,它将最小项按一定的规则排列成方格阵列。根据变量的数目N ,则应有n 2个小方格,每个小方格代表一个最小项。 卡诺图中将N 个变量分成行变量和列变量两组,行变量和列变量的取值,决定了小方格的编号,也即最小项的编号。行、列变量的取值顺序一定要按格雷码排列。P26列出了二变量、三变量和四变量的卡诺图。 卡诺图的特点是形象地表达了各个最小项之间在逻辑上的相邻性。图中任何几何位置相邻的最小项,在逻辑上也是相邻的。 所谓逻辑相邻,是指两个最小项只有一个是互补的,而其余的变量都相同, 所谓几何相邻,不仅包括卡诺图中相接小方格的相邻,方格间还具有对称相邻性。对称相邻性是指以方格阵列的水平或垂直中心线为对称轴,彼此对称的小方格间也是相邻的。 卡诺图的主要缺点是随着变量数目的增加,图形迅速复杂化,当逻辑变量在五个以上时,很少使用卡诺图。 2、 逻辑函数卡诺图 用卡诺图表示逻辑函数就是将函数真值表或表达式等的值填入卡诺图中。 可根据真值表或标准与或式画卡诺图,也可根据一般逻辑式画卡诺图。若已知的是一般的逻辑函数表达式,则首先将函数表达式变换成与或表达式,然后利用直接观察法填卡诺图。观察法的原理是:在逻辑函数与或表达式中,凡是乘积项,只要有一个变量因子为0时,该乘积项为0;只有乘积项所有因子都为1时,该乘积项为1。如果乘积项没有包含全部变量,无论所缺变量为1或者为0,只要乘积项现有变量满足乘积项为1的条件,该乘积项即为1。 例1: 可写成

相关文档
相关文档 最新文档