字符串是C语言中最重要的数据类型之一,不过C语言中没有自带的字符串类型,而是使用一串以’\0’结尾的字符数组来表示字符串。下面雅乐网总结了一下常用的C语言中字符串的知识
字符串简介
字符串就是以空字符(’\0’)结尾的char数组。例如字符串”Hello”,在内存中是这样表示的
因此,要用一个char数组存放字符串hello,就必须分配5+1个空间,多余的一个用来存放空字符’\0’。
用双引号可以表示字符串,例如 “Hello” ,这是一个表达式,它的值实际上是’H’字符所在的地址。因此,可以像数组名那样用”Hello”,例如
“Hello”[2]就等于’l’。
表示字符串的双引号并不是字符串的一部分,只是告诉编译器这是个字符串,编译器会自动分配一个内存,如上图所示,”Hello”的值就是p的位置。
双引号和单引号的区别
从上面可以看出,双引号包起来的字符串,它的值是一个地址,是字符串第一个字符的地址。
单引号表示的是一个字符,而字符又是ASCII码表示的,所以单引号包起来的一个字符相当于一个int。
‘A’ 表示字符A,它的值是’A’的ascii码,也就是十进制65 。
而”A”表示的是字符串,它的值是一个指向char的地址,他在内存中有两个char空间,’A’和’\0′ 。”A”[0]就是’A’
双引号表示的字符串存储在常量区,字符串的内容不允许被修改。
字符串数组的初始化
初始化字符串数组的时候可以使用””
char m[10] = “Hello”;
m数组初始化成这样
而如果不指定数组大小,char m[] = “Hello” 那么m会分配为6个char 。也就是字符串字符个数+1
只有初始化的时候可以这样赋初始值,一旦声明了数组后,不能用这种形式给数组赋值
char m[10];
m = “Hello”;
这是错误的。因为一旦声明了char m[10] m就是这一块内存的名字了,他不能改变为指向其他的内存。
声明之后还要给数组赋值,只能这样了
m[0] = ‘H’;
m[1] = ‘e’;
m[2] = ‘l’;
m[3] = ‘l’;
m[4] = ‘o’;
m[5] = ‘\0′;
这样之后,m[6]以及后面的值是不知道的。可能是’\0’ 更可能不是。可以先使用memset给数组全体赋初始值0.
memset(m, 0, sizeof(m));
因为’\0’的ascii码就是0,所以现在数组里全部是空字符。
sizeof数组名 得到的是整个数组的大小。
字符串输入
读入一个字符串,首先要预留存储该字符串的空间。
可以使用char m[10]来分配10个字节的空间,它可以存储9个字符,加上一个空字符’\0′
char *gets( char *str );
gets()函数从标准输入获取一个字符串存入str所指向的内存中。
gets()在读取字符传的时候以换行‘\n’(按下回车键)作为字符串的结束标志。遇到回车后,将换行之前的所有字符(不包括\n)的末尾添加一个’\0’字符,存入str所指向的内存。然后丢弃这个换行。这样下次读取的时候,从新的一行开始。
例如代码
char m1[10];
char m2[10];
gets(m1);
gets(m2);
运行后输入abcdef回车123456回车,两个数组的内容是这样的
未知部分是保持原有值的。
gets()的返回值一般读取成功时就是str的值。如果读取失败,例如遇到文件尾,什么也没读进去,就会返回一个NULL
while (gets(name) != NULL)
这样写既可以读取值,又可以检测文件尾。
由于gets不检查数组大小是否足够容纳字符串,因此是不安全的。c11提供了带字符串数目的char *gets_s( char *str, rsize_t n );函数。
char *fgets( char *str, int count, FILE *stream );
fgets函数的第一个参数和gets的参数作用一致。
fgets函数的第二个参数说明了允许读入的最大字符数。
fgets函数的第三个参数是为文件输入而设计的一个文件指针。不过,我们可以使用stdin作为第三个参数,这样会从标准输入读取。
返回值和gets函数类似。成功读入返回str 失败返回NULL
fgets仍然以换行作为字符串结束的标志,不过它会把换行也作为字符串的一部分。如果一直遇不到换行,fgets最多会读取count-1个字符后就会停止。
不管什么情况,fgets总会在读取字符的最后面添加一个’\0′
例如 代码
char m1[10];
char m2[10];
fgets(m1, 5, stdin);
fgets(m2, 5, stdin);
输入 abcdefg回车 两个数组是这样的
int scanf( const char *format, … );
scanf读取字符串时使用%s。它和gets函数的主要区别在于字符串的结束标志。scanf是读取单词的形式。
%s时它会读到空白符(空格 制表符\t 换行)不包括空白符时结束并在末尾添加’\0′ 下次读取从下一个非空白符开始,会跳过中间的所有空白符
%10s指定了最多读取10个字符。由于在末尾加上’\0′ 所以最多需要11个存储空间。
字符串输出
int puts( const char *str );
puts的参数是字符串地址,它在屏幕显示字符串,直到遇到空字符\0.
它会在末尾自动添加换行。(和gets不读取换行对应)
int fputs( const char *str, FILE *stream );
fputs的第一个参数是要输出的字符串地址,第二个参数是文件指针。可以使用stdout参数 代表标准输出
fputs不会在字符串末尾添加\n (和fgets读取\n对应)
int printf( const char *format, … );
printf使用%s指定字符串格式。它不会自动换行。效率也比puts要低一点。
getchar和putchar
int getchar();
getchar从标准输入读一个字符,并返回ascii码 遇到文件尾则返回EOF
int putchar( int ch );
在标准输出输出ch 。ch会转化为unsigned类型。
成功返回ch的值 不然返回EOF