学习c++的第七天

编程入门 行业动态 更新时间:2024-10-25 13:13:34

学习c++的<a href=https://www.elefans.com/category/jswz/34/1769430.html style=第七天"/>

学习c++的第七天

目录

字符串

C 风格字符串

C++ 中的 String 类

示例

指针

什么是指针?

实例

指针详解

C++ Null 指针

C++ 指针的算术运算

C++ 指针 vs 数组

C++ 指针数组

C++ 指向指针的指针

C++ 传递指针给函数

C++ 从函数返回指针


字符串

C++ 提供了两种类型的字符串表示形式:C 风格字符串和 C++ 引入的 string 类类型。

C 风格字符串

C 风格字符串是一种使用字符数组表示的字符串。其定义方式为:

char str[] = "Hello, world!";

其中,字符串 "Hello, world!" 将被存储在名为 str 的字符数组中,数组大小会自动根据字符串长度调整。C 风格字符串以 NULL 结尾,即以字符 '\0' 表示字符串结束。

可以使用 C++ 标准库提供的字符串处理函数来操作 C 风格字符串,

序号函数 & 目的
1strcpy(s1, s2);
复制字符串 s2 到字符串 s1。
2strcat(s1, s2);
连接字符串 s2 到字符串 s1 的末尾。连接字符串也可以用 + 号,例如:
string str1 = "runoob";
string str2 = "google";
string str = str1 + str2;
3strlen(s1);
返回字符串 s1 的长度。
4strcmp(s1, s2);
如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0。
5strchr(s1, ch);
返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
6strstr(s1, s2);
返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。

C++ 中的 String 类

string 类类型是 C++ 标准库提供的字符串类,其定义方式为:

#include <string>std::string str = "Hello, world!";

可以使用 string 类提供的成员函数来操作字符串,以下是一些常见的 string 类的成员函数:

  • length() 或 size(): 返回字符串的长度。
  • empty(): 检查字符串是否为空,返回布尔值。
  • clear(): 清空字符串中的内容。
  • c_str(): 返回以 null 结尾的 C 风格字符串的指针。
  • substr(pos, len): 返回从指定位置开始的指定长度的子字符串。
  • append(str): 在字符串末尾追加另一个字符串。
  • insert(pos, str): 在指定位置插入另一个字符串。
  • erase(pos, len): 删除从指定位置开始的指定长度的字符。
  • replace(pos, len, str): 用指定的字符串替换从指定位置开始的指定长度的字符。
  • find(str, pos): 在字符串中搜索指定的子字符串,并返回第一次出现的位置。
  • rfind(str, pos): 在字符串中反向搜索指定的子字符串,并返回最后一次出现的位置。
  • compare(str): 将字符串与另一个字符串进行比较,返回一个整数表示比较结果。
  • find_first_of(str, pos): 在字符串中查找第一个与指定字符集合中任何一个字符匹配的字符,并返回该字符的位置。如果找不到,则返回 string::npos。
  • find_last_of(str, pos): 在字符串中查找最后一个与指定字符集合中任何一个字符匹配的字符,并返回该字符的位置。如果找不到,则返回 string::npos。
  • find_first_not_of(str, pos): 在字符串中查找第一个与指定字符集合中任何一个字符都不匹配的字符,并返回该字符的位置。如果找不到,则返回 string::npos。
  • find_last_not_of(str, pos): 在字符串中查找最后一个与指定字符集合中任何一个字符都不匹配的字符,并返回该字符的位置。如果找不到,则返回 string::npos。
  • tolower(): 将字符串中所有大写字母转换为小写字母。
  • toupper(): 将字符串中所有小写字母转换为大写字母。
  • replace(pos, len, str): 用指定的字符串替换从指定位置开始的指定长度的字符。

这些成员函数可以帮助我们对字符串进行更加灵活和全面的操作,例如,在进行字符串搜索和比较时,我们可以使用 find_first_of(),find_last_of(),find_first_not_of() 和 find_last_not_of() 函数来指定要搜索的字符范围。大小写转换函数 tolower() 和 toupper() 可以将字符串中的字母字符统一转换为小写或大写,方便进行比较和处理。替换函数 replace() 可以用指定的字符串替换字符串中的一部分内容,实现字符串修改的功能。

