当前位置:   article > 正文

【C/C++】 string类与字符串的处理_c++ string 添加 整型 字符串 混合

c++ string 添加 整型 字符串 混合

目录

一. 基本性质

1. 声明与初始化

2. 基本用法

3. 与字符数组区别

二. 字符处理

1. string输入方法

2. 字符串流stringstream

三. 例题分析

1. UVA1592 datebase

2. UVA814 邮件发送模拟

3. UVA1593 代码排版


一. 基本性质

1. 声明与初始化

        头文件#include<string>

  1. string s;
  2. cin>>s;//输入,遇空格结束
  3. string c1("wx love my!");//初始化可有空格
  4. string c2=c1;
  5. string c3(5,'c');//初始化为5个c即"ccccc"
  6. string s1[10];//二维数组10行n列

2. 基本用法

(1)字符运算

        string支持+,+=连接字符串,支持=赋值,支持> >= == < <= !=的比较(按照字典序,即对应位置的ASCII码)

  1. string s;
  2. cin>>s;
  3. string c1("wx love my!");//初始化可有空格
  4. s+=c1;
  5. cout<<s;

(2)基本操作函数

  • begin() 得到指向字符串开头的Iterator
  • end ()得到指向字符串结尾的Iterator
  • size() 得到字符串的大小
  • length() 和size函数功能相同
  • empty 判断是否为空
  • swap()交换两字符串//s1.swap(s2)
  • insert(n,s) //插入字符,在下标n之前(n从0开始)插入字符串s,insert()函数不支持传入单个字符,这时的单个字符必须写成字符串形式
  • erase() //删除字符
  1.    s.erase(13);//从下标13开始往后全删除(包括下标13)
  2.    s.erase(7,5);//从下标7开始往后删5个
  • clear() //删除全部字符 
  • append 在尾部追加字符//c.append("i'm coming!"),c.append(2,'!'),c.append(str)若添加单个字符只能前面带数字表示添加几个
  • push_back 追加字符//只能增加单个字符
  • find(str) 查找//s.find()在当前字符串里查找子串str,如果找到返回str在当前字符串里的首字母起始下标数字位置,没有就返回npos(-1)
  • find_first_of(str) 查找子串str在字符串里第一次出现的首字母下标
  • find_last_of()查找子串str在字符串里最后一次出现的首字母下标
  • substr() //返回某个子字符串 substr(n1,n2)从当前字符串n1下标开始取出n2个字符
  • substr(k)从当前位置k开始一直到结尾取出子串

3. 与字符数组区别

        string是复杂的模板容器,而字符数组是char型指针,string可以使用[]下标运算符来读取元素或者附给字符数组或者改变已有元素,但是不能通过下标来给string赋值!

  1. string c1;
  2. char a[100]="i'm coming!";
  3. c1=a;//字符数组附给string
  4. c1[0]='I';//通过下标改变string
  5. cout<<a<<endl;
  6. cout<<c1;
  7. //----------------------------------------------------
  8. string c1("i'm coming!!");
  9. cout<<c1<<endl;
  10. for(int i=0;i<c1.size();i++)//通过下标读取string元素
  11. cout<<c1[i]<<endl;
  12. //----------------------------------------------------
  13. char a[100]="my";
  14. string c1("i'm coming!!");
  15. cout<<c1<<endl;
  16. c1[0]=a[0];//数组与string单个元素改值
  17. //----------------------------------------------------
  18. char a[100]="my";
  19. string c1("i'm coming!!");
  20. cout<<c1<<endl;
  21. a[0]=c1[0];//string给字符数组改值;
  22. cout<<a<<endl;
  23. //------------string支持迭代器遍历----------------------
  24. string c1("i'm coming!!");
  25. string::iterator it=c1.begin();//定义迭代器
  26. for(;it!=c1.end();it++)
  27. cout<<*it<<endl;

二. 字符处理

1. string输入方法

(1)cin

        cin遇空格回车结束,但是cin的回车与空格会留在键盘缓冲区,不过cin读取会跳过所有的空格回车(包括缓冲区里的),读取其后的东西,所以对于cin输入无影响。但是对于getchar或者cin.get() cin.getline getline get都有影响,他们都会读取cin的缓冲区遗留!

(2)cin.get()

        cin.get(字符变量名char ch)可以用来接收字符;cin.get(无参数)常用来掠去空格回车。其回车会留在缓冲区,多余字符也会留下。可以通过ch=cin.get()吸收多余字符

(3)cin.getline()

        该方法接受一个字符串,可以接收空格并输出,默认遇回车结束。cin.getline(字符串名称,接受字符个数n,结束标志),方法会读取n-1个字符,自动在n的位置加上'\0',因此该输入只能输入字符串数组!而不能输入string!

        注意结束方法是 遇到结束符号或者读够n-1个字符,但是如果输入字符多于n-1个,cin会自动设置输入失效自动关闭输入,后面的cin均不能输入就结束!且其回车结束符不留在缓冲区

