在写一个字符串分隔函数时遇到了关于string和c字符串的问题,函数如下:
//从一行中分隔出单词
vector<string> split(const string &line) {
vector<string> words;
auto word_begin = line.begin();
auto iter = line.begin();
while(iter != line.end()) {
//单词内容
if(*iter >= 'A' && *iter <= 'Z'){
iter++;
continue;
}
else if(*iter >= 'a' && *iter <= 'z'){
iter++;
continue;
}
else if(*iter >= '0' && *iter <= '9'){
iter++;
continue;
}
else if(*iter == '@' || *iter == '_' || *iter == '.'){
iter++;
continue;
}
else{//分隔符
if(iter != word_begin) {//存入单词
string tmp;
tmp.insert(tmp.begin(), word_begin, iter);
words.push_back(tmp); //insert插入不包括迭代器指向的最后一个元素
iter++; //即插入[word_begin,iter)范围内的元素
word_begin = iter; //要保存部分分隔符就注释iter++
}i //不要让其跳过分隔符
else{ //非空格存入,空格跳过,递增迭代器
//if(*iter != ' '){
// string tmp(1, *iter);
// words.push_back(tmp);
//}
iter++;
word_begin = iter;
}
}
}
return words;
}
有两种方式来存放分隔后的字符串,vector
和vector
,这两种不同的方涉及到了string和char*的相互转换。
c字符串:字符构成的序列。
单引号为单个字符,如:
'c'
。双引号为字符串,以'\0'
结尾,如:"s"
。c字符串char*和char[]两种形式,char*以'\0'
结束,char[]可以不以'\0'
结束。c字符串的长度可以通过strlen()来求(在头文件中),strlen()函数会求从开始到第一个遇到
'\0'
之间的字符个数(不包括'\0'
)。char*与char[]也并不相同,虽然char[]是指向字符串的首地址,当作指针来使用,但与指针仍有区别。可以用char[]来初始化char*,却不能用char*来初始化char[]。sizeof(char*)
与sizeof(char[])
并不相同,前者
返回指针内存大小,后者返回数组内存大小,即类型大小×数组容量。
char *p = "string";
//s[6] = "string";报错,初始化时,字符串太长,"string"末尾默认有'\0',为7个字符
char s[6] = {'s', 't', 'r', 'i', 'n', 'g'};
char a[] = "string"; //包含'\0'
//char a[] = s; //错误
char *b = a; //正确
cout << strlen(p) << endl; //输出6
cout << strlen(s) << endl; //此处没有'\0',计数到内存中第一个遇到的'\0'处
cout << sizeof(p) << endl; //输出8
cout << sizeof(s) << endl; //输出6 char为1 1×6
cout << sizeof(a) << endl; //输出7
cout << sizeof(b) << endl; //输出8
cout << sizeof(a)/sizeof(char); //输出7,数组容量
string:以字符为元素的一种容器,一种类。
与char*不同string不一定以NULL(
'\0'
)结束,可以通过s.begin()和s.end()访问元素,也可以通过下标访问。string中单个元素为char类型,可通过s.length()
获取string长度
string s = "string";
for(auto c : s){
cout << typeid(c).name() << endl; //输出为c,char类型,实际上c为char&
}
cout << s.length() << endl; //输出为6
(1). 将c字符串转换成string可以通过string的构造函数string(const char *s);
和string (int n, char c);
来完成。
char *p = "string";
char s[6] = {'s', 't', 'r', 'i', 'n', 'g'};
char a[] = "string";
char *b = a;
string str1(p);
string str2(a);
string str3(b);
string str4(s);
(2). 将string转换成char*可以调用const char *c_str() const
和const char *data()const
两个函数。前者是一个以NULL('\0'
)结束的c字符串,后者是一个以非NULL('\0'
)结束的c字符串。但只能转换成const char*
string s = "string";
const char *s1 = s.c_str();
const char *s2 = s.data();
也可以通过函数int copy(char *s, int n, int pos) const
来转换,该函数将string
以下标pos开始的n个字符拷贝到以s为起始位置的字符数组中。
string s1 = "string";
string s2 = "string_copy";
char a[s2.length() + 1] = "";
char *p = a;
s1.copy(a, s1.length(), 0);
for (int i = 0; i < s1.length(); i++)
cout << a[i]; //输出string
cout << endl;
s2.copy(p, s2.length(), 0);
int i = 0;
while(i < s2.length()) {
cout << *p; //输出string_copy
p++;
i++;
}
cout << endl;
for (int i = 0; i < s2.length(); i++)
cout << a[i]; //输出string_copy
cout << endl;
return 0;
(3). 字符串分隔函数的另一种写法:
//从一行中分隔出单词
vector<string> split(const char *line) {
char word[strlen(line) + 1] = ""; //用来存放单词的临时数组
size_t pos = 0; //下标
vector<string> words;
while(*line != 0) { //*line为char类型,比较时按ASCII码比较,而0为空字符。
//单词内容
if(*line >= 'A' && *line <= 'Z'){
word[pos] = *line;
pos++;
line++;
continue;
}
else if(*line >= 'a' && *line <= 'z'){
word[pos] = *line;
pos++;
line++;
continue;
}
else if(*line >= '0' && *line <= '9'){
word[pos] = *line;
pos++;
line++;
continue;
}
else if(*line == '@' || *line == '_' || *line == '.'){
word[pos] = *line;
pos++;
line++;
continue;
}
else{//分隔符
if(word[0] != 0){ //存在单词,存入vector容器
string tmp(word);
words.push_back(tmp);
memset(word,0,sizeof(word)); //清空word,以便下次存放
pos = 0; //重置下标
}
line ++;
}
}
return words;
}
(4). 用iostringstream做简单的字符串分隔:
int main(int argc, char *argv[]){
string line;
getline(cin,line);
string word;
istringstream input(line);
while(input >> word){
//cout << word << endl;
ostringstream os;
os << word;
cout << os.str() << endl;
}
return 0;
}
//输入hello,string this is a test
//输出:
//hello,string
//this
//is
//a
//test