除了上述列举的常用成员函数外,string 类还提供了其他一些成员函数。这些函数使得对字符串进行各种操作变得更加方便和高效。

相比于 C 风格字符串,string 类类型具有更好的可读性、安全性和可移植性,并且支持更多的字符串处理功能,因此在实际开发中更加常用。

示例

以下是一个简单的示例代码,演示了 C 风格字符串和 C++ 的 string 类类型的使用,

#include <iostream>
#include <cstring> // 包含 C 风格字符串相关的头文件
#include <string> // 包含 string 类型相关的头文件int main() {// 使用 C 风格字符串const char* cStr = "Hello, World!"; // 定义一个 C 风格字符串// 输出 C 风格字符串std::cout << "C 风格字符串: " << cStr << std::endl;// 获取 C 风格字符串的长度int cStrLength = strlen(cStr);std::cout << "C 风格字符串长度: " << cStrLength << std::endl;// 使用 string 类型std::string cppStr = "Hello, World!"; // 定义一个 string 对象// 输出 string 对象std::cout << "C++ string 对象: " << cppStr << std::endl;// 获取 string 对象的长度int cppStrLength = cppStr.length();std::cout << "C++ string 对象长度: " << cppStrLength << std::endl;return 0;
}

输出结果:

C 风格字符串: Hello, World!
C 风格字符串长度: 13
C++ string 对象: Hello, World!
C++ string 对象长度: 13

这个示例中,首先定义了一个 C 风格字符串 cStr,然后通过 strlen() 函数获取了该字符串的长度,并输出到控制台。接下来,定义了一个 C++ 的 string 对象 cppStr,并使用 length() 成员函数获取了该对象的长度,并同样输出到控制台。

值得注意的是,C++ 中的 string 类型和 C 风格字符串在操作上有一些差异。C 风格字符串使用字符数组表示,需要手动处理内存分配和释放,而 string 类型则提供了方便的成员函数来操作字符串,且自动处理内存管理,更加安全和易用。

指针

什么是指针?

在C++中,指针是一种变量,用于存储内存地址。通过指针,可以直接访问和操作内存中的数据。

每个变量在计算机内存中都有一个唯一的地址,指针就是用来存储这个地址的变量。通过指针,我们可以间接地访问存储在内存中的数据,而不需要直接使用变量名。

指针的声明和使用步骤如下:

  1. 声明指针变量:指针变量的声明与其他变量类似,但在类型前加上 * 符号来表示该变量是一个指针。例如,int* ptr; 声明了一个指向整数类型的指针变量。
  2. 将地址赋给指针变量:使用取地址运算符 & 将变量的地址赋给指针变量。例如,int num = 10; int* ptr = &num; 将 num 的地址赋给指针 ptr。
  3. 使用指针访问数据:通过解引用运算符 * 可以访问指针所指向的内存中的数据。例如,int value = *ptr; 将指针 ptr 指向的内存中的值赋给 value。

指针在C++中的应用非常广泛,特别是在动态内存分配、数据结构和函数参数传递等方面。通过指针,我们可以有效地管理和操作内存中的数据,并实现更高级的数据结构和算法。然而,指针的使用需要谨慎,因为错误的指针操作可能导致内存访问错误和程序崩溃。在C++中,引入了一些安全机制(如智能指针)来帮助减少指针相关的错误和问题。

实例

#include <iostream>int main() {int num = 10;int* ptr = &num; // 声明一个指向整数类型的指针变量,将num的地址赋给ptrstd::cout << "num的值:" << num << std::endl;std::cout << "num的地址:" << &num << std::endl;std::cout << "ptr存储的地址:" << ptr << std::endl;std::cout << "通过指针访问num的值:" << *ptr << std::endl; // 解引用指针,获取存储在ptr指向地址上的值*ptr = 20; // 通过指针修改num的值std::cout << "修改后的num的值:" << num << std::endl;return 0;
}

 这段代码演示了指针的基本用法。首先,我们声明了一个整数变量 num,并将其初始化为10。然后,我们声明了一个指向整数类型的指针变量 ptr,并将 num 的地址赋给了它。接下来,通过指针 ptr 我们可以间接地访问和修改 num 的值。在示例中,我们输出了 num 的值、地址以及指针 ptr 存储的地址,然后通过解引用运算符 * 输出了通过指针访问到的 num 的值。最后,我们通过指针 ptr 将 num 的值修改为20,并再次输出修改后的 num 的值。

