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年左右未能提供一个像样的字符串处理包。。。