获得字符串向量的中位元素[C ++]

时间:2016-11-29 16:37:10

标签: c++

我有以下任务: 给出一组N个正数。编写一个程序,找到集合的中间元素。 输入:第一行有很多例子, 第二行是集合的长度。下一行是用空格分隔的集合的数字。 有点像这样:
2(例子数)
5(长度)
12 4 22 31 32(套)
8(长度)
22 33 44 11 55 66 88 99(设置)

然后你必须对集合进行排序并打印中间元素。 输出:
22(第一集中期元素)
44(第二组中期元素)

约束:N&lt; 10 ^ 11且每个数量的集合应该<10。 10 ^ 20个
所以我选择直接使用字符串,因为数字很大。这是我的代码:

#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cstring>
using namespace std;

bool comparer (const string s1, const string s2)
{
   return atoi(s1.c_str()) < atoi(s2.c_str());
}


int main()
{
    int numberOfExamples;
    cin >> numberOfExamples;

    for (int i = 0; i < numberOfExamples; i++)
    {
        long length;
        string input;
        cin >> length;
        string buffer;
        while(getline(cin, input))
        {
            vector<string> v;
            istringstream is(input);
            while (is >> buffer) v.push_back(buffer);

            sort (v.begin(), v.end(), comparer);

            string middle;
            if (v.size() % 2 == 0)
            {
                middle = v[v.size()/2 -1];
            }
            else
            {
                middle = v[v.size()/2];
            }
            cout << middle;
        }

    }
    return 0;
}

编译完成后,在第二行停止输入第一个例子的长度,我得到类型0xC00000005的错误。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

您尝试实施的算法是:

  • 读取测试次数; 忽略其余部分
  • 每次测试
    • 读取测试值的数量,忽略该行的其余部分
    • 阅读包含测试值的单行
    • 将测试线分割为值向量
    • 排序矢量
    • 找到中间元素

上面的粗体部分要么失败,要么根本不做。例如,您的代码:

cin >> length; 
string buffer;
while(getline(cin, input))

将读取格式化的长度为整数,但当前行的其余部分(可能只是换行符)保留在输入流中。因此getline消耗 ,而不是测试值行。更糟糕的是,这意味着for循环中的所有逻辑都将使用空输入行,这意味着向量中不会存储任何值。这意味着当你到达这里时:

if (v.size() % 2 == 0)
{
    middle = v[v.size()/2 -1];
}

v.size()为零,这意味着v.size() % 2为零,这意味着您的“中间”现在设置为v[-1],这显然是超出范围的。

所以最大的问题是你在格式化输入之后没有正确地消耗剩余行数据,这是开始C ++程序员的一个常见问题。 See this question and related answers

第二个问题,while (getline(...))是错误的。这将消耗所有数据,直到文件结束。你只想要一行数据;并非所有剩余的数据行。修复之前提到的格式化输入问题后,while应该是if

<强>代码

#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <string>
#include <limits>
#include <iterator>

int main()
{
    unsigned int numberOfExamples;
    if (!(std::cin >> numberOfExamples) || numberOfExamples == 0)
        return EXIT_FAILURE;

    while (numberOfExamples-- > 0)
    {
        unsigned int n_tests = 0;
        if (std::cin >> n_tests)
        {
            if (n_tests == 0)
                continue;

            // consume remainder of test lines
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

            // read set of values
            std::string line;
            if (std::getline(std::cin, line))
            {
                std::istringstream iss(line);
                std::vector<int> v {
                    std::istream_iterator<int>(iss),
                    std::istream_iterator<int>() };

                if (v.size() > 0)
                {
                    std::sort(v.begin(), v.end());

                    if (v.size() % 2 == 0)
                        std::cout << v[v.size()/2-1] << '\n';

                    else
                        std::cout << v[v.size()/2] << '\n';
                }
            }
        }
        else
        {
            std::cerr << "Failed to read number of test values\n";
        }
    }
}

<强>输入

2
5
12 4 22 31 32
8
22 33 44 11 55 66 88 99

<强>输出

22
44

See it live

答案 1 :(得分:0)

我能看到的代码最大的问题是在比较器中使用atoi是行不通的。如果输入数据大于int可以容纳的内容,则atoi将无效,因为它会尝试将字符串转换为int

你可以做的是将字符串相互比较。您必须考虑到大小,否则100会在5之前出现,但实施起来并不难。以下内容应该有效。

bool comparer (const string& s1, const string& s2)
{
    if (s1.size() != s2.size())
        return s1.size() < s2.size();
    return s1 < s2;
}

请注意,我将s1s2更改为引用,因为按值传递会产生大量副本并导致性能下降。

答案 2 :(得分:0)

谢谢大家! 我修复了我的代码,现在它正常工作了。这是修复

#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cstring>  
using namespace std;

bool comparer (const string& s1, const string& s2)
{
    if (s1.size() != s2.size())
        return s1.size() < s2.size();
    return s1 < s2;
}


int main()
{
    int numberOfExamples;
    cin >> numberOfExamples;
    cin.ignore();
    vector<string> outputs;

    for (int i = 0; i < numberOfExamples; i++)
    {
        long long length;
        string input;
        cin >> length;
        cin.ignore();
        string buffer;
        if(getline(cin, input))
        {
            vector<string> v;
            istringstream is(input);
            while (is >> buffer) v.push_back(buffer);
            if (v.size() != length)
            {
                cout << "Incorrect length!";
                return 1;
            }

            sort (v.begin(), v.end(), comparer);

            string middle;
            if (v.size() % 2 == 0)
            {
                middle = v[v.size()/2 -1];
            }
            else
            {
                middle = v[v.size()/2];
            }
            outputs.push_back(middle);
        }


    }

    for (vector<string>::iterator it = outputs.begin(); it != outputs.end(); it++)
    {
        cout << *it << endl;
    }
    return 0;
}

我也在一个新的向量中推送答案,当for循环结束时显示所有这些。还有最后一个问题。我应该每次从用户那里使用cin.ignore()吗?