c++基础复习之数组与指针

数组

定义: 数组是由类型名、标识符和维数组成的复合数据类型,类型名规定了存放在数组中的元素的类型,而维数则指定数组中包含的元素个数。
1. 如果没有显示提供元素初值,则数组元素会像普通变量一样初始化
- 在函数体外定义的内置数组,其元素均初始化为0;
- 在函数体内定义的内置数组,其元素无初始化;
- 不管数组在哪里定义,如果其元素为类类型,则自动调用该类的默认构造函数进行初始化;如果该类没有默认构造函数,则必须为该数组的元素提供显示初始化。

  1. 与vector类型相比,数组的显著缺陷在于:数组的长度是固定的,而且程序员无法知道一个给定数组的长度。数组没有获取其容量大小的size操作,也不提供push_back操作在其中自动添加元素。如果需要更改数组的长度,程序员只能创建一个更大的新数组,然后把原数组的所有元素复制到新数组空间中去。
习题(c 风格字符串)
  1. 编写必要的代码将一个数组赋值给另一个数组,然后改用vector实现。
/*数组实现*/
#include<iostream>
#include<string>

using namespace std;

int main()
{
    const size_t array_size = 7;
    int ia1[] = {0,1,2,3,4,5,6};
    int ia2[array_size];

    for(size_t ix = 0; ix !=  array_size; ++ix)
    {
        ia2[ix] = ia1[ix];
        cout<< ia2[ix];
    }
    cout << endl;
    return 0;
}


/*vector实现*/
#include <vector>
#include<iostream>

using namespace std;
int main()
{
    vector<int> ivec1(10, 1);//每个元素初始化为 0
    vector<int> ivec2;
    for (vector<int>::iterator iter = ivec1.begin();
        iter != ivec1.end(); ++iter)
    {   ivec2.push_back(*iter);
    cout << *iter << ' ';
    }
    return 0;
}
  1. 编写程序判断两个数组是否相等,然后编写一段类似的程序比较两个vector。
int main()  
{  
    const int arr_size = 7;  
    int arr1[arr_size] = {1,2};  
    int arr2[arr_size] = {1,2,0};  

    for (int i = 0;i != arr_size; ++i)  
    {  
        if (arr1[i] != arr2[i])  
        {  
            cout << "arr1 is not equal to arr2" << endl;  
            break;  
        }  
    }  
    return 0;  
}  

/*比较两个vector*/
#include <iostream>
#include <vector>

using namespace std;

int main()  
{  
    vector<int> ivec1;  
    vector<int> ivec2;  

    int ival;
    //读入两个 vector  的元素值
    cout << "Enter numbers for vector1(-1 to end):" << 
        endl;
    cin >> ival;
    while (ival != -1) {
        ivec1.push_back(ival);
        cin >> ival;
    }
    cout << "Enter numbers for vector2(-1 to end):" << 
        endl;
    cin >> ival;
    while (ival != -1) {
        ivec2.push_back(ival);
        cin >> ival;
    }

    if (ivec1 == ivec2)  
    {  
        cout << "ivec1 is equal to ivec2" << endl;  
    }  
    else  
    {  
        cout << "ivec1 is not equal to ivec2" << endl;  
    }  
    return 0;  
}  

指针的引入

定义:
指针用于指向对象。与迭代器一样,指针提供对其所指对象的间接访问,只是指针结构更通用一些。与迭代器不同的是,指针用于指向单个对象,而迭代器只能用于访问容器内的元素。
1. 对指针进行初始化或赋值只能使用以下几种类型的值:
- 0值常量表达式,例如,在编译时刻获取0值的整形const对象或字面值常量0。
- 类型匹配的对象的地址。
- 另一对象之后的下一地址。

  1. 指针和引用的比较

 使用引用(reference)和指针(pointer)都可间接访问另一个值,但它们之间存在两个重要区别: (1)引用总是指向某个确定对象(事实上,引用就是该对象的别名),定义引用时没有进行初始化会出现编译错误; (2) 赋值行为上存在差异:给引用赋值修改的是该引用所关联的对象的值,而不是使该引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象。给指针赋值修改的是指针对象本身,也就是使该指针指向另一对象,指针在不同时刻可指向不同的对象(只要保证类型匹配)。

  1. 指向指针的指针
int ival = 1024;  
int *pi = &ival;  
int **ppi = &pi;  

cout << "ival is: " << ival  
     << "\n*pi is: " << *pi  
     << "\n**ppi is: " << **ppi << endl;  

 对指向指针的指针获取其真正的值,需要进行两次解引用!

image
ppi通过两次解引用获得ival值。

  1. 输出指针元素

 初始化指针pbegin指向数组的第一个元素,而指针pend则指向该数组的超出末端的位置。
image

const size_t arr_sz = 5;  
int int_arr[arr_sz] = {0,1,2,3,4};  

for (int *pbegin = int_arr,*pend = int_arr+arr_sz; pbegin != pend; ++pbegin)  
{  
    cout << *pbegin << endl;  
}  
  1. 指针和const限定符
    • 指向const对象的指针

 const限定了cptr指针所指向的对象的类型,而并非cptr本身!允许用指针来改变其所指的const值。

const double *cptr; //cptr是一个指向double类型const对象的指针
  • const指针

  const指针—指针本身值不能修改,因此const指针必须在定义时初始化,而且初始化之后再也不能修改。而指针所指对象的值能否修改,则完全取决于该对象的类型。

int ivec = 0;
int *const ia = &ivec;//ia是指向int型对象的const指针
  • 指向const对象的const指针

 既不能修改指针的值,也不能修改指针所指向的对象。