(4)getline()

        getline接受一个字符串,可以接收空格并输出,遇回车结束!cin.getline()类似,但是cin.getline()属于istream流,而getline()属于string流,是不一样的两个函数,getline可用来接受string!getline(cin,str);且getline的回车不留在缓冲区里!

2. 字符串流stringstream

        其头文件为#include<sstream>;stringstream是字符串流,经常被我用来作数据切分或者类型转化。编译器拥有足够的信息来判断需要哪些转换。<sstream>库中声明的标准类就利用了这一点,自动选择所必需的转换。而且,转换结果保存在stringstream对象的内部缓冲中。你不必担心缓冲区溢出,因为这些对象会根据需要自动分配存储空间。stringstream可以方便的实现数字与字符串之间的转化。

        注意:stringstream流输出时会按照输出的类型自动赋值比如  ss<<"123456\\}"; int m; ss>>m; m=123456!!

(1)例题一

Problem Description

输入的第一行有一个数字 N 代表接下來有 N 行資料,每一行資料里有不固定個數的整數(最多 20 個,每行最大 200 個字元),請你寫一個程式將每行的总和印出來。

Sample Input

3
1 2 3
20 17 23 54 77 60
111 222 333 444 555 666 777 888 999

Sample Output

6
251
4995

  1. #include <iostream>
  2. #include<string>
  3. #include<sstream>
  4. using namespace std;
  5. int main()
  6. {
  7. int N;
  8. cin>>N;
  9. cin.get();//读取换行
  10. while(N--)
  11. {
  12. string num;
  13. getline(cin,num);
  14. stringstream ss;
  15. ss<<num;//流读入ss
  16. int n;
  17. int sum=0;
  18. while(ss>>n)//流读出,按照n的类型读出以空格为分隔符
  19. sum+=n;
  20. cout<<sum<<endl;//输出
  21. ss.clear();//清空!!
  22. }
  23. return 0;
  24. }

(2)例题二

  1. #include <iostream>
  2. #include<string>
  3. #include<sstream>
  4. using namespace std;
  5. int main()
  6. {
  7. int n;
  8. stringstream ss;
  9. string str;
  10. while(cin>>n)
  11. {
  12. ss<<n;
  13. }
  14. ss>>str;
  15. cout<<str<<endl;
  16. return 0;
  17. }

输入1 2 45 90 12 输出12459012

  1. int n;
  2. stringstream ss;
  3. string str;
  4. while(cin>>n)
  5. {
  6. ss<<n<<" ";//加入空格
  7. }
  8. ss>>str;//ss遇空格为分隔符
  9. cout<<str<<endl;

输入:1 2 3 51 26 99输出 1;其解决方法(输出空格)

  1. int n;
  2. stringstream ss;
  3. string str;
  4. while(cin>>n)
  5. {
  6. ss<<n<<" ";
  7. }
  8. cout<<ss.str()<<endl;//ss.str()将ss里保存的流全部输出!

三. 例题分析

1. UVA1592 datebase

(1)问题描述

Problem Description

给一个数据库,查找是否存在(r1,c1)=(r2,c1) && (r1,c2)=(r2,c2),即:不同的二行,对应二列字符串相同。返回找到的第一个数据。若有输出NO并且下面两行分别输出r1 r2和c1 c2.若无则输出YES。输入以逗号分隔!m<1000,n<10;

Sample Input

3 3
How to compete in ACM ICPC,Peter,peter@neerc.ifmo.ru
How to win ACM ICPC,Michael,michael@neerc.ifmo.ru
Notes from ACM ICPC champion,Michael,michael@neerc.ifmo.ru
2 3
1,Peter,peter@neerc.ifmo.ru
2,Michael,michael@neerc.ifmo.ru

Sample Output

NO
2 3
2 3
YES

