【C/C++】string操作方法汇总
2015-03-04 20:22
141 查看
本文提供【C/C++】string操作方法汇总如下:原文地址:http://sodino.com/2015/02/04/c-string-operate/判断内容是否相同
字符串复制
字符串拼接
字符串拼接单个char
字符串类别检查
字符串子串截取 (substring)
字符串界位符切割 (strtok strtok_r)
int strncmp(const char s1, const char s2, size_t n); Thread-Safe
对s1与s2进行的比较。大小写敏感。
return ==0, s1 == s2;
return >0, s1 > s2;
return <0, s1 < s2;
int memcmp(const void s1, const void s2, size_t n); Thread-safe
注意,这里的参数是void而不是普通的char *,所以memcmp可以对更广泛的对象进行对比,如字符数组,整型,类,结构体等。比较的内容为第三个参数所限定的长度范围内。
int strcoll(const char s1, const char s2);
比较字符串s1和s2。功能和strcmp类似,用法也一样.
特别注意:strcoll()会依环境变量LC_COLLATE所指定的文字排列次序来比较s1和s2字符串。
strcmp是根据ASCII来比较2个字符串的.若LC_COLLATE为”POSIX”或”C”,则strcoll()与strcmp()作用完全相同。
int strncasecmp(const char s1, const char s2, size_t n);
对s1与s2进行大小写无关的比较。
return ==0, s1 == s2;
return >0, s1 > s2;
return <0, s1 < s2;
int bcmp(const void s1, const void s2, size_t n) Thread-Safe
已废弃的方法,不推荐使用。推荐使用memcmp代替。
char strncpy(char dest, const char src, size_t n); Thread-Safe
将src指向的字符串(全部或指定的n个字符)复制到dest中,其中dest与src指向的内存空间不能重叠。要保证dest有足够的空间能够容纳src中的内容,否则may make the impossible possible.
对于strncpy()只负责拷贝指定长度的字符,拷贝完并不会在字符的结尾加上字符串终止符。所以见下面的示例代码中会打印出”c.st strcpy()”.对于n其长度最大值就为dest_length -1,因为最后一个位置还要放一个字符串终止符。
strncpy()如果src比较小,而指定的n比较大时,则strncpy会把多出来的长度用/0填充,这就引出一个效率上不高的问题:如下面的代码中strncpy会填写99个char,而不止是”ab”本身。
void memcpy(void dest, const void *src, size_t n);
用法同strncpy(),但注意到这是纯内存拷贝操作,可以对更广泛的对象进行对比,如字符数组,整型,类,结构体等。
size_t strlcpy(char restrict dst, const char restrict src, size_t size);
strlcpy()是为替代strncpy()而实现的更简易、更安全、更不容易出错的字符串拷贝方式。
使用时仅需如下例子在size参数中传入sizeof(dst)即可不用考虑执行结果中是否包含字符串终止符的问题(自动给加上了)。
strlcpy()仅仅会从src中拷贝最多size -1个字符,并在dest最后添加上字符串终止符。
strlcpy()的返回值是src的长度,所以一旦结果为len > sizeof(buf),则表示拷贝的结果把src截断了。
char strncat(char dest, const char src, size_t n); Thread-Safe
string concatenate
字符串拼接同上面的复制,都要求dest有足够的空间,且dest和src所指向的空间不能重叠。
dest的空间长度最小值为 strlen(dest) + n + 1。其中n表示strlen(src)或指定要拼接的长度值n,最后一个1表示字符串终止符。
size_t strlcat(char restrict dst, const char restrict src, size_t size);
同strlcpy(),是保证进行字符串拼接时以字符串终止符结尾。第三个参数size应传入dst的长度。
在如下代码中,很明显dest的空间是不足以拼接”123456789”的,所以最后的拼接结果是“12345”+1个字符串终止符。
strlen()直接计算参数
但如果把代码稍作修改成如下,则strlen(dest)返回的结果可就不一定了。
可以看到,strlen()返回的长度已经超出了dest可容纳的最大值。所以该函数返回的结果存在一定的溢出风险。
如何解决该问题?可以使用下面的函数。size_t strnlen(const char *s, size_t maxlen);
strnlen()的第2个参数指定
返回1表示字符
int isalpha(int c);
返回1表示字符
相当于(isupper(c) || islower(c))。在某些locale设置下,有可能一些非字母字符也返回1。
int isascii(int c);
返回1表示字符
int isblank(int c);
返回1表示字符
int iscntrl(int c);
返回1表示字符
int isdigit(int c);
返回1表示字符
int isgraph(int c);
返回1表示字符
int islower(int c);
返回1表示是英文字母中的小写字符;否则返回0。
int isprint(int c);
同isgraph(c),区别在于
int ispunct(int c);
返回1表示排除了空格及英文字母数字的可打印字符集;否则返回0。
int isspace(int c);
返回1时表示
int isupper(int c);
返回1时表示
int isxdigit(int c);
返回1时表示
如果是想截取指定字符串从起始位置开始的前n个字符,可以使用
但如果是想字符串截取从第n个到第n+x个字符的子字符串,得自己实现了。示例代码如下:
char strtok_r(char str, const char delim, char *saveptr);
以上两个函数可以将指定的字符串切割成0个或数个非空子串.
以上两个函数在第一次调用时,第一个参数
第2个参数
函数执行后的返回结果是切割后的子字符串,如果返回为NULL,则表示已经没有目标切割对象了,可以停止循环。
以下代码示例strtok()的使用,切割标准为
对src置空后,循环的调用仍可输出切割的子字符串结果,个人觉得应该是在strtok()方法体内使用了函数内静态参数的原因。strtok_r():strtok reentrant
strtok_r()是可重入版本的strtok()方法。第三个参数
如下示例代码中演示了strtok_r()的可重入计算,即在循环体内再嵌套一个循环用第二种界位符对字符进行二次切割。
在命令行工具下执行命令,对长字符进行两次切割,先”-:”后”/“。
运行结果:
字符串复制
字符串拼接
字符串拼接单个char
字符串类别检查
字符串子串截取 (substring)
字符串界位符切割 (strtok strtok_r)
判断内容是否相同
#include <string.h>int strcmp(const char s1, const char s2); Thread-Safe
int strncmp(const char s1, const char s2, size_t n); Thread-Safe
对s1与s2进行的比较。大小写敏感。
return ==0, s1 == s2;
return >0, s1 > s2;
return <0, s1 < s2;
int memcmp(const void s1, const void s2, size_t n); Thread-safe
注意,这里的参数是void而不是普通的char *,所以memcmp可以对更广泛的对象进行对比,如字符数组,整型,类,结构体等。比较的内容为第三个参数所限定的长度范围内。
int strcoll(const char s1, const char s2);
比较字符串s1和s2。功能和strcmp类似,用法也一样.
特别注意:strcoll()会依环境变量LC_COLLATE所指定的文字排列次序来比较s1和s2字符串。
strcmp是根据ASCII来比较2个字符串的.若LC_COLLATE为”POSIX”或”C”,则strcoll()与strcmp()作用完全相同。
#include <strings.h>int strcasecmp(const char s1, const char s2);
int strncasecmp(const char s1, const char s2, size_t n);
对s1与s2进行大小写无关的比较。
return ==0, s1 == s2;
return >0, s1 > s2;
return <0, s1 < s2;
int bcmp(const void s1, const void s2, size_t n) Thread-Safe
已废弃的方法,不推荐使用。推荐使用memcmp代替。
字符串复制
#include <string.h>char strcpy(char dest, const char src); Thread-Safe
char strncpy(char dest, const char src, size_t n); Thread-Safe
将src指向的字符串(全部或指定的n个字符)复制到dest中,其中dest与src指向的内存空间不能重叠。要保证dest有足够的空间能够容纳src中的内容,否则may make the impossible possible.
对于strncpy()只负责拷贝指定长度的字符,拷贝完并不会在字符的结尾加上字符串终止符。所以见下面的示例代码中会打印出”c.st strcpy()”.对于n其长度最大值就为dest_length -1,因为最后一个位置还要放一个字符串终止符。
123456 | char * strA = "Test strcpy()"; // 对于下面的strDest中长度最小要13 + 1=14。char strDest[100]; // 声明一个数组,空间对于将要复制的字符串来说要足够大。char *strcpy = strcpy(strDest, strA); // 执行复制。printf("%s \n", strcpy); // 打印出:Test strcpy()strcpy = strncpy(strDest, "c.code", 2); // 执行指定长度的字符串内容。printf("%s \n", strcpy); // 打印出:c.st strcpy() |
12 | char strDest[100];strncpy(strDest, "ab", 99); |
用法同strncpy(),但注意到这是纯内存拷贝操作,可以对更广泛的对象进行对比,如字符数组,整型,类,结构体等。
size_t strlcpy(char restrict dst, const char restrict src, size_t size);
strlcpy()是为替代strncpy()而实现的更简易、更安全、更不容易出错的字符串拷贝方式。
使用时仅需如下例子在size参数中传入sizeof(dst)即可不用考虑执行结果中是否包含字符串终止符的问题(自动给加上了)。
strlcpy()仅仅会从src中拷贝最多size -1个字符,并在dest最后添加上字符串终止符。
strlcpy()的返回值是src的长度,所以一旦结果为len > sizeof(buf),则表示拷贝的结果把src截断了。
12345 | char *src, *p, buf[BUFSIZ];int len = strlcpy(buf, src, sizeof(buf));if (len > sizeof(buf)){ printf("%s \n", "string src is truncated.");} |
字符串拼接
#include <string.h>char strcat(char dest, const char src); Thread-Safe
char strncat(char dest, const char src, size_t n); Thread-Safe
string concatenate
字符串拼接同上面的复制,都要求dest有足够的空间,且dest和src所指向的空间不能重叠。
dest的空间长度最小值为 strlen(dest) + n + 1。其中n表示strlen(src)或指定要拼接的长度值n,最后一个1表示字符串终止符。
1234567 | // 声明一个数组,空间对于将要复制和拼接的字符串来说要足够大。// 6是最小值, 6 = strlen(strA) + 2(strcat) + 1(\0)char strDest[6];char * strA = "abc";strcpy(strDest, strA);strncat(strDest, "123", 2);printf("%s \n", strDest); // 打印出:abc12 |
同strlcpy(),是保证进行字符串拼接时以字符串终止符结尾。第三个参数size应传入dst的长度。
在如下代码中,很明显dest的空间是不足以拼接”123456789”的,所以最后的拼接结果是“12345”+1个字符串终止符。
1234567 | char strDest[6];char * strA = "123456789";int result = strlcat(strDest, strA, sizeof(strDest));printf("%s\n", strDest); // 打印出“12345”if (result){ printf("%s be truncated.\n", strA);} |
字符串拼接单个char
c中没有现成的函数可以拼接单个char,这里需要用到指针进行赋值,如下:123456789101112 | char dest[5];char *str = "abc";// 对dest赋值strcpy(dest, str);char * pDest;pDest = dest + strlen(dest);// 拼接单个字符串*pDest++ = '1';*pDest++ = 0; // 字符串终止符// 打印出:abc1 5 4 printf("%s %lu %lu \n", dest, sizeof(dest), strlen(dest)); |
字符串长度
之所以把字符串长度放在
字符串拼接之后,是为了更方便讲述理解。
#include <string.h>size_t strlen(const char *s);
strlen()直接计算参数
s中字符的个数,直至碰到字符串终止符
\0时停止计算。所以在
字符串拼接单个char中,strlen(dest)返回结果是4。
但如果把代码稍作修改成如下,则strlen(dest)返回的结果可就不一定了。
123456789101112 | char dest[5];char *str = "abc";// 对dest赋值strcpy(dest, str);char * pDest;pDest = dest + strlen(dest);// 拼接单个字符串*pDest++ = '1';*pDest++ = '2'; // 改动点:不以字符串终止符结尾// 打印出:abc12\300\370\277_\377 5 11 内容是不固定的printf("%s %lu %lu \n", dest, sizeof(dest), strlen(dest)); |
如何解决该问题?可以使用下面的函数。size_t strnlen(const char *s, size_t maxlen);
strnlen()的第2个参数指定
s的最大值,正常情况下和strlen()能力是一致的。区别在于strnlen()返回的最大值最多只能是
maxlen。所以如果返回值为参数
maxlen时,即可以判断出
s是非正常的字符串终止符结尾,需要特别处理。见下示例代码。
123456 | int n_len = strnlen(dest, sizeof(dest));if (n_len >= sizeof(dest)){ printf("dest is not NUL-TERMINALED \n");} else { printf("dest.len=%d \n", n_len);} |
字符类别检查
#include <ctype.h>int isalnum(int c);
返回1表示字符
c是 大小写字母 或 数字;否则返回0。
int isalpha(int c);
返回1表示字符
c是 大小写字母 ;否则返回0。
相当于(isupper(c) || islower(c))。在某些locale设置下,有可能一些非字母字符也返回1。
int isascii(int c);
返回1表示字符
c属于 ASCII字符集 ;否则返回0。
int isblank(int c);
返回1表示字符
c是 空格 或 Tab符
\t;否则返回0。注意有些系统或编辑器下的Tab符是由多个空格组成的,这种情况下返回0。
int iscntrl(int c);
返回1表示字符
c是控制制服(c:[0:31…]等等)
int isdigit(int c);
返回1表示字符
c属于0~9的数字;否则返回0。
int isgraph(int c);
返回1表示字符
c属于印刷可见的字符(不包含空格);否则返回0。大部分情况下返回结果和iscntrl(c)是相反的。
int islower(int c);
返回1表示是英文字母中的小写字符;否则返回0。
int isprint(int c);
同isgraph(c),区别在于
c是空格时也返回1。
int ispunct(int c);
返回1表示排除了空格及英文字母数字的可打印字符集;否则返回0。
int isspace(int c);
返回1时表示
c属于 空格、\f、换行符‘\n’、回车’\r’、水平Tab
\t、垂直Tab
\v;否则返回0。
int isupper(int c);
返回1时表示
c羽毛球英文字母中的大写字母。
int isxdigit(int c);
返回1时表示
c属于数字十六进制表示形式中的字符(0~9、a~f、A~F);否则返回0。
字符串子串截取
c的类库中目前没有找到现成的字符串子串截取方法。如果是想截取指定字符串从起始位置开始的前n个字符,可以使用
strncpy或
memcpy代替。
但如果是想字符串截取从第n个到第n+x个字符的子字符串,得自己实现了。示例代码如下:
1234567891011121314151617181920212223242526272829303132333435363738394041 | staticchar* substring(const char* src, const int idxStart, const int idxEnd) { if (strlen(src) == 0) { printf("arg src.length is 0, return."); return (void*)0; } if (idxEnd > strlen(src)) { printf("idxEnd=%d > strlen(src)=%lu, return.", idxEnd, strlen(src)); return (void*)0; } if (idxStart >= idxEnd) { printf("idxStart=%d >= idxEnd=%d, return.", idxStart, idxEnd); return (void*)0; } // 避免直接定义固定长度 int length = idxEnd - idxStart + 1; const int sub_length = length; // 使用malloc,避免在函数体结束之后即回回收导致函数返回值无法被使用。 // 需要使用free()释放; char * pDest = (char*)malloc(sub_length); for (int i = idxStart;i < idxEnd;i ++) {// printf("src %c \n", *(src+i)); *(pDest + (i-idxStart)) = *(src+i);// printf("dest %c \n", *(pDest + (i-idxStart))); } *(pDest+(idxEnd - idxStart)) = 0; // 添加上字符串终止符// printf("pDest=%s %p\n", pDest, pDest); return pDest;}int main(int argc, const char * argv[]) { char * src = "abc123ABC"; char *dest = substring(src, 3, 6); //打印出"123" printf("substring1=[%s] \n", dest); // 不要了,回收掉 free(dest); // 不需要了之后对指针置空,防止野指针 dest = NULL; printf("%s \n", dest);} |
字符串界位符切割
#include <string.h>char strtok(char str, const char *delim);
char strtok_r(char str, const char delim, char *saveptr);
以上两个函数可以将指定的字符串切割成0个或数个非空子串.
以上两个函数在第一次调用时,第一个参数
str传入待切割的长字符串;在下次循环调用之前需要把
str置为NULL。
第2个参数
delim指定切割关键字符集(所以可以包含多种情况)。
函数执行后的返回结果是切割后的子字符串,如果返回为NULL,则表示已经没有目标切割对象了,可以停止循环。
以下代码示例strtok()的使用,切割标准为
-或
:字符:
123456789101112131415 | char * token; char original[] = "ab-cd;ef-gh"; char * src = original; char * delim = ";-"; for(int i = 0;; i ++) { token = strtok(src, delim); if (token == NULL){ break; } printf("%d:%s ", i, token); if (src != NULL) { src = NULL; // 对src置空 } }// 打印出:0:ab 1:cd 2:ef 3:gh |
strtok_r()是可重入版本的strtok()方法。第三个参数
saveptr用于指向未进行切割处理的字符串子串。是指向指针的指针。这也是可重入计算的关键。
如下示例代码中演示了strtok_r()的可重入计算,即在循环体内再嵌套一个循环用第二种界位符对字符进行二次切割。
123456789101112131415161718192021222324252627282930313233343536373839 | #include <stdio.h>#include <string.h>#include <ctype.h>#include <stdlib.h>int main(int argc, const char * argv[]) { char *str1, *str2, *token, *subtoken; char *saveptr1, *saveptr2; int j; if (argc != 4) { fprintf(stderr, "Usage: %s string delim subdelim\n", argv[0]); exit(EXIT_FAILURE); } const unsigned long argv1_len = strlen(argv[1]); char argv1[argv1_len]; strcpy(argv1, argv[1]); printf("argv1=%s \n", argv1); // for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) { // 这种写法,避免Assigning to 'char *' from 'const char *' discards qualifiers for (j = 1, str1 = argv1; ; j++, str1 = NULL) { token = strtok_r(str1, argv[2], &saveptr1); if (token == NULL) break; printf("%d: %s %s\n", j, token, saveptr1);// 当saveptr1为null时,则下个循环时strtok_r()返回结果亦为null for (str2 = token; ; str2 = NULL) { subtoken = strtok_r(str2, argv[3], &saveptr2); if (subtoken == NULL) break; printf(" --> %s \n", subtoken); } } exit(EXIT_SUCCESS);} |
运行结果:
1234567891011121314151617181920 | sodino:CString sodino$ ./a.out "a-b-cd:ef/hi/jk:///lm://no-p:q" "-:" "/"argv1=a-b-cd:ef/hi/jk:///lm://no-p:q 1: a b-cd:ef/hi/jk:///lm://no-p:q --> a 2: b cd:ef/hi/jk:///lm://no-p:q --> b 3: cd ef/hi/jk:///lm://no-p:q --> cd 4: ef/hi/jk ///lm://no-p:q --> ef --> hi --> jk 5: ///lm //no-p:q --> lm 6: //no p:q --> no 7: p q --> p 8: q (null) --> q |
相关文章推荐
- c/c++ 收集string的操作汇总
- c++中string用法汇总
- Java中JNI的使用详解第四篇:C/C++中创建Java对象和String字符串对象及对字符串的操作方法
- 关于c++的string的成员函数汇总
- c/c++ 收集string的操作汇总
- C/C++中字符串String及字符操作方法
- STL + c++ + 模板 + 重要思维 + 基础算法+ 经典算法 + 经典实例 + 编程总结+ 心得+ 入门必会 + 知识点汇总。+string +dfs +bfs等重要算法
- 关于C++中string对象向int、float、double类型的转换的方法汇总
- c++ stl 使用汇总(string,vector,map,set)
- C/C++中字符串String及字符操作方法
- C++ STL string对象操作汇总
- C++:STL标准入门汇总
- C++:string转换成int的几种方式
- c++笔试题汇总
- C++的string替换所有指定字符串(C++)
- C++中CString,string,char*之间的转换
- C++中无法调用DLL解决方法汇总
- C++中string的用法STL
- C++使用string.getline()和cin混合输入的问题(cin清空缓存)
- C++中将int转变成string和string转变成int