const double pi = 3.14159
//pi_ptr is const and point to a const object
const double *const pi_ptr = &pi;

习题

编写程序比较两个string类型的字符串,然后编写另一个程序比较两个C 风格字符串的值。

//比较两个 string  类型的字符串
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1, str2;
//输入两个字符串
cout << "Enter two strings:" << endl;
cin >> str1 >> str2;
//比较两个字符串
if (str1 > str2)
cout << "\"" << str1 << "\"" << " is bigger than "
<< "\"" << str2 << "\"" << endl;
else if (str1 < str2)
cout << "\"" << str2 << "\"" << " is bigger than "
<< "\"" << str1 << "\"" << endl;
else
cout << "They are equal" << endl;
return 0;
}



//比较两个 C  风格字符串的值
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
//char *str1 = "string1", *str2 = "string2";
const int str_size = 80;
char *str1, *str2;
//为两个字符串分配内存
str1 = new char[str_size];
str2 = new char[str_size];
if (str1 == NULL || str2 == NULL) {
cout << "No enough memory!" << endl;
return -1;
}
//输入两个字符串
cout << "Enter two strings:" << endl;
cin >> str1 >> str2;
//比较两个字符串
int result;
result = strcmp(str1, str2);
if (result > 0)
cout << "\"" << str1 << "\"" << " is bigger than "
<< "\"" << str2 << "\"" << endl;
else if (result < 0)
cout << "\"" << str2 << "\"" << " is bigger than "
<< "\"" << str1 << "\"" << endl;
else
cout << "They are equal" << endl;
//释放字符串所占用的内存
delete [] str1 ;
delete [] str2 ;
return 0;
}

创建动态数组

 数组类型变量有三个限制:
1)数组长度固定不变。
2)在编译时必须知道其长度。
3)数组只能在定义他的语句块内存在。
与数组变量不同,动态分配的数组将一直存在,直到程序显示的释放它为止。
1. 每个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区,或堆(heap),在C++中使用newdelete在自由存储区中分配存储空间。

int *pia = new int[10];/*new表达式分配了一个含有10个int型元素的
数组,并返回指向该数组第一个元素的指针,此返回值初始化了指pia。*/

int *pia2 = new int[10]()/*一对圆括号对数 组元素做初始化*/
  1. 动态空间的释放

 动态分配的内存到最后必须进行释放,否则,内存最终将会耗尽。如果不再需要使用动态创建的数组,则必须显式的将所占用的存储空间返还给程序的自由存储空间。

delete []pia;   /*不要忘记了[],即使忘记了,编译器也不会发现,但
是程序运行时出错。*/
  1. 动态数组的使用

 通常就是在编译时无法知道数组的维数,所以才使用动态数组!

const char *errno = "success";  
   const char *errinfo = "Error: a function declaration must "  
                         "specify a function return type!";  

   const char *errTxt;  
   if (errFound)  
    errTxt = errinfo;  
else  
    errTxt = errno;  

/* 
*在获得字符串的长度上,必须+1,以便在动态分配内存时 
*预留出存储结束符的空间 
*/  
int dimension = strlen(errTxt) + 1;  
char *errMsg = new char[dimension];  
strncpy(errMsg,errTxt,dimension);  
习题
  1. 编写程序由从标准输入设备读入的元素数据建立一个 int型
    vector对象,然后动态创建一个与该 vector 对象大小一致
    的数组,把 vector 对象的所有元素复制给新数组。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
    vector<int> ivec;
    int ival;
    //读入元素数据并建立 vector
    cout << "Enter numbers:(Ctrl+Z to end)" << endl;
    while (cin >> ival)
        ivec.push_back(ival);
    //动态创建数组
    int *pia = new int[ivec.size()];
    //复制元素 
    int *tp = pia;
    for (vector<int>::iterator iter = ivec.begin();
        iter != ivec.end(); ++iter, ++tp)
        *tp = *iter;
    //释放动态数组的内存
    delete [] pia;
    return 0;
}
  1. 编写程序从标准输入设备读入字符串,并把该串存放在字符数组中。描述你的程序如何处理可变长的输入。提供比你分配的数组长度长的字符串数据测试你的程序。
//  从标准输入设备读入字符串,并把该串存放在字符数组中
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
    string in_str;//  用于读入字符串的 string  对象
    const size_t str_size = 10;
    char result_str[str_size+1];
    //  读入字符串
    cout << "Enter a string(<=" << str_size
        << " characters):" << endl;
    cin >> in_str;
    //  计算需复制的字符的数目
    size_t len = strlen(in_str.c_str());
    if (len > str_size)
    {
        len = str_size;
        cout << "String is longer than " << str_size
            << " characters and is stored only "
            << str_size << " characters!" << endl;
    }
    //  复制 len  个字符至字符数组 result_str
    strncpy(result_str, in_str.c_str(), len);
    //  在末尾加上一个空字符(null  字符)
    result_str[len+1] = '\0';
    return 0;
} 

为了接受可变长的输入,程序中用一个 string对象存放读入的字符串,然后使用 strncpy 函数将该对象的适当内容复制到字符数组中。因为字符数组的长度是固定的因此首先计算字符串的长度。若该长度小或等于字符数组可容纳字符串的长度,则复制整个字符串至字符数组,否则,根据数组的长度,复制字符串中前面部分的字符,以防止溢出。注意,上述给出的是满足题目要求的一个解答,事实上,如果希望接受可变长的输入并完地存放到字符数组中,可以采用动态创建数组来实现。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wcyd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值