(2)题解代码

        思路是因为不存在二维的字符串容器或者数组,因此要处理字符串,想到可以把字符串标号储存,让最后标号构成二维数组,然后遍历这个二维数组寻找相同即可。

        但是注意因为m<1000而n<10所以可以分别遍历列n1,n2每一组遍历一遍行(三重循环即可),每一组中遇到新的组合就保存下来,如果有相同的就可以输出break了,注意每一组清空!因为相同只可能出现在每一组里。且刚开始读入时只能一整串读入,然后每行按照逗号分割字符串,保存map,遇到出现的用同一个编号即可。还要注意pair<int,int>容器的使用(保存一对数据及其对应编号),make_pair()在map的插入使用。

  1. #include <iostream>
  2. #include<map>
  3. #include<string>
  4. #include<utility>
  5. #include<algorithm>
  6. using namespace std;
  7. int main()
  8. {
  9. map<string,int> date;//字符串-编号
  10. int m,n;
  11. while(cin>>m>>n)
  12. {
  13. int num[m][n];//二维数组记录
  14. date.clear();
  15. int k=0;//记录编号
  16. cin.get();//读取回车
  17. for(int i=0; i<m; i++)
  18. {
  19. int r=0;//列数
  20. string s;
  21. s.clear();
  22. getline(cin,s);//读入整串
  23. string str;
  24. int len=s.length();
  25. for(int j=0; j<len; j++)
  26. {
  27. if(s[j]!=',')
  28. str.push_back(s[j]);//追加字符
  29. else
  30. {
  31. if(date.count(str)==0)//没出现过
  32. {
  33. date.insert(make_pair(str,k));//保存string-k
  34. num[i][r]=k++;//同时记录入二维数组
  35. }
  36. else
  37. num[i][r]=date[str];//出现过就直接记录
  38. r++;//每一个逗号都表示列数要+1了
  39. str.clear();
  40. }
  41. }
  42. if(date.count(str)==0)//每行最后一个字符串后面没有逗号,单独处理
  43. {
  44. date.insert(make_pair(str,k));
  45. num[i][r]=k++;
  46. }
  47. else
  48. num[i][r]=date[str];
  49. str.clear();
  50. }
  51. int flag=0;
  52. for(int i=0; i<n-1; i++)
  53. {
  54. for(int j=i+1; j<n; j++)//枚举两列
  1. {
  2. map<pair<int,int>,int> mmp;记录这行两列俩字符串编号pair-行数
  3. for(int a=0; a<m; a++)
  4. {
  5. if(mmp.count(make_pair(num[a][i],num[a][j]))==0)//没出现过
  6. mmp.insert( make_pair(make_pair(num[a][i],num[a][j]),a));//插入
  7. else//出现过了
  8. {
  9. cout<<"NO\n"<<mmp[make_pair(num[a][i],num[a][j])]+1<<" "<<a+1<<"\n"<<i+1<<" "<<j+1<<endl;//输出
  10. flag=1;
  11. break;
  12. }
  13. }
  14. mmp.clear();
  15. if(flag==1)
  16. break;
  17. }
  18. if(flag==1)
  19. break;
  20. }
  21. if(flag==0)
  22. cout<<"YES"<<endl;
  23. }
  24. return 0;
  25. }

2. UVA814 邮件发送模拟

(1)问题描述

Problem Description

本题的任务为模拟发送邮件时MTA(邮件传输代理)之间的交互。所谓MTA,就是email地址格式user@mtaname的“后面部分”。当某人从user1@mta1发送给另一个人user2@mta2时,这两个MTA将会通信。如果两个收件人属于同一个MTA,发送者的MTA只需与这个MTA通信一次就可以把邮件发送给这两个人。注意排除重复和判断这个用户在输入MTA下是否存在!