输出结果

num的值:10
num的地址:0000004797CFF574
ptr存储的地址:0000004797CFF574
通过指针访问num的值:10
修改后的num的值:20

指针详解

在 C++ 中,有很多指针相关的概念,这些概念都很简单,但是都很重要。下面列出了 C++ 程序员必须清楚的一些与指针相关的重要概念:

C++ Null 指针

在C++中,Null指针是一个特殊的指针值,表示指针不指向任何有效的内存地址。Null指针通常用于初始化指针变量,或者用于检测指针是否指向有效的对象。

在C++中,可以使用字面值 nullptr 来表示Null指针。以下是一个示例:

int* ptr = nullptr; // 声明一个整型指针并将其初始化为Null指针if (ptr == nullptr) {std::cout << "指针为空" << std::endl;
} else {std::cout << "指针不为空" << std::endl;
}

在这个示例中,我们声明了一个整型指针 ptr,并将其初始化为Null指针。然后,我们使用条件语句检查指针是否为空。如果指针等于 nullptr,则输出"指针为空";否则,输出"指针不为空"。

需要注意的是,在旧版本的C++标准中,可能会使用字面值 NULL 或 0 来表示Null指针。但是自从C++11标准引入了 nullptr,它被推荐用作Null指针的表示方式。

Null指针的使用可以帮助我们避免对未初始化的指针进行操作,以及在需要判断指针是否为空时进行判断。确保在使用指针之前,先进行Null指针的检查,以避免悬空指针错误。

C++ 指针的算术运算

在C++中,指针可以进行算术运算。指针的算术运算涉及指针的加法和减法操作,以及和整数的加减运算。

1、指针的加法运算:当一个指针 ptr 加上一个整数 n 时,指针会向前移动 n 个元素的大小(以字节为单位)。例如:

int arr[] = {10, 20, 30, 40, 50};
int* ptr = arr; // 将指针指向数组的第一个元素// 向前移动2个元素
ptr = ptr + 2;

在这个例子中,我们有一个整型数组 arr,并声明了一个指向数组的指针 ptr,初始时指向数组的第一个元素。然后,我们使用 ptr = ptr + 2 将指针向前移动2个元素,即指向数组的第三个元素。 

2、指针的减法运算:当一个指针 ptr1 减去另一个指针 ptr2 时,结果是两个指针之间元素的个数。例如:

int arr[] = {10, 20, 30, 40, 50};
int* ptr1 = &arr[3]; // 指向数组的第四个元素
int* ptr2 = &arr[1]; // 指向数组的第二个元素// 计算两个指针之间的元素个数
int numElements = ptr1 - ptr2;

在这个例子中,我们有一个整型数组 arr,并声明了两个指向数组元素的指针 ptr1 和 ptr2。然后,我们使用 ptr1 - ptr2 计算两个指针之间的元素个数,即指针 ptr1 指向的元素与指针 ptr2 指向的元素之间的距离。 

3、指针和整数的加减运算:指针也可以与整数进行加减运算。当一个指针 ptr 加上一个整数 n 时,指针会向前移动 n 个元素的大小。当一个指针 ptr 减去一个整数 n 时,指针会向后移动 n 个元素的大小。例如:

int arr[] = {10, 20, 30, 40, 50};
int* ptr = &arr[1]; // 指向数组的第二个元素// 向前移动3个元素
ptr = ptr + 3;// 向后移动2个元素
ptr = ptr - 2;

在这个例子中,我们有一个整型数组 arr,并声明了一个指向数组元素的指针 ptr,初始时指向数组的第二个元素。然后,我们使用 ptr = ptr + 3 将指针向前移动3个元素,然后使用 ptr = ptr - 2 将指针向后移动2个元素。

需要注意的是,指针的算术运算应该在合法范围内进行。不应该越界访问数组的边界以及未分配的内存。此外,对于非字符类型的指针,指针运算的结果是以元素大小为单位的字节偏移量。

C++ 指针 vs 数组

C++中指针和数组都是非常重要的概念,它们具有不同的用途和功能。

