⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c++b.txt

📁 C语言是一种面向过程的计算机程序设计语言。最初为unix而生。它既有高级语言的特点
💻 TXT
📖 第 1 页 / 共 5 页
字号:
16  *ptr = 7;
17  ptr = &y;
18
19  return 0;
20 }

输出结果:
Compiling FIG05 14.CPP:
Error FIG05_14.CPP 16: Cannot modify a const object
Error FIG05_14.CPP 17: Cannot modify a const object
Warning FIG05_14.CPP 20: 'y' is declared but never used

                                                 图5.14  修改常量数据的常量指针

5.6  按引用调用的冒泡排序
下面将图4.16的冒泡排序程序修改成用两个函数bubbleSort和swap(如图5.15)。函数bubbleSort进行数组排序,它调用函数swap,变换数组元素array[j)和array[j+1]记住,C++强制函数之间的信息隐藏,因此swap并不能访问bubbleSort中的各个元素。由于bubbleSort要求swap访问交换的数组元素,因此bubbleSort要将这些元素按引用调用传递给swap.每个数组元素的地址显式传递。
尽管整个数组自动按引用调用传递,但各个数组元素是标量,通常按值调用传递。因此,bubbleSort对swap调用中的每个数组元素使用地址运算符(&),如下所示的语句:
    swap( &array[ j ], array[j+ 1]);
实现按引用调用。函数swap用指针变量element1Ptr接收&array[j]。由于信息隐藏,swap并不知道名称&array[j],但swap可以用*element1Ptr作为&array[j]的同义词。这样,swap引用*element1Ptr时,实际上是引用bubbleSort中的&array[j]。同样,swap引用*element2Ptr时,实际上是引用bubbleSort中的array[j+1]。虽然swap不能用:
    hold = array [ j ];
    array[ j ]  = array[ j + 1 ];
    array[ j + 1 ]  = hold;  

但图5.15中的swaP函数用
      hold = * element1Ptr;
      *element1Ptr = *element2Ptr;
      *element2Ptr = hold;  
达到相同的效果。

1 // Fig. 5.15: fig05_15.cpp
2 // This program puts values into an array, sorts the values into
3 // ascending order, and prints the resulting array.
4 #include <iostream.h>
5 #include <iomanip.h>
6
7 void bubbleSort{ int *, const int );
8
D int main(}
l0 {
11   const int arraySize = 10;
12   int a[ arraySize ) = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
13   int i;
14
15   cout << "Data items in original order\n";
16
17   for ( i = 0; t < arraySize; i++ )
18      cout << setw( 4 ) << a[ i ];
19
20   bubbleSort( a, arraySize );        // sort the array
21   cout << "\nData items inascending order\n";
22
23   for ( i = 0; i < arraySize; i++ )
24      cout << setw( 4 ) << a[ i ];
25
26   cout << endl;
27   return 0;
28 }
29
30 void bubbleSort( int *array, const int size )
31 {
32   void swap( int *, iht * );
33
34   for (int pass = 0; pass < size - 1; pass++ )
35
36     for (int j = 0; j < size - 1; j++ )
37
38             if  ( array[ j ]  > array[ j + 1 ]  )
39          swap( &array[ j ], &arra[ j + 1 ] );
4O }
41
42 void swap( int *element1Ptr, int *element2Ptr )
43 {
44   int hold = *elementlPtr;
45   *element1Ptr = *element2Ptr;
46   *element2Ptr = hold;
47 }

               输出结果:
    Data  item:  in  Original  Order
    2    6    4    8    10    12    89    68    45    37
    Data  items  in  ascendinq  Order
    2    4    6    8    lO    12    37    45    68    89

                                图5.15  按引用调用的冒泡排序

注意函数bubbleSort中的几个特性。函数首部中将array声明为int* array而不是int array[],表示bubbleSort接收单下标数组作为参数(这些符号是可以互换的)。参数size声明为const以保证最低权限原则。尽管参数size接收main中数值的副本,且修改该副本并不改变main中的值,但是bubbleSort不必改变size即可完成任务。bubbleSort执行期间数组的长度保持不变,因此,size声明为const以保证不被修改。如果排序过程中修改数组长度,则排序算法无法正确执行。
    bubbleSort函数体中包括了函数swap的原型,因为它是调用swap的惟一函数。将原型放在bubbleSort中,使得只能从bubbleSort正确地调用swap。其他函数要调用swap时无法访问正确的函数原型,这通常会造成语法错误,因为C++需要函数原型。

    软件工程视点5.4
    将函数原型放在其他函数中能保证最低权限原则,只能从该原型所在函数中正确地调用。
    注意函数bubbleSort接收数组长度参数。函数必须知道数组长度才能排序数组。数组传递到函数时,函数接收数组第一个元素的内存地址。数组长度要单独传递给函数。
    通过将函数bubbleSort定义成接收数组长度作为参数,可以让函数在排序任何长度单下标整型数组的程序中使用。

    软件工程视点5.5
    向函数传递数组时,同时传递数组长度(而不是在函数中建立数组长度信息),这样能使函数更加一般化,以便在许多程序中复用。

    数组长度可以直接编程到函数内,这样会把函数的使用限制在特定长度的数组并减少其复用性。程序中只有处理特定长度的单下标整型数组时才能使用这个函数。
    C++提供一元运算符sizeof,确定程序执行期间的数组长度或其他数据类型长度(字节数)。采用数组名时(如图5.16所示),sizeof算符返回数组中的总字节数为size_t类型的值,通常是unsigned int类型。这里使用的计算机将float类型的变量存放在4字节内存中,array声明为20个元素,因此array使用80字节内存空间。在接收数组参数的函数中采用指针参数时,sizeof运算符返回指针长度的字节数(4)而不是数组长度。

    常见编程错误5. 7
    在函数中用sizeof运算符寻找数组参数长度的字节数时返回指针长度的字节数而不是数组长度的字节数。

1 // Fig. 5.16: fig05_16.cpp
2 // Sizeof operator when used on an array name
3 // returns the number of bytes in the array.
4 #include <iostream.h>
5
6 size_t getSize( float * );
7
8 int main()
9 {
10   float array[ 20 ];
11
12   cout << "The number of bytes in the array is"
13       << sizeof( array )
14       << "\nThe number of bytes returned by getSize is"
15       << getSize( array ) << endl;
16
17   return 0;
18 }
19
20 size_t getSize( float *ptr )
21 {
22   return sizeof( ptr );
23 }

输出结果:
The number of bytes in the array is 80
The number of bytes returned by getSize is 4

                       图5.16  采用数组名时,sizeof运算符返回数组中的总字节数

数组中的元素个数也可以用两个sizeof操作的结果来确定。例如,考虑下列数组声明:
    double realArray[ 22 ];
如果double数据类型的变量存放在8个字节的内存中,则数组realArray总共包含176个字节。要确定数组中的元素个数,可以用下列表达式:
    sizeof realArray/sizeof(double)
这个表达式确定realArray数组中的字节数.并将这个值除以内存中存放—个double值的字节数,图5.17的程序用size运算符计算我们所用的个人计算机上存放每种标准数据类型时使用的字节数。
    可移植性提示 5.3
    存放特定数据类型时使用的字节数随系统的不同而不同。编写的程序依赖于数据类型长度而且要在几个计算机系统上运行时,用sizeof确定存放这种数椐类型时使用的宇节数。

