Если я понимаю ваши вопросы, и если вы все еще застряли, то обзор процесса будет просто заполнять vector
верхними n
суммами (по умолчанию: 3), вычисленными из каждой строки значений в файле,Вы хотите получить значение в порядке убывания.
Всякий раз, когда вам нужно получить неизвестное количество значений из строки в файле (независимо от того, разделяются ли значения запятыми или пробелами и т. Д.), Ваш подходследует прочитать всю строку данных в string
, создав stringsteam
из строки, а затем зацикливая ввод значений от stringstream
до тех пор, пока EOF
не встретится на stringstream
.
Почему stringstream
, а не просто читать значения непосредственно из файла?(Ответ: линия-контроль).Так как cin
отбрасывает начальные пробелы, а '\n'
(новая строка) - пробелы, невозможно определить, когда вы достигнете конца строки, читающей непосредственно из файла.Читая сначала строку, а затем создавая stringstream
, вы можете просто читать, пока не достигнете конца созданного вами stringstream
- и вы введете все значения в одну строку.
Единственный vector
, который вам нужно поддерживать в коде, - это вектор сумм в убывающем порядке.При чтении каждого из значений из stringstream
, который вы создаете, вы можете просто использовать временный вектор для хранения каждого из значений в данной строке, а затем вызвать accumulate
для временного вектора, чтобы получить сумму.
Задача состоит в том, чтобы поддерживать максимальное число сумм в вашем векторе конечных результатов для вывода в конце программы.Подход там на самом деле довольно простой.Если сумма является первой суммой, просто используйте 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';
}
( note: код ожидает имя файла в качестве 1-го аргумента, а затем принимает необязательный аргумент числа topсуммы для отчета - используется значение по умолчанию 3
)
Пример входного файла
Следующий ввод был просто получен путем записи 50 строк, содержащих 5 случайных значений между 0 - 999
:
$ cat dat/50x5.txt
106 114 604 482 340
815 510 690 228 291
250 341 774 224 545
174 546 537 278 71
706 139 767 320 948
328 683 410 401 123
140 507 238 744 990
810 559 732 732 20
24 982 361 30 439
139 204 217 676 714
288 615 853 287 935
801 847 851 211 249
206 583 756 676 328
978 486 119 711 219
139 967 433 733 997
872 104 433 89 12
147 609 627 0 897
795 34 744 878 477
225 84 61 982 761
621 960 479 740 903
930 112 870 364 77
99 468 181 532 790
193 911 399 53 912
296 80 178 273 958
887 498 274 180 712
267 801 905 747 774
40 677 118 911 273
195 242 974 376 775
764 801 686 163 854
830 692 166 240 197
124 128 927 399 540
640 898 342 777 645
348 817 555 466 960
60 661 203 34 269
978 798 302 896 194
389 959 886 555 199
83 680 559 10 311
100 882 209 442 659
87 22 709 874 488
669 934 381 104 969
650 314 999 952 211
193 341 170 79 129
601 394 809 161 637
352 261 519 793 935
411 112 957 352 986
677 21 153 58 358
122 708 672 353 892
883 547 466 285 858
595 887 253 636 48
122 220 541 641 245
Если вы хотите проверить суммы, вы можете использовать короткий 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
awk
вывод для файла примера будет выглядеть так:
$ 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)
...