数组

作者: gpfworld | 来源:发表于2018-12-31 23:06 被阅读0次
    (1)传统的数组实现方式
    见另一篇博客传统数组
    (2)自动分配数组
    (1)一维数组(malloc/delete)
    
    #include <iostream>
            #include<iterator>
            #include<list>
            #include<stdlib.h>
            #include<stdio.h>
            #include<time.h>
    
            using namespace std;
            int main(void)
            {
                    cout<<"使用malloc实现动态分配的数组空间"<<endl;
                    int *p1 = (int *)malloc(sizeof(int)*10);
                    for(int i=0; i<10; i++) {
                            *(p1+i) = i+10;
                    }
                    for(int i=0; i<10; i++) {
                            cout << *(p1+i);
                    }
                cout << endl;
                    free(p1);
    
                    cout<<"\n使用new实现动态分配的数组空间"<<endl;
                    int *p2 = new int[10];
                    for(int i=0; i<10; i++) {
                            *(p1+i) = i+20;
                    }
                    for(int i=0; i<10; i++) {
                            cout << *(p1+i);
                    }
                cout << endl;
                    delete p2;
    
                    return 0;
            }
    
    (2)多维数组
    
    #include <iostream>
            #include<iterator>
            #include<list>
            #include<stdlib.h>
            #include<stdio.h>
            #include<time.h>
    
            using namespace std;
            int main(void)
            {
                    cout<<"使用malloc开辟e二维数组"<<endl;
                    int **p1 = (int **)malloc(sizeof(int *)*5);
                    for(int i=0; i<5; i++) {
                            *(p1+i) = (int *)malloc(sizeof(int)*5);
                    }
                    for(int i=0; i<5; i++) {
                            for(int j=0; j<5; j++) {
                                    p1[i][j] = i+j;
                            }
                    }
                    for(int i=0; i<5; i++) {
                            for(int j=0; j<5; j++) {
                                    cout<< *(*(p1+i)+j)<<" ";
                            }
                            cout<<endl;
                    }
                    for(int i=0; i<5; i++) {
                            free(*(p1+i));
                    }
                    free(p1);
    
                    cout<<"\n使用new关键字动态开辟二位数组"<<endl;
                    int **p2 = new int*[5];
                    for(int i=0; i<5; i++) {
                            *(p2+i) = new int[5];
                    }
                    for(int i=0; i<5; i++) {
                            for(int j=0; j<5; j++) {
                                    p2[i][j] = i+j;
                            }
                    }
                    for(int i=0; i<5; i++) {
                            for(int j=0; j<5; j++) {
                                    cout<< *(*(p2+i)+j)<<" ";
                            }
                            cout<<endl;
                    }
                    for(int i=0; i<5; i++) {
                            delete(*(p2+i));
                    }
                    delete p2;
    
                    return 0;
            }
    
    (3)使用动态分配方式实现数组时需要注意
        (1)动态分配实现多维数组时,利用的是多级指针来实现的,而传统的
            多维数组是靠数组指针这种特殊形式的指针实现的,但是让它
            们在多维构建的逻辑上都是一样。
    
        (2)传统方式实现的多位数组本质还是一维数组,元素全部都是连续的
            但是动态分配空间不是的,它是由指针数组组织起来的,所有
            的一维数组的空间不一定是连续的。
    
        (3)动态方式实现多维数组时,由于单维数组间的空间并不连续,因此
            在释放内存空间时一定要小心,不要导致内存泄漏。需要分批
            释放空间,就像上面的例子所示。
        
        (4)传统的多位数组中*的作用与动态分配的多维数组访问时*的含义是不同
            的,比如如二维数组*访问形式:
            传统方式:*(*(buf+i)+j) = 5; buf[i][j]
                其中的*(buf+i)中的*实际上是强制转换的功能,强制的
                将数组指针类型转换为数组元素指针类型。
                
            
            动态分配方式:*(*(p+i)+j) = 5; buf[i][j]
                其中的*(p+i)中*其实时寻找空间操作,或者也称为解引用
                操作。
                
        (5)动态分配的数组不能初始化,只能使用赋值的方式给值。
        
    
        (6)传统方式实现的数组,特别是多维数组会大量涉及数组指针的概念
            动态的方式实现的数组则大量涉及多级指针的概念。
    
    (4)什么时候使用自动内存分配的方式实现数组
        当需要程序运行后,动态确定数组的大小的时候,这个时候就是必须使用这种方式。
    (3)C++提供数组类封装的方式式。
    c++中还有一种数组类封装的实现方式,就对传统和动态分配这两种方式进行了类封装,类名为array,有些编译器不支持这样的实现方式。
    使用
    
    (1)一维
    array<int,5> myarray={1,2,3,4,5};  
    
    (2)二维 
    array<array<int,2>,3 > myarray2D={1,2,3,4,5,6}; 
    (4)c++中数组实现方式总结
    (1)传统方式 
        自定义固定长度数组时,常用这种方式
    (2)动态分配方式
        需要在程序运行时具体决定元素个数时使用这种方式,C++中的STL vector
        容器就是使用的动态分配数组的方式封装实现的。
        
    (3)array类封装方式
        array对数组进行了类封装,至于它的具体实现方式要看定义类对象的
        方式。如果是通过new关键字实现的,就是使用动态分配的方式。
        否者就是使用传统的方式实现。
    
    在java中,java摈弃了c++个各种各样复炸的数组实现方式,只保留了Array类封装
    样式的数组,在java中由于类对象空间全部都是开辟于动态分配区(堆),因此本质上
    java的数组全部采用动态空间分配方式,单维数组空间之间不连续。
    
    
    (3)字符串(特殊的字符数组)
    (1)C样式字符串
        (1)数组形式
        (2)指针形式
    
    (2)C++提供的string形式
        (1)声明   
            //string str1 = "hello world";
                //string str1("hello wolrd");
                string *str1 = new string("hello world");
    
            如果不初始化字符串就是空字符串。
    
    
        (2)string对[]/=/==/+进行了重载
            (1)可以使用[]访问字符串字符
            (2)可以使用=直接相互间赋值
            (3)可以使用==比较两个字符串对象是否相等,但是如果是指针形式的对象,不能使用==判断
                    string *str1 = new string("hello world");
                    string *str2 = new string("hello world");
                    string str3("hello world");
                    string str4("hello world");
    
                    str1[0] = '$';
    
                    string str;
                    if(str3 == str4) {
                            str = "==";
                    } else {
                            str = "!=";
                    }   
                    cout << str  << endl;
    
            (4)字符串可以使用+进行连接,但是要求第一个必须是string类型的字符串
                不能使用字符串字面量(常量字符串,任何形式的C类型的字符串),因为
                只有string重载了+运算符
                        string str1 = "hello!, ";
                        string str = str1+"world"+" is "+ "world";
    
                
                注意:
                        string *str1 = new string("hello!, ");
                        char *str2= " wwww ";
                        string str = *str1+"world"+ str2 + " is "+ "world";
    
                        cout << str << endl;  
            (5)+=的使用
                (1)左边的第一个必须是string类型字符串
                (2)右边的string类型变量必须先声明后使用
                            string *str1 = new string("hello!, ");
                            string str;
                            // = *str1 +  "world"+" is "+ "world";
                            str += *str1 + "world"+" is "+ "world";
            
                            cout << str << endl;    
    
    
            (6)使用>>向string操作数中输入字符串时,无法输入带有空格的字符串
                (1)使用getline(cin, str);函数,就可以输入带有空格的字符串,
                    默认结尾符是回车。
    
                (2)使用第三参数输入指定结尾符的字符串
                    getline(cin, str,'#');//输入#结尾的字符串
    
        (3)访问字符串的字符
            由于string对[]进行了重载,因此,可以使用[]访问字符串中的元素,既可以作为左值使用
            也可以作为右值使用。
                    string str;
    
                    getline(cin, str);
    
                    for(int i=0; i<str.length(); i++) {
                            str[i] = std::toupper(str[i]);
                    }
    
                    cout<< str << endl;
    
                
        (4)常见操作字符串的一些string的成员函数的回顾
            (1)substr():提取子字符串
                (1)只有一个参数时:指定索引位置
                    如果指定的索引位置超出范围,会抛出超出范围的异常。
                    
                (2)两个参数时:第一个参数指定索引位置,第二个参数指定提取的字符串长度
                    (1)如果指定的索引位置超出范围,会抛出超出范围的异常。
                    (2)如果指定的长度超过范围,自动提取到字符串结束为止即可。
        
            (2)字符串比较
                (1)c字符串的比较
                    (1)比较的函数:使用strcmp或者strncmp函数进行比较
                        (1)strcmp函数:比较两个字符串是否完全相等
                            char *p = "hello";
                            char buf[] = {"hellw"};
                            int ret = strcmp(p, buf);
                        (2)strncmp函数:比较两个字符串前n个字符是否相等
                            char *p = "hello";
                            char buf[] = {"hellw"};
                            int ret = strncmp(p, buf, 4);
                            
                        (3)函数返回值:如果两个字符串相等,返回0,如果第一个参数指向的字符串小于第二个参数指向的字符串,
                        返回一个小于0的数,否则就返回一个大于0的数。
    
                        
                    (2)字符串比较的规则(以strcmp为例)
                        将两个字符串的字符逐个今次那个比较,知道找到不同的字符或者到达字符串的末尾,如果找到不同字符,就
                        根据器asscii值进行比较(函数返回asscii差值),如果两个字符串找到最后发现长度不相等,就返回长度差值。
                    
                
                (2)使用重载后的比较运算符 ==/!=/<=/>=进行比较
                    (1)比较的方法与strcmp同
                    (2)对string对象进行比较,或者将string对象与c样式的字符串进行比较
                                string str1 = "hello";
                                string str2 = "he";
    
                                string str;
                                if(str1 < "dsdf") {
                                        str = "small";
                                } else {
                                        str = "lage";
                                }
    
                                cout<< str << endl;
    
            
                (3)使用compare成员函数进行比较
                    (1)比较的方法与strcmp同
                    (2)对string对象进行比较,或者将string对象与c样式的字符串进行比较
                    (3)compare不同的重载版本
                        (1)word.compare(string str);:比较word与str是否完全相等
                        (2)word.compare(int index, int num, string str1);:比较word中从index开始向后num个字符与str1是否完全相等。
                        (3)word.compare(int index1, int num1, string str1, int dex2, int num2);:比较word与str1的子字符串是否相等。
    
                    (4)使用substr实现子字符串的比较
                        if(word.substr(2,4)==word.substr(3,5));
    
    
            (3)搜索字符串
                (1)搜索成员函数find:返回索引
                (2)的不同重载版本
                    (1)word.find(char c):在word中搜索字符,成功返回索引,失败返回string::npos(4294967295)表示非法字符位置。
                    (2)word.find(string/char * str):    
                    (3)word.find(string/char * str, int i):从word的i位置开始找。
                    (2)word.find(string/char * str, int i, int n):从word的i位置开始找str中前n个字符。
    
                (3)逆向搜索函数rfind,用法同find
                (4)在字符串中搜索字符集中的字符
                    (1)涉及函数
                        (1)word.find_first_of(string/char str);:从word头开始索引,第一次出现str中字符的位置
                        (2)word.find_first_not_of(string/char str);:从word头开始索引,第一次出现非str中字符的位置
                        (3)word.find_last_of(string/char str);:从word尾部开始索引,第一次出现str中字符的位置
                        (4)word.find_last_not_of(string/char str);:从word尾部开始索引,第一次出现非str中字符的位置
    
                    (2)使用例子:将字符串拆分成子字符串
    
    #include <stdlib.h>
                            #include <iostream>
                            #include <string>
    
                            using namespace std;
                            int main(void)
                            {
                                    string str = "sdfa sdaf,sdffsdf,fsdf/fsdf";
                                    int start = 0;
                                    int end = 0;
                                    string s = " ,/";
    
                                    start = str.find_first_not_of(s);
                                    while(start != string::npos) {
                                            end = str.find_first_of(s, start+1);
                                            if(end == string::npos)
                                                    end = str.length();
    
                                            cout << str.substr(start, end-start) << endl;
    
                                            start = str.find_first_not_of(s, end+1);
                                    }
    
                                    return 0;
                            }
    
    (4)修改字符串
                (1)插入字符串
                    (1)涉及成员函数:insert
                    (2)不同重载版本
                        (1)word.inset(int i, string/char *str):将字符串插入word的i之前
                        (2)word.inset(int i, string/char *str, int n):将字符串插入str中前n个字符word的i之前
                        (2)word.inset(int i, string/char *str, int j, int n):将字符串插入str中j位置开始的n个字符word的i之前
    
                    (3)测试例子
    
                (2)字符串的替换
                    (1)涉及成员函数:replace
                    (2)涉及不同的重载版本
                        (1)word.replace(int i, int n, string/char * str);:将word中的i位置开始的n个字符,用str替换
                        (2)word.replace(int i, int n, string/char * str,int n1);:将word中的i位置开始的n个字符,用str中的前n1个替换
                        (3)word.replace(int i, int n, string/char * str,int i1, int n1);:将word中的i位置开始的n个字符,用str中i1位置开始的n1个字符替换。
                    (3)用例
    
    
                (3)删除字符
                    (1)涉及成员函数erase
                    (2)重载版本
                        (1)word.erase(int i, int n);:将word中的i位置开始的n个字符删除
    
                    (3)用例
    
        (5)字符串数组
            (1)c样式的字符串数组
            
            (2)c样式字符串数组
                char *p[] = {"hello", "world", "is", "buitful"};
    
            (3)string样式字符串              
                string p[] = {"hello", "world", "is", "buitful"};
    
    
            (4)二者的区别
                c样式的字符串数组中,字符串是常量,存放在常量区,内容不能被更改,否者会导致段错误。
                string样式字符串,字符串在string类中,是以字符串数组的形式存放的,内容是可以修改的。
    
            (5)用例
    
    #include <stdio.h>
                    #include <stdlib.h>
                    #include <iostream>
                    #include <string>
    
                    using namespace std;
                    int main(void)
                    {
                            #if 0
                            char *p[] = {"hello", " world", " is", " buitful"};
            
                            p[0][1] = 'w';
                            #endif  
    
                            string p[] = {"hello", " world", " is", " buitful"};
                            p[0][1] = 'w';
    
                            cout << p[0] << endl;
            
                            return 0;
                    }       
    

    相关文章

      网友评论

          本文标题:数组

          本文链接:https://www.haomeiwen.com/subject/ualglqtx.html