1 // Fig. 5.17:fig05 17.cpp
2 // Demonstrating the sizeof operator
3 ~include <iostream.h>
4 ~include <iomanip.h>
5
76 ~nt main(}
8   char c;
9   short s;
10  iht i;
11  long 1;
12  float f;
13  double d;
14  long double ld;
15  int arras 20 ], *ptr = array;
16
17  cout << "sizeof c = " << sizeof c
18       << "\tsizeof(char) =" << sizeof( char )
19      << "\nsizeof s = "<< sizeof s
20      << "\tsizeof(short) = "<< sizeof( short )
2I         "\nsizeof i = " << sizeof i
22      << "\tsizeof(int) =" << sizeof  (int )
23         "\nsizeof 1 = "<<sizeof 1
24      << "\tsizeof(long) =" << sizeof( long )
25      << "\nsizeof f = "<< sizeof f
27         "\nsizeof d =" << sizof d
28      << "\tsizeof(double) =" << sizeof( double )
29      << "\nsizeof ld =" << sizeof ld
30      << "\tsizeof(long double) = "<< sizeof( long double )
31      << "\nsizeof array = "<< sizeof array
32      << "\nsizeof ptr = "<< sizeof ptr
33      << endl;
34  return 0;
35 }

输出结果:
 sizeof c = 1   sizeof(char) = 1
 sizeof s = 2   sizeof(short) = 2
 sizeof i = 4   sizeof(int) = 4
 sizeof l = 4   sizeof(long) = 4
 sizeof f = 4   sizeof(float) = 4
 sizeof d = 8   sizeof(double) = 8
 sizeof ld = 8  sizeof(long double) = 8
 sizeof array =
 sizeof ptr = 4

                               图 5.17  用sizeof运算符计算存放每种标准数据类型时使用的字节数

 sizeof运算符可以用于任何变量名、类型名或常量值。用于变量名(不是数组名)和常量值时,返回存放特定变量或常量类型所用的字节数。注意,如果提供类型名操作数,则sizeof使用的括号是必需的;如果提供变量名操作数,则sizeof使用的括号不是必需的。记住,sizeof是个运算符而不是个函数。
    常见编程错误5.8
    如果提供类型名操作数,而不在sizeof操作中使用括号则是个语法错误。
    性能提示5.2
    sizeof属于编译时的一元运算符,而不是个执行时函数。这样,使用sizeof并不对执行性能遣成不良影响。

5.7  指针表达式与指针算法
    指针是算术表达式、赋值表达式和比较表达式中的有效操作数。但是,通常并不是这些表达式中使用的所有运算符都在指针变量中有效。本节介绍可以用指针操作数的运算符及这些运算符的用法。
    只有少量操作可以对指针进行。指针可以自增(++)或自减(--),整数可以加进指针中(+或+=),也可以从指针中减去整数(-或-=),指针可以减去另一指针。
    假设声明了数组int v[5],其第一个元素位于内存地址3000。假设指针vPtr已经初始化为指向数组v[0],即vPtr的值为3000。图5.18演示了在32位的机器中的这种情况。注意vPtr可以初始化为数组v的指针,如下所示:
               vPtr = v;
               vPtr = &v[ 0 ]



?????????????????????流敢???潃癮牥整??金??吠楲污瘠牥楳湯??????????????????

                          图5.18 数组v和指向v的指针变量vPtr
    可移植性提示5.4
    如今的大多数计算机都是16位或32位,有些较新的计算机用8字节整数。由于指针算法的结果取决于指针所指对象的长度,因此指针算法与机器有关。
 按照传统算法,3000+2得到3002。而指针算法通常不是这样。将指针增加或减去一个整数时,指针并不是直接增加或减去这个整数,而是加上指针所指对象长度的这个倍数。这些字节数取决于对象的数据类型。例如,下列语句:
    vPtr += 2;
在用4字节内存空间存储整数时得到的值为3008(3000+2*4)。对数组v,这时vPtr指向v[2]如图5.19。如果用2字节内存空间,则上述结果得到3004(3000+2*2)。如果数组为不同数据类型,则上述语句将指针递增指针所指对象长度的2倍。对字符数组进行指针算法时,结果与普通算法相同,因为每个字符的长度为一个字节。



?????????????????????流敢???潃癮牥整??金??吠楲污瘠牥楳湯??????????????????

                                  图 5.19经过指针运算之后的vPtr

     如果vPtr递增到3016,指向v[4],则下列语句:
    vptr -= 4;
将vPtr复位为3000,即数组开头。如果指针加1或减1,则可以用自增(++)和自减(--)运算符。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -