关于char*、char[]与string的初始化及转换

3 年前

由于刷题是发现自己对于这里的越界访问以及转换有一些陌生,所以做个记录

首先是一道常见题:替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

输入:s = "We are happy."

输出:"We%20are%20happy."

解法为先统计s的长度len和空格的count数目,预先计算好输出的长度newlen,从newlen-1,len-1开始,遇到空格t替换。

这里的代码实现问题在于如果参数为string s,如何在不新建新的string对象不占用额外空间在原有s上改动,思路是newlen-len的空间s+=' ';

而如果参数是char*呢?

class Solution {
public:
    void replaceSpace(char *str,int length) {
        if(str==NULL||length<0)
            return ;
        int orignallength = 0;
        int countofbalnk = 0;
        for(int i=0;str[i]!='\0';i++){
            orignallength++;
            if(str[i]==' ')
                countofbalnk++;
        int newlength=orignallength+countofbalnk*2;//插入后的长度
        int pOrignallength=orignallength;
        int pNewlength=newlength;
        while(pOrignallength>=0 && pNewlength>pOrignallength)
            if(str[pOrignallength]==' ')
                str[pNewlength--]='0';
                str[pNewlength--]='2';
                str[pNewlength--]='%';
                str[pNewlength--]=str[pOrignallength];
            pOrignallength--;
};

答案是参数为char*时,都不用像string一样扩充空间填充为' ',直接改变就可以了,下面就是讲解为什么不会越界呢?

一、char*与char[]

初始化

char s[10] = "Hello"; // 剩余的自动加\0

再仔细观察内存存储会发现,在s[5]-s[9]未越界范围内是'\0',接着在s[10]也存储’\0‘,在s[11]存储11,11为int型十进制表示前面的个数,但一般我们关注0-9即可

char str1[8] = "0123456";//长度为8,因为加了\0

char s[10] = {'H','e','l','l','o','\0'}; //

char s[10] = {'H','e','l','l','o'}; // 和前面效果一样

char s[10] = {0} // 全部初始化为0,原因在于剩余的元素使用了默认值0,这里的0其实也就对应于字符'\0',也要主要'0'的ascii码为48不是0

char s[10] = "Hello, world.\n"; // 超出部分丢弃,没有字符串结尾符,在vscode中无法编译

char s[] = "Hello, world.\n"; // sizeof = strlen + 1,因为sizeof是操作符,而strlen是统计到\0停止

char *c = c2 指针,可以通过c[index]进行改变
char[index]不用考虑越界,直接覆盖,但是输出时要覆盖到'\0'才可以,因为char*关键点在于'\0',只需要把\0都去掉改变成自己需要的xxxx\0形式就可以,因为为指针,所以也不需要在意数组本身的空间

当然需要明白的是c是指针,指针指向的是c2这个字符数组的内存空间

通过上面两个引用快的解释,可以对上面代码进行解释了,因为参数为char*,而newlen从尾巴开始每一个都被赋值为有效的非空字符,并且结尾处加上了'\0'那么输出时也就可以正常输出了

下面讲一些之外的小知识

注意的是 sizeof是针对str1的空间进行操作数计算 ,因为str1的大小为8,所以sizeof的结果等于8,而strlen要统计到\0,所以越界改变的数也要算进去,如果改变ss[10]这些,结果是sizeof=8,strlen会增加

char str1[8] = "0123456";//在str[7] = '\0',之后也为空字符
 printf("%c\n",str1[7]);//\0
 printf("%c\n",str1[8]);//\0
 char* ss = str1;