(2)题解代码

        大意就是给你一些MTA,每一个MTA有限定的使用用户名称,然后输入发件人和收件人,以及发件内容,按照格式输出,同时判断收件人use1@MTA1中use1是否是在MTA1允许的用户里,否则就是不存在,若用户均不存在不就不发送内容。

        在解题时首先是注意对输入的处理:即先用set将输入拼成邮箱地址直接保存,查找有无时直接set.count即可,不用map了,map还要对比字符串效率低。然后输入邮件信息,由于题目要求按照先后MTA顺序输出,这里就用到了队列那一题的思路:先用vector来保存MTA顺序,每个MTA名称在map里对应一个容器vector<string>来保存输入的对应邮件,每一个输入判断对应MTA是否存在,若存在则直接存入对应map即可,若不存在则新建并且push_back vector,并先用set来去除重复名字。最后是输出即对于多行文本的保存以及输出格式处理。

        注意:知道map可以通过vector来映射多个数map<string,vector<string> >可以用字符串来映射一个容器;注意输入处理特别是文本分行的输入;注意map,vector,set,string综合运用。

  1. #include <iostream>
  2. #include<set>
  3. #include<string>
  4. #include<vector>
  5. #include<map>
  6. #include<algorithm>//1.输入处理特别是文本分行的输入2.map,vector,set综合运用
  7. using namespace std;
  8. void deverse_address(string &s,string &mta)//处理函数,分离MTA与名字,后面输出以及储存要用
  9. {
  10. int k=s.find('@');
  11. mta=s.substr(k+1);
  12. }
  13. int main()
  14. {
  15. string s,user1,MTA,user2,MTA2;
  16. int num;
  17. set<string> addr;
  18. while(cin>>s&&s!="*")//MTA限定保存
  19. {
  20. cin>>MTA>>num;
  21. while(num--)
  22. {
  23. cin>>user1;
  24. user1=user1+"@"+MTA;//string链接
  25. addr.insert(user1);//保存
  26. }
  27. }
  28. while(cin>>s&&s!="*")//输入邮件信息
  29. {
  30. deverse_address(s,MTA2);//发件人
  31. map<string,vector<string> >dest;//保存MTA对应所有邮件地址容器
  32. set<string> vis;//去重复
  33. vector<string> mta;//排序MTA
  34. string t,name;
  35. while(cin>>t&&t!="*")//输入收件人
  36. {
  37. if(vis.count(t))//去重
  38. continue;
  39. vis.insert(t);
  40. deverse_address(t,name);
  41. if(!dest.count(name))//不存在此MTA
  42. {
  43. mta.push_back(name);//插入
  44. }
  45. dest[name].push_back(t);存入对应map
  46. }
  47. cin.get();//吃回车
  48. string date;
  49. while(getline(cin,t)&&t!="*")//输入文本内容防止回车结束所以用while循环累加!!!
  50. date=date+" "+t+"\n";//文本处理自带五空格和换行!!!到时候直接输出即可
  51. for(int i=0;i<mta.size();i++)//按MTA顺序输出
  52. {
  53. bool flag=false;
  54. // vector<string> uses=dest[mta[i]];
  55. cout<<"Connection between "<<MTA2<<" and "<<mta[i]<<endl;
  56. cout<<" HELO "<<MTA2<<"\n"<<" 250"<<endl;
  57. cout<<" MAIL FROM:"<<"<"<<s<<">\n"<<" 250\n";
  58. for(int j=0;j<dest[mta[i]].size();j++)//每个MTA下输出用户
  59. {
  60. cout<<" RCPT TO:<"<<dest[mta[i]][j]<<">\n";//dest[mta[i]][j]
  61. if(addr.count(dest[mta[i]][j]))//判断用户是否存在!
  62. {cout<<" 250\n";flag=true;}
  63. else
  64. cout<<" 550\n";
  65. }
  66. if(flag==true)//至少存在一个才输出文本date
  67. {
  68. cout<<" DATA\n"<<" 354\n"<<date;
  69. cout<<" ."<<endl;
  70. cout<<" 250"<<endl;
  71. }
  72. cout<<" QUIT\n"<<" 221"<<endl;
  73. }
  74. }
  75. return 0;
  76. }

3. UVA1593 代码排版

(1)问题描述

Problem Description

输入若干行代码,要求各列单词的左边界对齐且尽量靠左(每列中与最长的单词长度相同)。单词之间至少要空一格。每个单词不超过80个字符,每行不超过180个字符,一共最多1000行。

Sample Input

start:  integer;    // begins here
stop: integer; //  ends here  
s:  string;   
c:   char; // temp

Sample Output

start: integer; // begins here 
stop:  integer; // ends   here 
s:     string;
c:     char;    // temp

(2)题解代码

        是一道字符串处理题。思路是因为要与每一列里最长的字符串对齐,因此必须要把每一列里最长的长度都保存下来;除此之外,文本按照行输入,按照行保存每一行的单词,再次用到stringstream;以前妄想便用流输出每个单词边输出格式,结果很乱。不如全部保存下来以后,再一起输出即可!

  1. #include <iostream>
  2. #include<vector>
  3. #include<string>
  4. #include<sstream>
  5. using namespace std;
  6. int main()
  7. {
  8. vector<string> all[1002];//保存每一行的所有单词,实现字符串二维
  9. int num[200]={0};//保存每一列的最大长度,初始化为零!不用vector的原因是vector入元素只能push_back后缀
  10. int row=0,col=0;
  11. string s;
  12. stringstream ss;
  13. while(getline(cin,s))//一整行输入
  14. {
  15. ss.clear();
  16. ss<<s;
  17. string t;
  18. while(ss>>t)//流输出
  19. {
  20. all[row].push_back(t);//添加单词
  21. num[col]=max(num[col],(int)t.size());//每一列的最大长度
  22. col++;//列更新
  23. }
  24. row++;//更新
  25. col=0;
  26. }
  27. for(int i=0; i<row; i++)//输出
  28. {
  29. for(int j=0; j<all[i].size()-1; j++)
  30. {
  31. cout<<all[i][j];
  32. for(int k=0; k<=num[j]-all[i][j].size(); k++)//输出空格,与最大长度对应!
  33. cout<<" ";
  34. }
  35. cout<<all[i][all[i].size()-1]<<endl;//最后一个单词后无空格单独输出
  36. }
  37. return 0;
  38. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/736023
推荐阅读
相关标签
  

闽ICP备14008679号