B - 排序
你的任务是:对这些分割得到的整数,依从小到大的顺序排序输出。
Input
输入包含多组测试用例,每组输入数据只有一行数字(数字之间没有空格),这行数字的长度不大于1000。
输入数据保证:分割得到的非负整数不会大于100000000;输入数据不可能全由‘5’组成。
Output
对于每个测试用例,输出分割得到的整数排序的结果,相邻的两个整数之间用一个空格分开,每组输出占一行。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1010; 4 char s[maxn]; 5 int a[maxn], ans; 6 char *p; 7 int v; 8 9 int main() { 10 while(gets(s)) { 11 ans = 0; 12 p = strtok(s, "5");//(地址,"分隔符") 13 while(p){ 14 sscanf(p, "%d", &v);//把 p 写入 v 15 a[ans++] = v; 16 p = strtok(NULL, "5");//第二次调用NULL 17 } 18 sort(a, a+ans); 19 for(int i=0;i<ans;i++) { 20 if(i == 0) 21 printf("%d", a[i]); 22 else 23 printf(" %d", a[i]); 24 } 25 printf("\n"); 26 } 27 }
字符串分割函数strtok(会改变原字符串)
头文件:#include <cstring>
函数原型:char *strtok(char *str, const char *delimiters);
函数功能:分割字符串,将str分割成一个个子串
函数参数:
str: 在第一次被调用的时候str传入需要被分割字符串的首地址;在后面调用的时候传入NULL。
delimiters: 表示分割字符串中包含的所有字符。
函数返回值:
当s中的字符查找到末尾时,返回NULL;
如果查不到delimiters所标示的字符,则返回当前strtok的字符串的指针。
需要注意的是:使用该函数进行字符串分割时,会破坏并分解字符串的完整,调用前和调用后的str已经不一样了。strtok在切割字符串的时候,实际上就是将分割符的字符delimiter替换为'\0'并且返回首地址。这点在下面会有例子说明。
例一:分割单个字符
(1)将字符串通过'@'分割开:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 char str[] = "@I am@a great@young man@!"; 7 char *temp = strtok(str, "@"); 8 while (temp) 9 { 10 cout << temp << endl; 11 temp = strtok(NULL, "@"); 12 } 13 14 return 0; 15 }
运行结果:
I am
a great
young man
!
(2)下面我们来观察一下调用strtok()函数之后的str会是什么样的:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 char str[] = "@I am@a great@young man@!"; 7 char *temp = strtok(str, "@"); 8 while (temp) 9 { 10 cout << temp << endl; 11 temp = strtok(NULL, "@"); 12 } 13 14 for (int i = 0; i < sizeof(str); i++) 15 cout << str[i]; 16 return 0; 17 }
我们发现调用完strtok函数后再输出的完整的str是:
@I am a great young man !
例一总结:strtok在分割字符串的过程,实际上就是将被分割的字符串的分割字符替换为'\0' 并且返回标记字符串的首地址,直到返回NULL结束。调用完strtok后,如果只是直接输出str,而不是像上面一样将所有的字符都输出,则输出的是@I am。但需要注意的是,此处有点特殊,因为有一个分割符在字符串首位,所以第一个@没被替换,后面的@全部被替换;但如果第一位不是分割字符,则后面的分割符也是全部被替换为'\0',而不是第一个分割符不被替换。
例二:分割多个字符
将字符串通过'@'和'!'分割开:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 char str[] = "I!am@a!great@young!man.!"; 7 char *temp = strtok(str, "@!"); 8 while (temp) 9 { 10 cout << temp << endl; 11 temp = strtok(NULL, "@!"); 12 } 13 14 return 0; 15 }
可以看出,只需要将分割字符全部放到一个字符串里即可,如"@!"。
1.定义
分解字符串为一组字符串。s为要分解的字符,delim为分隔符字符(如果传入字符串,则传入的字符串中每个字符均为分割符)。首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL。在头文件#include<string.h>中。
2.原型
char *strtok(char s[], const char *delim);
3.说明
(1)当strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回指向被分割出片段的指针。
(2)返回值
从s开头开始的一个个被分割的串。当s中的字符查找到末尾时,返回NULL。如果查找不到delim中的字符时,返回当前strtok的字符串的指针。所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。
(3)需要注意的是,使用该函数进行字符串分割时,会破坏被分解字符串的完整,调用前和调用后的s已经不一样了。第一次分割之后,原字符串str是分割完成之后的第一个字符串,剩余的字符串存储在一个静态变量中,因此多线程同时访问该静态变量时,则会出现错误。
4.使用
strtok函数会破坏被分解字符串的完整,调用前和调用后的s已经不一样了。如果要保持原字符串的完整,可以使用strchr和sscanf的组合等。
5、strtok_s函数
strtok_s是windows下的一个分割字符串安全函数,其函数原型如下:
char *strtok_s( char *strToken, const char *strDelimit, char **buf);
这个函数将剩余的字符串存储在buf变量中,而不是静态变量中,从而保证了安全性。
6、strtok_r函数
strtok_r函数是linux下分割字符串的安全函数,函数声明如下:
char *strtok_r(char *str, const char *delim, char **saveptr);
该函数也会破坏带分解字符串的完整性,但是其将剩余的字符串保存在saveptr变量中,保证了安全性。
要使用strtok函数需要包含头文件string.h
#include <string.h>
strtok函数的作用是把字符串以规定的字符分割开:
p = strtok(buf, "$");
p为指针,buf也是指针,这句代码的意思就是把buf中的字符串以"$"为分隔符分割开来,分割出来的字符串保存到指针p中。
再次调用strtok函数时,把buf换成NULL,不需要再写buf。即:
p = strtok(NULL, "$");
需要注意的是,strtok函数会把分割前的字符串破坏掉,即每次分割后,原来的字符串就会少掉一部分,完整性会被破坏。
while循环离有一个判断p是否等于NULL的语句是因为strtok函数分割到最后没东西分的时候会返回一个空指针,所以需要加个判断跳出循环,否则就会出现段错误。这里也让我知道了,对于指针的使用前面必须加判断,判断是否为空指针,如为空指针需要报错,否则出现段错误都不知道是哪里出错。strtok函数的分隔字符还可以是多个,不一定只为一个
p = strtok(buf, "$,");
这句代码的意思是以"$"和","为分隔符分割buf中的字符串。每当遇到这两个字符其中一个都会分割,不是遇到"$,"两个字符连在一起才分割,记住只需要遇到其中一个字符就可以了,这样对于函数的使用人性化很多。
1 p = strtok(buf, "$"); 2 3 while( p!=NULL ) 4 { 5 6 p = strtok(NULL, "$"); 7 8 if( p==NULL ) 9 { 10 break; 11 12 } 13 14 }
strtok函数是一个非常好用的字符串处理函数,会用这个函数对编程会有非常大的帮助。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <sstream> 5 #include <vector> 6 #include <algorithm> 7 8 using namespace std; 9 10 int main() 11 { 12 string str; 13 while(cin>>str) 14 { 15 int tem; 16 int num=0; 17 vector<int> vi; 18 for(int i=0;i<str.size();i++) 19 { 20 if(str[i]=='5') 21 str[i]=' '; 22 } 23 istringstream is(str); 24 while(is>>tem) 25 { 26 num++; 27 vi.push_back(tem); 28 } 29 sort(vi.begin(),vi.begin()+num); 30 for(int i=0;i<num;i++) 31 { 32 if(i==0) 33 printf("%d",vi[i]); 34 else printf(" %d",vi[i]); 35 } 36 printf("\n"); 37 } 38 return 0; 39 }