Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说C\C++语言22|C风格字符串及其字符串函数、字符串类,希望能够帮助你!!!。
字符串处理是任何编程语言都要涉及到的内容。
在C中,字符串是以空字符'\0'为终止元素的字符数组来表示的,称为C风格的字符串,C标准库同时在库<string.h>中提供了一族字符串操作函数。
在C++中,字符串被封装为类,由类库<string>提供相应成员函数的接口和实现。
相对来说,C风格字符串效率较高,string类安全性要好。同时,因为C++出现的时间相对于C较晚,一些函数库是在C++出现之前开发的,所以使用的是C风格的字符串,而不是string类,如win32 API。
在C中,字符串是以空字符(\0)结尾的字符数组。
可以像其他数组那样声明并初始化字符串:
char carr[] = {'w','w','u','h','n','\0'};
也可以用字面量初始化字符串的简捷方式:
char carr[] = "wwuhn";
这种初始化方法不需要使用空字符,而是由编译器自动添加。
当然也可以使用指针的方式:
char *cp = "wwuhn";
字符串的字面量会保存到内存的数据段(字符串以外的字面量会以代码的形式存在),返回的是一个常量指针。数组初始化不一样,其右值的字符串保存在栈中。
所以,cp指向的是字面量,相当于常量,不能单个元素更改(其本身cp是一个变量,可以另有指向)。
cp[2] = 'r'; //错误 cp = carr; //正确
因为其是常量指针,所以一般写成:
const char *cp = "wwuhn";
carr是常量,数组名是指针常量,本身不能再另有指向,而其指向的内容却是可以更新的:
carr[2] = 'r'; //正确 carr = cp; //错误
C或C++的函数库中提供了一些用来处理字符串的函数。这些函数在库<string.h>(C++中写成<cstring>中。
空字符'\0'标记字符数组中存储的C 字符串的结束。如果字符数组以这种方式使用,该数组就称为C 字符串变量。虽然空字符'\0'要写成两个符号,但实际只代表一个字符,可以用char 类型的变量或者字符数组的索引变量来存储它。
不能用=对C 字符串变量进行赋值。用==测试C 字符串相等性也得不到你希望的结果。原因很简单,因为C 字符串和C 字符串变量本质上是数组。
为C 字符串变量赋值不像为其他类型的变量赋值那么简单。
char aString[10]; aString = "Hello"; //非法,只能在初始化时赋值
虽然可在声明时用等号为C 字符串变量赋值,但在程序的其他任何地方都不能这样做。从技术上说,在声明时使用等号,就像下面这样:
char happyString[7] = "DoBeDo";
它其实是一个初始化操作,而不是赋值操作。要为C 字符串变量赋值,必须采取其他方式。
可采取许多不同的方式为C 字符串变量赋值。最简单的是使用预定义函数strcpy,
strcpy(aString, "Hello");
这也是为什么将后面的值复制到前面的值,而不是返回一个新的存储空间的指针的原因。
这会将aString 的值设为"Hello"。遗憾的是,strcpy 函数的这个版本不检查复制的字符串是否超过字符串变量(第一个参数)的长度。
许多(但并非全部)C++版本还提供了strcpy 的一个更安全的版本。这个安全版本要拼写成strncpy(多了一个n)。strncpy 函数要获取第3 个参数,指定最多能复制多少字符。
char anotherString[10]; strncpy(anotherString, aStringVariable, 9);
使用这个strncpy 函数,最多能从C 字符串变量aStringVariable 中复制9 个字符(包括'\0'),无论aStringVariable 中的字符串有多长。
也不能在表达式中使用操作符==测试两个C 字符串是否相等。更糟的是,可以为C 字符串使用==,但作用不是测试C 字符串是否相等。所以,用==测试两个C 字符串的相等性可能得到错误结果,而且编译器不报告任何错误!要测试两个C 字符串是否相等,可以使用预定义函数strcmp。例如下面的代码:
if (strcmp(cString1, cString2)) cout << "The strings are NOT the same."; else cout << "The strings are the same.";
注意,strcmp 函数的工作方式可能和你想的不同。两个字符串不匹配,结果反而是true。strcmp 函数每次比较C 字符串参数的一个字符。任何时候只要cString1 的一个字符的数值编码小于cString2 的对应字符的数值编码,测试就会停止,并返回一个负数。
如果cString1 的字符大于cString2 的对应字符,则返回一个正数(strcmp 的有些实现返回字符编码的差值,但不应依赖于此)。
两个C 字符串完全相同,则返回0。字符比较依据的是词典顺序(lexicographic order)。它的重点是,两个字符串采用全部大写或小写的形式,词典顺序就和字母顺序一样。
基于词典顺序,在C 字符串比较结果是小于、大于或者等于的情况下,strcmp 分别返回负值、正值或零。在if 或循环语句中将strcmp 作为布尔表达式使用,在字符串不相等的前提下,返回的所有非零值都被转换成true;在字符串相等的前提下,返回的零值被转换成false。所以在测试C 字符串的相等性时,务必记住这一反转逻辑。
字符串库函数(包括内存块函数):
strcat() 连接两个字符串 strchr() 查找某字符在字符串中首次出现的位置 strcmp() 比较两个字符串 strcoll() 采用目前区域的字符排列次序来比较字符串 strcpy() 拷贝字符串 strcspn() 在某字符串中匹配指定字符串 strerror() 返回错误码对应的文本信息 strlen() 返回指定字符串的长度 strncat() 连接某一长度的两个字符串 strncmp() 比较某一长度的两个字符串 strncpy() 复制某一长度的一个字符串到另一字符串中 strpbrk() 查找某字符串在另一字符串中首次出现的位置 strrchr() 查找某字符在字符串中末次出现的位置 strspn() 返回子串的长度,子串的字符都出现包含于另一字符串中 strstr() 在一字符串中查找指定的子串首次出现的位置 strtod() 将字符串转换成浮点数 strtok() 查找指定字符之前的子串 strtol() 将字符串转换成长整型数 strtoul() 将字符串转换成无符号长整型数 strxfrm() 转换子串, 可以用于字符串比较 memchr() 在某一内存范围中查找一特定字符 memcmp() 比较内存内容 memcpy() 拷贝内存内容 memmove() 拷贝内存内容 memset() 将一段内存空间填入某值
在将各种类型的数据构造成字符串时,sprintf 的强大功能很少会让你失望。由于sprintf 跟printf 在用法上几乎一样,只是打印的目的地不同而已,前者打印到字符串中,后者则直接在命令行上输出。这也导致sprintf 比printf 有用得多。
sprintf指的是字符串格式化命令,主要功能是把格式化的数据写入某个字符串中。sprintf 是个变参函数。使用sprintf 对于写入buffer的字符数是没有限制的,这就存在了buffer溢出的可能性。解决这个问题,可以考虑使用 snprintf函数,该函数可对写入字符数做出限制。
实例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buffer[200], s[] = "computer", c = 'l';
int i = 35, j;
float fp = 1.7320534f;
// 格式化并打印各种数据到buffer
j = sprintf( buffer, " String: %s\n", s );
j += sprintf( buffer + j, " Character: %c\n", c );
j += sprintf( buffer + j, " Integer: %d\n", i );
j += sprintf( buffer + j, " Real: %f\n", fp );
printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
system("pause");
return 0;
}
输出:
string 类在名称同为的库中定义,定义放在std 命名空间中。所以,要使用string 类,代码必须包含以下语句(或其他等价的语句):
#include <string> using namespace std;
string 类的默认构造函数将string 对象初始化成空字符串,另一个构造函数获取一个C 字符串作为参数,将string 对象初始化成一个值来表示由参数给定的字符串。例如:
string s1, s2("Hello");
string对象要获得C风格表示,可使用成员函数c_str()。
string类函数成员:
append() 在字符串的末尾添加文本 assign() 为字符串赋新值 at() 按给定索引值返回字符 begin() 返回一个迭代器,指向第一个字符 c_str() 将字符串以C字符数组的形式返回 capacity() 返回重新分配空间前的字符容量 compare() 比较两个字符串 copy() 将内容复制为一个字符数组 data() 返回内容的字符数组形式 empty() 如果字符串为空,返回真 end() 返回一个迭代器,指向字符串的末尾。(最后一个字符的下一个位置) erase() 删除字符 find() 在字符串中查找字符 find_first_of() 查找第一个与value中的某值相等的字符 find_first_not_of() 查找第一个与value中的所有值都不相等的字符 find_last_of() 查找最后一个与value中的某值相等的字符 find_last_not_of() 查找最后一个与value中的所有值都不相等的字符 get_allocator() 返回配置器 insert() 插入字符 length() 返回字符串的长度 max_size() 返回字符的最大可能个数 rbegin() 返回一个逆向迭代器,指向最后一个字符 rend() 返回一个逆向迭代器,指向第一个元素的前一个位置 replace() 替换字符 reserve() 保留一定容量以容纳字符串(设置capacity值) resize() 重新设置字符串的大小 rfind() 查找最后一个与value相等的字符(逆向查找) size() 返回字符串中字符的数量 substr() 返回某个子字符串 swap() 交换两个字符串的内容
对于字符类型char,其宽度为1个字节,用多个字节来代表的字符称之为宽字符。
<wchar.h>中定义了类型wchar_t(unsigned short),用来表示WCHAR,及宽字符。
宽字符字符串表示为一个 wchar_t[] 数组并由 wchar_t* 指针指向它。可以通过用字母 L 作为字符的前缀将任何 ASCII 字符表示为宽字符形式。例如,L'\0' 是终止宽(16 位)NULL 字符。同样,可以通过用字母 L 作为 ASCII 字符串的前缀 (L"Hello") 将任何 ASCII 字符串表示为宽字符字符串形式。
通常,宽字符在内存中占用的空间比多字节字符多,但处理速度更快,因为很多系统的内核包括Windows NT内核都是从底层向上使用Unicode编码的。另外,在多字节编码中一次只能表示一个区域设置,Unicode编码可以毫无障碍地在世界上任何书面语言的字符中转换。
实例1
#include <iostream>
using namespace std;
#include <wchar.h>
void main()
{
wchar_t wstr[] = L"hi";
wcout<<wstr<<endl;
}
实例2
#include <tchar.h>
#include <stdio.h>
void main()
{
TCHAR wstr[] = "你好";
printf("%s\n",wstr);
}
实例3
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
char input[50];
cout<<"请输入包含汉字的字符串:";
cin>>input;
int size;
size=::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,NULL,0);
if(size==0)
return -1;
wchar_t *widebuff=new wchar_t[size];
::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,widebuff,size);
cout<<endl<<"输出:"<<input<<endl;
system("pause");
}
/*
请输入包含汉字的字符串:中国abc
输出:中国abc
/*
当然,也可以用字符串类string来处理:
std::string是ANSI,但std::wstring是Unicode。如果要定义Unicode,只需要在正常的ANSI字符串前加上“L”就可以了。
#include <iostream>
#include <string>
using namespace std;
void main()
{
string str = "你好";
wstring str2 = L"你好";
cout<<str.length()<<endl;//4
cout<<str2.length()<<endl;//2,string处理wstring有问题
wcout.imbue(locale("chs"));
wcout<<str2<<endl;//你好
}
-End-
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章