我有几个包含数字和字母的输入字符串。有时空间不足。每当字符串从数字变为字母或从字母变为数字时,我想添加一个额外的空格。
示例输入:
"30EinsteinStreet"
"548 Roe Drive5500 TestCity"
"44B SaarlouisDrive1234Testtown"
他们应该成为:
"30 EinsteinStreet"
"548 Roe Drive 5500 TestCity"
"44 B SaarlouisDrive 1234 Testtown"
我现有的功能不起作用,我认为很复杂。有人能提供简单的解决方案吗?最好使用现代C ++ 11类,但不使用Boost。我也在使用GCC所以所有正则表达式的东西对我都不起作用。
由于
这是我现有的方法:
inline string separateAlphanumChunks(const std::string& s)
{
string ret = "";
const int sl = s.length();
//int inserts = 0;
if (sl<=4)
return s;
for (int i=0 ; i< sl ; i++)
{
// cerr << "separateAlphanumChunks: '" << ret << "'" <<endl;
// check if index would go out of range
if (i+4 > sl)
{
ret += s.substr (i,sl-i);
//TODO add the remain to ret
break;
}
// seperate chars
const char c0 = s[i+0];
const char c1 = s[i+1];
// check if 0 and 1 are the same class
const bool c0c = isCharAnInt (c0);
const bool c1c = isCharAnInt (c1);
bool class0 = false;
if (c0c == c1c)
{
class0 = c0c;
}
else
{
ret += c0;
// cerr << "cont1: '" << c0 << "'" <<endl;
continue;
}
// seperate chars
const char c2 = s[i+2];
const char c3 = s[i+3];
// check if 2 and 3 are the same class
const bool c2c = isCharAnInt (c2);
const bool c3c = isCharAnInt (c3);
bool class2 = false;
if (c2c == c3c)
{
class2 = c2c;
}
else
{
ret += c0;
// cerr << "cont2: '" << c0 << "'" <<endl;
continue;
}
// check if the 2 classes are different
if (class0 != class2)
{
// split!
ret += c0+(c1+string(" ")+c2)+c3;
//inserts++;
i+=3;
}
else
{
ret += c0;
// cerr << "cont3: '" << c0 << "'" <<endl;
continue;
}
}
// remove double spaces
//replaceStringInPlace(ret, " "," ");
//cerr << "separateAlphanumChunks: '" << ret << "'" <<endl;
return ret;
}
inline bool isCharAnInt (char c)
{
//TODO might be able to use isdigit() here
int i = c - '0';
return ((i>=0) && (i<=9));
}
答案 0 :(得分:2)
我看到了各种复杂的答案,这也是给出另一个答案的原因。 您的问题的答案恰好在问题陈述中: &#34;每次字符串从数字变为字母或从字母变为数字时添加额外的空格。&#34;
所以这正是你想要的(我使用了之前答案中的一些代码)编译应该使用标志-std = c ++ 11
完成#include <string>
#include <iostream>
using namespace std;
enum charTypeT{ other, alpha, digit};
charTypeT charType(char c){
if(isdigit(c))return digit;
if(isalpha(c))return alpha;
return other;
}
string separateThem(string inString){
string oString = "";charTypeT st=other;
for(auto c:inString){
if( (st==alpha && charType(c)==digit) || (st==digit && charType(c)==alpha) )
oString.push_back(' ');
oString.push_back(c);st=charType(c);
}
return oString;
}
int main(){
string str1 = "30EinsteinStreet";
string str2 = "548 Roe Drive5500 TestCity";
string str3 = "44B SaarlouisDrive1234Testtown";
cout << separateThem(str1) << endl;
cout << separateThem(str2) << endl;
cout << separateThem(str3) << endl;
}
答案 1 :(得分:1)
我认为你在寻找什么以及Ajay所暗示的是解析字符串的finite-state machine。 虽然这不是C ++ 11解决方案,您可以通过正则表达式找到更优雅的解决方案,但我提供了下面的代码示例。
#include <iostream>
#include <sstream>
bool isDigit(const char c)
{
bool res = true;
switch (c)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
break;
default:
res = false;
break;
}
return res;
}
std::string separateNumbers(const std::string& inputString)
{
const size_t N = inputString.length();
std::ostringstream os;
bool readDigit = false;
for (size_t i = 0; i < N; ++i)
{
if (isDigit(inputString[i]))
{
if ((i > 0) && (i < N) && (! readDigit))
{
if (inputString[i] != ' ')
os << ' ';
}
readDigit = true;
}
else
{
if ((i > 0) && (i < N) && (readDigit))
{
if (inputString[i] != ' ')
os << ' ';
}
readDigit = false;
}
os << inputString[i];
}
return os.str();
}
int main(int argc, char** argv)
{
std::string strings[3] = {
"30EinsteinStreet",
"548 Roe Drive5500 TestCity",
"44B SaarlouisDrive1234Testtown"
};
for (int i = 0; i < 3; ++i)
{
std::cout << "input #" << i << ": " << strings[i] << std::endl;
std::cout << "output #" << i << ": " << separateNumbers(strings[i]) << std::endl;
std::cout << std::endl;
}
return 0;
}
答案 2 :(得分:1)
这是我的五美分。
#include <iostream>
#include <string>
#include <cctype>
std::string SeparateAlphanumChunks( const std::string &s )
{
std::string::size_type n = 0;
bool ctype = std::isdigit( s[0] );
for ( char c : s )
{
if ( !ctype != !std::isdigit( c ) )
{
ctype = std::isdigit( c );
if ( !isblank( c ) ) ++n;
}
}
std::string t;
t.reserve( s.size() + n );
ctype = std::isdigit( s[0] );
for ( char c : s )
{
if ( !ctype != !std::isdigit( c ) )
{
ctype = std::isdigit( c );
if ( !isblank( c ) ) t.push_back( ' ');
}
t.push_back( c );
}
return t;
}
int main()
{
for ( const std::string &s : { "30EinsteinStreet",
"548 Roe Drive5500 TestCity",
"44B SaarlouisDrive1234Testtown"
} )
{
std::cout << SeparateAlphanumChunks( s ) << std::endl;
}
return 0;
}
输出
30 EinsteinStreet
548 Roe Drive 5500 TestCity
44 B SaarlouisDrive 1234 Testtown
您也可以“就地”更改字符串。例如
#include <iostream>
#include <string>
#include <cctype>
std::string & SeparateAlphanumChunks( std::string &s )
{
std::string::size_type n = 0;
bool ctype = std::isdigit( s[0] );
for ( char c : s )
{
if ( !ctype != !std::isdigit( c ) )
{
ctype = std::isdigit( c );
if ( !isblank( c ) ) ++n;
}
}
s.reserve( s.size() + n );
ctype = std::isdigit( s[0] );
for ( std::string::size_type i = 0; i < s.size(); i++ )
{
if ( !ctype != !std::isdigit( s[i] ) )
{
ctype = std::isdigit( s[i] );
if ( !isblank( s[i] ) )
{
s.insert( i, 1, ' ' );
}
}
}
return s;
}
int main()
{
for ( std::string s : { "30EinsteinStreet",
"548 Roe Drive5500 TestCity",
"44B SaarlouisDrive1234Testtown"
} )
{
std::cout << SeparateAlphanumChunks( s ) << std::endl;
}
return 0;
}
答案 3 :(得分:1)
我建议通过迭代字符串元素。 这样的事情会有所帮助:
#include <string>
#include <iostream>
using namespace std;
string separateThem(string inString){
string numbers = "1234567890";
string oString = "";
int i;
for(i=0; i<inString.size()-1; i++){
if ((numbers.find(inString[i]) != string::npos) && (numbers.find(inString[i+1]) == string::npos) && !isspace(inString[i+1])){
oString += inString.substr(i,1) + " ";
}
else if ((numbers.find(inString[i]) == string::npos) && (numbers.find(inString[i+1]) != string::npos) && !isspace(inString[i+1])){
oString += inString.substr(i,1) + " ";
}
else oString += inString.substr(i,1);
}
oString += inString.substr(i,1);
return oString;
}
int main(){
string str1 = "30EinsteinStreet";
string str2 = "548 Roe Drive5500 TestCity";
string str3 = "44B SaarlouisDrive1234Testtown";
cout << separateThem(str1) << endl;
cout << separateThem(str2) << endl;
cout << separateThem(str3) << endl;
}
如果执行此操作,输出将为:
30 EinsteinStreet
548 Roe Drive 5500 TestCity
44 B SaarlouisDrive 1234 Testtown
希望这会有所帮助:)
答案 4 :(得分:1)
升级到GCC 4.9(其第一个版本已于4月发布)并使用简单的正则表达式:
#include <regex>
#include <iostream>
std::string fix(const std::string& in)
{
return std::regex_replace(
in,
std::regex("(?:([a-zA-Z])([0-9]))|(?:([0-9])([a-zA-Z]))"),
"\\1\\3 \\2\\4",
std::regex_constants::format_sed
);
}
int main()
{
const std::string in[] = {
"30EinsteinStreet",
"548 Roe Drive5500 TestCity",
"44B SaarlouisDrive1234Testtown"
};
for (auto el : in)
std::cout << fix(el) << '\n';
}
/*
"30 EinsteinStreet"
"548 Roe Drive 5500 TestCity"
"44 B SaarlouisDrive 1234 Testtown"
*/
答案 5 :(得分:0)
我建议你将string
迭代为原始字符串(即string::c_str()
),并完全生成一个新字符串。这将是我的算法(不是很完整):
您可能需要进一步调整它。
如果字符串是这样的:
"enter 144 code here 123 "