15.字符数组

15.数组-字符数组


15.1 知识点

字符数组的声明和初始化

字符数组就是类型为字符 char 的一维数组。

常用方式:

方式一:聚合初始化

char charArr[5] = { 'H', 'E', 'L', 'L', 'O' };
char charArr2[] = { 'H', 'E', 'L', 'L', 'O' };

方式二:单独初始化

char charArr3[5];
charArr3[0] = 'H';
charArr3[1] = 'E';

这几种声明初始化的方式,如果直接将字符数组拿来打印,会出现问题:

cout << charArr << endl;  // 乱码 烫烫烫烫
cout << charArr2 << endl; // 乱码 烫烫烫烫
cout << charArr3 << endl; // 乱码 烫烫烫烫

使用字符串初始化字符数组

可以直接使用字符串对字符数组进行赋值:

char charArr4[] = "Hello World"; // string
cout << charArr4 << endl; // Hello World 正常打印

原本看起来只有12个字符的字符串,但是长度却有13个:

int length = sizeof(charArr4) / sizeof(char);
cout << length << endl; // 13

通过观察长度,我们发现了一个潜在规则:对字符数组用字符串去赋值时,会默认在尾部加上一个 \0 的转义字符,表示字符串的结束。前面几种初始化方式不会默认添加 \0,所以会出现乱码。

手动加 \0

char charArr44[] = "Hello\0 World"; // string
cout << charArr44 << endl; // Hello

利用结束符号决定字符数组表示的字符串何时结束

尝试自定义\0位置决定字符串何时结束

如果不对字符数组后面的内容进行初始化,并且其中没有 \0,在打印时就不知道何时结束,程序会不停地往后读取。由于没有明确的终止符,程序会根据内存中是否存在 \0 停止打印,可能打印出多余字符,甚至是乱码。

这意味着可能出现访问到字符数组范围之外的内存区域,产生未定义的行为。

char charArr5[5];
charArr5[0] = 'A';
charArr5[1] = 'B';
// cout << charArr5[2] << endl; // 空
// cout << charArr5 << endl; // AB烫烫烫烫烫烫烫烫烫烫烫烫烫愼@
charArr5[2] = 'X';
charArr5[3] = 'C';
charArr5[4] = '\0';

cout << charArr5[2] << endl; // X
cout << charArr5 << endl; // ABXC

关于“烫”字符

在内存中,汉字字符使用多字节编码(如 UTF-8 或 GBK)。当程序读取到这些内存内容时,会尝试解释它们。由于编码规则,有可能形成合法的汉字编码,导致控制台上显示出汉字或其他非预期字符。


15.2 知识点代码

Lesson15_数组_字符数组.cpp

#include <iostream>
using namespace std;
int main()
{
    std::cout << "字符数组\n";

    #pragma region 知识点一 字符数组的声明和初始化

    //字符数组就是类型为字符char的一维数组

    //常用方式:
    //方式一:聚合初始化
    char charArr[5] = { 'H', 'E', 'L', 'L', 'O' };
    char charArr2[] = { 'H', 'E', 'L', 'L', 'O' };

    //方式二:单独初始化
    char charArr3[5];
    charArr3[0] = 'H';
    charArr3[1] = 'E';

    //这几种声明初始化的方式,如果直接将字符数组拿来打印 会出现问题
    //cout << charArr << endl;//乱码 烫烫烫烫
    //cout << charArr2 << endl;//乱码 烫烫烫烫
    //cout << charArr3 << endl;//乱码 烫烫烫烫

    #pragma endregion

    #pragma region 知识点二 使用字符串初始化字符数组

    //可以直接使用字符串对字符数组进行赋值
    char charArr4[] = "Hello World"; //string
    cout << charArr4 << endl;//Hello World 正常打印

    //原本看起来只有12个字符的字符串 但是长度却有13个
    int length = sizeof(charArr4) / sizeof(char);
    cout << length << endl;//13

    //通过观察长度,我们发现了一个潜在规则
    //对字符数组用字符串去赋值时,会默认在尾部加上一个\0的转移字符
    //代表字符串的结束
    //前面几种初始化方式不会默认添加\0 所以会乱码

    //手动加\0 检测到\0后不会打印后面的字符了
    char charArr44[] = "Hello\0 World"; //string
    cout << charArr44 << endl;//Hello

    #pragma endregion

    #pragma region 知识点三 利用结束符号决定字符数组表示的字符串何时结束

    //如果不对字符数组后面的内容进行初始化 并且其中没有\0
    //在打印时就不知道何时结束,就会不停的往后读取
    //因为没有明确的终止符,程序会根据内存中是否存在 '\0' 停止打印
    //可能打印出多余字符,甚至是乱码
    //也就是说可能出现访问到字符数组范围之外的内存区域,产生未定义的行为

    char charArr5[5];
    charArr5[0] = 'A';
    charArr5[1] = 'B';

    //cout << charArr5[2] << endl;//空
    //cout << charArr5 << endl;//AB烫烫烫烫烫烫烫烫烫烫烫烫烫愼@

    charArr5[2] = 'X';
    charArr5[3] = 'C';
    charArr5[4] = '\0';

    cout << charArr5[2] << endl;//X
    cout << charArr5 << endl;//ABXC

    //关于“烫”字符
    //在内存中,汉字字符使用多字节编码(比如 UTF-8 或 GBK)
    //当程序读取到这些内存内容时,会尝试解释它们。
    //由于编码规则,有可能形成合法的汉字编码,导致控制台上显示出汉字或其他非预期字符

    #pragma endregion
}

15.3 练习题

字符数组中,为什么要注意加入\0转移字符?

因为\0转移字符代表结束,如果没有它,当我们使用字符数组用于打印时,会不知道何时停止,导致越界打印。

利用所学知识点,你认为打印出的“烫”可能占几个字节?

在不同编码格式中,”烫”可能所占字节数各不相同,编码值也不同。

  • 在UTF-8中,”烫”占3个字节
  • 在UTF-16中,”烫”占2个字节
  • 在GBK中,”烫”占2个字节


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