精华内容
下载资源
问答
  • C语言 字符指针
    千次阅读
    2019-07-10 19:40:09

    字符数组

    字符串常量是一个字符数组,例如:

    “i am a string”

    在字符串内部,字符数组以空字符 '\0' 结尾,程序可以通过检查空字符找到字符数组的结尾。字符串常量占据的存储单元数也因此比双引号内的字符数大 1。

    字符指针

    char *p;

    p = "now is the time";

    将一个指向该字符数组的指针赋值给 p。(C语言没有提供将整个字符串作为一个整体进行操作的运算符)

     

    下面两个定义之间有很大差别:

    char a[] = "now is the time";        //定义一个数组

    char *p = "now is the time";        //定义一个指针

    a是一个仅仅足以存放初始化字符串以及空字符 '\0' 的一维数组,可以修改数组中的单个字符。

    p是一个指针,其初值指向一个字符串常量,之后可以修改它指向其它字符串,可以输出它的内容中的某个字符,但修改不了它指向的字符串的内容。

     

    更多相关内容
  • 1, 字符指针有初始值时,不能修改其中字符的值 #include<iostream> using namespace std; int main() { char *p1 = "nihao";//字符指针赋值给字符指针只能读不能修改字符的值 char *p2 = p1; p1[0] = 'm';...

    1, 字符指针有初始值时,不能修改其中字符的值

    #include<iostream>
    using namespace std;
    int main()
    {
    	char *p1 = "nihao";//字符指针赋值给字符指针只能读不能修改字符的值
    	char *p2 = p1;
    	p1[0] = 'm';//尝试修改,会报错
    	return 0;
    }
    

    会报错:
    在这里插入图片描述

    原因

    因为char * 字符指针,指向的数据存储在静态存储区,里面的值不允许修改。相当于const char *表示指针指向内存区域不能修改。也就是上面的字符串nihao不能修改。

    2,字符指针赋值给另外一个字符指针,接受字符串的指针也只能进行读取操作。

    #include<iostream>
    using namespace std;
    int main()
    {
    	char *p1 = "nihao";//字符指针赋值给字符指针只能读不能修改字符的值
    	char *p2 = p1;
    	p2[0] = 'm';//尝试修改,会报错
    	return 0;
    }
    

    同样报错:访问权限的问题
    在这里插入图片描述

    原因

    这里原因跟上面一样,只不过将char *赋值给另一个char *,本质上还是尝试修改一个const char *.也不允许修改。

    3,如果想要对字符指针里面的值进行操作怎么办呢?(最简单的方法直接看4.)

    - 申请动态内存(在堆中,属于动态存储区,允许修改)malloc(c)或者new(C++)

    - 将静态数据区数据复制到动态内存中进行修改

    看例子:
    1)用C语言中strcpy函数

    #define _CRT_SECURE_NO_WARNINGS
    #include<iostream>
    using namespace std;
    int main()
    {
    	char *p1 = "nihao";
    	char *p2=new char[sizeof(p1)+1];//new 开辟一段新的内存,注意要加上1,要加上字符串末尾‘\0’
    	strcpy(p2, p1);//调用字符串copy函数,将静态内存区数据复制到动态内存中。
    	p2[0] = 'm';//对新开辟的内存进行操作
    	cout << p2<<endl;//输出操作后的结果
    	cout << p1<<endl;//对原来字符串没有影响,原来字符串可以看做常量,不能修改。
    	
    }
    

    原因

    为什么这里字符指针可以修改?因为char * =new 在堆中new(malloc和new一样的效果)了一块内存,该内存是动态存储区,允许修改值。
    2)可以用C++中string 类解决

    #define _CRT_SECURE_NO_WARNINGS
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
    	string a= "nihao";
    	string b = a;
    	b[2] = 'M';//将一个string a赋值给另外一个string b后,可以对b进行操作,对原来那个string a类没影响。
    	/*a[1] = 'M';*/
    	cout << b<<endl;//输出操作结果
    	cout << a << endl;//对原来那个string a类没影响,验证结果
    	
    }
    

    在这里插入图片描述

    4,直接用char []定义字符变量,允许修改某个字符

    代码

    	char a[10] = "nimao";
    	a[2] = 'h';//直接修改。因为定义了一个字符数组。字符数组放在栈内存中,属于动态内存区,允许修改。
    	for (int i = 0; i < sizeof(a); i++)
    	{
    		cout << a[i];
    	}
    

    原因

    因为定义了一个字符数组char a[10]。字符数组放在栈内存中,属于动态内存区,允许修改。

    补充:

    需要了解的c语言几个存储区

    动态存储区

    包括堆存储区、栈存储区。

    • 你需要知道的是:堆一般是留给程序员用的,比如我们new一个数组,malloc数组,都是存放在堆中,用完后我们需要自己delete清理内存(虽然系统也会帮忙自动垃圾清理)。
    • 定义一个数组,是放在栈储存区。栈一般是系统自己用的,像递归执行每一层执行状态都存储在栈存储区中。

    静态存储区

    存放常量、静态变量、全局变量

    程序区

    存放程序语句

    参考链接

    动态存储区、静态存储区、堆和栈的区别

    注意char * 和char []区别

    char *不可以修改某个字符,char []可以修改某个字符。

    参考链接

    char *a 与char a[] 的区别

    展开全文
  • 第二个字符数组被指定为const,以保证该数组中的内容不会在函数调用期间修改。连接后的字符串放在第一个字符数组中,函数调用后得到的函数值,就是第一个字符数组的地址。例如: char str1[30]=″People′s ...
  • 字符指针

    万次阅读 多人点赞 2019-08-10 16:37:09
    2019-8-9字符指针字符指针:指向字符型数据的指针变量。每个字符串在内存中都占用一段连续的存储空间,并有唯一确定的首地址。即将字符串的首地址赋值给字符指针,可让字符指针指向一个字符串。 ② char *ptr = ...

    字符指针

    ①字符指针:指向字符型数据的指针变量。每个字符串在内存中都占用一段连续的存储空间,并有唯一确定的首地址。即将字符串的首地址赋值给字符指针,可让字符指针指向一个字符串。

    char *ptr = "Hello";//将保存在常量存储区的"Hello"的首地址赋值给ptr
    与
    char *ptr;
    ptr = "Hello";//是等价的,注意不能理解为将字符串赋值给ptr
    

    char str[10] = "Hello";
    char *ptr = str;//数组名代表数组的首地址
    //等价于
     char *ptr;
     ptr = str;//等价于ptr = &str[0];将数组的首地址赋给字符指针ptr
    

    ④对于数组名str,不能使用str++操作使其指向字符串中的某个字符,因为数组名是一个地址常量,其值是不能被改变的。

    *(ptr+i):字符串中第i+1个字符,相当于*(str+i),即str[i]
    也可以用ptr++,移动指针ptr,使ptr指向字符中的某个字符
    

    ⑤字符串的长度(指字符串所含的字符个数,但不包括最后的’\0’)与字符数组的大小(指字符串所包含的字符个数加上’\0’,故+1)不一样。

    for(i = 0;str[i] != '\0'; i++ )
    {
         printf("%c",str[i]);//常用借助字符串结束标志'\0'识别字符串的结束
    }
    scanf("%s",str);//表示读入一个字符串,直到遇到空白字符(空格、回车符、制表符)为止
    //如果输入带有空格的字符串(比如人名)只会读到空格以前而空格以后不会读入,留在了输入缓冲区中
    printf("%s",str);//表示输出一个字符串,直到遇到字符串结束标志'\0'为止(注意这里可以带有空格输出)
    

    gets():可以输入带有空格的字符串。以回车符作为字符串的终止符,同时将回车符从输入缓冲区读走,但不作为字符串的一部分。而scanf()不读走回车符,回车符仍留在输入缓冲区中。 gets()不能限制输入字符串的长度,很容易引起缓冲区溢出。同样即使scanf(“12s%”,name)也不能解决这个问题。当使用scanf()和gets()时,确保输入字符串的长度不超过数组的大小,否则使用限制输入字符串长度的函数fgets(name,sizeof(name),stdin)
    puts():用于从括号内的参数给出的地址开始,依次输出存储单元中的字符,当遇到第一个’\0’时输出结束,并且自动输出一个换行符’\n’

    #include <stdio.h>
    #define N 12
    int main()
    {
        char name[N];
        char *ptrName = name;//声明一个指向数组name的字符指针ptrName
        //注意这里,用字符指针输入字符串前提,必须保证字符指针事先已指向一个数组的首地址,如ptrName指向了数组name,如果只是单纯声明字符指针,编译会报错
        printf("Enter your name:");
        gets(ptrName);//输入字符串存入字符指针ptrName所指向的内存
        //为提高程序安全性,也可以使用fgets(name,sizeof(name),stdin);
        printf("Hello %s!\n",ptrName);
        return 0;
    }
    

    ⑥if(str1==str2)时合法语句,比较这两个地址的大小(作为指针,有不同的地址,一定为假),而不是比较字符串的大小,也不是比较字符串的内容。
    函数功能:用字符指针作为函数参数,实现字符串复制(将str2复制到str1中)

    void MyStrcpy(char *str1,char *str2)
    {
            while(*str2!='\0')//若当前str2所指字符不是字符串结束标志
            {
               *str1 = *str2;//复制字符
                str2++;//使str2指向下一个字符
                str1++;//使str1指向下一个存储单元
            }
            *str1 = '\0';//当复制循环结束时,在str1的末尾添加字符串结束标志
    }
    

    函数功能:用字符型数组作函数参数,计算字符串的长度

    unsigned int MyStrlen(const char str[])
    {
               int i;
               unsigned int len = 0;//计数器设置为0
               for(i=0;str[i]!='\0';i++)
               {
                    len++;//循环统计不包括'\0'在内的字符个数
               }
               return len;
    }
    

    函数功能:用字符指针作函数参数,计算字符串的长度

    unsigned int MyStrlen(const char *pStr)//为防止实参在被调函数中被意外修改,在相应的形参前面加上类型限定符const
    {
               unsigned int len = 0;//计数器设置为0
               for(;*pStr !='\0';pStr++)
               {
                    len++;//循环统计不包括'\0'在内的字符个数
               }
               return len;
    }
    

    补充:
    int型变量范围:-2147483648~2147483647
    unsigned int型变量范围:0~4294967295
    从函数返回字符串指针
    函数功能:将字符串str2连接到字符串str1的后面

    char *MyStrcat(char *str1,char *str2)
    {
          char *pStr = str1;//定义一个字符指针并保存字符串str1的首地址
          while(*str1! = '\0')//当没有读到str字符串的结束标志
          {
                str1++;//将指针移动到字符串str1的末尾
          }//注意这里,在读到'\0'之前时,指针已经移到了这个位置,当读到时跳出循环不再指向下一个
          所以复制str2的首地址是'\0'之前的位置
          for(;*str2!='\0';str1++,str2++)
          {
                *str1 = *str2;//将字符串str2复制到字符串str1的后面
          }
                *str1 = '\0';//在连接后的字符串的末尾添加字符串结束标志
                return pStr;//返回连接后的新的字符串str1的首地址
    }
    

    char *f(); 声明的是一个返回字符指针的函数f()。如上代码
    char(*f)(); 函数指针f。指向的函数没有形参,返回值是字符型。f是一个指针,表示该指针变量可以指向一个返回值为字符型的函数

    ⑦const类型限定符
    数据传到被调函数内部,不希望其在函数内部被修改,防止数据被意外修改,用const对参数进行限定
    ⑧字符处理函数

    函数原型功能描述
    int isdigit(int c);判断是否为数字,返回真假值
    int isalpha(int c);判断是否为字母,返回真假值
    int isalnum(int c)判断是否为字母或者数字,返回真假值
    int islower(int c)判断是否为小写字母,返回真假值
    int isupper(int c)判断是否为大写字母,返回真假值
    int tolower(int c)若c是大写字母,将c转换成小写字母后返回
    int toupper(int c)若c是小写字母,将c转换成大写字母后返回
    int isspace(int c)若c是空白符(换行符(’\n’)、空格符(’ ‘)、换页符(’\f’)、回车符(’\r’)、水平(’\t’)、垂直制表符(’\v’)),返回真值
    int iscntrl(int c)若c是控制字符(水平、垂直制表符、换页符、响铃报警符(’\a’)、退格符(’\b’)、回车符、换行符),返回真值
    int isprint(int c)若c是一个包含空格在内的可打印字符,返回真值
    int isgraph(int c)若c是一个除空格以外的所有可打印字符,返回真值
    展开全文
  • 字符数组与字符指针的区别

    千次阅读 多人点赞 2020-09-09 11:39:33
    1.字符指针可以指向一个字符串。 我们可以用字符串常量对字符指针进行初始化。例如,有说明语句: char *str = "This is a string."; 是对字符指针进行初始化。此时,字符指针指向的是一个字符串常量的首地址,...

    1.字符指针可以指向一个字符串。

    我们可以用字符串常量对字符指针进行初始化。例如,有说明语句:

    char *str = "This is a string.";

    是对字符指针进行初始化。此时,字符指针指向的是一个字符串常量的首地址,即指向字符串的首地址。

    这里要注意字符指针与字符数组之间的区别。例如,有说明语句:

    char string[ ]="This is a string.";

    此时,string是字符数组,它存放了一个字符串。

    字符指针str与字符数组string的区别是:str是一个变量,可以改变str使它指向不同的字符串,但不能改变str所指的字符串常量。string是一个数组,可以改变数组中保存的内容。

    2.实例:

    char *str, *str1="This is another string.";

    char string[100]="This is a string.";

    则在程序中,可以使用如下语句:

    str++; /* 指针str加1 */

    str = "This is a NEW string."; /* 使指针指向新的字符串常量 */

    str = str1; /* 改变指针str的指向 */

    strcpy( string, "This is a NEW string.") /* 改变字符串的的内容 */

    strcat( string, str) /* 进行串连接操作 */

    在程序中,不能进行如下操作:

    string++; /* 不能对数组名进行++运算 */

    string = "This is a NEW string."; /* 错误的串操作 */

    string = str1; /* 对数组名不能进行赋值 */

    strcat(str, "This is a NEW string.") /* 不能在str的后面进行串连接 */

    strcpy(str, string) /* 不能向str进行串复制 */

    3.其它说明:

    1) 以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,如在代码中写:"abc",那么编译器帮你存储的是"abc\0"

    2) "abc"是常量吗?答案是有时是,有时不是。

      不是常量的情况:"abc"作为字符数组初始值的时候就不是,如

                      char str[] = "abc";

    因为定义的是一个字符数组,所以就相当于定义了一些空间来存放"abc",而又因为字符数组就是把字符一个一个地存放的,所以编译器把这个语句解析为 char str[3] = {'a','b','c'};又根据上面的总结1,所以char str[] = "abc";的最终结果是 char str[4] = {'a','b','c','\0'};

     做一下扩展,如果char str[] = "abc";是在函数内部写的话,那么这里的"abc/0"因为不是常量,所以应该被放在栈上。

     是常量的情况:  把"abc"赋给一个字符指针变量时,如

                      char* ptr = "abc";

     因为定义的是一个普通指针,并没有定义空间来存放"abc",所以编译器得帮我们找地方来放"abc",显然,把这里的"abc"当成常量并把它放到程序的常量区是编译器最合适的选择。所以尽管ptr的类型不是const char*,并且ptr[0] = 'x';也能编译通过,但是执行ptr[0] = 'x';就会发生运行时异常,因为这个语句试图去修改程序常量区中的东西。

    记得哪本书中曾经说过char* ptr = "abc";这种写法原来在c++标准中是不允许的,但是因为这种写法在c中实在是太多了,为了兼容c,不允许也得允许。虽然允许,

    但是建议的写法应该是const char* ptr = "abc";这样如果后面写ptr[0] = 'x'的话编译器就不会让它编译通过,也就避免了上面说的运行时异常。

    又扩展一下,如果char* ptr = "abc";写在函数体内,那么虽然这里的"abc/0"被

    放在常量区中,但是ptr本身只是一个普通的指针变量,所以ptr是被放在栈上的, 只不过是它所指向的东西被放在常量区罢了。

    3) 数组的类型是由该数组所存放的东西的类型以及数组本身的大小决定的。如char s1[3]和char s2[4],s1的类型就是char[3],s2的类型就是char[4],

    也就是说尽管s1和s2都是字符数组,但两者的类型却是不同的。

    4) 字符串常量的类型可以理解为相应字符常量数组的类型,

      如"abcdef"的类型就可以看成是const char[7]

    5) sizeof是用来求类型的字节数的。如int a;那么无论sizeof(int)或者是sizeof(a)都是等于4,因为sizeof(a)其实就是sizeof(type of a)

    6) 对于函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通的指针类型,如对于void func(char sa[100],int ia[20],char *p)

      则sa的类型为char*,ia的类型为int*,p的类型为char*

    7) 根据上面的总结,来实战一下:

     对于char str[] = "abcdef";就有sizeof(str) == 7,因为str的类型是char[7],

     也有sizeof("abcdef") == 7,因为"abcdef"的类型是const char[7]。

     对于char *ptr = "abcdef";就有sizeof(ptr) == 4,因为ptr的类型是char*。

     对于char str2[10] = "abcdef";就有sizeof(str2) == 10,因为str2的类型是char[10]。

      对于void func(char sa[100],int ia[20],char *p);

      就有sizeof(sa) == sizeof(ia) == sizeof(p) == 4,

      因为sa的类型是char*,ia的类型是int*,p的类型是char*。

    4.区别:

    (1)字符数组由若干个元素组成每个元素中存放字符串的一个字符,而字符指针变量中存放的是字符串的首地址

    (2)初始化方式不同。对字符数组初始化要用static存储类别,在编译时进行。而对字符指针变量初始化不必加static,在实际执行时进行。

    (3)赋值方式不同。对字符数组不能整体赋值,只能转化成份量,对单个元素进行。而字符指针变量赋值可整体进行。

    例如:

    char s[10];

    s= /"C++/";/*错,s是常量,怎能被赋值*/

    (4)在定义一个字符数组时,编译时即已分配内存单元,有确定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,但该指针变量具体指向哪个字符串,并不知道,即指针变量存放的地址不确定。例如:

    char a[10];
    char *p;
    scanf(/"%s/",a);/*正确*/

    scanf(/"%s/",p);/*非常危险,p的值动态*/

    (5)字符指针变量的值可以改变,字符数组名是一个常量,不能改变。例如,有简单程序:

    int main() {
    
        char* s="china man";
    
        s +=6;
    
        printf("%s",s);
    }
     

    运行结果:man

    展开全文
  • 字符指针修改问题

    千次阅读 2015-01-14 21:31:11
    字符串的定义方式有两种,直接先上代码: 第一种: char num[20] = "hello"; *num = '0'; //可行 num[1] = '0'; //可行 cout 第二种: char* num = "hello"; *num = '0'; //错误 num[1] = '0'; //错误 cout...
  • 目录指向字符串的指针为何不能用来修改字符串为何char a[ ]可以修改字符串 指向字符串的指针为何不能用来修改字符串 如上图操作,指向字符串的指针不能用来修改字符串,会出错。 这是因为: char *p="hello...
  • 字符指针与字符串

    千次阅读 多人点赞 2018-04-23 21:54:38
    1.字符指针可以指向一个字符串。我们可以用字符串常量对字符指针进行初始化。例如,有说明语句:char *str = "This is a string.";是对字符指针进行初始化。此时,字符指针指向的是一个字符串常量的首地址...
  • C语言中没有特定的字符串类型,我们通常是将字符串放在一个字符数组中,字符数组用法很简单我们还是来你看个例子吧。 #include <stdio.h> #include <string.h> int main() { char str[] = ...
  • 如何给一个字符指针char *p 赋值?很多人会迅速的写出:我看到很多博客上面写的是这样操作: char *p; p="hello"; 在C语言中这种方式确实是被允许的,但是到c++11中会给出警告(报错): 错误提示的...
  • 字符串赋值给字符指针

    千次阅读 2020-06-28 15:58:01
    此时的指针类似与一个字符数组的数组名,但不同的是,这个指针是可变的,而数组名指针是常量指针。这也就是为什么修改后的代码是错误的,因为我们不能赋值给一个常量。 于是我做了更大幅度的修改。 #include using ...
  • C语言中没有特定的字符串类型,我们通常是将字符串放在一个字符数组中,这在《C语言字符数组和字符串》中已经进行了详细讲解,这里不妨再来演示一下: #include <stdio.h> #include <string.h> ...
  • 前言 在指针初体验(C语言–指针初体验)中我们简单了解了指针的知识和使用: 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。 指针的大小是固定的4/8个字节(32位平台/64位平台)。...一、字符指针
  • 字符指针数组(二级指针)

    千次阅读 2017-03-29 12:47:39
    一、字符指针数组 - 11、字符指针数组概念字符指针数组是指一个数组中的各个元素都是字符指针 或者是字符串(字符数组)的首地址2、初始化char *name[]={"zhangsan","lisi","wangwu"};变量名联系:&name[0]=&'z' , &...
  • 字符指针和字符数组的初始化 例如: char *p=“hello”;和char c[10]="hello"有什么区别呢? 字符串常量存储在数据区中的常量区,好处是相同的字符串,比如hello只会存储一遍,常量区的含义就是字符串本身是不可修改...
  • c++中的字符数组与字符指针

    千次阅读 2018-02-06 11:44:09
    1.字符指针可以指向一个字符串。 我们可以用字符串常量对字符指针进行初始化。例如,有说明语句: char *str = "This is a string."; 是对字符指针进行初始化。此时,字符指针指向的是一个字符串常量的首地址,即...
  • c语言中输出字符指针相关问题

    万次阅读 多人点赞 2017-05-01 01:41:21
    首先搞清楚在c语言中没有字符串的类型,所以对字符串操作,有两种形式:可以用字符指针(为什么不叫字符串指针,我个人觉得,字符指针针对的是单个字符的操作,即指针操作,所以就叫它字符指针吧。。。),或者字符串...
  • 指针字符串常量

    千次阅读 2020-07-25 18:04:07
    指针字符串常量 选择为真的表达式: char str1[] = “abc”; char str2[] = “abc”; const char str3[] = “abc”; const char str4[] = “abc”; const char *str5 = “abc”; const char *str6 = “abc”...
  • c语言中字符指针与字符数组的区别:

    千次阅读 多人点赞 2018-06-14 13:48:56
    char 是用来存储单个字符的;例如:char ch=’a’;char[]是用来存储多个字符的;例如:char ch[5]={‘h’, ‘e’, ‘l’, ‘l’, ‘o’};//数组本质上就是同时定义了多个变量,并对变量进行初始化当char[]最后一个...
  • 关于字符指针不可修改的问题C/C++ codechar*m =" hello "; *(m+1) =' s '; for(;*m !=' \0 ';m++){ printf(" %c\n ",*m); }但是出运行时错误。------------------------------------...
  • 这些字符串常量是不能改变的,如果试图改变指针所指向的内容是错误的 因为字符串常量是存在静态内存区的,不可以改变的。 如定义字符串常量: char* a="i love you."; a[3]='p'(非法操作)。 因为a[3]...
  • C语言中,为什么字符串可以赋值给字符指针变量

    万次阅读 多人点赞 2018-08-15 11:59:11
    C语言中,为什么字符串可以赋值给字符指针变量 char *p,a='5'; p=&amp;a; //显然是正确的, p="abcd"; //但为什么也可以这样赋值?? 问:一直理解不了为什么可以将字串常量赋值给字符指针变量,请...
  • C++ 字符指针字符指针数组详解

    千次阅读 多人点赞 2020-04-19 17:34:19
    C++处理字符串有两种方式,即:指针方式和数组方式 数组方式:char a[] = "HelloWorld"; 指针方式:const char* s= "HelloWorld"; const可以忽略 接下来详细讲解一下字符指针 首先,为什么字符串可以直接赋值给...
  • [C语言] 指针处理字符

    千次阅读 2019-08-14 17:39:10
    字符串和字符指针 首先是字符串常量的存储,字符串常量是用一对双引号括起来的字符序列,与基本类型常量的存储相似,字符串常量在内存中的存放位置由系统自动安排。 由于字符串常量是一串字符,通常被视为一个特殊的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 374,016
精华内容 149,606
关键字:

字符指针修改