C++ 从std::string解析两个或一个数字
我一直在设计这个函数:C++ 从std::string解析两个或一个数字,c++,string,C++,String,我一直在设计这个函数: //Turns "[0-9]+,[0-9]+" into two integers. Turns "[0-9]+" in two *equal* integers static void parseRange(const std::string, int&, int&); 我无法访问需要C++11或Boost库的正则表达式。我需要找出字符串是否包含2个整数并将其拆分,然后得到每个整数 我想我需要一个使用std::string的版本来确定是否有逗号以及在哪
//Turns "[0-9]+,[0-9]+" into two integers. Turns "[0-9]+" in two *equal* integers
static void parseRange(const std::string, int&, int&);
我无法访问需要C++11或Boost库的正则表达式。我需要找出字符串是否包含2个整数并将其拆分,然后得到每个整数
我想我需要一个使用std::string的版本来确定是否有逗号以及在哪里。我可能可以使用std::string::c_str value进行操作。广泛的搜索导致了这一点,但我想使用std::string,而不是C string:
void Generator::parseRange(const std::string str, int& min, int& max) {
const char* cstr = str.c_str();
const char* comma_pos;
//There's a comma
if((comma_pos=strstr(cstr, ","))!=NULL) { //(http://en.cppreference.com/w/cpp/string/byte/strstr)
//The distance between begining of string and the comma???
//Can I do this thing with pointers???
//Is 1 unit of pointer really 1 character???
unsigned int num_len = (comma_pos-cstr);
//Create new C string and copy the first part to it (http://stackoverflow.com/q/8164000/607407)
char* first_number=(char *)malloc((num_len+1)*sizeof(char));//+1 for \0 character
//Make sure it ends with \0
first_number[num_len] = 0;
//Copy the other string to it
memcpy(first_number, cstr, num_len*sizeof(char));
//Use atoi
min = atoi(first_number);
max = atoi(comma_pos+1);
//free memory - thanks @Christophe
free(first_number);
}
//Else just convert string to int. Easy as long as there's no messed up input
else {
min = atoi(cstr); //(http://www.cplusplus.com/reference/cstdlib/atoi/)
max = atoi(cstr);
}
}
我在谷歌上搜索了很多。你不能说我没有试过。上面的函数可以工作,但我更喜欢一些不那么幼稚的实现,因为上面看到的是旧时代的核心C代码。这一切都取决于这样一个事实,即没有人会把输入搞糟。这个更为原生的版本:
void Generator::parseRange(const std::string str, int& min, int& max) {
stringstream sst(str);
if (!(sst>>min && sst.get()==',' && sst>>max))
cerr<<"String has an invalid format\n";
}
使用这个更原生的版本:
void Generator::parseRange(const std::string str, int& min, int& max) {
stringstream sst(str);
if (!(sst>>min && sst.get()==',' && sst>>max))
cerr<<"String has an invalid format\n";
}
使用std::string功能,您可以非常轻松地完成所有搜索和分离
int pos = str.find(',');
assert(pos != std::string::npos);
std::string first = str.substr(0, pos);
std::string second = str.substr(pos+1, -1);
或者,您可以非常轻松地使用stringstream进行解析。例如:
std::istringstream s(str);
int one, two;
char ch;
s >> one >> ch >> two;
assert(ch == ',');
请注意,这也使得分离字符串和将单个片段转换为数字的组合变得非常容易。使用std::string功能,您可以非常轻松地完成所有搜索和分离
int pos = str.find(',');
assert(pos != std::string::npos);
std::string first = str.substr(0, pos);
std::string second = str.substr(pos+1, -1);
或者,您可以非常轻松地使用stringstream进行解析。例如:
std::istringstream s(str);
int one, two;
char ch;
s >> one >> ch >> two;
assert(ch == ',');
请注意,这也使得分离字符串和将单个片段转换为数字的组合变得很容易。您可以通过使用std::string和std::atoi提供的内置搜索工具来实现这一点,而无需制作副本或使用malloc或new来存储字符串的部分
#include <cstdlib>
#include <string>
void Generator::parseRange(const std::string &str, int& min, int& max)
{
// Get the first integer
min = std::atoi(&str[0]);
// Check if there's a command and proces the second integer if there is one
std::string::size_type comma_pos = str.find(',');
if (comma_pos != std::string::npos)
{
max = std::atoi(&str[comma_pos + 1]);
}
// No comma, min and max are the same
else
{
max = min;
}
}
您可以通过使用std::string和std::atoi提供的内置搜索工具来实现这一点,而无需制作副本,也无需使用malloc或new来存储字符串的部分内容
#include <cstdlib>
#include <string>
void Generator::parseRange(const std::string &str, int& min, int& max)
{
// Get the first integer
min = std::atoi(&str[0]);
// Check if there's a command and proces the second integer if there is one
std::string::size_type comma_pos = str.find(',');
if (comma_pos != std::string::npos)
{
max = std::atoi(&str[comma_pos + 1]);
}
// No comma, min and max are the same
else
{
max = min;
}
}
不需要std::无论如何,它只会为不可读的代码消耗更多内存 试试这个大约1980年的C代码,它应该可以做到:
void generator::parse_range (const std::string input, int & min, int & max)
{
const char * scan = input.c_str();
min = (int) strtol (scan, &scan, 0);
max = (*scan == ',') ? (int)strtol (scan+1, &scan, 0) : min;
if (errno || *scan != '\0') panic ("you call that numbers?");
}
这将接受十六进制或八进制输入,尽管您可以使用第三个参数修复基址。
您也可以在第一次转换后检查errno或测试长整数溢出,但我认为这并不是问题最糟糕的部分:不需要std::无论如何,它只会为不可读的代码消耗更多内存 试试这个大约1980年的C代码,它应该可以做到:
void generator::parse_range (const std::string input, int & min, int & max)
{
const char * scan = input.c_str();
min = (int) strtol (scan, &scan, 0);
max = (*scan == ',') ? (int)strtol (scan+1, &scan, 0) : min;
if (errno || *scan != '\0') panic ("you call that numbers?");
}
这将接受十六进制或八进制输入,尽管您可以使用第三个参数修复基址。
您也可以在第一次转换或长整数溢出测试之后检查ErNO,但是我认为这不是您问题中最糟糕的部分: 1避免C++中的MALOC!2你是内存泄漏,这就是为什么我要C++解决方案。在学校里,他们只教我们C。我正在做我能做的事情,这是我想要的。1避免C++中的Maloc!2你是内存泄漏,这就是为什么我要C++解决方案。在学校里,他们只教我们C。我在做我能做的,所以我想要的很明显。如果它失败了,它会在整数中添加任何东西吗?实际上,我有一些默认值,所以最好是它失败并且不改变值。它不会覆盖失败的整数。但是,如果第一个整数有效,它将被存储,即使第二个整数无效。如果失败,它会在整数中放入任何内容吗?实际上,我有一些默认值,所以最好是它失败并且不改变值。它不会覆盖失败的整数。但是,如果第一个整数有效,它将被存储,即使第二个整数无效。我只想添加一个临时变量,在传递无效666时将min恢复到其原始状态,因为它不太清楚要输入什么。其他方面都很完美,谢谢。istringstream解决方案是最完美的。我只想添加一个临时变量,在传递无效666时将min恢复到其原始状态,因为它不太清楚要输入什么。否则很好,谢谢。我想这是最快的解决方案。感谢您显示C尚未失效:如果无法识别有效格式,errno将设置为EINVAL,strtol将返回0。您必须进行检查以保留默认值。至于C是生是死,好吧,责怪Stourstrup先生和他的朋友们在过去25年左右未能提供一个像样的字符串处理包……我想这是最快的解决方案。感谢您显示C尚未失效:如果无法识别有效格式,errno将设置为EINVAL,strtol将返回0。您必须进行检查以保留默认值。至于C是生是死,好吧,责怪Stourstrup先生和他的朋友在过去25年左右未能提供一个像样的字符串处理包。。。