如何解析c_str

How to parse a c_str

本文关键字:str 何解析      更新时间:2023-10-16

我有一个包含[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;

有什么更好的方法可以做到这一点吗?

像这样:

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 */
}

使用 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

编辑:

对于只会解析以 10 为基数的数字的更粗鲁的解决方案,您应该使用这样的东西:

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

尝试将字符串解析为"1337h4x0r"等时会抛出std::invalid_argument,这与使用 std::istringstream 不同。Se 这个以获取更多信息

出于多种原因,我建议采用两步过程,而不是尝试一次完成所有过程。

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

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

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

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

如果你对字符串的格式有相当的信心,你可以把整个东西放到一个stringstream中,然后使用提取运算符;例如:

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

实际上,您也希望在那里进行一些错误检查,但希望这足以让您入门。

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

我有一个包含 [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().