1、指针
指针是一个变量,它存储了另一个变量的地址。可以通过指针来间接访问该变量。指针在C++中具有以下特点:

  • 指针可以动态地分配和释放内存。
  • 指针可以用于遍历和操作任意类型的数据结构。
  • 指针可以作为函数的参数,使得函数能够修改传递给它的实际参数。
  • 指针还可以用于实现动态数据结构,如链表、树等。

2、数组
数组是一组同类型的元素的集合,可以通过下标来访问每个元素。数组在C++中具有以下特点:

  • 数组是一个静态的数据结构,其大小在定义时已经确定,不能动态地增加或减少。
  • 数组的元素在内存中是连续存储的,这样可以提高访问数组元素的效率。
  • 数组的下标从0开始。

指针和数组之间存在紧密的联系,因为数组名本身就是一个指向数组第一个元素的指针。例如,如果有一个整型数组arr,那么arr和&arr[0]是等价的,都是指向数组第一个元素的指针。

虽然指针和数组都可以用于访问内存中的数据,但它们在语法上有很大的不同。例如,对于一个指针p,可以使用*p来访问指针指向的值,而对于一个数组a,可以使用a[i]来访问第i个元素。

总之,指针和数组都是C++中重要的概念。指针可以动态地分配和释放内存,并且可以用于遍历和操作任意类型的数据结构,而数组可以提高访问元素的效率,因为元素在内存中是连续存储的。

C++ 指针数组

C++中的指针数组是一个包含指针元素的数组。每个元素都是一个指向特定类型的指针,可以通过数组下标来访问每个指针。指针数组在C++中有着广泛的应用。

下面是一个简单的示例,说明如何声明和使用指针数组:

#include <iostream>int main() {int a = 10, b = 20, c = 30;int* ptrArr[3]; // 声明一个指针数组ptrArr[0] = &a; // 指针数组的第一个元素指向变量aptrArr[1] = &b; // 指针数组的第二个元素指向变量bptrArr[2] = &c; // 指针数组的第三个元素指向变量c// 使用指针数组访问指针指向的值std::cout << "Value of a: " << *ptrArr[0] << std::endl;std::cout << "Value of b: " << *ptrArr[1] << std::endl;std::cout << "Value of c: " << *ptrArr[2] << std::endl;return 0;
}

在这个示例中,我们声明了一个指针数组 ptrArr,它包含了3个整型指针元素。然后,我们将这些指针分别指向变量 a、b 和 c。通过 ptrArr[i],我们可以访问指针数组的第 i 个元素,并使用 * 运算符来获取指针指向的值。

输出结果将是:

Value of a: 10
Value of b: 20
Value of c: 30

指针数组在许多情况下都很有用,特别是当需要处理多个同类型的指针时。例如,在动态内存分配中,可以使用指针数组来管理分配的内存块。

C++ 指向指针的指针

C++中,指向指针的指针是一个非常有用的概念,它可以通过多级间接寻址访问内存中存储的数据。在指向指针的指针中,一个指针变量包含另一个指针的地址,并且该指针指向另一个指针变量。因此,指向指针的指针通常称为二级指针。

下面是一个简单的示例,说明如何声明和使用指向指针的指针:

#include <iostream>int main() {int a = 10;int* ptr1 = &a; // 指针变量ptr1指向变量aint** ptr2 = &ptr1; // 指针变量ptr2指向指针变量ptr1// 使用指向指针的指针访问变量astd::cout << "Value of a: " << **ptr2 << std::endl;return 0;
}

输出结果将是:

Value of a: 10

在这个示例中,我们首先声明了一个整型变量 a,然后声明了一个指向 a 的指针 ptr1。接着,我们声明了一个指向指针的指针 ptr2,并将其指向指针 ptr1。

通过使用 ** 运算符,我们可以访问指向指针的指针中存储的地址所指向的值。在上面的示例中,我们输出了变量 a 的值。

指向指针的指针可以用于许多高级编程任务,例如动态内存分配和指针参数的传递。在这些情况下,二级指针可以用于允许多个函数间进行对同一数据结构的修改。

C++ 传递指针给函数

在C++中,我们可以通过将指针作为参数传递给函数来实现对函数外部变量的修改。这允许函数在调用过程中直接操作指针所指向的内存地址上的数据。通过传递指针给函数,可以实现对变量的引用传递,从而避免在函数中复制大量的数据。

