愿天天向上,愿学以致用,愿掌握生活

发布新日志

  • 数组定义

    2007-10-19 14:36:36

    数组定义由类型名,标识符和维数组成.维数指定数组中包含的元素的数目,它被写在一对方括号里边.我们必须为数组指定一个大于等于1 的维数.维数值必须是常量表达式——即,必须能在编译时刻计算出它的值.这意味着非const 的变量不能被用来指定数组的维数.
    下面的例子包含合法的和非法的数组定义:

    extern int get_size();
    // buf_size 和max_files 都是const
    const int buf_size = 512, max_files = 20;
    int staff_size = 27;
    // ok: const 变量
    char input_buffer[ buf_size ];
    // ok 常量表达式: 20 - 3
    char *fileTable[ max_files - 3 ];
    // 错误: 非const 变量
    double salaries[ staff_size ];
    // 错误非const 表达式
    int test_scores[ get_size() ];

    虽然staff_size 被一个文字常量初始化,但是staff_size 本身是一个非const 对象,系统只能在运行时刻访问它的值,因此它作为数组维数是非法的.

    但是用户必须清楚,C++没有提供编译时刻或运行时刻对数组下标的范围检查.除了程序员自己注意细节,并彻底地测试自己的程序之外,没有别的办法可防止数组越界.能够通过编译并执行的程序仍然存在致命的错误,这不是不可能的.

  • const与指针

    2007-10-17 18:15:51

       使用const修饰指针时,由于const的位置不同,而含意不同。下面举两个例子,说明它们的区别。

      下面定义的一个指向字符串的常量指针:

      char * const prt1 = stringprt1;

      其中,ptr1是一个常量指针。因此,下面赋值是非法的。

      ptr1 = stringprt2;

      而下面的赋值是合法的:

      *ptr1 = "m";

      因为指针ptr1所指向的变量是可以更新的,不可更新的是常量指针ptr1所指的方向(别的字符串)。

      下面定义了一个指向字符串常量的指针:

      const * ptr2 = stringprt1;

      其中,ptr2是一个指向字符串常量的指针。ptr2所指向的字符串不能更新的,而ptr2是可以更新的。因此,

      *ptr2 = "x";

      是非法的,而:

      ptr2 = stringptr2;

      是合法的。

      所以,在使用const修饰指针时,应该注意const的位置。定义一个指向字符串的指针常量和定义一个指向字符串常量的指针时,const修饰符的位置不同,前者const放在*和指针名之间,后者const放在类型说明符前。
  • 对象声明

    2007-10-17 16:12:37

    // file module0.C
    // 定义fileName 对象
    string fileName;
    // ... 为fileName 赋一个值


    // file module1.C
    // 需要使用 fileName 对象
    // 喔: 编译失败:
    // 在module1.C 中fileName 未定义
    ifstream input_file( fileName );

    在C++中,程序在使用对象之前必须先知道该对象.这对"编译器保证对象在使用时的类型正确性"是必需的.引用一个未知的对象将引起编译错误.在本例中,由于在model1.C中没有定义fileName,所以该文件编译失败.
    要编译model1.C,必须让程序知道fileName.

    要编译model1.C,必须让程序知道fileName,但又不能引入第二个定义.我们可以通过声明(declaring)该变量来做到这一点.
    // file module1.C
    // 需经使用fileName 对象
    // 声明fileName, 也即, 让程序知道它,
    // 但又不引入第二个定义
    extern string fileName;
    ifstream input_file( fileName );
    对象声明(declaration)的作用是使程序知道该对象的类型和名字.它由关键字extern以及跟在后面的对象类型以及对象的名字构成.声明不是定义,不会引起内存分配.实际上,它只是说明了在程序之外的某处有这个变量的定义.

    虽然一个程序只能包含一个对象的一个定义,但它可以包含任意数目的对象声明.比较好的做法,不是在每个使用对象的文件中都提供一个单独的声明而,是在一个头文件中声明这个对象,然后再在需要声明该对象的时候包含这个头文件.按照这种做法,如果需要修改对象的声明,则只需要修改一次就能维持多个使用该对象的文件中声明的一致性.

  • 幂函数pow

    2007-10-17 15:57:37

    假设有这样一个问题:计算2 的10 次方.我们首先想到的可能是
    #include <iostream>
    int main() {
    // 第一个解决方案
    cout << "2 raised to the power of 10: ";
    cout << 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2;
    cout << endl;
    return 0;
    }
    这样确实能够解决问题,但是可能需要检查两到三遍以确保正好有10个常数2参与乘法.

    接着我们被要求算出2的17次方和2的23次方.每次都要修改程序确实很麻烦,但更糟糕的是,这样做经常会出错.修改后的程序常常会多乘或少乘了一个2.最后我们又被要求生成2的从0到15次方的数值的表.使用文字常量需要与32行类似下面的格式
    cout << "2 raised to the power of X\t";
    cout << 2 * ... * 2;
    这里X随每对语句递增1.
    虽然这种蛮力型的方案也能解决问题,但是它总让人感到不快而且有些危机感.

    在下例中用来取代这种蛮力型的方案包括两部分内容:使用有名字的对象来读写每步的计算;引入一个控制流结构以便在某个条件为真时可以重复执行一系列语句.
    下面是一种技术先进的计算2 的10 次幂的程序:
    #include <iostream.h>
    int main()
    {
    // int 类型的对象
    int value = 2;
    int pow = 10;
    cout << value << " raised to the power of "
    << pow << ": \t";
    int res = 1; // 保存结果
    // 循环控制语句: 反复计算res
    // 直至cnt 大于pow
    for ( int cnt=1; cnt <= pow; ++cnt)
    res = res * value;
    cout << res << endl;
    }
    value,pow,res以及cnt是变量.它们允许对数值进行存储修改和查询.for循环使计算过程重复执行pow次.虽然这种层次的通用化能使程序更加灵活,但是这样的程序仍然是不可重用的.

    我们必须进一步通用化:把计算指数值的那部分程序代码抽取出来,定义成一个独立的函数以使其他函数能够凋用它.例如:
    int pow( int val, int exp )
    {
    for ( int res = 1; exp > u; --exp )
    res = res * val;
    return res;
    }
    现在每个需要计算指数值的程序,都可以使用pow()的实例,而不是重新实现它

    我们可以用如下的代码来生成2的幂的表:
    #include <iostream>
    extern int pow(int, int);
    int main()
    {
    int val = 2;
    int exp = 15;
    cout << "The Powers of 2\n";
    for ( int cnt=0; cnt <= exp; ++cnt )
    cout << cnt << ": "
    << pow(val, cnt) << endl;
    return 0;
    }
    实际上,这个pow()的实现既不够健壮也不够通用.例如,如果指数是负数该怎么办,如果是1 000 000 呢,对于负数指数,我们的程序总是返回1.对于一个非常大的指数,变量int res又小得不能够容纳这个结果.因此,对于一个大的指数将返回一个任意的不正确的值(在这种情况下,最好的解决方案是将返回值的类型修改为double类型)从通用的角度来说,我们的程序应该能够处理整数和浮点数类型的底数和指数,甚至其他的类型.正如你所看到的,为一个未知的用户组写一个健壮的通用函数,比实现一个特定的算法来解决眼前的问题要复杂得多.

数据统计

  • 访问量: 21356
  • 日志数: 30
  • 建立时间: 2007-10-02
  • 更新时间: 2007-11-14

RSS订阅

Open Toolbar