1.字符串翻转
输入一个英文句子,翻转句子中单词的顺序,要求单词内字符的顺序不变。标点视为单词的一部分,单词间以空格分开。
显然,先将整个字符串翻转,再翻转以空格隔开的各个小区间即可。 这里需要用空格将字符串分成多个小区间,这种需求在split等函数中也有。
上代码
#include <stdio.h>
#include <string.h>
// 翻转p到q之间的内容,包括p和q
void rev_by_char(char *p, char *q) {
if (NULL == p || NULL == q) {
return;
}
while (p < q) {
char ch = *p;
*p = *q;
*q = ch;
++p;
--q;
}
}
// 是否空格
int is_space(int ch) {
if (ch == ' ' || ch == '\t' || ch == '\v' || ch == '\n') {
return 1;
}
return 0;
}
// 按单词翻转
void rev_by_word(char *p, int (*f)(int)) {
if (NULL == p) {
return;
}
int size = strlen(p);
if (size == 0) {
return;
}
char *end = p + size - 1;
char *pre = p;
char *cur = p;
while (cur <= end) {
if (f(*cur) != 1) {
++cur;
continue;
}
rev_by_char(pre, cur - 1);
++cur;
pre = cur;
}
rev_by_char(pre, cur - 1);
}
void test(char *p) {
printf("pre : [%s]\n", p);
rev_by_word(p, is_space);
rev_by_char(p, p+strlen(p)-1);
printf("post: [%s]\n", p);
}
int main() {
{
char a[] = {"I am a student."};
test(a);
}
{
char a[] = {" I am a student."};
test(a);
}
{
char a[] = {"I am a student. "};
test(a);
}
{
char a[] = {""};
test(a);
}
{
char a[] = {"a"};
test(a);
}
{
char a[] = {" "};
test(a);
}
}
执行结果:
[root@localhost fall]# g++ test.cc -o ts && ./ts
pre : [I am a student.]
post: [student. a am I]
pre : [ I am a student.]
post: [student. a am I ]
pre : [I am a student. ]
post: [ student. a am I]
pre : []
post: []
pre : [a]
post: [a]
pre : [ ]
post: [ ]2.类似需求
rev_by_word函数稍加改造,就可以用于split:
#include <string.h>
#include <vector>
#include <string>
#include <iostream>
// 是否空格
int is_space(int ch) {
if (ch == ' ' || ch == '\t' || ch == '\v' || ch == '\n') {
return 1;
}
return 0;
}
//
void split(const std::string &s, std::vector<std::string> &vs, int (*f)(int)) {
size_t size = s.size();
if (size <= 0) {
return;
}
std::string::const_iterator it = s.begin();
std::string::const_iterator pre = it;
std::string::const_iterator itend = s.end();
while (it < itend) {
if (f(*it) != 1) {
++it;
continue;
}
vs.push_back(std::string(pre, it));
++it;
pre = it;
}
vs.push_back(std::string(pre, it));
}
void test(const std::string &s) {
std::cout << "pre : [" << s << "]" << std::endl;
std::vector <std::string> vs;
split(s, vs, is_space);
for (size_t i = 0; i < vs.size(); ++i) {
std::cout << i << " [" << vs[i] << "]" << std::endl;
}
}
int main() {
{
std::string s("I am a student.");
test(s);
}
{
std::string s(" I am a student.");
test(s);
}
{
std::string s("I am a student. ");
test(s);
}
{
std::string s("");
test(s);
}
{
std::string s("a");
test(s);
}
{
std::string s(" ");
test(s);
}
}执行结果:
[root@localhost fall]# g++ test.cc -o ts && ./ts
pre : [I am a student.]
0 [I]
1 [am]
2 [a]
3 [student.]
pre : [ I am a student.]
0 []
1 []
2 [I]
3 [am]
4 [a]
5 [student.]
pre : [I am a student. ]
0 [I]
1 [am]
2 [a]
3 [student.]
4 []
pre : []
pre : [a]
0 [a]
pre : [ ]
0 []
1 []split还可以加上两个参数,以决定: 1.多个连续空格是否合并,2.支持split出前几个元素
#include <string.h>
#include <vector>
#include <string>
#include <iostream>
/*
* split("a bc d ", " ", vs, true, -1);
*/
void split(const std::string &s,
const std::string &seps,
std::vector<std::string> &vs,
bool do_not_merge = false,
int n = -1)
{
size_t size = s.size();
if (size <= 0) {
return;
}
static const std::string __s_empty;
std::string::const_iterator it = s.begin();
std::string::const_iterator pre = it;
std::string::const_iterator itend = s.end();
while (it < itend) {
if (seps.find(*it) == std::string::npos) {
++it;
continue;
}
if (pre < it || do_not_merge) {
vs.push_back(__s_empty);
vs.back().assign(pre, it);
if (n > 0 && vs.size() >= n) {
vs.push_back(__s_empty);
vs.back().assign(it, itend);
return;
}
}
++it;
pre = it;
}
if (pre < it || do_not_merge) {
vs.push_back(__s_empty);
vs.back().assign(pre, it);
}
}
void test(const std::string &s) {
std::cout << "pre : [" << s << "]" << std::endl;
std::vector <std::string> vs;
split(s, " ", vs, true, 2);
//split(s, " ", vs);
split(s, " ", vs, true);
for (size_t i = 0; i < vs.size(); ++i) {
std::cout << i << " [" << vs[i] << "]" << std::endl;
}
}
int main() {
{
std::string s("I am a student.");
test(s);
}
{
std::string s(" I am a student.");
test(s);
}
{
std::string s("I am a student. ");
test(s);
}
{
std::string s("");
test(s);
}
{
std::string s("a");
test(s);
}
{
std::string s(" ");
test(s);
}
}总结一下这个问题,实际上是一种对数组做切分,再对每个区间做操作的框架:
以字符串为例:已知p和size
itend <- p+size
it <- p
pre <- p
while (it < itend) {
if (!func(*it)) {
// 元素不符合某条件,继续循环
++it;
continue;
}
// 元素符合某条件
do_something(pre, it); // 取出前闭后开区间 [pre, it) 中的内容,完成某个任务。 注意,如果pre <it,区间非空;否则区间为空
++it;
pre = it;
}
// 处理结尾. 结尾也视为分隔符。
do_something(pre, it);
1569

被折叠的 条评论
为什么被折叠?



