您的位置:首页 > 编程语言 > C语言/C++

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

2017-08-22 14:06 375 查看

数组

定义: 数组是由类型名、标识符和维数组成的复合数据类型,类型名规定了存放在数组中的元素的类型,而维数则指定数组中包含的元素个数。

1. 如果没有显示提供元素初值,则数组元素会像普通变量一样初始化

- 在函数体外定义的内置数组,其元素均初始化为0;

- 在函数体内定义的内置数组,其元素无初始化;

- 不管数组在哪里定义,如果其元素为类类型,则自动调用该类的默认构造函数进行初始化;如果该类没有默认构造函数,则必须为该数组的元素提供显示初始化。

与vector类型相比,数组的显著缺陷在于:数组的长度是固定的,而且程序员无法知道一个给定数组的长度。数组没有获取其容量大小的size操作,也不提供push_back操作在其中自动添加元素。如果需要更改数组的长度,程序员只能创建一个更大的新数组,然后把原数组的所有元素复制到新数组空间中去。

习题(c 风格字符串)

编写必要的代码将一个数组赋值给另一个数组,然后改用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;
}


编写程序判断两个数组是否相等,然后编写一段类似的程序比较两个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。

- 类型匹配的对象的地址。

- 另一对象之后的下一地址。

指针和引用的比较

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

指向指针的指针

int ival = 1024;
int *pi = &ival;
int **ppi = π

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


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



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

输出指针元素

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



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;
}


指针和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 = π


习题

编写程序比较两个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]()/*一对圆括号对数 组元素做初始化*/


动态空间的释放

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

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


动态数组的使用

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

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);


习题

编写程序由从标准输入设备读入的元素数据建立一个 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;
}


编写程序从标准输入设备读入字符串,并把该串存放在字符数组中。描述你的程序如何处理可变长的输入。提供比你分配的数组长度长的字符串数据测试你的程序。

//  从标准输入设备读入字符串,并把该串存放在字符数组中
#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 函数将该对象的适当内容复制到字符数组中。因为字符数组的长度是固定的因此首先计算字符串的长度。若该长度小或等于字符数组可容纳字符串的长度,则复制整个字符串至字符数组,否则,根据数组的长度,复制字符串中前面部分的字符,以防止溢出。注意,上述给出的是满足题目要求的一个解答,事实上,如果希望接受可变长的输入并完地存放到字符数组中,可以采用动态创建数组来实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++-primer