我们知道C语言中的字符数组就是C++当中的string类型的字符串变量。因此在C++程序中有两种表达字符串的方式。一个是字符数组一个是string类型的字符串变量。虽然使用string类型的字符串更容易进行内存管理,但是很C++程序中仍然使用字符数组。因此很多函数参数需要传入一个字符串,就会出现很多方式。比如:字符数组传惨、string字符串传参、甚至还会出现字符指针传参。其实他们都是存在关联的我将一一阐述。
不知道为什么存在字符数组和字符串或不知道他俩都可以代表字符串可以看我这篇文章。字符数组和string字符串的关系
1、C风格字符数组传参
#include <iostream>
void printCStringArray(char* arr[], int size) {
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << std::endl;
}
}
int main() {
char* cStringArray[] = {"Hello", "World", "C++"};
int size = sizeof(cStringArray) / sizeof(cStringArray[0]);
printCStringArray(cStringArray, size);
return 0;
}
这是最简单的最常见的传递字符数组的方式。但是传递字符数组时,实际上是传递数组的首地址,但在函数参数列表中,仍然可以使用数组形式定义参数。
使用
sizeof
运算符计算数组长度时,只能在数组定义的同一作用域内使用。传递到函数内部时,数组会退化为指针,不能再使用sizeof计算数组长度,所以需要在调用函数之前计算并传递数组长度。
2、传递指向字符数组的指针
由上可知传递字符数组的本质是传递数组的首地址,那我们就可以用指针来传递。
#include <iostream>
void printCStringArray(char* arr[], int size) {
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << std::endl;
}
}
int main() {
char* cStringArray[] = {"Hello", "World", "C++"};
int size = sizeof(cStringArray) / sizeof(cStringArray[0]);
printCStringArray(cStringArray, size);
return 0;
}
3、传递string对象数组
#include <iostream>
#include <string>
void printStringArray(const std::string arr[], int size) {
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << std::endl;
}
}
int main() {
std::string cppStringArray[] = {"Hello", "World", "C++"};
int size = sizeof(cppStringArray) / sizeof(cppStringArray[0]);
printStringArray(cppStringArray, size);
return 0;
}
4、传递指向string对象的指针
同样可以使用指针来传递
#include <iostream>
#include <string>
void printStringPointerArray(const std::string* arr[], int size) {
for (int i = 0; i < size; ++i) {
std::cout << *arr[i] << std::endl;
}
}
int main() {
std::string s1 = "Hello";
std::string s2 = "World";
std::string s3 = "C++";
const std::string* cppStringPtrArray[] = {&s1, &s2, &s3};
int size = sizeof(cppStringPtrArray) / sizeof(cppStringPtrArray[0]);
printStringPointerArray(cppStringPtrArray, size);
return 0;
}
5、为什么要用字符数组指针来传参
我们经常看到许多函数接受字符串参数是使用字符数组指针,这是因为在C和C++中,字符串本质上是一个以空字符(‘\0’)结尾的字符数组,而字符数组指针提供了一个高效且灵活的方式来处理这些字符串。以下是一些原因和详细解释:
内存和指针
1. 效率:使用指针传递字符串比复制整个字符串更高效。指针仅占用一个内存单元,而复制字符串需要占用更多的内存和时间。
2. 共享数据:通过指针传递字符串允许多个函数共享同一块内存区域,避免不必要的内存复制和占用。
灵活性
1. 动态长度:字符数组指针允许处理不同长度的字符串。因为字符串以 ‘\0’ 结尾,函数可以通过遍历直到 ‘\0’ 来确定字符串的长度。
2. 修改字符串:通过指针传递字符串允许函数在原地修改字符串的内容,而不需要返回修改后的字符串。
函数实例
以下是一些示例函数,展示如何使用字符数组指针处理字符串:
- 读取字符串
#include <iostream>
void printString(const char* str) {
std::cout << "字符串内容: " << str << std::endl;
}
int main() {
const char* myString = "Hello, World!";
printString(myString);
return 0;
}
这里 printString 函数接受一个字符数组指针 const char*,并输出字符串内容。
- 修改字符串
#include <iostream>
#include <cstring>
void toUpperCase(char* str) {
for (int i = 0; str[i] != '\0'; ++i) {
str[i] = toupper(str[i]);
}
}
int main() {
char myString[] = "Hello, World!";
toUpperCase(myString);
std::cout << "修改后的字符串: " << myString << std::endl;
return 0;
}
这里 toUpperCase 函数接受一个字符数组指针 char*,并将字符串中的所有字符转换为大写。
细节解释
- 字符数组指针 (char*):这是一个指向字符数组的指针,允许函数访问和修改数组中的字符。
- const char* 和 char*:
• const char*:表示指向字符数组的指针,但函数不能修改数组中的字符。
• char*:表示指向字符数组的指针,函数可以修改数组中的字符。 - 字符串结尾符 (‘\0’):在C和C++中,字符串以空字符 ‘\0’ 结尾。函数通过遍历直到 ‘\0’ 来处理字符串。
总结:使用字符数组指针处理字符串在C和C++中非常常见,因为它提供了高效、灵活的方式来共享、读取和修改字符串。理解这一点对编写高效的C和C++代码非常重要。
6、补充 c_str()
背景
在 C++ 中,std::string 是一个方便的字符串类,提供了很多内置的操作和功能。然而,许多 C 库函数以及一些 C++ 库函数仍然使用 C 风格的字符串(const char*)作为参数。因此,在使用这些函数时,有时需要将 std::string 转换为 const char*。
因此·c_str() ·是 C++ 中 std::string 类的一个成员函数,它返回一个指向 C 风格字符串(即以 null 结尾的字符数组)的指针。这个函数的作用是将 C++ 的 std::string 对象转换为 C 风格的字符串,以便与接受 C 风格字符串的函数兼容。
详细解释
- std::string:C++ 中的字符串类,提供了丰富的字符串操作方法。
- c_str():返回一个指向 null 终止的字符数组的指针(即 C 风格字符串)。这个指针指向的字符数组与 std::string 对象内部的数据相同,但确保以 null 结尾。
以下是一个示例,展示如何使用 filename.c_str() 将 std::string 转换为 const char*,以便与接受 C 风格字符串的函数兼容:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
std::string filename = "example.txt"; // 定义一个 std::string 对象
ifstream file;
// 使用 c_str() 将 std::string 转换为 const char*
file.open(filename.c_str());
if (file.fail()) {
cerr << "无法打开文件: " << strerror(errno) << endl;
return 1; // 返回非零值表示失败
}
// 读取文件内容并输出
std::string line;
while (getline(file, line)) {
cout << line << endl;
}
// 关闭文件
file.close();
return 0; // 返回0表示成功
}