从std :: string中解析两个或一个数字

时间:2014-12-08 00:54:42

标签: 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个整数并将其拆分,然后得到每个整数。

我想我需要strstr版本使用std::string来查看是否有逗号和位置。我可能会以std::string::c_str值运行。广泛的搜索引导我(但我想使用 std::string ,而不是C字符串):

  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);
      }
  }

我用Google搜索了很多。你不能说我没有尝试过。上面的函数有效,但我更喜欢一些不太天真的实现,因为你在上面看到的是旧时代的硬核C代码。这一切都依赖于事实,没有人会对输入感到困惑。

4 个答案:

答案 0 :(得分:2)

您可以使用std::string提供的内置搜索工具和std::atoi来完成此操作,而无需复制或需要使用mallocnew来存储零件字符串。

#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::istringstream来处理整数解析。这将允许您在解析整数值时执行其他输入验证

#include <sstream>
#include <string>

bool Generator::parseRange(const std::string& str, int& min, int& max)
{
    std::istringstream sst(str);

    //  Read in the first integer
    if (!(sst >> min))
    {
        return false;
    }

    //  Check for comma. Could also check and error out if additional invalid input is
    //  in the stream
    if (sst.get() != ',')
    {
        max = min;
        return true;
    }

    //  Read in the second integer
    if (!(sst >> max))
    {
        return false;
    }

    return true;
}

答案 1 :(得分:1)

这个更原生的版本是什么:

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"; 
     }

答案 2 :(得分:1)

您可以使用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 == ',');

请注意,这也可以很容易地将字符串分开并将各个部分转换为数字。

答案 3 :(得分:1)

不需要std :: whatever,它只会消耗更多的内存,而且不会有不易读的代码。

尝试使用大约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或测试长整数溢出,但我认为这不是您问题中最糟糕的部分:)