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++中使用new和delete在自由存储区中分配存储空间。
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/c++ 复习基础要点01-const指针、指针函数 函数指针、new/delete与malloc/free区别与联系
- [C++学习历程]基础部分 C++中的指针数组和结构
- C++基础学习系列第一部分——再议数组与指针
- C/C++复习:数组作实参,指针作形参排序
- [C++学习历程]基础部分 C++中的指针数组和结构
- 【C/C++语言基础学习】在主函数的定义的指针数组、二维数组通过三级指针在被调用函数分配内存
- C++第8周项目 数组和指针 【项目1 - 数组作数据成员】(复习新版)
- C++复习5.指针数组字符串
- C++第8周项目 数组和指针 【项目2-用对象数组操作长方柱类】(复习新版)
- [C++基础]027_数组和指针是不等价的一个实例
- C/C++基础知识总结——数组、指针域、字符串
- [C++基础]那些容易被混淆的概念:函数/数组指针-指针函数/数组,类/函数模板-模板类/函数
- 【C++基础】 指针&字符串&数组
- c++ 基础 指针访问数组两种方法 下标法 指针法
- C++第8周项目 数组和指针 【项目4-游戏中的角色类增强版】 (复习新版)
- Unix/Linux C++应用开发-C++基础概念"数组、指针和字符串"
- C++基础概念-数组、指针和字符串
- c语言基础复习一之指针与数组
- CPP-基础:C/C++数组名与指针的区别
- C++基础积累(2)指针与数组、指针与函数关系详解