【问题标题】:How can I extract numbers between a parenthesis from a txt file c++?如何从 txt 文件 c++ 中提取括号之间的数字?
【发布时间】:2018-08-05 05:19:58
【问题描述】:

我的问题是:我的逻辑有些问题。我已经检测到它何时有括号,但现在我需要找到数字并知道它们在 txt 文件中重复了多少次。这是我的txt文件:

(Visual basic)
(Llorente)
(Porto, 2008)
(Sommerville, 2010)
References
Visual Basic. (s.f.). Navarra.
Llorente, P.B. (s.f.). Fortran.
Porto, J.P. (2008)
Sommerville, I. (2010). Software Engineering. Unite Kingdom: Pearson.

结果应该是:年份:2008 - 2 次,年份:2010 - 2 次,等等。 PD:谢谢,我很菜鸟。

#include <regex>
#include <iostream>
#include <fstream>
#include <map>
//33
int main()
{
    std::ifstream readStream("references.txt");
    std::map<int, int> cMap; 
    std::string input;
    std::regex reg(R"(\([a-zA-Z\s]*,?\s*([0-9]+)\))");
    std::regex inte("(\\+|-)?[[:digit:]]+");

    ///333
    while (std::getline(readStream, input)) {
            std::match_results < std::string::const_iterator > m;
    if ((std::regex_search(input, m, reg)) ) {
        int year = std::stoi(m[1]); 
        auto value = cMap.find(year);
        if (value != cMap.end()) { 
            cMap[value->first] = value->second + 1;
        } else {
            cMap[year] = 1; 
        }
    }



}
//33
for (auto x : cMap) { 
    std::cout << "year " << x.first << " is - " << x.second << " times." << std::endl;
}
//3
return 0;
}

【问题讨论】:

  • 对于regex 来说,这听起来像是一份完美的工作(就像首先找到括号一样)
  • 我使用 g++ 我不能使用正则表达式。
  • 嗯? g++ 支持正则表达式,它们是 C++ 的一部分。
  • @john “我遇到了一个问题,我选择了正则表达式来解决它。现在,我遇到了两个问题。” ;-)
  • 要在字符串中查找数字,您可以遍历字符 c 直到找到数字 (c &gt;= '0' &amp;&amp; c &lt;= '9')。然后,只要找到数字,就进行迭代。或者,更简单:使用strtol()。 (它也会告诉你停止字符的数字和指针。)

标签: c++ file-io extract ifstream


【解决方案1】:

您可以使用std::regex_search 方法来匹配行。但请记住在文件顶部包含#include &lt;regex&gt;

#include <regex>
#include <iostream>
#include <fstream>
#include <map>


int main()
{
    std::ifstream readStream("path/to/your/Example.txt");
    std::map<int, int> countMap; // Map containing (year, count) value pairs.
    std::string in;
    std::regex reg(R"(\([a-zA-Z\s]*,?\s*([0-9]+)\))"); // For the regex: \([a-zA-Z\s]*,?\s*([0-9]+)\)

    while (std::getline(readStream, in)) {
        std::match_results < std::string::const_iterator > m;
        if (std::regex_search(in, m, reg)) { // If the current line matches our regex pattern.
            int year = std::stoi(m[1]); // The second element of the array contains our string representing the year.

            auto val = countMap.find(year);
            if (val != countMap.end()) { // If the year is already in the countMap we want to increment it.
                countMap[val->first] = val->second + 1;
            } else {
                countMap[year] = 1; // year doesn't exist in the countMap, it is the first time.
            }
        }
    }

    for (auto x : countMap) { // x is of type std::pair<int, int> which is our (year, count) value pair
        std::cout << "year " << x.first << " is - " << x.second << " times." << std::endl;
    }

    return 0;
}

【讨论】:

  • 谢谢,这很有帮助,我有一个问题,当我尝试向 if 语句添加一个正则表达式时,但是当我添加另一个 std::stoi 时,我得到了异常。
【解决方案2】:

对于 OP 的任务,一个简单的循环可以完成遍历字符串所有字符的工作。因此,管理了两个状态:

  • open ... true'(' 之后和')' 之前,否则为假
  • number ... trueopentrue 时找到数字。

numbertrue 时,数字被收集并组合成int。如果在 numbertrue 时发现非数字,则这是数字的结尾,并存储该值。

也可以在行尾检查号码。在这种特定情况下,这意味着语法错误,因为这意味着缺少右括号 ())。 (OP 没有声明如何处理这个问题。)

我的示例代码:

#include <iostream>
#include <sstream>
#include <vector>
#include <map>

std::vector<int> parseLine(const std::string &text)
{
  bool open = false, number = false;
  std::vector<int> values; int value = 0;
  for (char c : text) {
    switch (c) {
      case '(': open = true; break;
      case ')': open = false;
      default:
        if (open && c >= '0' && c <= '9') {
          number = true;
          (value *= 10) += (c - '0'); // value = 10 * value + (c - '0')
        } else if (number) {
          values.push_back(value);
          value = 0; number = false;
        }
    }
  }
  if (number) {
    values.push_back(value);
    std::cerr << "ERROR: Missing ')' at line end!\n";
  }
  return values;
}

const std::string text =
"(Visual basic)\n"
"(Llorente)\n"
"(Porto, 2008)\n"
"(Sommerville, 2010)\n"
"References\n"
"Visual Basic. (s.f.). Navarra.\n"
"Llorente, P.B. (s.f.). Fortran.\n"
"Porto, J.P. (2008)\n"
"Sommerville, I. (2010). Software Engineering. Unite Kingdom: Pearson.\n";

int main()
{
  // open file
  std::istringstream in(text);
  // parse/process file line by line
  std::map<int, int> histo;
  for (std::string line; std::getline(in, line);) {
    const std::vector<int> values = parseLine(line);
    // count occurrences of values
    for (int value : values) ++histo[value];
  }
  // report
  std::cout << "Report:\n";
  for (const std::pair<int, int> &entry : histo) {
    std::cout << entry.first << ": " << entry.second << '\n';
  }
  // done
  return 0;
}

输出:

Report:
2008: 2
2010: 2

Live Demo on coliru

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-27
    • 2015-05-11
    • 2020-02-10
    • 2011-02-01
    • 2020-01-26
    • 2019-02-26
    • 2022-12-16
    • 1970-01-01
    相关资源
    最近更新 更多