上一篇简单介绍了字符串,这篇说一说字符串的常见函数.
1.字符串输出
内容在书11.3章.
当然了,这里的输入输出不只是从键盘读取,还可能是从文件中读取.
1.1 puts()
puts()函数使用简单,只需把字符串的地址作为参数即可.
# define STR "define string"
int main(void) {
const char * str1 = "const main string";//没有添加换行符
char str2[] = "char array main string";
puts(STR);
puts(str1);
puts(str2);
puts(&str1[9]);
puts(str2 + 7);
return 0;
}
运行结果
define string
const main string
char array main string
n string
ray main string
puts()函数会自动添加换行符.在读取到空白字符的时候就会停止输出.如果对指针进行加法运算,则从计算完毕的位置开始输出.
1.2 fputs()
相比于puts(),fputs()多了一个参数,用来指明如何输出(如输出在显示器上或硬盘中).
若要输出在显示器(标准输出),则第二个参数为"stdout".此时跟puts()的效果是一样的,不同的是fputs()不会自动添加换行符.
# define STR "define string"
int main(void) {
fputs(STR, stdout);
fputs(STR, stdout);
return 0;
}
运行结果
define stringdefine string
可以看到两次输出之间并没有换行,也没有空格等空白字符.
1.3 printf()
printf()我们经常使用,相对于前两个,可能稍显麻烦,但是可以通过转换说明更加自由的输出字符串.前面已经说过,所以这里就一笔带过.
2. 字符串输入
内容在书11.2章.
其实还有一个gets()函数,它与puts()刚好相反,但是由于安全性问题所以在C11标准中直接被废除.通常与puts()配合使用.
2.1 fgets()
与fputs()相比,fgets()多了一个参数.同样经常与fputs()配合使用.
fgets(字符串, 读取字符的最大数量, 要读入的源)
使用时有几点需要注意
1.如果指明读取的最大数量为n,则fgets()会读取"n-1"个字符,或者读取到第一个换行符.
2.读取到第一个换行符时,会将其存储在字符串中.
3.若要读取键盘输入(标准输入),则需将第三个参数设置为"stdin".
int main(void) {
char input[10];
printf("请输入长度小于10的字符.\n");
fgets(input, 10, stdin);
printf("puts输出:");
puts(input);
printf("fputs输出:");
fputs(input, stdout);
printf("请输入长度大于10的字符.\n");
fgets(input, 10, stdin);
printf("puts输出:");
puts(input);
printf("fputs输出:");
fputs(input, stdout);
puts("结束");
return 0;
}
运行结果
请输入长度小于10的字符.
123456
puts输出:123456
fputs输出:123456
请输入长度大于10的字符.
12345678987654321
puts输出:123456789
fputs输出:123456789结束
可以看出,如果读取到的字符小于第二个参数,puts()由于自带一个换行符,而fgets()又会添加一个换行符,所以换行了两次.
fputs()不会自动添加换行符,所以只有fgets()的换行符.
而大于第二个参数之后,只会读取传入参数的值的字符,比如传入10就只读取10个字符.puts由于自带换行符所以依旧换行,但是由于fgets()不能在最后添加换行符,所以只有一次换行.
fputs()就干脆没有换行,可以看到最后一个puts()的内容是紧接着fputs()输出的.
2.2 scanf()
scanf()也是前面经常使用的一个函数.
scanf()通过两种方式确定输入是否结束.
1.遇到空白字符(空格,空行,制表符或换行符)则结束.
2.如果指定了字符串宽度,比如"%8s",则在第8个字符或第8个字符之前的空白字符结束
函数的返回值为成功读取到的项数或EOF.
# include <stdio.h>
# include <string.h>
int main(void) {
char str1[64];
char str2[64];
int r1;
int r2;
printf("随便输入字符串:\n");
r1 = scanf("%s", str1);
printf("限制宽度为5:\n");
r2 = scanf("%5s", str2);
printf("str1 = %s\n", str1);
printf("str2 = %s\n", str2);
printf("r1 = %d\nr2 = %d\n", r1, r2);
return 0;
}
运行结果
随便输入字符串:
affwfsfdeggrgew
限制宽度为5:
123456789
str1 = affwfsfdeggrgew
str2 = 12345
r1 = 1
r2 = 1
3.其他函数
内容在书11.5章.
需要引入"string.h"头文件.
3.1 strlen()
可以输出字符串长度
# include <stdio.h>
# include <string.h> //注意需要引入strlen.h头文件.
# define STR "define string"
int main(void) {
printf("strlen函数测试:字符串[%s]的长度为[%d]\n", STR, strlen(STR));
return 0;
}
运行结果
strlen函数测试:字符串[define string]的长度为[13]
3.2 strcat()
这个函数可以将两个字符串拼接起来,参数是两个"char*".返回值为第一个参数,即"拼接第2个字符串后第1个字符串的地址"(343页).
# include <stdio.h>
# include <string.h>
int main(void) {
char input[32];
char prefix[] = "你输入的字符串是:";
printf("请输入一个字符串:\n");
fgets(input, 32, stdin);
fputs(prefix, stdout);
return 0;
}
运行结果
请输入一个字符串:
dafsdfs
你输入的字符串是:dafsdfs
3.3 strncat()
strcat()有一个问题,比如第一个参数的数组不能容纳第二个参数的字符串.如果发生会导致溢出,溢出的字符可能溢出到相邻存储单元.
strncat()可以解决这个问题,它有第三个参数,用来限定最大添加大字符数.与fgets()一样,最后需要有一个空字符.
# include <stdio.h>
# include <string.h>
int main(void) {
char input[32];
char prefix[] = "你输入的字符串是:";
printf("请输入一个字符串:\n");
fgets(input, 32, stdin);
strncat(prefix, input, 5); //第三个参数为5
fputs(prefix, stdout);
puts("结束");
return 0;
}
运行结果
请输入一个字符串:
qafsdfsf
你输入的字符串是:qafsd结束
3.4 strcmp()
可以用来比较两个字符串是否相同.这个函数比较的是内容而不是地址.相同返回0,不相同返回非0值.
# include <stdio.h>
# include <string.h>
int main(void) {
char str1[32] = "123456";
char str2[] = "123456";
char str3[32] = "123456 "; //有一个空格
printf("sizeof str1 = %d\n", sizeof str1);
printf("sizeof str2 = %d\n", sizeof str2);
int result1 = strcmp(str1, str2);
int result2 = strcmp(str1, str3);
int result3 = strcmp(str2, str3);
printf("str1与str2:%d\n", result1);
printf("str1与str3:%d\n", result2);
printf("str2与str3:%d\n", result3);
return 0;
}
运行结果
sizeof str1 = 32
sizeof str2 = 7
str1与str2:0
str1与str3:-1
str2与str3:-1
可以看这个函数比较的是字符串内容,而不是存储字符串的数组. 至于结果的正负,是两个字符串长度相减的结果:第1个长度小于第2个为-1,第1个长度大于第2个为1.
3.5 strcpy()和strncpy()
首先需要明白一件事,假如"str1"和"str2"都是指向字符串的指针.这行代码
str1 = str2;
拷贝的是字符串地址而非字符串本身.所以若要拷贝字符串,可以使用提供的strcpy()函数.返回值为第1个字符的地址.
# include <stdio.h>
# include <string.h>
int main(void) {
char* p1 = "qwert";
char* p2 = p1;
printf("字符串指针赋值\np1 = %s p1的值 = %p\n", p1, p1);
printf("p2 = %s p2的值 = %p\n", p2, p2);
char str1[10] = "qweasdzxc";
char str2[10];
char * ret = strcpy(str2, str1); //目标字符串, 源字符串
printf("str1的内容: %s\n", str1);
printf("拷贝后的str2: %s\n", str2);
printf("strcpy()的返回值为第1个字符的地址:%d\n", ret);
return 0;
}
运行结果
字符串指针赋值
p1 = qwert p1的值 = 0000000000404000
p2 = qwert p2的值 = 0000000000404000
str1的内容: qweasdzxc
拷贝后的str2: qweasdzxc
strcpy()的返回值为第1个字符的地址:2293264
当然这个函数同样存在不能检查目标空间是否能容纳源字符串的内容,所以还存在一个strncpy()函数,可以指定拷贝的最大字符数.
# include <stdio.h>
# include <string.h>
int main(void) {
char str1[10] = "qweasdzxc";
char str2[10];
strncpy(str2, str1, 6);
printf("str1的内容: %s\n", str1);
printf("拷贝后的str2: %s\n", str2);
return 0;
}
运行结果
str1的内容: qweasdzxc
拷贝后的str2: qweasd
3.6 sprintf()
这个函数声明在stdio.h中而不是string.h.
功能与printf()差不多,不同点在于这个函数多了一个参数,是将字符串写入一个字符串变量,而printf()是直接输出在屏幕上.
sprintf(字符串, 要传给字符串的内容(可能有转换说明), 转换说明参数.....);
# include <stdio.h>
# include <string.h>
int main(void) {
char str[128];
sprintf(str, "测试sprintf函数\n转换说明1:%d\n转换说明2:%s", 123, "字符串");
printf(str);
return 0;
}
运行结果
测试sprintf函数
转换说明1:123
转换说明2:字符串