【问题标题】:Unknown input size cin未知输入大小 cin
【发布时间】:2015-04-30 21:01:11
【问题描述】:

我确信这是一个简单的问题。老实说,这应该是编写 SAT 求解器最简单的部分,但是,我应该让用户输入数据如下:

Sample Input:
1              <-- 1st number denotes the number of cases I will have
5              <-- 2nd number represents the number of variables, followed 
1 2 3              who knows how many clauses.
-1 3 4
-2 -3 5
-5 -1 2
-4 1 -2
-4 -1 -2 -3 -5

*blank line separates the different cases*
.... followed by as many cases as the user said they had

所以,我将这些子句存储到字符串向量中,它们都将进入另一个向量。那么从用户那里获得这种输入的最佳方式是什么?最初没有给出子句数量的事实是最让我困惑的部分。我会尝试一段时间()......但我不知道如何终止它。我想我有点不确定 cin 在这种情况下会如何工作。

感谢您的所有帮助。

【问题讨论】:

  • 为什么有六个“变量”?

标签: c++ input cin


【解决方案1】:

有两个不同的问题:(a) 读取未知数量的输入行和 (b) 将给定的输入行解析为未知数量的ints。

首先,从输入中读取行。那只是std::getline

std::string str
while (std::getline(std::cin, str)) {
    // ???
}

然后,给定str,我们必须将其解析为ints。最简单的方法就是放到stream

std::istringstream iss(str);

然后要么一一阅读ints:

int i;
while (iss >> i) {
    // do something
}

或者通过传递一对istream_iterator&lt;int&gt;,一次性将它们全部放入vector

std::vector<int> v{std::istream_iterator<int>{iss},
                   std::istream_iterator<int>{}};

因此,记录每行输入总和的完整示例是:

std::string str
while (std::getline(std::cin, str)) {
    std::istringstream iss(str);
    std::vector<int> v{std::istream_iterator<int>{iss},
                       std::istream_iterator<int>{}};

    if (!v.empty()) {
        std::cout << "sum=" << std::accumulate(v.begin(), v.end(), 0) << '\n';
    }
}

【讨论】:

    【解决方案2】:

    这在家庭作业和竞赛题中很常见,答案是这样的:

    #include <sstream> //you may not have known about this
    
    int num_cases = 0;
    std::cin >> num_cases;
    for(int case_num=0; case_num<num_cases; ++case_num) { //for each case       
        std::vector<std::vector<int>> variables;
        int num_variables = 0;
        std::cin >> num_variables;
        std::cin.ignore(1); //ignore the newline character, it messes with getline
        for(int var=0; var<num_variables; ++var) { //for each variable
            std::string linestr;
            std::getline(std::cin, linestr, '\n'); //read whole line into string
            std::istringstream linestream(linestr); //make a stream from the line
    
            int newclause = 0;
            std::vector<int> lineclauses;
            while(linestream >> newclause) //for each clause
                lineclauses.push_back(newclause); //add it to the row
            //when that fails, we read the whole line
            variables.push_back(lineclauses); //so add the row to 'variables'
        }
        //Do stuff with variables vector.
    }
    

    【讨论】:

    • 嗯。如果我正确理解 OP,子句的数量是未知的?
    • @PeterSchneider:对,第一行是病例数。每个案例都以包含“变量”数量的行开头。每个“变量”都是一条带有未知数量的“子句”的行。这就是为什么我们必须通过getline 将整行抓取到istringstream 并循环遍历直到它为空。为了清楚起见,我添加了 cmets。
    • 我不熟悉这种格式(虽然我已经看到它出现在这里的问题中);但在给出的示例中,5 之后有 6 行。疏忽?
    • 阅读getline() 我知道它会读取(并丢弃)换行符;为什么是 cin.ignore()`?
    • @PeterSchneider:哦,你说得对,是&gt;&gt; 留下了换行符。我已经转移了忽略。您是对的,示例中的 5 后面有 6 行,我对此没有任何解释。
    猜你喜欢
    • 2020-11-13
    • 2021-01-20
    • 1970-01-01
    • 2014-01-19
    • 2013-10-21
    • 2011-12-06
    • 2015-11-05
    • 1970-01-01
    • 2022-08-06
    相关资源
    最近更新 更多