• 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语言库交互或性能敏感场景中仍有重要作用。

10 条评论

  • @ 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