下面是一个简单的示例,展示了如何传递指针给函数:

#include <iostream>void modifyValue(int* ptr) {*ptr = 20; // 修改指针所指向的值
}int main() {int value = 10;std::cout << "Value before modification: " << value << std::endl;modifyValue(&value); // 传递指针给函数std::cout << "Value after modification: " << value << std::endl;return 0;
}

输出结果将是:

Value before modification: 10
Value after modification: 20

在这个示例中,我们定义了一个 modifyValue 函数,它接受一个整型指针作为参数。在函数内部,我们通过解引用指针,并将新的值赋给该指针所指向的内存地址上的变量。

在 main 函数中,我们声明了一个整型变量 value,并输出其初始值。然后,我们通过将 &value 作为参数调用 modifyValue 函数,将变量 value 的地址传递给函数。函数内部修改了指针所指向的值。

最后,我们再次输出变量 value 的值,可以看到其值已经被修改为20。

通过传递指针给函数,我们可以在函数内部对变量进行修改,而无需复制大量的数据。这对于处理大型数据结构或需要对同一数据进行多次修改的情况非常有用。

C++ 从函数返回指针

在 C++ 中,可以从函数中返回指针。

1、返回指向局部变量的指针(不推荐):

int* createNumber() {int number = 10;return &number; // 错误示例:返回指向局部变量的指针
}int main() {int* ptr = createNumber(); // 指针指向一个已经销毁的局部变量// 使用 ptr 可能导致未定义行为return 0;
}

在上述示例中,createNumber() 函数试图返回一个指向局部变量 number 的指针。然而,当函数结束时,number 的生命周期也结束了,指针 ptr 将会指向一个已经销毁的内存区域,这可能导致未定义行为。因此,返回指向局部变量的指针是不安全的,不推荐使用。

2、返回指向堆内存的指针:

int* createNumber() {int* ptr = new int(10);return ptr; // 返回指向堆内存的指针
}int main() {int* ptr = createNumber();// 使用 ptrdelete ptr; // 使用完指针后,记得释放对应的堆内存return 0;
}

在这个示例中,createNumber() 函数通过使用 new 运算符在堆上分配了一个整数的内存,并返回指向该内存的指针。在 main() 函数中,我们可以使用这个指针,并在使用完后使用 delete 运算符释放对应的堆内存,以避免内存泄漏。

需要注意的是,在返回指针指向的堆内存后,需要负责管理该内存的分配和释放。这意味着我们需要确保在不再使用指针时及时释放对应的内存,以防止内存泄漏。

另外,还可以返回指向静态变量、全局变量或动态分配的数组等其他类型的指针。但无论返回何种类型的指针,都需要谨慎处理,确保在使用完毕后适时释放相应的内存。

实例

当从函数中返回指针时,需要确保返回的指针指向的内存是有效的,并且在使用完毕后能够正确释放。下面是一个示例代码,

#include <iostream>int* createNumber() {int* ptr = new int(10); // 在堆上动态分配一个整数内存return ptr; // 返回指向堆内存的指针
}int main() {int* ptr = createNumber(); // 调用函数获取指针std::cout << "Number: " << *ptr << std::endl; // 输出指针指向的值delete ptr; // 释放堆内存ptr = nullptr; // 将指针置为 nullptr,避免成为悬挂指针return 0;
}

在这个示例中,createNumber() 函数使用 new 运算符在堆上动态分配一个整数的内存,并返回指向该内存的指针。在 main() 函数中,我们通过调用 createNumber() 函数来获取指针,并使用 *ptr 来访问指针指向的值。注意,在使用指针后,我们使用 delete 运算符释放对应的堆内存,并将指针设置为 nullptr,以避免成为悬挂指针。

需要谨记的是,返回指针时需要确保返回的指针指向的内存是有效的,并且在使用完毕后进行正确的释放,以避免内存泄漏。同时,也要注意悬挂指针(dangling pointer)的问题,即指针指向已释放的内存。为了避免悬挂指针的问题,建议将指针设置为 nullptr。

更多推荐

学习c++的第七天

本文发布于:2023-11-17 11:39:22,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1642492.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:第七天

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!