目录
下一篇:c语言字符串2
字符数组
char word[]={'H','e','l','l','o','!'};
这不是c语言的字符串,因为不能用字符串的方式做计算
如何定义字符串?
char word[]={'H','e','l','l','o','\0'};
这才是字符串,把单引号和\去掉也是一样的意思
现在有了7个单元
'\0'就是0
字符串定义:
1、以0(整数0)结尾的一串字符
0或'\0'是一样的,但是和'0'不同,'0'是ASCII的一个字符,某些时候会强调是单引号里的0,因为单引号一定 是1个字节,而0是个int
0标志字符串的结束,但它不是字符串的一部分
计算字符串的长度的时候不包含这个0
2、字符串以数组的形式存在,以数组或指针的形式访问
更多的是以指针的形式
3、string.h里有很多处理字符串的函数
字符串的定义方式:
char *str="Hello";//表示现在有一个字符指针str,指向了一个字符数组
char word[]="Hello";//有一个字符数组里面的内容是Hello
char line[10]="Hello";//有一个10个字节大小的字符数组,里面放了Hello,Hello加上结尾的0一共6个字节,结尾的0是编译器自动补的
c语言中用双引号括起来的东西叫做字符串常量
"Hello"这个东西会被编译器变成一个字符串数组放在某处,这个数组的长度是6,结尾有0
这个东西在函数参数里面很常见:比如printf,scanf。。。
两个相邻的字符串常常会被自定连接起来
比如:
printf("字符常量1""字符常量2");
两个字符常量间第一个没有结束的" 第二个没有开始的" 使用反斜杠\连接起来
printf("字符常量1,\
字符常量2");
这种方法有个缺点,他们中间的tab也会被显示出来,为了不显示table只能将第二个字符退格到行首
总结:
c语言表现出来懂字符串的标志:能识别双引号里的东西
字符串变量
上代码
两个指针都指向了同内容的字符串常量"Hello World"
char *s="Hello World";
char *s2="Hello World";
printf("s=%p\n",s);
printf("s=%p\n",s2);
return 0;
结果他们指向的地址都是一样的
我们再来看一个本地变量i的地址作为对比
会发现本地变量i的地址很大和字符串常量的地址差了很远不在同一个区域
![](https://img-blog.csdnimg.cn/20210112233458234.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjkxOTQxOQ==,size_16,color_FFFFFF,t_70)
这个地方的地址很小,位于程序的代码段,是只读的,
如果试图写,操作系统的保护机制会使程序崩溃
强行写的结果
为什么会这样?
因为:这个字符串是在编译时刻就已经有值的东西,所以放在一个只读的地方,并让指针指向,如果有两处相同的东西,那些指针就会指向同一个地方,不然会产生s1改变了值,而s该怎么办
字符串常量:
s是一个指针,初始化为指向一个字符串常量
由于这个常量所在的地方,所以实际上s是const char* s,但是由于历史的原因,编译器接受不带const的写法
但是试图对s所指的字符串做写入会导致严重的后果
如果需要修改字符串,应该用数组
char s[]="Hello,world!";//代表这个字符串就在我这里,之前用指针的是指针指向
会把那段不可写的Hello World的内容拷贝到这个数组里
#include <stdio.h>
int main() {
char *s="Hello World";
char *s2="Hello World";
char s3[]="Hello World";
printf("s=%p\n",s);
printf("s2=%p\n",s2);
printf("s3=%p\n",s3);
s3[0]='B';//修改值
printf("Here!s3[0]=%c\n",s3[0]);
return 0;
}
看到s3也在一个很大的地方,是一个本地变量
![](https://img-blog.csdnimg.cn/20210112233611953.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjkxOTQxOQ==,size_16,color_FFFFFF,t_70)
那么怎么选?指针还是数组?
数组:这个字符串在这里,作为本地变量空间自动被回收
指针:这个字符串不知道在哪里
就当做一个字符串,只读的字符串
处理参数(因为数组和指针一样,不如就用指针)
动态分配空间(如果字符串空间用malloc得到的)
char*是字符串?
字符串可以表达为char*的形式
char*不一定是字符串,char*只是指向一个字节或者一串连续的字节
本意是指向字符的指针,可能指向的是字符的数组(像int*一样)
只有它所指的字符数组有结尾的0,才能说它所指的是字符串
字符串输入输出
字符串的赋值
char *t="title";
char *s=t;
这段代码并没有创建一个新的字符串,而是让s指向了"title",对是做的任何操作都是对t做
要创建一个新的字符串让s指向需要字符串函数,之后再讲
字符串输入输出
int main() {
char string[8];
scanf("%s",string);//这里是数组=指针=地址不用&
printf("%s##\n",string);//这里两个#是输入边界测试
return 0;
}
发现读到了第一个单词hello,没有包含空格,第二个单词没有读到,如果有第二个scanf就会读到word
int main(){
char word[8];
char word2[8];
scanf("%s",word);
scanf("%s",word2);
printf("%s##%s##\n",word,word2);
return 0;
}
会发现也不带空格,说明空格是用来区分输入的分隔符
同样用回车也是
注意:这个scanf是不安全的,因为不知道要读入的内容的长度
现在给出超过8个字符的输入,则会出现数组越界
解决办法:在百分号和s中间加一个数字,告诉scanf最多读7个字符,多的不要了
scanf("%7s",word);
可以看出第一个输入都读到了,第二个输出抛弃了8
但是!如果第一个输入超出了7个字符,程序就会自动把多出来的给第二个输入
这个%s间的数字应该比数组大小小
常见错误
char *string;//这是一个指针变量
scanf("%s",string);//错误
误以为char*是字符串类型,定义了一个字符串类型变量string就直接用了,由于没有对string初始化为0,所以不一定每次运行都出错
空字符串