Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从C++;_C++_File_Double_Ifstream - Fatal编程技术网

C++ 从C++;

C++ 从C++;,c++,file,double,ifstream,C++,File,Double,Ifstream,大家早上好 我有一个学校作业,我希望你能在这方面帮助我。 该计划的目标非常简单。计算这些数字的和 在文件的每一行上,并在屏幕上显示N个最高的不同结果,以减少rorder,其中N个结果的出现次数,N由用户作为参数提供(默认值=3)。 因此标题称我在C++中工作,而且我的程序必须从提供的TXT文件中读取行数(double)。我已经知道ifsream类型的概念,并设法打开了该文件。我知道我可以使用>>操作符读取文件,但是每行的双倍数不是固定的,所以我不能进行简单的循环。以下是我这边到目前为止的情况:

大家早上好

我有一个学校作业,我希望你能在这方面帮助我。 该计划的目标非常简单。计算这些数字的和 在文件的每一行上,并在屏幕上显示N个最高的不同结果,以减少rorder,其中N个结果的出现次数,N由用户作为参数提供(默认值=3)。 因此标题称我在C++中工作,而且我的程序必须从提供的TXT文件中读取行数(double)。我已经知道ifsream类型的概念,并设法打开了该文件。我知道我可以使用>>操作符读取文件,但是每行的双倍数不是固定的,所以我不能进行简单的循环。以下是我这边到目前为止的情况:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;

