C++ primer 复习 第三章 字符串,向量和数组(2)

简介: C++ primer 复习 第三章 字符串,向量和数组

3.5.1 数组定义和访问

数组:复合类型


声明形式 数组名称 [元素个数] 例,Arr[N],N必须是常量表达式


unsigned cnt =42;
constexpr unsigned int sz =1;//常量表达式
int arr[10];
int* ptr[sz];
// std::string bad[cnt]; 错误,cnt不是常量表达式

不存在引用数组,可以使用列表初始化,但必须指定数组类型,不允许使用 auto


constexpr unsigned sz =3;//常量表达式
int arr1[sz] = { 0, 1, 2 };
int arr2[] = { 0, 1, 2 }; //自动推断元素个数为3
int arr3[5] = { 0, 1, 2 };//等价 { 0, 1, 2 ,0 ,0 }
std::string arr4[3] = {"hi“ , "bye"};//等价 {"hi" , "bye" , ""}int arr5[2] = { 0, 1, 2 }; //错误,初始值过多

字符数组特殊性


字符串默认结尾是空字符


char a1[] = { 'C', '+', '+' };//列表初始化,没有空字符
char a2[] = { 'C', '+', '+', '\0' };//列表初始化,含有显示的空字符
char a3[] ="C++";//含有空字符
const char a4[6] ="Danial";//错误,没有空间存放空字符

不允许拷贝和赋值


int a[] = { 0, 1, 2 };
//int a2[] = a;//初始化时不允许拷贝赋值

理解复杂的数组声明


【】优先级高于*


int *ptrs[10];//含有十个整型指针的数组
int&refs[10];//错误,不存在引用数组
int(*parray)[10];//指向一个含有十个整数的数组
int(&parray)[10] = arr;//引用一个含有十个整数的数组
int*(&arry)[10] = ptrs;//数组的引用,该数组包含十个整型指针

3.5.2 指针和数组,C风格字符串

指针和数组

编译器一般会把数组转为指针


std::string nums[] = { "one", "two", "three" };
std::string* p1 = &nums[0];//p指向nums的第一个元素
std::string* p2 = nums;//等价于p2 = &nums[0]
int arr1[] = { 0, 1, 2, 4, 5 };//arr1是含有5个整数的数组
auto arr2(arr1);//arr2是一个整型指针,指向arr1的第一个元素
arr2 =42;//错误,arr2是一个指针
//当使用decltype时,不会出现上述转换
decltype(arr1) arr3 = { 0, 1, 2 };
arr3 = arr2;//错误,不能把整型指针赋值给数组
arr3[0] =-1;

指针也是迭代器


这种方式可得到尾后指针,易错故不推荐


int arr[] = { 0, 1, 2 };
int *p = arr;
++p;//p指向了arr[1]
int* p1 = &arr[3];//指向arr尾元素的下一个位置
for (int *b = arr; b != p1; ++b){
  std::cout << *b << std::endl;
}


/*
  寻找第一个负数
*/
int arr1[] = { 0, 1, 2, 3, 4 };
int* beg = std::begin(arr1);
int* end = std::end(arr1);
while (beg != end && beg>0){
++beg;
}
if (beg != end){
  std::cout << *beg << std::endl;
}

解引用和指针运算交互


int arr1[] = { 0, 1, 2 };
int last = *(arr1 +2);//last =2last = *arr1 +4;//last =4;

下标和指针


标准库类型限定使用下标不能为负,但内置类型无此要求


数组(内置) string,vector(STL 标准库)


int arr1[] = { 0, 1, 2, 3, 4};
int i = arr1[2];//与下面两条等价,充分理解
int *p = arr1;
i = *(p +2);
int *p1 = &arr1[3];
int j = p1[1];//等于 *(p1+1)
int k = p1[-2];//等于 *(p1-2)

C风格字符串

C 风格字符串不是一种类型,而是一种约定俗成的写法


C 风格字符串的处理函数定义在 cstring 头文件中


作为参数的字符串,必须以空字符结束



#include<cstring>char str1[] = { 'C', '+', '+' };//必须以空字符结尾,已修复
std::cout << strlen(str1) << std::endl;
std::string s1 ="A string example";
std::string s2 ="A different string";
if (s1 < s2) {//false 利用字符在字典顺序比较
std::cout << "s1 len 小于 s2 len " << std::endl;
}
const char* cstr1 ="A string example";
const char* cstr2 ="A different string";
if (cstr1 < cstr2) {//true 比较数组的size
  std::cout << "cstr1 len 小于 cstr2 len " << std::endl;
}
if (strcmp(cstr1, cstr2)<0){//和上面两个string比较一样
  std::cout << "cstr1 len 大于 cstr2 len " << std::endl;
}


与旧代码的接口


std::string s1("Hello World");
char* c_s2 = s1; //错误,不能将string对象赋值给char*
const char* c_s3 = s1.c_str();//正确,将string转换c字符串

若后续改变了 s1 的值,那么 c_str 返回的数组将失效


//使用数组初始化 vector 对象
int int_arr[] = { 0, 1, 2, 3 };
std::vector<int> vec1(std::begin(int_arr), std::end(int_arr));//{ 0, 1, 2, 3 }
std::vector<int> vec1(int_arr+1, int_arr+3);//{1,2,3}

3.6 多维数组

多维数组:严格来讲 C++ 没有多维数组,C++的多维数组是靠数组的数组实现的


int arr[3][4];//大小为3的数组,每个元素是含有4个整数的数组
int arr[10][20][30] = { 0 };//将所有元素初始化为0

初始化


一个括号即为一行


//允许使用花括号初始化多维数组
int arr2[2][2] = {
  { 0, 1},
  { 2, 3}
};
int arr3[2][2] = { 0, 1, 2, 3 };
int arr3[2][2] = { { 0 }, { 2 } };//0,0,2.0 
int arr3[2][2] = { 0, 2 }; //0,2,0,0

下标引用


允许数组元素本身就是数组


//用arr1的首元素给arr0最后一行的最后一个元素赋值
arr0[3][4] = arr1[0][0][0];
/*
  给数组元素初始化
*/
constexpr size_t rowCnt =3, colCnt =4;
int arr4[rowCnt][colCnt];//12个未初始化的元素
for (size_t i =0; i < rowCnt; ++i){
for (size_t j =0; j < colCnt; ++j){
    arr4[i][j] = i * rowCnt + colCnt;
  }
}
/*
  将数组元素改为 0-12*/
size_t cnt =0;
for (auto& row : arr4){
for (auto& col : row){
    col = cnt;
++cnt;
  }
}
//使用&可有效避免 取出的数组被编译器自动转为指针
for (auto row : arr4)
for (auto col : row)//报错 int* row没有begin函数

指针和多维数组

两种形式

int arr0[3][4] = {
  {0,1,2,3},
  {4,5,6,7},  
    {8,9,10,11}
};//大小为3的数组,每个元素是含有4个整数的数组
//定义int arr0[3][4]; 
// arr0类型 int(*)[4] arr0[0]类型 int*
int(*p)[4] = arr0;//等同于 int(*p)[4] = &arr0[0];
/*
  输出arr0每个元素值
  两种形式
*/
for (auto p = arr0; p != arr0 +3; ++p){
for (auto q = *p; q != *p +4; ++q){
    std::cout << *q << " ";
  }
  std::cout << std::endl;
}
for (auto p = std::begin(arr0); p != std::end(arr0); ++p){
for (auto q = std::begin(*p); q != std::end(*p); ++q){
    std::cout << *q << " ";
  }
  std::cout << std::endl;
}

类型别名简化多维数组的指针

using int_array = int[4];//typedef int int_array[4]
for (int_array *p = arr0; p != arr0 +3; ++p){
for (int *q = *p; q != *p +4; ++q){
    std::cout << *q << " ";
  }
  std::cout << std::endl;
}

附 思维导图

相关文章
|
3月前
|
搜索推荐 编译器 C语言
【C++核心】特殊的元素集合-数组与字符串详解
这篇文章详细讲解了C++中数组和字符串的基本概念、操作和应用,包括一维数组、二维数组的定义和使用,以及C风格字符串和C++字符串类的对比。
101 4
|
2月前
|
缓存 网络协议 API
C/C++ StringToAddress(字符串转 boost::asio::ip::address)
通过上述步骤和示例代码,你可以轻松地在C++项目中实现从字符串到 `boost::asio::ip::address`的转换,从而充分利用Boost.Asio库进行网络编程。
82 0
|
2月前
|
编译器 C语言 C++
C/C++数字与字符串互相转换
C/C++数字与字符串互相转换
|
3月前
|
C++
C++(十一)对象数组
本文介绍了C++中对象数组的使用方法及其注意事项。通过示例展示了如何定义和初始化对象数组,并解释了栈对象数组与堆对象数组在初始化时的区别。重点强调了构造器设计时应考虑无参构造器的重要性,以及在需要进一步初始化的情况下采用二段式初始化策略的应用场景。
|
3月前
|
C++
HTML+JavaScript构建一个将C/C++定义的ANSI字符串转换为MASM32定义的DWUniCode字符串的工具
HTML+JavaScript构建一个将C/C++定义的ANSI字符串转换为MASM32定义的DWUniCode字符串的工具
|
3月前
|
存储 C++
C++(五)String 字符串类
本文档详细介绍了C++中的`string`类,包括定义、初始化、字符串比较及数值与字符串之间的转换方法。`string`类简化了字符串处理,提供了丰富的功能如字符串查找、比较、拼接和替换等。文档通过示例代码展示了如何使用这些功能,并介绍了如何将数值转换为字符串以及反之亦然的方法。此外,还展示了如何使用`string`数组存储和遍历多个字符串。
|
26天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
42 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
84 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
81 4
|
1月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
89 4