在 C++ 中读取格式化输入的最简单方法是啥?

Posted

技术标签:

【中文标题】在 C++ 中读取格式化输入的最简单方法是啥?【英文标题】:The easiest way to read formatted input in C++?在 C++ 中读取格式化输入的最简单方法是什么? 【发布时间】:2012-07-07 11:31:57 【问题描述】:

有没有办法读取这样的格式化字符串,例如:48754+7812=Abcs

假设我有三个 stringz X、Y 和 Z,我想要

X = 48754 
Y = 7812
Z = Abcs

两个数字的大小和字符串的长度可能会有所不同,所以我不想使用substring()或类似的东西。

是否可以给C++这样的参数

":#####..+####..=SSS.."

所以它直接知道发生了什么?

【问题讨论】:

【参考方案1】:
#include <iostream>
#include <sstream>

int main(int argc, char **argv) 
  std::string str = ":12341+414112=absca";
  std::stringstream ss(str);
  int v1, v2; 
  char col, op, eq; 
  std::string var;
  ss >> col >> v1 >> op >> v2 >> eq >> var;
  std::cout << v1 << " " << v2 << " " << var << std::endl;
  return 0;

【讨论】:

+1 因为这是唯一准确考虑实际问题的答案。其他答案没有,因为1。使用 boost 不是最简单的方式(我承认它可能是最优雅的方式)和 2. scanf 不是 C++ 风格(正如相应答案的作者所提到的)。【参考方案2】:

一种可能性是boost::split(),它允许指定多个分隔符并且不需要事先知道输入的大小:

#include <iostream>
#include <vector>
#include <string>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>

int main()

    std::vector<std::string> tokens;
    std::string s(":48754+7812=Abcs");
    boost::split(tokens, s, boost::is_any_of(":+="));

    // "48754" == tokens[0]
    // "7812"  == tokens[1]
    // "Abcs"  == tokens[2]

    return 0;

或者,使用sscanf()

#include <iostream>
#include <cstdio>

int main()

    const char* s = ":48754+7812=Abcs";
    int X, Y;
    char Z[100];

    if (3 == std::sscanf(s, ":%d+%d=%99s", &X, &Y, Z))
    
        std::cout << "X=" << X << "\n";
        std::cout << "Y=" << Y << "\n";
        std::cout << "Z=" << Z << "\n";
    

    return 0;

但是,这里的限制是必须在解析输入之前确定字符串的最大长度(Z)。

【讨论】:

非常感谢答案,但除了 boost 或任何外部库之外还有什么其他的......是否可以在标准 c++ 或至少 stl 中完成【参考方案3】:

您可以使用scanf。它不是过度 C++ - ish,但它用非常少的代码行就可以了:

char a[101], b[111], c[121];
sscanf(":48754+7812=Abcs", ":%100[^+]+%110[^=]=%120s", a, b, c);
string sa(a), sb(b), sc(c);
cout << sa << "-" << sb  << "-" << sc << endl;

这个想法是使用非常有限的正则表达式语法指定您读取的字符串所接受的字符。在这种情况下,第一个字符串被读取到加号,第二个字符串被读取到等号。

【讨论】:

【参考方案4】:

例如。

#include <boost/regex.hpp>
#include <iostream>

int main()

   boost::regex re("\":(\\d+)\\+(\\d+)=(.+)\"");
   std::string example = "\":48754+7812=Abcs\"";
   boost::smatch match;
   if (boost::regex_match(example, match, re))
   
      std::cout << "f number: " << match[1] << " s number: " << match[2] << " string: " << match[3]
      << std::endl;
   
   else
   
      std::cout << "not match" << std::endl;
   

第二个变体,仅适用于字符串。

#include <string>
#include <iostream>

int main()

   std::string s = "\":48754+7812=Abcs\"";
   std::string::size_type idx = s.find(":");
   std::string::size_type end_first = s.find("+", idx + 1);
   std::string f_number = s.substr(idx + 1, end_first - (idx + 1));
   std::cout << f_number << std::endl;
   std::string::size_type end_second = s.find("=", end_first + 1);
   std::string s_number = s.substr(end_first + 1, end_second - (end_first + 1));
   std::cout << s_number << std::endl;
   std::string::size_type string_end = s.find("\"", end_second);
   std::string str = s.substr(end_second + 1, string_end - (end_second + 1));
   std::cout << str << std::endl;

【讨论】:

在许多此类情况下,正则表达式是一个很好的建议,为此 +1。请注意,正则表达式支持在 C++11 中作为 C++ 的一部分提供——不再需要使用 Boost 正则表达式。 @jogojapan 不是现在=( liveworkspace.org/code/b66dcfa19ce7620fb7b9e4c203c42f43 @ForEveR 对。我应该检查一下,但确实 GCC 的正则表达式支持仍然不是它应该在的地方,尤其是。捕获组不起作用。此外,正则表达式语法也存在差异。例如。在 C++11 中执行 [\d] 的标准方法是 [[:digit:]]。无论如何,作为最后的评论,如果您使用 Clang,对 C++11 正则表达式的支持会更好。通过正确的语法调整,您的示例代码应该可以在那里工作。

以上是关于在 C++ 中读取格式化输入的最简单方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中从文件末尾读取的最有效方法是啥? (解析文件中的最后 128 位)

C++ OpenCV:应用二维卷积的最简单方法是啥

在 Visual C++ 中执行查询的最简单方法是啥

C++:在 Windows 上使用 C++ 读写 BMP 文件的最简单方法是啥?

在 C++ 预印卡上打印的最简单方法是啥?

在 Java 中解析 INI 文件的最简单方法是啥?