如何解析c_str

时间:2013-11-06 15:01:55

标签: c++ string parsing casting

我有一个包含[51,53]的c_str。我想将这些对分成两个整数。它们位于c_str中,因为我从输入文件中读取它们。

必须有一种简单的方法来解析它们。我在考虑使用.at函数:但我相信我已经成功了。此外,它不起作用,因为它输出:

pair: 0x7ffffcfc2998
pair: 0x7ffffcfc2998 
etc
string pairstring = buffertm.c_str();
stringstream pair1, pair2;
int pairint1, pairint2;
pair1 << pairstring.at(1) << pairstring.at(2);
cout << "pair: " << pair1;
pair1 >> pairint1;
pair2 << pairstring.at(4) << pairstring.at(5);
//cout << "pair: " << pair2;
pair2 >> pairint2;

有更好的方法吗?

6 个答案:

答案 0 :(得分:5)

这样的事情:

char c1, c2, c3;
int first, second;

std::istringstream iss(str);

if (iss >> c1 >> first >> c2 >> second >> c3
    && c1 == '['  && c2 == ',' && c3 == ']' )
{
    // success
}

您可能需要额外检查以查看结束括号后是否还有其他字符:

if ((iss >> std::ws).peek() != EOF) {
   //^^^^^^^^^^^^^^
   // eats whitespace chars and returns reference to iss
   /* there are redundant charactes */
}

答案 1 :(得分:4)

使用C ++ 11 std::stoi

尝试此操作
char c_str[] = "[51,53]";
std::string s(c_str);
int num1 = std::stoi(s.substr(1, 2));
int num2 = std::stoi(s.substr(4, 2));

如果您知道数字将超出10-99范围,请改用:

char c_str[] = "[5156789,5]";
std::string s(c_str);
s.assign(s.substr(1, s.size() - 2));         // Trim away '[' and ']'
std::string::size_type middle = s.find(','); // Find position of ','
int num1 = std::stoi(s.substr(0, middle));
int num2 = std::stoi(s.substr(middle + 1, s.size() - (middle + 1)));

如果无法解析数字,函数stoi将抛出std::invalid_argument

修改

对于只能解析 base-10 数字的更多rubust解决方案,您应该使用以下内容:

char c_str[] = "[51,0324]";

int num1, num2;
try {
    std::string s(c_str);
    s.assign(s.substr(1, s.size() - 2));
    std::string::size_type middle = s.find(',');

    std::unique_ptr<std::size_t> pos{new std::size_t};

    std::string numText1 = s.substr(0, middle);
    num1 = std::stoi(numText1, pos.get()); // Try parsing first number.
    if (*pos < numText1.size()) {
        throw std::invalid_argument{{numText1.at(*pos)}};
    }

    std::string numText2 = s.substr(middle + 1, s.size() - (middle + 1));
    num2 = std::stoi(numText2, pos.get()); // Try parsing second number.
    if (*pos < numText2.size()) {
        throw std::invalid_argument{{numText2.at(*pos)}};
    }
} catch (const std::invalid_argument& e) {
    std::cerr << "Could not parse number" << std::endl;
    std::exit(EXIT_FAILURE);
}

尝试将字符串解析为std::invalid_argument时会抛出"1337h4x0r",这与使用std::istringstream时不同。 Se this for more info

答案 2 :(得分:3)

出于多种原因,我建议采用两步法,而不是一次性尝试。

此外,其中一些很大程度上取决于你可以安全地做出什么样的假设。

1)只是标记化。如果你知道它将以“[”开头并且你知道会有一个逗号,并且你知道你只会得到两个数字,在字符串中搜索“[,”然后使用substr()来获取所有内容它和逗号之间。这是一个令牌。然后从逗号到“]”执行类似的操作以获取第二个标记。

2)一旦你有两个字符串,将它们转换为整数是相对简单的,并且有很多方法可以做到。

在我打字的时候添加了一些答案,但我仍然建议采用两步法。

答案 3 :(得分:1)

如果您对字符串的格式有合理的信心,可以将整个事物放入stringstream,然后使用提取运算符; e.g:

stringstream strm(pairstring);    
int pairint1 = 0, pairint2 = 0;
char c = 0;

strm >> c >> pairint1 >> c >> pairint2 >> c;

实际上你也想在那里进行一些错误检查,但希望这足以让你开始。

答案 4 :(得分:0)

尝试使用strtok功能拆分字符串。 对于转换,请使用atoi

答案 5 :(得分:0)

  

我有一个包含[51,53]

的c_str

不,c_str()不是数据结构,它是std::basic_string的一种方法,它返回一个常量C字符串,其数据等同于std::string中存储的数据。

string pairstring = buffertm.c_str();很麻烦,只需string pairstring = buffertm;或直接使用buffertm

其次,你以错误的方式使用你的字符串流,你应该使用istringstream(这里你将它用作ostringstream

int i, j;
istringstream iss(buffertm);
iss.get()
iss >> i;
iss.get()
iss >> j;
iss.get().