int main(){

    int nbresult=3;
    string filename;
    double tmp;

    cin >> filename;
    cin >> nbresult;

    ifstream file;
    file.open(filename.c_str());

    if(file.is_open())
    {
        cout << "Opening file: " << filename << endl;

        while(file.eof() == false)
        {
            vector<double> nbres;
            file >> tmp;
            nbres.push_back(tmp);
        }

        fichier.close();
    }
    else 
    {
        cout << "Erreur à l'ouverture !" << endl;
    }

    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main(){
int nbresult=3;
字符串文件名;
双tmp;
cin>>文件名;
cin>>nbresult;
ifstream文件;
打开(filename.c_str());
if(file.is_open())
{

cout如果我理解您的问题,并且如果您仍然被卡住,那么这个过程的概述就是用从文件中的每行值计算的顶部
n
和(默认值:3)填充
向量

每当您需要从文件中的一行中获取未知数量的值时(无论这些值是用逗号还是空格等分隔的),您的方法应该是将整行数据读取到
字符串中,从该行创建
stringsteam
,然后从
stringstream
循环输入值,直到在
stringstream
上遇到
EOF

为什么是
stringstream
而不是直接从文件中读取值?(回答:行控制)。因为
cin
丢弃前导空格,而
'\n'
(换行)如果是空白,则无法确定何时到达直接从文件读取的行尾。通过先读取该行,然后创建一个
stringstream
,您可以简单地读取,直到到达所创建的
stringstream
的末尾,并且在一行中输入所有值

在整个代码中,您需要维护的唯一
向量是按降序排列的和向量。从您创建的
stringstream
读取每个值时,您只需使用一个临时向量,将每个值存储在给定行中,然后在临时v上调用
accumulate
埃克托提供总额

挑战是在程序结束时保持最终结果向量中的前X个和的数量。那里的方法实际上相当简单。如果和是第一个和,只需使用
push_back()
存储它。对于所有后续的和,使用迭代器遍历向量,将已存储的内容与当前和进行比较,直到和大于向量的元素,然后调用
.insert()
方法将当前和插入到结果向量中迭代器引用的元素之前

完成后,只需使用自动范围的
for
循环输出结果向量

有许多不同的方法来实现它,但是按照上面的方法,您可以执行以下操作。代码注释有助于引导您完成它:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <numeric>  /* for accumulate */

int main (int argc, char **argv) {

    if (argc < 2) {     /* validate at least filename given */
        std::cerr << "error: insufficient arguments\n"
                "usage: " << argv[0] << " filename (nresults: 3)\n";
        return 1;
    }

    std::string filename = argv[1],     /* string for filename */
                line;                   /* string to hold line */
    std::vector<int> results;           /* vector of results */
    std::ifstream f;                    /* input file stream */
    size_t nresults = 3, n = 0;         /* num of results, countner */

    if (argc >= 3)  /* if addition arg given, set nresults */
        nresults = std::stoi(argv[2]);

    f.open (filename);      /* open filename */
    if (! f.is_open()) {    /* validate file open for reading */
        perror (("error file open failed " + filename).c_str());
        return 1;
    }

    while (std::getline (f, line)) {    /* read each row of values */
        int val, sum;                   /* current value, line sum */
        std::vector<int> v;             /* vector to hold values */
        std::stringstream s (line);     /* create stringstream from line */
        while ((s >> val))              /* read each value */
            v.push_back (val);          /* add it to vector v */
        sum = accumulate (v.begin(), v.end(), 0);   /* sum values in v */
        if (results.empty())            /* if empty */
            results.push_back (sum);    /* just add */
        else    /* otherwise insert in decreasing order */
            for (auto it = results.begin(); it != results.end(); it++)
                if (sum > *it) {
                    results.insert (it, sum);
                    break;
                }
        if (results.size() > nresults)  /* trim excess elements */
            results.pop_back();
        n++;                            /* increment line count */
    }
    /* output results */
    std::cout << nresults << " greatest sums from " << n << " lines in " << 
                filename << '\n';
    for (auto& p : results)
        std::cout << " " << p;
    std::cout << '\n';
}
如果要验证总和,可以使用简短的
awk
脚本[1]

示例使用/输出

$ ./bin/vector_n_greatest dat/50x5.txt
3 greatest sums from 50 lines in dat/50x5.txt
 3703 3494 3302

$ ./bin/vector_n_greatest dat/50x5.txt 4
4 greatest sums from 50 lines in dat/50x5.txt
 3703 3494 3302 3269

$ ./bin/vector_n_greatest dat/50x5.txt 10
10 greatest sums from 50 lines in dat/50x5.txt
 3703 3494 3302 3269 3268 3168 3146 3126 3057 3039
仔细检查一下,如果你还有其他问题,请告诉我

脚注:

(1.)要输出排序后的行和进行验证,您可以使用简短的
awk
脚本和
sort
,例如

awk '{
    sum = 0
    for (i=1; i<=NF; i++)
        sum += $i
    printf "%-20s (%4d)\n", $0, sum
}' file | sort -r -b -k6.2

回到这里,你以后需要这些数字做什么吗?如果不需要,你不必存储它们。你可以在阅读它们的同时将它们相加,然后将总和转换成一个向量(假设你以后需要这些总和,不能简单地立即打印出来然后忘记它们)。你可以
#include
并使用
double sum=累加(nbres.begin(),nbres.end(),0)
从每行填充
nbres
后,可以非常方便地计算每行的总和。
awk '{
    sum = 0
    for (i=1; i<=NF; i++)
        sum += $i
    printf "%-20s (%4d)\n", $0, sum
}' file | sort -r -b -k6.2
$ awk '{
>     sum = 0
>     for (i=1; i<=NF; i++)
>         sum += $i
>     printf "%-20s (%4d)\n", $0, sum
> }' dat/50x5.txt | sort -r -b -k6.2
 621 960 479 740 903 (3703)
 267 801 905 747 774 (3494)
 640 898 342 777 645 (3302)
 139 967 433 733 997 (3269)
 764 801 686 163 854 (3268)
 978 798 302 896 194 (3168)
 348 817 555 466 960 (3146)
 650 314 999 952 211 (3126)
 669 934 381 104 969 (3057)
 883 547 466 285 858 (3039)
 389 959 886 555 199 (2988)
 ...