C++ string

标准库定义了三种类型字符串流:istringstream,ostringstream,stringstream,看名字就知道这几种类型和iostream中的几个非常类似,分别可以读、写以及读和写string类型,它们也确实是从iostream类型派生而来的。要使用它们需要包含sstream头文件。

除了从iostream继承来的操作

  1. sstream类型定义了一个有string形参的构造函数,即: stringstream stream(s);创建了存储s副本的stringstream对象,s为string类型对象
  2. 定义了名为str的成员,用来读取或设置stringstream对象所操纵的string值:stream.str();返回stream中存储的string类型对象stream.str(s); 将string类型的s复制给stream,返回void

类型转换

  1. string转char*
  1. string str=“world”;
  2. const char *p = str.c_str();//同上,要加const或者等号右边用char*
  1. char * 转string

可以直接赋值。

  1. string s;
  2. char *p = "hello";//直接赋值
  3. s = p;
  1. int转string

c++11标准增加了全局函数std::to_string:

  1. string to_string (int val);
  2. string to_string (long val);
  3. string to_string (long long val);
  4. string to_string (unsigned val);
  5. string to_string (unsigned long val);
  6. string to_string (unsigned long long val);
  7. string to_string (float val);
  8. string to_string (double val);
  9. string to_string (long double val);

采用sstream中定义的字符串流对象来实现

  1. int aa = 30;
  2. stringstream ss;
  3. ss<<aa;
  4. string s1 = ss.str();
  5. cout<<s1<<endl; // 30
  6. string s2;
  7. ss>>s2;
  8. cout<<s2<<endl; // 30
  1. string转换成int

stringstream可以吞下任何类型,根据实际需要吐出不同的类型。

  1. string s = "17";
  2. stringstream ss;
  3. ss<<s;
  4. int i;
  5. ss>>i;
  6. cout<<i<<endl; // 17

采用sstream头文件中定义的字符串流对象来实现转换

  1. istringstream is("12"); //构造输入字符串流,流的内容初始化为“12”的字符串
  2. int i;
  3. is >> i; //从is流中读入一个int整数存入i中

将n进制的字符串转化为十进制 stoi(字符串,起始位置,几进制)

  1. bool isnum(string s){
  2. //题目只保证第二个非空,第一个未说
  3. if(s.length()<1)
  4. return false;
  5. for(int i = 0;i<s.length();i++){
  6. if(!isdigit(s[i]))//不是数字,返回false
  7. return false;
  8. }
  9. //遍历完后,可以断定是数字,但需要判断是否越界,测试点5和6
  10. if(stoi(s)<1||stoi(s)>1000)
  11. return false;
  12. return true;
  13. }

find函数

c++中string类中的find函数用于寻找字符串中是否包含子串,如果包含,那么函数返回第一个找到的子串的位置,如果不包含,返回-1.

用法例子:

  1. #include<iostream>
  2. #include<string>
  3. using namespace std;
  4. int main()
  5. {
  6. string a="testcodecodecode";
  7. string b="code";
  8. string c="lee";
  9. int a_b=a.find(b);
  10. int a_c=a.find(c);
  11. cout<<a_b<<endl;
  12. cout<<a_c<<endl;
  13. return 0;
  14. }

输出:

  1. 4
  2. -1


分割字符串

find_first_not_of()函数:

  1. size_type find_first_not_of( const basic_string &str, size_type index = 0 );
  2. size_type find_first_not_of( const char *str, size_type index = 0 );
  3. size_type find_first_not_of( const char *str, size_type index, size_type num );
  4. size_type find_first_not_of( char ch, size_type index = 0 );
  • 在字符串中查找第一个与str中的字符都不匹配的字符,返回它的位置。搜索从index开始。如果没找到就返回string::nops
  • 在字符串中查找第一个与str中的字符都不匹配的字符,返回它的位置。搜索从index开始,最多查找num个字符。如果没找到就返回string::nops
  • 在字符串中查找第一个与ch不匹配的字符,返回它的位置。搜索从index开始。如果没找到就返回string::nops

