字符串操作系列库函数
scanf()函数 要注意的点:
#include <stdio.h> int main() { char a[100]={1,2,3,4,5,6,7,8,9,10}; scanf("%s",a); int i; for (i = 0; i<10 ; i++) { printf("%d\n",a[i]); } return 0; }
scanf()对回车符认为是结束符,结束略过。对于空格也认为是输入结束。
输入:aa 回车
aa
97 //a
97 //a
0 //结束
4
5
6
7
8
9
10
输入:aa 空格 bb
aa bb
97 //aa
97 //aa
0 //结束
4 //没有b,被舍弃
5 //没有b,被舍弃
6
7
8
9
10
通过scanf输入的时候,最后按的是一个什么键?回车键,回车键scanf会认为是输入完成,而不是字符串的内容
scanf认为回车和空格都代表输入完成
当字符数组的成员数量小于用户在键盘输入字符的数量之后,scanf并不会自动处理,而是把用户输入的所有字符都放入了数组,导致数组溢出了
gets()函数
示例:
#include <stdio.h> int main() { char c[100] = {0}; gets(c); printf("%s\n",c); return 0; }
对比scanf(),这里输入空格,gets()能传输空格,接收一行,输出一行。
[email protected]:~$ gets
Hello World!
Hello World!
scanf( )函数和gets( )函数都可用于输入字符串,但在功能上有区别。若想从键盘上输入字符串"hi hello",则应该使用"gets()"函数。
gets可以接收空格;而scanf遇到空格、回车和Tab键都会认为输入结束,所有它不能接收空格。
char string[15]; gets(string); /*遇到回车认为输入结束*/
scanf("%s",string); /*遇到空格认为输入结束*/
所以在输入的字符串中包含空格时,应该使用gets输入。
gets认为回车代表输入完成,空格只是字符串中的一部分而已
gets和scanf一样有缓冲区溢出的危险
fgets()函数
#include <stdio.h> int main() { char a[10]={0}; fgets(a,sizeof(a),stdin); printf("%s",a); return 0; }
fgets()没有了scanf()与gets()缓冲区溢出的问题。fgets()是一个安全的函数,中间有限定接收的长度,超出长度无效。fgets会认为用户输入的回车也是字符串的一部分内容,fgets是安全的,不会因为用户恶意的输入过长的字符串导致溢出。
puts()函数
#include<stdio.h> int main() { char a[]="Hello World!"; puts(a);//自动加一个\n return 0; }
运行:
[email protected]:~$ puts
Hello World!
[email protected]:~$ //已经换行了
自动加一个\n,换行。看示例:
#include<stdio.h> int main() { char a[]="Hello World!\n";//手动加一个换行符 puts(a); return 0; }
结果:
[email protected]:~$ gcc -o puts puts.c
[email protected]:~$ puts
Hello World! //两个换行
[email protected]:~$ vi puts.c
手动加了个\n输出时打印了2个换行。说明puts()会自动加上一个换行。printf()不会自动加换行。
fputs()函数
比puts()多了一个参数:stdout; fputs()函数不会自动加换行。
#include<stdio.h> int main() { char a[]="Hello World!"; //puts(a); fputs(a,stdout); return 0; }
不会自动加上换行:
[email protected]:~$ gcc -o fputs fputs.c
[email protected]:~$ fputs
Hello World![email protected]:~$ vi fputs.c //没有换行
fputs并不会像puts那样输出的时候自动结尾加\n
strlen()函数 字符串长度
要包含头文件 <string.h>
我们自己可以实现:求字符串的长度。
#include <stdio.h> int main() { char a[100]= "hello world!"; unsigned int len = 0; while(a[len]) { len++; } printf("%u\n",len); return 0; }
运行:
[email protected]:~$ gcc -o strlen strl.c
[email protected]:~$ strlen
12
因为这个功能太常用了,所以C语言就加了strlen()这个库函数。
SYNOPSIS //概要
#include <string.h> //需要头文件支持。
size_t strlen(const char *s); //返回一个size_t
示例:
#include <stdio.h> #include <string.h> int main() { char a[100]= "hello world!"; unsigned int len = 0; len = strlen(a); printf("%u\n",len); return 0; }
运行:
[email protected]:~$ gcc -o strlen strl.c
[email protected]:~$ strlen
12
strlen()函数,就是得到字符串的长度,不包含0。它得出字符串的字节数,看示例:
#include <stdio.h> #include <string.h> int main() { char a[100]= "hello中国!"; unsigned int len = 0; /*while(a[len]) { len++; } */ len = strlen(a); printf("%u\n",len); return 0; }
[email protected]:~$ gcc -o strlen strl.c
[email protected]:~$ strlen
14 //hello占5个字节 ,“中国!”3个汉字,在linux(UTF8)中占用9个字节 (3* 3),5+9=14。
strcat()函数 字符串追加
看示例:
#include <stdio.h> #include <string.h> int main() { char a[100] = "hello "; char b[100] = "world! "; strcat(a,b); printf("%s\n",a); return 0; }
运行:
hello world!
strcat(a,b),这里把a和b的内容合并到a中去,那么,a的空间就要大,大到足够装下b的内容,看示例:
#include <stdio.h> #include <string.h> int main() { char a[10] = "hello "; char b[255] = "world! abcdefg你好中国!用strcat的时候要注意,第一个字符串一定要有足够的空间容纳第二个字符串"; strcat(a,b); printf("%s\n",a); return 0; }
运行:
用strcat的时候要注意,第一个字符串一定要有足够的空间容纳第二个字符串
strncat()函数 字符串有限追加
strncat最后的整数代表最多追加几个字符
示例:
#include <stdio.h> #include <string.h> int main() { char a[100] = "hello "; char b[255] = "world! abcdefg你好中国!用strcat的时候要注意,第一个字符串一定要有足够的空间容纳第二个字符串"; //strcat(a,b); strncat(a,b,5); printf("%s\n",a); return 0; }
运行:
hello world
追加5个字符。
strcmp()函数 字符串内容比较
注意返回值:相同返回0,大于返回正数,小于返回负数,C标准中没有硬性规定,但是一般都是1 0 -1
strcmp(char *s1,char * s2);
当s1<s2时,返回值<0
当s1=s2时,返回值=0
当s1>s2时,返回值>0
看代码示例:
#include <stdio.h> #include <string.h> int main() { char a[100] = "Hello "; char b[100] = "Hello "; if( a == b ){;} //不能通过这种方式比较,因为a和b它们各代表内存地址,不会相同 if( strcmp(a,b)==0 ) //比较a和b是否相同正确的用法。 { printf("相同\n"); } else { printf("不同\n"); } return 0; }
运行 :
相同
注意:上面高亮部分给出了错误的写法。
strncmp()函数 字符串有限比较
指定比较两个字符串的前几个字符,注意返回值:相同返回0,大于返回正数,小于返回负数,C标准中没有硬性规定,但是一般都是1 0 -1
#include <stdio.h> #include <string.h> int main() { char a[100] = "Hello "; char b[100] = "Hello World!"; if(strncmp( a,b,6 )==0) { printf("相同\n"); } else { printf("不同\n"); } return 0; }
运行:
相同
注意高亮部分:判断中后面“==0”来作为条件,如果没有“==0”的话,strncmp()相同时,返回的是0,数字0就是否则,就会运行else下面的“不同”
strcpy()函数 字符串拷贝
strcpy()也存在内存溢出的问题。
*********************************************
SYNOPSIS
#include <string.h>
char *strcpy(char *dest, const char *src);
将源字符串:char *src 拷贝到目标字符串:char *dest中。
*********************************************
没有这个函数,我们自己可以写:
#include <stdio.h> #include <string.h> int main() { char a[100] = "Hello"; char b[100] = "World"; int index = 0; while(a[index]) { a[index] = b[index]; index++; } printf("%s\n",a); return 0; }
运行:
World
有了strcpy()这个函数,就不用上面的代码了:
{ char a[100] = "Hello"; char b[100] = "World"; /*int index = 0; while(a[index]) { a[index] = b[index]; index++; } */ strcpy(a,b); printf("%s\n",a); return 0; }
运行:
World
需要注意的是,内存溢出的问题:
#include <stdio.h> #include <string.h> int main() { char a[10] = "Hello"; char b[255] = "World同一个世界,相同的梦想~~~~~~~~~~~~~~~~~~~~~~~!警报:注意内存溢出!!!!!"; /*int index = 0; while(a[index]) { a[index] = b[index]; index++; } */ strcpy(a,b); printf("%s\n",a); return 0; }
为了避免内存溢出的状况,就有了strncpy()
strncpy()函数 字符串有限拷贝
char *strncpy(char *dest, const char *src, size_t n);
n代表有限拷贝
#include <stdio.h> #include <string.h> int main() { char a[11] = "Hello"; char b[255] = "World同一个世界,相同的梦想~~~~~~~~~~~~~~~~~~~~~~~!警报:注意内存溢出!!!!!"; //strcpy(a,b); strncpy(a,b,5); printf("%s\n",a); return 0; }
运行:
World
再看:
#include <stdio.h> #include <string.h> int main() { char a[11] = "Hello"; char b[255] = "World同一个世界,相同的梦想~~~~~~~~~~~~~~~~~~~~~~~!警报:注意内存溢出!!!!!"; //strcpy(a,b); strncpy(a,b,sizeof(a)); //这里把字符数组填满了,成不了字符串了(没有\0) printf("%s\n",a); return 0; }
运行:
World同一2�
没有了\0结尾。
应该写成sizeof(a)-1
#include <stdio.h> #include <string.h> int main() { char a[11] = "Hello"; char b[255] = "Worldaaaaaaaaaaaa"; //strcpy(a,b); strncpy(a,b,sizeof(a)-1); printf("%s\n",a); return 0; }
运行:
Worldaaaaa
注意字符串的结尾。
sprintf()函数
sprintf实现将数字转化为字符串的功能
printf是向标准输出设备输出一个字符串
sprintf向一个char的数组输出一个字符串
sprintf的使用方法和printf基本一致,区别是多了第一个参数,第一个参数是一个char的数组
所有printf的转移符对于sprintf是一样的
#include <stdio.h> int main() { char a[100]; int i = 100; sprintf(a,"%s%d","hello world",i); printf("%s\n",a); return 0; }
运行:
[email protected]:~$ sprintf
hello world100
相比printf(),sprintf()只是多了一个输出的字符串数组。.
sscnaf()函数
ssccanf()相比 scanf()多了第一个参数:char的数组,sscanf()会从这个char的数组中读取相关内容。
#include <stdio.h> #include <string.h> int main() { char a[100] = "103+105"; int i,j; sscanf(a,"%d+%d",&i , &j ); printf("%d + %d = %d\n",i,j,i+j ); return 0; }
运行:
103 + 105 = 208
从字符串数组里面格式化扫描
范例:
#include <stdio.h> #include <string.h> int main() { char a[100] = "105/10"; int i,j,res; char c; sscanf(a,"%d%c%d",&i , &c , &j ); switch(c) { case '+': res = i + j ; break; case '-': res = i - j ; break; case '*': res = i * j ; break; case '/': res = i /j ; break; default : res = 0; } sprintf(a,"%d%c%d = %d\n",i,c,j,res ); printf("%s",a); return 0; }
运行:
105/10 = 10
strchr()函数 查找字符
#include <string.h>
char *strchr(const char *s, int c);
在参数char *s中查找参数int c 指定字符,找到返回c在*s在所在位置,没有找到返回NULL;
#include <stdio.h> #include <string.h> int main() { char a[100] = "hello world!"; char *s; s = strchr(a,'w'); printf("%s\n",s); return 0; }
运行:
world!
如果没有要查找的字符呢?最好是有个判断,不为空,就打印:
#include <stdio.h> #include <string.h> int main() { char a[100] = "hello world!"; char *s; s = strchr(a,'w'); if(s != NULL) printf("%s\n",s); return 0; }
运行:
world!
strstr()函数 查找字符串
#include <stdio.h> #include <string.h> int main() { char a[100] = "hello world!"; char *s; s = strchr(a,'a'); if(s != NULL) printf("%s\n",s); s = strstr(a,"llo"); printf("%s\n",s); return 0; }
运行:
[email protected]:~$ gcc -o strchr strchr.c
[email protected]:~$ strchr
llo world!
strtok()函数 分割字符串
SYNOPSIS
#include <string.h>
char *strtok(char *str, const char *delim);
#include <stdio.h> #include <string.h> int main() { char a[100]= "[email protected]@[email protected]@[email protected]"; char *s; s = strtok(a,"@"); printf("%s\n",s); s = strtok(NULL,"@"); printf("%s\n",s); s = strtok(NULL,"@"); printf("%s\n",s); s = strtok(NULL,"@"); printf("%s\n",s); s = strtok(NULL,"@"); printf("%s\n",s); s = strtok(NULL,"@"); printf("%s\n",s); s = strtok(NULL,"@"); printf("%s\n",s); return 0; }
运行:
[email protected]:~$ gcc -o strtok strtok.c
[email protected]:~$ strtok
hello
1234567890
qq.com
zhanguser
password
xxxxx
段错误 (核心已转储) //已经没有了,再取就报错。
[email protected]:~$
以上呆笨的写法,只是为了证明:当取值到了最后,已经清空了取不到数据的时候,出现段错误。
那么有没有好的用法呢:
#include <stdio.h> #include <string.h> int main() { char a[100]= "[email protected]@[email protected]@[email protected]"; char *s; s = strtok(a,"@"); while(s) { printf("%s\n",s); s = strtok(NULL,"@"); } return 0; }
运行:
[email protected]:~$ gcc -o strtok strtok.c
[email protected]:~$ strtok
hello
1234567890
qq.com
zhanguser
password
xxxxx
完美~!
atoi()函数 字符串转化为int
SYNOPSIS
#include <stdlib.h> //看准用好头文件
int atoi(const char *nptr);
#include <stdio.h> #include <stdlib.h> int main() { char a[100]= "300"; char b[100]= "500"; int sum = a+b; //示范错误用法 sum = atoi(a) + atoi(b); printf("%d\n",sum); return 0; }
运行:
[email protected]:~$ gcc -o atoi atoi.c
atoi.c: In function ‘main’:
atoi.c:8:13: error: invalid operands to binary + (have ‘char *’ and ‘char *’)
int sum = a+b; //示范错误用法
正确的用法:
#include <stdio.h> #include <stdlib.h> int main() { char a[100]= "300"; char b[100]= "500"; int sum = atoi(a) + atoi(b); printf("%d\n",sum); return 0; }
运行:
[email protected]:~$ gcc -o atoi atoi.c
[email protected]:~$ atoi
800
在c语言里面提供了把字符串转化为整数的函数,但并没有提供把整数转化为字符串的函数
atoi是标准的库函数
itoa不是c语言标准的库函数
atof()函数 字符串转化为float
double atof(const char *nptr);
如何把字符串“abc”和int型数45合并成“abc45”呢?标准C提供atoi,但没有itoa这个函数。那怎么办?试着用strcat函数试下子:
#include <stdio.h> #include <stdlib.h> int main() { char a[100]= "300"; char b[100]= "500"; int sum = atoi(a) + atoi(b); printf("%d\n",sum); char c[100]= "3.5"; double f = atof(c); char str1[100] = "abc"; int num = 45; strcat(str1,num); return 0; }
运行报错:
[email protected]:~$ gcc -o atoi atoi.c
atoi.c: In function ‘main’:
atoi.c:16:14: warning: passing argument 2 of ‘strcat’ makes pointer from integer without a cast [-Wint-conversion]
strcat(str1,num);
^
In file included from atoi.c:3:0:
/usr/include/string.h:133:14: note: expected ‘const char * restrict’ but argument is of type ‘int’
extern char *strcat (char *__restrict __dest, const char *__restrict __src)
^
[email protected]:~$ atoi
800
段错误 (核心已转储)
正确的用法是:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char a[100]= "300"; char b[100]= "500"; int sum = atoi(a) + atoi(b); printf("%d\n",sum); char c[100]= "3.5"; double f = atof(c); char str1[100] = "abc"; int num = 45; //strcat(str1,num); sprintf(a,"%s%d",str1,num); printf("%s\n",a); return 0; }
运行:
[email protected]:~$ gcc -o atoi atoi.c
[email protected]:~$ atoi
800
abc45
atol()函数 字符串转化为long
long atol(const char *nptr);
字符串分割合成范例:
到底有多少分号是不确定的,如:char a[100] = "120+15=;145-202=;334*2=;1024/64=";
写个程序,执行后=号后面自动添加计算结果。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char a[100] = "120+15=;145-202=;334*2=;1024/64="; char b[100] = { 0 }; char *s; s = strtok(a, ";"); while(s) { int i, j,res; char c; char tmp[15]; sscanf(s,"%d%c%d",&i, &c,&j); switch (c) { case '+' : res = i + j; break; case '-': res = i - j; break; case '*': res = i * j; break; case '/': res = i / j; break; default : res = 0; } sprintf(tmp, "%s%d;", s, res); strcat(b, tmp); s = strtok(NULL, ";"); } strcpy(a, b); printf("%s", a); getchar(); return 0; }
运行: