• 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风格字符串

可以使用cincout进行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) 比较s1s2,返回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;
}

安全建议:

  • 始终确保字符数组有足够空间
  • 初始化字符数组
  • 使用更安全的函数如strncpystrncat
  • 区分字符串常量和可修改的字符数组

总结

C风格字符串是C++中处理文本的基础方式,理解它的工作原理对学习C++至关重要。本教程涵盖了C风格字符串的定义、输入输出、常用操作、类型转换以及常见问题。在实际编程中,建议优先使用C++的string类,它提供了更安全、便捷的字符串操作,但C风格字符串在与C语言库交互或性能敏感场景中仍有重要作用。

14 条评论

  • @ 2025-6-18 19:36:33

    以下是关于 C++ 中 字符处理函数(如 tolowertoupper 等)的基础教程,采用通俗易懂的方式讲解,并使用 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) 判断是否为字母或数字(isalphaisdigit
    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. 注意事项

    1. 输入类型为 int
      函数参数为 int,但实际处理的是 char 的 ASCII 值。若传入超出 ASCII 范围的整数,结果未定义。

    2. 返回值为 int

      • tolower/toupper 的返回值需显式转换为 char
        char c = 'A';
        char lower = static_cast<char>(tolower(c));  // 推荐显式转换
        
      • 直接赋值可能导致隐式转换(如 intchar),但在 ASCII 范围内通常安全。
    3. 国际化限制
      这些函数仅适用于 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 语言允许传递任意类型。

    总结

    字符处理函数(如 tolowerisalpha)是 C++ 中处理文本的基础工具,适用于简单的字符转换和判断。使用时需注意:

    1. 包含 <cctype> 头文件。
    2. 输入输出为 int 类型,处理 ASCII 范围内的字符。
    3. 对于复杂文本处理(如国际化),需使用更高级的库。

    通过这些函数,你可以轻松实现字符串的大小写转换、字符类型过滤等操作。

    • @ 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. 注意事项

      1. 生命周期管理

        • stringc_str()/data() 返回的指针仅在 string 未被修改时有效。若 string 重新分配内存(如追加内容),指针会失效。
        string str = "Hello";
        const char* ptr = str.c_str();
        str += " World";  // str 重新分配内存,ptr 可能失效!
        
      2. const char* 不可修改

        • c_str()/data() 返回的是 const char*,不可直接修改。若需修改,必须复制到可写缓冲区(如 char[])。
      3. 自动转换的陷阱

        • 部分函数(如 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;
        }
        

        注意事项

        1. 缓冲区溢出风险
          strcpystrcat 等函数不检查目标数组大小,必须手动确保空间足够!推荐使用 strncpystrncat

        2. 结束符 '\0'

          • 所有字符串操作(如 strlencout)都依赖 '\0' 标记结束。
          • 使用 strncpy 后需手动补 '\0'strncat 会自动补。
        3. 字符串常量只读

          const char* str = "Hello";  // 存储在只读区
          // str[0] = 'J';  // 错误:修改只读内存会崩溃!
          
        4. 动态内存分配
          若需动态创建字符串,使用 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. 注意事项

          1. 缓冲区溢出风险
            strcpystrcat 等函数不检查目标数组大小,可能导致程序崩溃或安全漏洞。优先使用 strncpystrncat

          2. 手动内存管理
            字符数组需提前分配足够空间,动态分配(如 new char[size])后需手动 delete[]

          3. 性能考量
            C风格字符串操作比 string 类更高效(尤其是频繁操作时),但安全性更低。

          4. 字符串常量只读

            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++ 中,有两种主要的字符串处理方式:

            1. C++ 标准库中的 string 类型(如 std::string)——更现代、更安全、推荐使用
            2. 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 分割字符串
            • 学习 sprintfsscanf 格式化输入输出
            • 学习如何将数字转成字符串(如 itoa

            📖 推荐对比学习

            类型 示例 特点
            C风格字符串 char str[100] = "Hello"; 底层、灵活、容易出错
            C++ string string s = "Hello"; 安全、方便、推荐使用

            如果你希望我继续扩展以下内容,请告诉我:

            • 如何处理带空格的字符串?
            • 如何用 fgets 安全读取一行?
            • 如何实现自己的 my_strcpy 函数?
            • 如何将整数转为 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结尾,否则可能导致未定义行为。
              • 安全性:建议使用安全版本的函数,如strncpystrncat 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