C++11之前只能自己写,我目前发现的史上最优雅的一个实现是这样的:

  1. void split(const string& s, const string& delimiters = " ", vector<string>& tokens)
  2. {
  3. string::size_type first_pos = s.find_first_not_of(delimiters, 0);
  4. string::size_type last_pos = s.find_first_of(delimiters, first_pos);
  5. while (string::npos != first_pos || string::npos != last_pos) {
  6. tokens.push_back(s.substr(first_pos, last_pos - first_pos));//use emplace_back after C++11
  7. first_pos = s.find_first_not_of(delimiters, last_pos);
  8. last_pos = s.find_first_of(delimiters, first_pos);
  9. }
  10. }

从C++11开始,标准库中提供了regex,regex用来做split就是小儿科了,比如:

  1. std::string text = "Quick brown fox.";
  2. std::regex ws_re("\\s+"); // delimiter is whitespace
  3. std::vector<std::string> v(
  4. std::sregex_token_iterator(text.begin(), text.end(), ws_re, -1),
  5. std::sregex_token_iterator());
  6. for(auto&& s: v)
  7. std::cout<<s<<"\n";

统计函数

统计元素出现的次数

头文件 algorithm
std::count(Iterator first, Iterator last, T &val) 统计区间中某个元素出现的次数
std::count_if(InputIterator first, InputIterator last, UnaryPredicate pred) 自定义比较函数

  1. // count_if example
  2. #include <iostream> // std::cout
  3. #include <algorithm> // std::count_if
  4. #include <vector> // std::vector
  5. bool IsOdd (int i) { return ((i%2)==1); }
  6. int main () {
  7. std::vector<int> myvector;
  8. for (int i=1; i<10; i++) myvector.push_back(i); // myvector: 1 2 3 4 5 6 7 8 9
  9. int mycount = count_if (myvector.begin(), myvector.end(), IsOdd);
  10. std::cout << "myvector contains " << mycount << " odd values.\n";
  11. return 0;
  12. }

查找给定区间内最大/小值

头文件 algorithm
min_element() 查找给定区间内最小值
max_element() 查找给定区间内最大值

  1. #include <iostream>
  2. #include <vector>
  3. #include <windows.h>
  4. #include <algorithm>
  5. using namespace std;
  6. int main()
  7. {
  8. vector<int> vec = {-7, 1, 10, 7, 2, 1};
  9. vector<int>::iterator itMax = max_element(vec.begin(), vec.end());
  10. vector<int>::iterator itMin = min_element(vec.begin(), vec.end());
  11. cout << "最大值为:" << *itMax << " " << "所在位置:" << distance(vec.begin(), itMax) << endl;
  12. cout << "最小值为:" << *itMin << " " << "所在位置:" << distance(vec.begin(), itMin) << endl;
  13. system("pause");
  14. return 0;
  15. }

累加求和

  1. #include <numeric>
  2. template <class InputIterator, class T>
  3. T accumulate (InputIterator first, InputIterator last, T init);
  4. template <class InputIterator, class T, class BinaryOperation>
  5. T accumulate (InputIterator first, InputIterator last, T init,
  6. BinaryOperation binary_op);

accumulate带有三个形参:头两个形参指定要累加的元素范围,第三个形参则是累加的初值。

accumulate函数将它的一个内部变量设置为指定的初始值,然后在此初值上累加输入范围内所有元素的值。accumulate算法返回累加的结果,其返回类型就是其第三个实参的类型。

  1. int sum = accumulate(vec.begin() , vec.end() , 42);

对于自定义数据类型,我们就需要自己动手写一个回调函数来实现自定义数据的处理,然后让它作为accumulate()的第四个参数

  1. #include <vector>
  2. #include <string>
  3. using namespace std;
  4. struct Grade
  5. {
  6. string name;
  7. int grade;
  8. };
  9. int main()
  10. {
  11. Grade subject[3] = {
  12. { "English", 80 },
  13. { "Biology", 70 },
  14. { "History", 90 }
  15. };
  16. int sum = accumulate(subject, subject + 3, 0, [](int a, Grade b){return a + b.grade; });
  17. cout << sum << endl;
  18. system("pause");
  19. return 0;
  20. }