C++|static局部变量实用案例:生成随机数、生成斐波那契数列

  • A+
所属分类:体育平台

C++|static局部变量实用案例:生成随机数、生成斐波那契数列

"一词多义“在人类语言中普遍存在,在计算机语言中也是如此,都是通过”上下文“去区别。当然,计算机语言要求代码必须能够在“上下文”区隔“二义性”,否则会出现编译错误。

C++关键字static的用途主要有:

I 修饰函数内的局部变量,用来延长变量的存续期(duration),保挂其状态,也就是用static修饰的局部变量,只有在第一次函数调用时对其初始化,此后的调用对其不再初始化,其值为前一次调用后更新的值。要做到这一点,自然,static局部变量不能保存在栈区,static局部变量通常保存在全局静态区,会在程序代码加载到内存时,static局部变量连同其它外部变量(全局变量)一起,也提前加载到了内存,如果其值未初始化,编译器会将其初始化为0。

II 可以修饰函数外的外部变量(或称全局变量)以及函数,用来定义其链接性(linkage),也就是文件间的可访问性。

链接性为外部的标识符可在文件间共享(全局变量)。链接性为内部的标识符可在函数间共享(静态全局变量,const修饰的全局变量),没有链接性的标识符不能共享(局部变量,静态局部变量)。

不显式用static修饰的全局变量,具有外部链接性的,作用域是整个工程,由链接器完成外部链接。在一个文件内定义的全局变量,在另一个文件中,通过extern 全局变量名的声明,就可以使用。

显式用static修饰的全局变量,可以称为全局静态变量,作用域是声明此变量所在的文件,其他的文件即使用extern声明也不能使用。

static修饰函数也是如此,在函数的返回类型前加上static关键字,函数即被定义为静态函数。静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用。这样可以避免命名冲突和命名空间污染,因为C对于函数名是全局作用域的。

III 修饰类成员

当需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见时,可以使用静态数据成员。静态数据成员不能被不是静态的成员函数访问,可以被静态成员函数访问。

延长存续期(或保持状态)的静态局部变量,虽然由外部变量(或称全局变量)也可以完成,但相对而言,全局变量最明显的缺点是全部函数都可以访问并修改,容易出错,且访问全局变量的函数不方便移值(而在函数中定义的局部变量,仅仅受此函数控制)。

1 自定义简单的伪随机数函数

基本思路是通过设置随机函数使用的种子数(设置为静态局部变量)、组合乘法、加法和迭代,再通过循环求余便可以得出一些简单的随机数。

#include <stdio.h>
#include <malloc.h>
unsigned int PRNG() // 每次调用都利用静态局部变量特性生成一个不同的种子
{
    static unsigned int seed = 5323;  // 利用静态变量在每次调用时都会更新其值
    seed = 8253729 * seed + 2396403;
    return seed % 32768;
}
int* rnd(int rng,int size)
{
    int *arr = (int*)malloc(sizeof(int)*size);
    for (int i=0; i < size; ++i)
    {
        arr[i] = PRNG()*rng/32768;
    }
    return arr;
}
void arrPrint(int *arr,int size)
{
    for (int i=0; i < size; ++i)
    {
        printf("%d ",arr[i]);
        if ((i+1) % 5 == 0)
            printf("n");
    }
}
int main()
{
    int *arr = rnd(10,20);// 0-10,不包括10的随机数
    arrPrint(arr,20);
    getchar();
    return 0;
}
/*
7 8 6 3 8
3 9 6 6 0
8 1 1 8 4
8 3 8 6 7
*/

2 生成斐波那契数列

我们知道,递归函数如果在函数体内有自己的两次调用,其展开会是一个二叉树的结构,会涉及到大量的重复计算,其优化的思想通常是使用动态规划去使用一个数组来保存其已计算部分。通常,类似斐波那契数列的问题也可以直接使用一个数组,数组元素之间去迭代。也可以利用局部静态变量的特性去迭代:

#include <iostream.h> // STL generate(),generate_n()
#include <vector>
#include <algorithm>

using namespace std;

//返回一个Fibonacci数,其由generate_n()算法调用
int Fibonacci1(void)
{
    static int r;
    static int f1 = 0;
    static int f2 = 1;
    r = f1 + f2 ;
    f1 = f2 ;
    f2 = r ;
    return f1 ;
}
//返回一个Fibonacci数,其由generate()算法调用
int Fibonacci2(void)
{
    static int r;
    static int f1 = 0;
    static int f2 = 1;
    r = f1 + f2 ;
    f1 = f2 ;
    f2 = r ;
    return f1 ;
}
//定义整型数的vector容器类
typedef vector<int > IntVector ;

//显示vector容器中的元素
void put_vector(IntVector v,char *name)
{
    IntVector::iterator theIterator;
    cout<<name<<":"<<endl;
    for (theIterator=v.begin();theIterator!=v.end();++theIterator){
        cout<<(*theIterator)<<" ";
    }
    cout<<endl;
}

//测试generate()和generate_n()算法
void main()
{
    const int VECTOR_SIZE = 15 ;
    
    //定义迭代器类
    typedef IntVector::iterator IntVectorIt ;
    
    //声明vector容器对象
    IntVector Numbers1(VECTOR_SIZE),Numbers2(VECTOR_SIZE);
    int i ;
    
    //初始化vector容器对象
    for(i = 0; i < VECTOR_SIZE; i++)
        Numbers1[i] = i ;
    
    //显示vector容器对象的元素
    cout << "Before calling generate_n:" << endl ;
    put_vector(Numbers1,"Numbers1");
    
    //利用generate_n算法用Fibonacci 数填充vector容器
    generate_n(Numbers1.begin(), VECTOR_SIZE, Fibonacci1) ;
    
    //显示vector容器对象的元素
    cout << "After calling generate_n:" << endl ;
    put_vector(Numbers1,"Numbers1");
    
    //利用generate算法用Fibonacci 数填充vector容器
    generate(Numbers2.begin(),Numbers2.end(), Fibonacci2) ;
    
    //显示vector容器对象的元素
    cout << "After calling generate:" << endl ;
    put_vector(Numbers2,"Numbers2");
    while(1);
}
/*
Before calling generate_n:
Numbers1:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
After calling generate_n:
Numbers1:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
After calling generate:
Numbers2:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
*/

-End-

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: