zoukankan      html  css  js  c++  java
  • C++ 字符串与字符数组 详解

    写在前面:字符是单个的,字符串一般有多个,但也可以是单个,甚至可以是空的

    char c;
    c = 'a';  //字符a,注意使用单引号
    c = "a'; //出错!“a”使用的是双引号,代表是字符串,而c是字符类型
    
    string c="abcd";
    string c1="a";单个字符,但是双引号

    在C++中,有两种类型的字符串表示形式:

    • C-风格字符串
    • C++引入的string类

    C-风格字符串

    C 风格的字符串起源于 C 语言,并在 C++ 中继续得到支持。字符串实际上是使用 null 字符 ‘’ 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。
    下面的声明和初始化创建了一个 “Hello” 字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词 “Hello” 的字符数多一个。

    char greeting[6] = {'H', 'e', 'l', 'l', 'o', ''};

    其实不需要把 null 字符放在字符串常量的末尾。C++ 编译器会在初始化数组时,自动把 ‘’ 放在字符串的末尾。所以也可以利用下面的形式进行初始化

    char greeting[] = "Hello";

    以下是 C/C++ 中定义的字符串的内存表示:

    C++ 中有大量的函数用来操作以 null 结尾的字符串:

    序号函数功能
    1 strcpy(s1,s2) 复制字符串 s2 到字符串 s1
    2 strcat(s1,s2) 连接字符串 s2 到字符串 s1 的末尾
    3 strlen(s1) 返回字符串 s1 的长度
    4 strcmp(s1,s2) 返回s1与s2的比较结果
    5 strchr(s1,ch) 返回一个指针,指向字符串s1中字符ch的第一次出现的位置
    6 strstr(s1,s2) 返回一个指针,指向字符串s1中s2的第一次出现的位置

     

     

     

     

     

     

     

     

     

    C++ 中的 String 类

    C++ 标准库提供了 string 类类型,支持上述所有的操作,另外还增加了其他更多的功能。比如:

    • append() – 在字符串的末尾添加字符
    • find() – 在字符串中查找字符串
    • insert() – 插入字符
    • length() – 返回字符串的长度
    • replace() – 替换字符串
    • substr() – 返回某个子字符串

    C++中的字符串一般有以下四种类型,

    • string

    • char*

    • const char*
    • char[]

    下面分别做简单介绍,并说明其中的一些区别

    1)string

    string是一个C++类库中的一个类,它位于名称空间std中,因此必须使用using编译指令或者std::string来引用它。它包含了对字符串的各种常用操作,它较char*的优势是内容可以动态拓展,以及对字符串操作的方便快捷,用+号进行字符串的连接是最常用的操作;

    2)char*

    char* 是指向字符串的指针(其实严格来说,它是指向字符串的首个字母),你可以让它指向一串常量字符串;

    3)const char*

    该声明指出,指针指向的是一个const char类型,即不能通过当前的指针对字符串的内容作出修改

    注意这里有两个概念:

    • char * const [指向字符的静态指针]
    • const char * [指向静态字符的指针]

    前者const修饰的是指针,代表不能改变指针
    后者const修饰的是char,代表字符不能改变,但是指针可以变,也就是说该指针可以指针其他的const char;

    4)char[]

    与char*与许多相同点,代表字符数组,可以对应一个字符串,如

    char * a="string1";
    char b[]="string2";

    这里a是一个指向char变量的指针,b则是一个char数组(字符数组)

    二者的不同点

    一,char*是变量,值可以改变, char[]是常量,值不能改变!
    a是一个char型指针变量,其值(指向)可以改变;
    b是一个char型数组的名字,也是该数组首元素的地址,是常量,其值不可以改变

    二,char[]对应的内存区域总是可写,char*指向的区域有时可写,有时只读
    比如:

    char * a="string1";
    char b[]="string2";
    gets(a); //试图将读入的字符串保存到a指向的区域,运行崩溃! 
    gets(b) //OK

    解释: a指向的是一个字符串常量,即指向的内存区域只读;
    b始终指向他所代表的数组在内存中的位置,始终可写!

    注意,若改成这样gets(a)就合法了

    char * a="string1";
    char b[]="string2";
    a=b; //a,b指向同一个区域
    gets(a) //OK
    printf("%s",b) //会出现gets(a)时输入的结果

    解释: a的值变成了是字符数组首地址,即&b[0],该地址指向的区域是char *或者说 char[8],习惯上称该类型为字符数组,其实也可以称之为“字符串变量”,区域可读可写。

    总结:char *本身是一个字符指针变量,但是它既可以指向字符串常量,又可以指向字符串变量,指向的类型决定了对应的字符串能不能改变!

    三,char * 和char[]的初始化操作有着根本区别:

    char *a="Hello World"; 
    char b[]="Hello World"; 
    printf("%s, %d
    ","Hello World", "Hello World"); 
    printf("%s, %d %d
    ", a, a,  &a);                           
    printf("%s, %d %d
    ", b,     b,  &b);

    结果:

    Hello World,13457308
    Hello World,13457308    2030316
    Hello World,2030316 2030316

    结果可见:尽管都对应了相同的字符串,但”Hello World”的地址 和 a对应的地址相同,与b指向的地址有较大差异;&a 、&b都是在同一内存区域,且&b==b
    根据c内存区域划分知识,我们知道,局部变量都创建在栈区,而常量都创建在文字常量区,显然,a、b都是栈区的变量,但是a指向了常量(字符串常量),b则指向了变量(字符数组),指向了自己(&b==b==&b[0])。

    char * a=”string1”;是实现了3个操作:

    1. 声明一个char*变量(也就是声明了一个指向char的指针变量);
    2. 在内存中的文字常量区中开辟了一个空间存储字符串常量”string1”
    3. 返回这个区域的地址,作为值,赋给这个字符指针变量a

    最终的结果:指针变量a指向了这一个字符串常量“string1”
    (注意,如果这时候我们再执行:char * c=”string1”;则,c==a,实际上,只会执行上述步骤的1和3,因为这个常量已经在内存中创建)

    char b[]=”string2”;则是实现了2个操作:

    1. 声明一个char 的数组,
    2. 为该数组“赋值”,即将”string2”的每一个字符分别赋值给数组的每一个元素

    最终的结果:“数组的值”(注意不是b的值)等于”string2”,而不是b指向一个字符串常量

    实际上, char * a=”string1”; 的写法是不规范的!
    因为a指向了即字符常量,一旦strcpy(a,”string2”)就糟糕了,试图向只读的内存区域写入,程序会崩溃的!尽管VS下的编译器不会警告,但如果你使用了语法严谨的Linux下的C编译器GCC,或者在windows下使用MinGW编译器就会得到警告。
    所以,我们还是应当按照”类型相同赋值”的原则来写代码:

    onst char * a="string1";

    保证意外赋值语句不会通过编译。

    const char*与char[]的区别:
    const char * a=”string1”
    char b[]=”string2”;

    二者的区别在于:

      1. a是const char 类型, b是char const类型
        ( 或者理解为 (const char)xx 和 char (const xx) )

      2. a是一个指针变量,a的值(指向)是可以改变的,但a只能指向(字符串)常量,指向的区域的内容不可改变;

      3. b是一个指针常量,b的值(指向)不能变;但b指向的目标(数组b在内存中的区域)的内容是可变的

      4. 作为函数的声明的参数的时候,char []是被当做char *来处理的!两种形参声明写法完全等效!

    参考:https://blog.csdn.net/ksws0292756/article/details/79432329

  • 相关阅读:
    淘宝镜像安装方法
    vue项目 title处的小图标
    vue生成环境 访问路径配置
    element ui icon不展示
    vue 使用element-ui实现table表单列展示与隐藏
    通过id获取元素控制滚动位置回到顶部
    复杂传值
    vue 中el-card点击事件失效解决
    滚动条隐藏 兼容
    【javascript/PHP】当一个JavaScripter初次进入PHP的世界,他将看到这样的风景
  • 原文地址:https://www.cnblogs.com/USTC-ZCC/p/13732929.html
Copyright © 2011-2022 走看看