strcpy & strncpy
strcpy
strcpy(char* dest, const char *src);
复制字符串 src 到字符串 dest。
strcpy是一种C语言的标准库函数,strcpy把从src地址开始且含有’\0’结束符的字符串复制到以dest开始的地址空间,返回值的类型为char*。
- 原型声明:
char *strcpy(char* dest, const char *src); - 头文件:
#include <string.h>和#include <stdio.h> - 功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间
- 说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
- 返回指向dest的指针。
strncpy
strncpy(char *dest,char *src,size_t n);
将src中n个字符复制到dest中。
strncpy 是 C语言的库函数之一,来自 C语言标准库,定义于 string.h,char *strncpy(char *dest, const char *src, int n),把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。
- 原型:
char *strncpy(char *dest,char *src,size_t n); - 头文件:
#include<string.h> - 功能:(c/c++)复制字符串src中的内容(字符,数字、汉字….)到字符串dest中,复制多少由size_t n的值决定。如果src的前n个字符不含NULL字符,则结果不会以NULL字符结束。如果n<src的长度,只是将src的前n个字符复制到dest的前n个字符,不自动添加’\0’,也就是结果dest不包括’\0’,需要再手动添加一个’\0’。如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符长度+’\0’。
- demo code
#include<stdio.h>
#include<string.h>
int main()
{
char name[]={"Chinanet"},dest[20]={};
strncpy(dest,name,3);
dest[3]='\0';//没有会乱码
printf("%s\n",dest);
}
(1)src串长度<=dest串长度,(这里的串长度包含串尾NULL字符)
如果n>src由于长度达到src NULL,正常复制,特别注意,如果src中有NULL,strncpy复制到NULL即使没到n也提前停止。如果n = src串长度,与strcpy一致。注意n的选择当n > dest串长度,dest栈空间溢出产生崩溃异常。
(2)src串长度>dest串长度
如果n =dest串长度,则dest串没有NULL字符,会导致输出会有乱码。如果不考虑src串复制完整性,可以将dest 最后一字符置为NULL。
综上,一般情况下,使用strncpy时,建议将n置为dest串长度(除非你将多个src串都复制到dest数组,并且从dest尾部反向操作),复制完毕后,为保险起见,将dest串最后一字符置NULL,避免发生在第2)种情况下的输出乱码问题。当然喽,无论是strcpy还是strncpy,保证dest串容量(能容纳下src串)才是最重要的。
区别
strcpy只是复制字符串,但不限制复制的数量,很容易造成缓冲溢出。strncpy要安全一些。
strncpy能够选择一段字符输出,strcpy则不能。例如:
char name[]="Chinanet",dest[20]={0};
strncpy(dest,name,9);
printf("%s\n",dest);
strncpy可实现strcpy的字符串复制:
char name[]="Chinanet",dest[20]={0};
strncpy(dest,name,sizeof(name));
printf("%s\n",dest);
strcat & strncat
strcat
char *strcat(char *dest, const char *src);
连接字符串 src 到字符串 dest 的末尾。
- 原型:
extern char *strcat(char *dest, const char *src); - 头文件:在C中,函数原型存在
<string.h>头文件中。在C++中,则存在于<cstring>头文件中。 - 功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的’\0’)。
- 说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
strncat
strncat(char *dest, const char *src, size_t n); src所指字符串的前n个字符添加到dest所指字符串的结尾处,并覆盖dest所指字符串结尾的’\0’
- 原型
char * strncat(char *dest, const char *src, size_t n); - 头文件:
#include <string.h> - 说明:src和dest所指内存区域不可以重叠,并且dest必须有足够的空间来容纳src的字符串。
- demo code
#include<stdio.h> #include<string.h> int main(void) { char dest[20] = "Hello"; char src[10] = "World"; strncat(dest, src, sizeof(dest)); printf("%s\n", dest); return 0; } 【运行结果】:HelloWorld - 说明
strncat()将会从字符串src的开头拷贝n 个字符到dest字符串尾部,dest要有足够的空间来容纳要拷贝的字符串。如果n大于字符串src的长度,那么仅将src指向的字符串内容追加到dest的尾部。
strncat()会将dest字符串最后的’\0’覆盖掉,字符追加完成后,再追加’\0’。
sprintf & snprintf
sprintf
int sprintf( char *buffer, const char *format, [ argument] … );
把格式化的数据写入某个字符串缓冲区。
sprintf指的是字符串格式化命令,主要功能是把格式化的数据写入某个字符串中。sprintf 是个变参函数。使用sprintf 对于写入buffer的字符数是没有限制的,这就存在了buffer溢出的可能性。
snprintf
snprintf(char *str, size_t size, const char *format, …);
将可变个参数(…)按照format格式化成字符串,然后将其复制到str中
- 原型:
int snprintf(char *str, size_t size, const char *format, ...); - 头文件:
#include <stdio.h> - 功能:
- (1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符(‘\0’);
- (2) 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符(‘\0’),返回值为欲写入的字符串长度。
- (1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符(‘\0’);
- 函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。
-
与snprintf的返回值不同,sprintf的返回值是成功写入的字符串长度,此处需要谨慎处理!
- demo code
#include<stdio.h>
#include<stdlib.h>
int main()
{
char str[10]={0};
int nLen=snprintf(str,sizeof(str),"0123456789012345678");
printf("str=%s\n",str);
printf("nLen=%d\n",nLen);
return0;
}
运行结果:
str=012345678
nLen=19
strchr & strstr
strchr
strchr(s1, ch);
返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
- 原型:
char *strchr(const char* _Str,char _Val) - 头文件:
#include <string.h> - 功能:查找字符串_Str中首次出现字符_Val的位置
- 说明:返回首次出现_Val的位置的指针,返回的地址是被查找字符串指针开始的第一个与Val相同字符的指针,如果Str中不存在Val则返回NULL。
- 返回值:成功则返回要查找字符第一次出现的位置,失败返回NULL
函数实现
char* strchr(char *s, char c)
{
while(*s != '\0' && *s != c)
{
++s;
}
return *s==c ? s : NULL;
}
strstr
strstr(s1, s2);
函数用于判断字符串s2是否是s1的子串。如果是,则该函数返回s2在s1中首次出现的地址;否则,返回NULL。
- 原型:
extern char *strstr(char *str1, const char *str2); - 头文件:
string.h
函数实现
Copyright 1986 - 1999 IAR Systems. All rights reserved
char *strstr(constchar*s1,constchar*s2)
{
int n;
if(*s2)
{
while(*s1)
{
for(n=0;*(s1+n)==*(s2+n);n++)
{
if(!*(s2+n+1))
return(char*)s1;
}
s1++;
}
return NULL;
}
else
return (char*)s1;
}
GCC-4.8.0
char *strstr(const char *s1,const char *s2)
{
const char *p=s1;
const size_tlen=strlen(s2);
for(;(p=strchr(p,*s2))!=0;p++)
{
if(strncmp(p,s2,size_tlen)==0)
return (char*)p;
}
return(0);
}
常用经典实现方法
char *strstr(const char *str1, const char *str2)
{
char *cp = (char*)str1;
char *s1, *s2;
if (!*str2)
return((char *)str1);
while (*cp)
{
s1 = cp;
s2 = (char *)str2;
while (*s1 && *s2 && !(*s1 - *s2))
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
strcmp
strcmp(s1, s2);
如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。
- 原型:
extern int strcmp(const char *s1,const char *s2); - 头文件:
string.h - 功能:C/C++函数,比较两个字符串设这两个字符串为str1,str2,strcmp(str1, str2);
- 若str1==str2,则返回零;
- 若str1<str2,则返回负数;
- 若str1>str2,则返回正数。
strcmp()函数用于比较两个字符串,它锁存在的其中一个问题是:当两个字符串相等时函数的返还值为零。当字符串比较是条件语句的一部分是,这个问题就会导致令人费解的代码:
if(!strcmp(s,"volatile"))
return QUALIFIER;
返回值为零使条件语句的结果为假,所以我们不得不对其取反,得到我们需要的结果。
这里有个更好的方法。建立宏定义:
#define STRCMP(a, R, b) (strcmp(a, b) R 0)
if(STRCMP(s, ==, "volatile"))
展开为if(strcmp(s,"volatile") == 0)
使用这个宏定义,代码可以用更自然的风格来表示它的意思。
strlen
strlen(s1);
返回字符串 s1 的长度(不包括’\0’在内)。
- 原型:
extern unsigned int strlen(char *s); - 头文件:
<string.h> - 功能:计算给定字符串的(unsigned int型)长度,不包括’\0’在内.
- 说明:返回s的长度,不包括结束符NULL。
与sizeof的区别
strlen(char*)函数求的是字符串的实际长度,它求得方法是从开始到遇到第一个’\0’,如果你只定义没有给它赋初值,这个结果是不定的,它会从aa首地址一直找下去,直到遇到’\0’停止。而sizeof()返回的是变量声明后所占的内存数,不是实际长度,此外sizeof不是函数,仅仅是一个取字节运算符,strlen是函数。strlen的结果要在运行的时候才能计算出来,时用来计算字符串的长度,不是类型占内存的大小。
我们能常在用到 sizeof 和 strlen 的时候,通常是计算字符串数组的长度
char str[20]="0123456789";
int a=strlen(str); //a=10; >>>> strlen 计算字符串的长度,以结束符 0x00 为字符串结束。
int b=sizeof(str); //而b=20; >>>> sizeof 计算的则是分配的数组 str[20] 所占的内存空间的大小,不受里面存储的内容改变。
对指针时
char* ss = "0123456789";
sizeof(ss) 结果 4 >>>> ss是指向字符串常量的字符指针,sizeof 获得的是一个指针的之所占的空间,应该是
长整型的,所以是4
sizeof(*ss) 结果 1 >>>> *ss是第一个字符 其实就是获得了字符串的第一位'0' 所占的内存空间,是char类
型的,占了 1 位
strlen(ss)= 10 >>>> 如果要获得这个字符串的长度,则一定要使用 strlen