- C++
C++ C风格字符串学习笔记
- 2025-5-14 19:11:30 @
C++ C风格字符串教程
在C++中,C风格字符串是一种基础且重要的数据类型,它实际上是由字符数组构成,以空字符\0
结尾。本教程将带你全面了解C风格字符串的使用方法。
1. C风格字符串的定义与初始化
C风格字符串有多种定义和初始化方式:
#include <iostream>
using namespace std;
int main() {
// 方式1:字符数组初始化
char str1[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
// 方式2:字符串字面量初始化(推荐)
char str2[] = "Hello"; // 编译器自动添加'\0'
// 方式3:指定大小的数组初始化
char str3[10] = "Hello"; // 剩余元素自动初始化为'\0'
// 方式4:指针指向字符串常量(注意:不可修改)
const char* str4 = "Hello";
cout << "str1: " << str1 << endl;
cout << "str2: " << str2 << endl;
cout << "str3: " << str3 << endl;
cout << "str4: " << str4 << endl;
return 0;
}
注意事项:
- 字符串长度 = 可见字符数 + 1(结尾的
\0
) - 使用字符串字面量初始化指针时,不要尝试修改内容
- 字符数组大小应至少比可见字符数多1
2. 输入输出C风格字符串
可以使用cin
和cout
进行C风格字符串的输入输出:
#include <iostream>
using namespace std;
int main() {
char name[20];
cout << "请输入你的名字:";
cin >> name; // 遇到空格或换行符停止读取
cout << "你好," << name << "!" << endl;
// 读取包含空格的字符串
char sentence[100];
cout << "请输入一句话:";
cin.ignore(); // 忽略缓冲区中的换行符
cin.getline(sentence, 100); // 读取整行,最多99个字符
cout << "你输入的是:" << sentence << endl;
return 0;
}
输入函数说明:
cin >> str
:遇到空格或换行符停止cin.getline(str, size)
:读取整行,包含空格cin.ignore()
:忽略缓冲区中的字符
3. C风格字符串常用操作
C++标准库提供了一系列处理C风格字符串的函数,包含在<cstring>
头文件中。
#include <iostream>
#include <cstring> // 包含C风格字符串处理函数
using namespace std;
int main() {
char str1[20] = "Hello";
char str2[20] = "World";
char dest[50];
// 1. 字符串长度
cout << "str1长度:" << strlen(str1) << endl;
// 2. 字符串复制
strcpy(dest, str1); // 复制str1到dest
cout << "复制后dest:" << dest << endl;
// 3. 字符串拼接
strcat(dest, " "); // 拼接空格
strcat(dest, str2); // 拼接str2
cout << "拼接后dest:" << dest << endl;
// 4. 字符串比较
if (strcmp(str1, str2) == 0) {
cout << "str1和str2相等" << endl;
} else {
cout << "str1和str2不相等" << endl;
}
// 5. 查找子字符串
char* pos = strstr(dest, "World");
if (pos != nullptr) {
cout << "'World'出现在位置:" << pos - dest << endl;
}
return 0;
}
常用函数总结:
函数名 | 功能描述 |
---|---|
strlen(s) |
返回字符串s 的长度 |
strcpy(d, s) |
将字符串s 复制到d |
strcat(d, s) |
将字符串s 拼接到d 的末尾 |
strcmp(s1, s2) |
比较s1 和s2 ,返回0表示相等 |
strstr(s, sub) |
在s 中查找子串sub ,返回指针 |
4. 字符串与数字的转换
在C风格字符串中,可以使用以下函数进行字符串与数字的转换:
#include <iostream>
#include <cstdlib> // 包含atoi, atof等函数
using namespace std;
int main() {
// 1. 字符串转整数
char numStr1[] = "12345";
int num1 = atoi(numStr1);
cout << "字符串转整数:" << num1 << endl;
// 2. 字符串转浮点数
char numStr2[] = "3.14159";
double num2 = atof(numStr2);
cout << "字符串转浮点数:" << num2 << endl;
// 3. 整数转字符串(使用sprintf)
char result[20];
int value = 2025;
sprintf(result, "当前年份:%d", value);
cout << "整数转字符串:" << result << endl;
// 4. 浮点数转字符串
double pi = 3.1415926;
sprintf(result, "圆周率:%.4f", pi);
cout << "浮点数转字符串:" << result << endl;
return 0;
}
转换函数说明:
atoi(str)
:将字符串转换为int
atol(str)
:转换为long
atof(str)
:转换为double
sprintf(dest, format, value)
:格式化输出到字符串
5. C风格字符串与C++字符串的转换
C风格字符串与C++的string
类可以相互转换:
#include <iostream>
#include <string> // C++字符串类
using namespace std;
int main() {
// 1. C风格字符串转C++ string
char cStr[] = "Hello C++";
string cppStr = cStr;
cout << "C++ string: " << cppStr << endl;
// 2. C++ string转C风格字符串
string anotherStr = "World";
const char* newCStr = anotherStr.c_str(); // 返回const char*
cout << "C风格字符串: " << newCStr << endl;
// 3. 修改C++ string后,原指针仍然有效
anotherStr += "!";
cout << "修改后的C++ string: " << anotherStr << endl;
cout << "原指针内容: " << newCStr << endl; // 可能失效!
// 4. 安全的转换方式
char buffer[50];
strcpy(buffer, anotherStr.c_str());
cout << "安全复制后的内容: " << buffer << endl;
return 0;
}
转换注意事项:
string.c_str()
返回的指针可能随string
变化而失效- 如需长期保存,建议复制到字符数组中
string
类提供了更安全、方便的字符串操作
6. C风格字符串的常见问题与陷阱
使用C风格字符串时,需要注意以下问题:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
// 问题1:数组越界
char str[5] = "Hello"; // 错误!需要至少6个字符空间
// 问题2:未初始化的字符串
char uninit[10];
cout << uninit << endl; // 可能输出乱码
// 问题3:字符串拼接越界
char dest[6] = "Hello";
strcat(dest, " World"); // 缓冲区溢出!
// 问题4:修改字符串常量
const char* ptr = "Constant";
// ptr[0] = 'c'; // 错误!不能修改常量
// 安全做法:使用足够大的数组
char safeDest[20] = "Hello";
strcat(safeDest, " World");
cout << safeDest << endl;
return 0;
}
安全建议:
- 始终确保字符数组有足够空间
- 初始化字符数组
- 使用更安全的函数如
strncpy
和strncat
- 区分字符串常量和可修改的字符数组
总结
C风格字符串是C++中处理文本的基础方式,理解它的工作原理对学习C++至关重要。本教程涵盖了C风格字符串的定义、输入输出、常用操作、类型转换以及常见问题。在实际编程中,建议优先使用C++的string
类,它提供了更安全、便捷的字符串操作,但C风格字符串在与C语言库交互或性能敏感场景中仍有重要作用。
14 条评论
-
admin SU @ 2025-6-18 19:36:33
以下是关于 C++ 中 字符处理函数(如
tolower
、toupper
等)的基础教程,采用通俗易懂的方式讲解,并使用using namespace std;
:1. 字符处理函数概述
C++ 提供了一系列用于处理单个字符的函数,位于
<cctype>
头文件中。这些函数可用于判断字符类型(如是否为字母、数字)或转换字符大小写。
特点:- 输入输出均为
int
类型(实际为char
的 ASCII 值)。 - 处理的字符必须是 ASCII 范围内 的值,否则行为未定义。
2. 常用字符处理函数
2.1 大小写转换
函数 功能 示例 tolower(int c)
将字符转为小写(非字母不变) tolower('A')
→'a'
tolower('1')
→'1'
toupper(int c)
将字符转为大写(非字母不变) toupper('b')
→'B'
toupper('$')
→'$'
示例代码:
#include <iostream> #include <cctype> // 包含字符处理函数 using namespace std; int main() { char c1 = 'A'; char c2 = tolower(c1); // 'a' char c3 = '7'; char c4 = toupper(c3); // '7'(非字母不变) cout << c2 << ", " << c4 << endl; // 输出: a, 7 return 0; }
2.2 字符类型判断
函数 功能 返回值( bool
)isalpha(int c)
判断是否为字母(a-z, A-Z) 是 → true
,否 →false
isdigit(int c)
判断是否为数字(0-9) isalnum(int c)
判断是否为字母或数字( isalpha
或isdigit
)isspace(int c)
判断是否为空白字符(空格、制表符、换行符等) ispunct(int c)
判断是否为标点符号(非字母、数字、空白的字符) isupper(int c)
判断是否为大写字母(A-Z) islower(int c)
判断是否为小写字母(a-z) 示例代码:
char c = '!'; cout << isalpha(c) << endl; // 0(false) cout << ispunct(c) << endl; // 1(true) cout << isspace('\t') << endl; // 1(true,制表符是空白字符)
3. 注意事项
-
输入类型为
int
函数参数为int
,但实际处理的是char
的 ASCII 值。若传入超出 ASCII 范围的整数,结果未定义。 -
返回值为
int
tolower
/toupper
的返回值需显式转换为char
:char c = 'A'; char lower = static_cast<char>(tolower(c)); // 推荐显式转换
- 直接赋值可能导致隐式转换(如
int
转char
),但在 ASCII 范围内通常安全。
-
国际化限制
这些函数仅适用于 ASCII 字符集。对于 Unicode 或多字节字符(如中文),需使用<locale>
或<codecvt>
库。
4. 实际应用场景
4.1 字符串大小写转换
#include <iostream> #include <cctype> #include <string> using namespace std; int main() { string str = "Hello, World!"; // 转为小写 for (char& c : str) { c = tolower(c); } cout << str << endl; // 输出: hello, world! // 转为大写 for (char& c : str) { c = toupper(c); } cout << str << endl; // 输出: HELLO, WORLD! return 0; }
4.2 过滤非数字字符
string input = "a1b2c3"; string digits; for (char c : input) { if (isdigit(c)) { digits += c; } } cout << digits << endl; // 输出: 123
4.3 统计各类字符数量
string text = "Hello, 123!"; int letters = 0, numbers = 0, spaces = 0, puncts = 0; for (char c : text) { if (isalpha(c)) letters++; else if (isdigit(c)) numbers++; else if (isspace(c)) spaces++; else if (ispunct(c)) puncts++; } cout << "Letters: " << letters << endl; // 5 cout << "Numbers: " << numbers << endl; // 3 cout << "Spaces: " << spaces << endl; // 1 cout << "Punctuation: " << puncts << endl; // 1
5. 与 C 语言的区别
C++ 的字符处理函数与 C 语言基本相同,但 C++ 提供了更安全的类型检查。例如:
- C++ 中
tolower
的参数必须是可隐式转换为int
的类型(如char
),而 C 语言允许传递任意类型。
总结
字符处理函数(如
tolower
、isalpha
)是 C++ 中处理文本的基础工具,适用于简单的字符转换和判断。使用时需注意:- 包含
<cctype>
头文件。 - 输入输出为
int
类型,处理 ASCII 范围内的字符。 - 对于复杂文本处理(如国际化),需使用更高级的库。
通过这些函数,你可以轻松实现字符串的大小写转换、字符类型过滤等操作。
- 输入输出均为
-
2025-6-18 18:42:08@
以下是关于 C++ 中 C风格字符串 和
string
类 相互转换的详细教程,采用通俗易懂的方式讲解,并使用using namespace std;
:1. C风格字符串 →
string
1.1 直接赋值(最常用)
#include <iostream> #include <string> using namespace std; int main() { // 方式1:字符数组 char cstr1[] = "Hello"; string cppStr1 = cstr1; // 自动转换 // 方式2:字符串常量(const char*) const char* cstr2 = "World"; string cppStr2(cstr2); // 构造函数转换 // 方式3:部分转换 char buffer[] = "ABCDEFG"; string cppStr3(buffer, 3); // 从 buffer 取前3个字符 -> "ABC" cout << cppStr1 + " " + cppStr2 << endl; // 输出: Hello World return 0; }
1.2 从
char*
转换(带长度参数)char data[] = {'H', 'e', 'l', 'l', 'o', '\0'}; int len = 5; // 明确指定长度(不含 '\0') string str(data, len); // 结果:"Hello" string str2(data, 3); // 结果:"Hel"(只取前3个字符)
2.
string
→ C风格字符串2.1 获取只读版本(
const char*
)string cppStr = "Hello"; // 方式1:c_str()(最常用) const char* cstr1 = cppStr.c_str(); // 方式2:data()(C++11起与 c_str() 等价) const char* cstr2 = cppStr.data(); // 用于需要 const char* 的函数(如 printf) printf("C-style: %s\n", cstr1); // 输出: C-style: Hello
2.2 获取可修改的副本(
char[]
)string cppStr = "Hello"; // 方式1:使用 strcpy + 手动分配内存 char* buffer = new char[cppStr.length() + 1]; // +1 用于存储 '\0' strcpy(buffer, cppStr.c_str()); // 复制内容 // 使用 buffer... delete[] buffer; // 手动释放内存 // 方式2:使用 strncpy(更安全) char buffer2[10]; strncpy(buffer2, cppStr.c_str(), sizeof(buffer2) - 1); // 预留空间给 '\0' buffer2[sizeof(buffer2) - 1] = '\0'; // 确保以 '\0' 结尾
2.3 直接操作
string
的内部缓冲区(C++17起)string cppStr = "Hello"; // data() 返回可写指针(需确保 string 非空) if (!cppStr.empty()) { char* writableBuffer = &cppStr[0]; // 或 cppStr.data() writableBuffer[0] = 'J'; // 修改第一个字符 cout << cppStr << endl; // 输出: Jello }
3. 注意事项
-
生命周期管理
string
的c_str()
/data()
返回的指针仅在string
未被修改时有效。若string
重新分配内存(如追加内容),指针会失效。
string str = "Hello"; const char* ptr = str.c_str(); str += " World"; // str 重新分配内存,ptr 可能失效!
-
const char*
不可修改c_str()
/data()
返回的是const char*
,不可直接修改。若需修改,必须复制到可写缓冲区(如char[]
)。
-
自动转换的陷阱
- 部分函数(如
printf
)可自动将string
转为const char*
,但这并非标准行为,建议显式调用c_str()
。
string str = "Hello"; printf("%s\n", str); // 部分编译器允许,标准中不合法! printf("%s\n", str.c_str()); // 正确写法
- 部分函数(如
4. 示例程序
#include <iostream> #include <string> #include <cstring> // 用于 strcpy using namespace std; void printCString(const char* cstr) { cout << "C-style: " << cstr << endl; } int main() { // C风格 → string char cstr[] = "Hello"; string cppStr = cstr; // string → C风格(只读) const char* readOnlyPtr = cppStr.c_str(); printCString(readOnlyPtr); // 输出: C-style: Hello // string → C风格(可写副本) char writableBuffer[100]; strcpy(writableBuffer, cppStr.c_str()); writableBuffer[0] = 'J'; // 修改为 "Jello" cout << "Modified: " << writableBuffer << endl; return 0; }
5. 总结
转换方向 方法 示例 适用场景 C风格 → string
直接赋值/构造函数 string s = "Hello";
所有场景(推荐) string
→ C风格c_str()
/data()
const char* ptr = s.c_str();
传递给需要 const char*
的函数string
→ 可写副本strcpy
+ 手动分配内存char* buf = new char[s.length()+1];
strcpy(buf, s.c_str());
需要修改内容时 在 C++ 中,优先使用
string
类,仅在与 C 库交互或性能敏感场景下才需要转换为 C风格字符串。 -
-
2025-6-18 18:40:56@
以下是使用表格形式整理的 C++ C风格字符串 常用用法,包含示例代码和说明:
C风格字符串(字符数组)用法速查表
操作 代码示例 说明 声明与初始化 字符数组(自动加 \0
)char str1[] = "Hello";
自动计算长度(含 \0
),等价于{'H', 'e', 'l', 'l', 'o', '\0'}
。字符指针(指向常量) const char* str2 = "World";
字符串常量存储在只读内存区,不可修改。 手动初始化 char str3[6] = {'H', 'i', '\0'};
必须显式添加 '\0'
,否则不是合法字符串。输入输出 输出 cout << str1;
从首地址开始打印,直到遇到 '\0'
。输入(危险) cin >> str1;
读取到空格为止,可能导致缓冲区溢出! 安全输入 cin.getline(str1, 50);
读取整行,最多存储 49 个字符(留 1 个给 '\0'
)。字符串长度 获取长度 int len = strlen(str1);
返回字符数(不含 '\0'
),时间复杂度 O(n)。字符串复制 危险复制 strcpy(dest, src);
不检查目标数组大小,可能溢出! 安全复制 strncpy(dest, src, max_len);
最多复制 max_len
个字符,需手动补'\0'
:dest[max_len-1] = '\0';
字符串拼接 危险拼接 strcat(dest, src);
从 dest
的'\0'
位置开始追加,不检查空间!安全拼接 strncat(dest, src, max_len);
最多追加 max_len
个字符,自动补'\0'
。字符串比较 字典序比较 int cmp = strcmp(str1, str2);
返回负数(str1 < str2)、0(相等)、正数(str1 > str2)。 安全比较 int cmp = strncmp(str1, str2, n);
最多比较前 n
个字符。字符串查找 查找子串 char* pos = strstr(str1, "llo");
返回首次出现的位置指针,未找到返回 nullptr
。查找字符 char* pos = strchr(str1, 'l');
查找字符首次出现位置。 字符串分割 按分隔符分割 char* token = strtok(str, " ,");
首次调用传入字符串,后续传入 nullptr
继续分割。转换为数字 字符串 → 整数 int num = atoi(str);
等价于 stoi(str)
,但不检查溢出。字符串 → 浮点数 double d = atof(str);
等价于 stod(str)
。示例代码
#include <iostream> #include <cstring> // 包含 C 风格字符串函数 using namespace std; int main() { // 初始化 char str1[20] = "Hello"; const char* str2 = "World"; // 拼接 strncat(str1, " ", 18); // 预留空间给 '\0' strncat(str1, str2, 17); // str1 变为 "Hello World" // 长度 cout << "Length: " << strlen(str1) << endl; // 输出: 11 // 查找 char* pos = strstr(str1, "World"); if (pos != nullptr) { cout << "Found at position: " << (pos - str1) << endl; // 输出: 6 } // 分割字符串 char text[] = "Hello,World,C++"; char* token = strtok(text, ","); while (token != nullptr) { cout << token << endl; // 依次输出: Hello, World, C++ token = strtok(nullptr, ","); } return 0; }
注意事项
-
缓冲区溢出风险:
strcpy
、strcat
等函数不检查目标数组大小,必须手动确保空间足够!推荐使用strncpy
、strncat
。 -
结束符
'\0'
:- 所有字符串操作(如
strlen
、cout
)都依赖'\0'
标记结束。 - 使用
strncpy
后需手动补'\0'
,strncat
会自动补。
- 所有字符串操作(如
-
字符串常量只读:
const char* str = "Hello"; // 存储在只读区 // str[0] = 'J'; // 错误:修改只读内存会崩溃!
-
动态内存分配:
若需动态创建字符串,使用new char[size]
并在使用后delete[]
。
C风格字符串 vs C++
string
特性 C风格字符串( char*
)C++ string
内存管理 手动分配/释放(易泄漏) 自动管理(RAII) 安全性 无边界检查(易溢出) 自动检查边界 操作便利性 需调用库函数(如 strcpy
)直接用运算符(如 +
、==
)长度跟踪 需调用 strlen()
(O(n) 时间)直接访问 length()
(O(1) 时间)与 C 代码兼容性 完全兼容 需通过 c_str()
转换通过这张表格,你可以快速掌握 C风格字符串的核心用法,但在 C++ 中建议优先使用
string
类,除非有特殊性能或兼容性需求。 -
-
2025-6-18 18:39:52@
以下是关于 C++ 中 C风格字符串 的基础教程,采用通俗易懂的方式讲解,并使用
using namespace std;
简化代码:1. 什么是 C风格字符串?
C风格字符串是 以空字符
'\0'
结尾的字符数组,本质是字符数组(如char[]
),但必须以'\0'
标记字符串结束。
在 C++ 中,C风格字符串不如string
类安全方便,但在与 C 语言交互或性能敏感场景中仍常用。2. 基本用法
2.1 声明与初始化
#include <iostream> using namespace std; int main() { // 方式1:字符数组(自动添加 '\0') char str1[] = "Hello"; // 等价于 {'H', 'e', 'l', 'l', 'o', '\0'} // 方式2:字符指针指向字符串常量(只读) const char* str2 = "World"; // 字符串常量存储在只读内存区 // 方式3:手动初始化(需显式添加 '\0') char str3[6]; // 必须预留至少 6 个字符空间(5个字母 + 1个 '\0') str3[0] = 'H'; str3[1] = 'i'; str3[2] = '\0'; // 必须手动添加结束符 cout << str1 << endl; // 输出: Hello cout << str2 << endl; // 输出: World cout << str3 << endl; // 输出: Hi return 0; }
2.2 输入输出
char name[50]; cout << "Enter your name: "; cin >> name; // 读取到空格为止(危险:可能导致缓冲区溢出) // 安全输入:指定最大长度 cin.getline(name, 50); // 读取整行,最多 49 个字符(留 1 个给 '\0') cout << "Hello, " << name << "!";
3. 常用操作(需包含
<cstring>
)3.1 字符串长度
#include <cstring> // 包含 C 字符串处理函数 char str[] = "Hello"; int len = strlen(str); // 返回 5(不包含 '\0')
3.2 字符串复制
char src[] = "Source"; char dest[10]; // 危险:不检查目标数组大小,可能溢出 strcpy(dest, src); // dest 变为 "Source" // 安全:指定最大复制长度 strncpy(dest, src, 9); // 最多复制 9 个字符(留 1 个给 '\0') dest[9] = '\0'; // 手动补 '\0'(strncpy 不保证添加)
3.3 字符串拼接
char str1[20] = "Hello"; char str2[] = " World"; // 危险:不检查目标数组大小 strcat(str1, str2); // str1 变为 "Hello World" // 安全:指定最大追加长度 strncat(str1, str2, 10); // 最多追加 10 个字符
3.4 字符串比较
char str1[] = "Apple"; char str2[] = "Banana"; int result = strcmp(str1, str2); // result < 0:str1 < str2(按字典序) // result == 0:str1 == str2 // result > 0:str1 > str2
3.5 字符串查找
char str[] = "Hello World"; char* pos = strstr(str, "World"); // 查找子串,返回指针 if (pos != nullptr) { cout << "Found at position: " << (pos - str); // 输出: 6 }
4. 与 C++
string
的转换4.1 C风格字符串 →
string
const char* cstr = "Hello"; string cppStr = cstr; // 自动转换
4.2
string
→ C风格字符串string cppStr = "World"; const char* cstr = cppStr.c_str(); // 只读版本 const char* cstr2 = cppStr.data(); // C++11 起等价于 c_str() char buffer[50]; strcpy(buffer, cppStr.c_str()); // 复制到可修改的缓冲区
5. 注意事项
-
缓冲区溢出风险:
strcpy
、strcat
等函数不检查目标数组大小,可能导致程序崩溃或安全漏洞。优先使用strncpy
、strncat
。 -
手动内存管理:
字符数组需提前分配足够空间,动态分配(如new char[size]
)后需手动delete[]
。 -
性能考量:
C风格字符串操作比string
类更高效(尤其是频繁操作时),但安全性更低。 -
字符串常量只读:
const char* str = "Hello"; // 字符串常量存储在只读区 // str[0] = 'J'; // 错误:修改只读内存会导致运行时崩溃
6. 示例程序
#include <iostream> #include <cstring> using namespace std; int main() { char greeting[50] = "Hello"; const char* name = "Alice"; // 拼接 strncat(greeting, ", ", 48); // 预留空间给 '\0' strncat(greeting, name, 46); // 剩余空间 strcat(greeting, "!"); // 输出长度 cout << "Length: " << strlen(greeting) << endl; // 输出: 13 // 查找逗号位置 char* comma = strchr(greeting, ','); if (comma != nullptr) { *comma = ';'; // 修改字符(greeting 是可写数组) } cout << greeting << endl; // 输出: Hello; Alice! return 0; }
总结
- 优势:与 C 语言兼容、性能高、内存占用小。
- 劣势:安全性差(需手动管理内存和结束符)、操作繁琐。
建议:在 C++ 中优先使用
string
类,仅在必要时(如与 C 库交互)使用 C风格字符串。 -
-
2025-5-16 10:15:02@
C++ 教程:C风格字符串(char数组)详解(0基础通俗易懂)
📚 什么是 C 风格字符串?
在 C++ 中,有两种主要的字符串处理方式:
- C++ 标准库中的
string
类型(如std::string
)——更现代、更安全、推荐使用 - C 风格字符串(字符数组)——底层、灵活、常用于系统编程或与旧代码交互
本教程重点讲解 C 风格字符串(C-style string),也就是我们常说的:
使用字符数组来表示字符串的方式。
🧠 基本概念:字符数组 + '\0' 结束符
示例:
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
这串字符是
'H' 'e' 'l' 'l' 'o'
,最后一个\0
是 字符串结束符,表示“到这里为止”。更常见的写法:
char str[] = "Hello";
编译器会自动帮你加上结尾的
\0
,所以实际长度是6
字符。
🛠️ 常见操作
✅ 定义和初始化
char name[20]; // 定义一个最多放19个字符的字符串(最后要留一个\0) strcpy(name, "Tom"); // 赋值用 strcpy
或者直接初始化:
char name[] = "Tom"; // 自动推断大小为4(T o m \0)
⚠️ 注意:不能这样赋值:
char name[20]; name = "Tom"; // ❌ 错误!不能直接给数组赋值
要用
strcpy()
函数:#include <cstring> strcpy(name, "Tom"); // ✅ 正确
🔍 常用函数(来自
<cstring>
头文件)函数 功能 strcpy(dest, src)
把 src
拷贝到dest
strcat(dest, src)
把 src
拼接到dest
后面strlen(str)
获取字符串长度(不包括 \0
)strcmp(str1, str2)
比较两个字符串是否相等 strchr(str, ch)
在字符串中查找某个字符第一次出现的位置 strstr(str1, str2)
在字符串 str1
中查找子串str2
是否存在
💡 详细讲解几个常用函数
1.
strcpy
:复制字符串#include <iostream> #include <cstring> using namespace std; int main() { char src[] = "Hello World"; char dest[50]; strcpy(dest, src); // 把 src 拷贝到 dest cout << dest << endl; // 输出 Hello World return 0; }
2.
strcat
:拼接字符串char a[50] = "Hello "; char b[] = "World"; strcat(a, b); // 把 b 接到 a 后面 cout << a << endl; // 输出 Hello World
3.
strlen
:获取字符串长度char str[] = "Hello"; cout << strlen(str) << endl; // 输出 5
注意:不包括结尾的
\0
。4.
strcmp
:比较字符串char a[] = "Apple"; char b[] = "Banana"; if (strcmp(a, b) == 0) cout << "相同" << endl; else if (strcmp(a, b) < 0) cout << "a 小于 b" << endl; else cout << "a 大于 b" << endl;
输出:
a 小于 b
因为字母顺序 A < B。
⚠️ 常见错误 & 注意事项
❌ 不检查空间是否足够
char shortStr[5] = "Hi"; // 正确,占3个字符(H i \0) strcpy(shortStr, "Longer"); // ❌ 错误!目标空间不够,导致溢出
👉 解决办法:确保目标数组足够大!
❌ 忘记加
\0
或越界访问字符数组如果不以
\0
结尾,很多字符串函数会崩溃!❌ 试图修改字符串字面量(只读内存)
char* p = "Hello"; // 指向的是只读内存 p[0] = 'h'; // ❌ 运行时错误!不要改字面量内容
✅ 正确做法:
char arr[] = "Hello"; // 数组拷贝了字符串内容 arr[0] = 'h'; // ✅ 可以修改
🧪 示例程序:输入姓名并打招呼
#include <iostream> #include <cstring> using namespace std; int main() { char name[100]; cout << "请输入你的名字:"; cin >> name; // 输入不会带空格的字符串 cout << "你好," << name << "!欢迎学习C语言字符串!" << endl; return 0; }
📌 总结知识点
内容 说明 C风格字符串 是字符数组,以 \0
结尾初始化 char str[] = "Hello";
常用函数 strcpy
,strcat
,strlen
,strcmp
不可变性 字符串字面量不能修改 安全问题 要注意缓冲区溢出(buffer overflow)
🧩 进阶建议
- 学习如何手动实现
strcpy
,strlen
,strcmp
- 学习
strtok
分割字符串 - 学习
sprintf
和sscanf
格式化输入输出 - 学习如何将数字转成字符串(如
itoa
)
📖 推荐对比学习
类型 示例 特点 C风格字符串 char str[100] = "Hello";
底层、灵活、容易出错 C++ string string s = "Hello";
安全、方便、推荐使用
如果你希望我继续扩展以下内容,请告诉我:
- 如何处理带空格的字符串?
- 如何用
fgets
安全读取一行? - 如何实现自己的
my_strcpy
函数? - 如何将整数转为 C 风格字符串?
😊
- C++ 标准库中的
-
2025-5-14 20:32:35@
C++ C风格字符串教程
C风格字符串是C++中用于处理字符串的传统方式,以字符数组的形式存储,并以空字符
\0
结尾。1. 定义和初始化
1.1 字符数组定义
char str1[] = "Hello"; // 自动添加结尾的空字符 char str2[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // 手动添加空字符
1.2 字符指针定义
char* str3 = "World"; // 指向字符串常量 const char* str4 = "C++"; // 常量字符串指针,防止修改
2. 基本操作
2.1 获取字符串长度
#include <cstring> size_t len = strlen(str); // 返回字符串长度,不包括`\0`
2.2 复制字符串
#include <cstring> char dest[20]; strcpy(dest, src); // 将src复制到dest,需确保dest有足够的空间
2.3 连接字符串
#include <cstring> char str1[20] = "Hello"; char str2[] = " World"; strcat(str1, str2); // 将str2连接到str1的末尾
2.4 比较字符串
#include <cstring> int result = strcmp(str1, str2); // 返回比较结果: // 0:相等 // 小于0:str1小于str2 // 大于0:str1大于str2
3. 注意事项
- 内存管理:需要手动管理内存,防止缓冲区溢出和内存泄漏。
- 空字符:确保字符串以
\0
结尾,否则可能导致未定义行为。 - 安全性:建议使用安全版本的函数,如
strncpy
、strncat
、strncmp
,防止越界访问。
4. 示例
#include <iostream> #include <cstring> int main() { char str1[20] = "Hello"; char str2[20] = "World"; std::cout << "Length of str1: " << strlen(str1) << std::endl; char dest[40]; strcpy(dest, str1); strcat(dest, str2); std::cout << "Concatenated string: " << dest << std::endl; int result = strcmp(str1, str2); if (result == 0) { std::cout << "str1 and str2 are equal" << std::endl; } else if (result < 0) { std::cout << "str1 is less than str2" << std::endl; } else { std::cout << "str1 is greater than str2" << std::endl; } return 0; }
5. 总结
C风格字符串在处理性能要求高或与C代码兼容的场景下仍然有用,但需要注意内存管理和安全性问题。对于大多数现代C++开发,推荐使用
std::string
类,提供更便捷和安全的字符串操作。 -
2025-5-14 20:11:22@
#include<iostream> #include<cstring> using namespace std; int main() { //6换行符 //good morning int n; cin>>n; char ss[300]; //cin.getline(ss,300);// string getline(cin,ss) cin.ignore();//:忽略缓冲区中的字符 cin.getline(ss,300); cout<<n<<" "<<ss<<endl; return 0; }
-
2025-5-14 20:02:23@
#include<iostream> #include<cstring> using namespace std; int main() { //6换行符 //good morning int n; cin>>n; char ss[300]; cin.getline(ss,300);// string getline(cin,ss) cin.getline(ss,300); cout<<n<<" "<<ss<<endl; return 0; }
-
2025-5-14 19:37:01@
#include<iostream> #include<cstring> using namespace std; int main() { char a[300]={}; //cin>>a; cin.getline(a,300); cout<<a<<" "<<strlen(a)<<endl; return 0; }
-
2025-5-14 19:26:05@
-
2025-5-14 19:23:13@
#include<iostream> #include<cstring> using namespace std; int main() { char a[300]={}; //cin>>a; cin.getline(a,300); cout<<a<<endl; return 0; }
-
2025-5-14 19:22:07@
-
2025-5-14 19:19:17@
#include<iostream> using namespace std; int main() { char a[300]={}; cin>>a; cout<<a<<endl; return 0; }
-
2025-5-14 19:11:44@
#include<iostream> using namespace std; int main() { cout<<"hello world"<<endl; cout<<"he\0llo world"<<endl; char a[6]={'h','e','l','l','o','\0'}; char b[6]={"hello"}; char c[6]="hello"; cout<<a<<endl; cout<<b<<endl; cout<<c<<endl; return 0; }
- 1