#c #c 11 #ifstream #sstream
#c #c 11 #ifstream #sstream
Вопрос:
Я довольно новичок в c , и я хотел бы попросить предложений / советов, если есть лучший / более оптимальный способ использования функции, вызывающей ifstream и string stream.
У меня есть документ со структурой из 150 строк и 8 столбцов (небольшое подмножество с упрощенными значениями):
5.43e-08 0.0013 0.0105 0.013 0.026 0.068 0.216 0.663
6.98e-08 0.0004 0.0188 0.022 0.103 0.854 0 0
7.31e-08 0.0004 0.0125 0.017 0.074 0.895 0 0
5.82e-08 0.0006 0.0596 0.075 0.150 0.713 0 0
номер каждой строки представляет позицию (позиция 1 … позиция 150), а каждый столбец — вероятность качества (Qual1 .. Qual8). Моя цель — выполнить выборку из каждой строки, каждая из которых представляет распределение качества, чтобы создать строку качеств для всех 150 позиций. Я создал функцию, которая может это сделать.
std::string Qual(std::ifstream amp;infile){
std::string line;
double Q_1,Q_2,Q_3,Q_4,Q_5,Q_6,Q_7,Q_8;
char Qualities[] = {'1', '2', '3', '4' ,'5', '6', '7','8',''};
std::string Read_qual;
while (std::getline(infile, line)){
std::stringstream ss(line);
ss >> Q_1 >> Q_2 >> Q_3 >> Q_4 >> Q_5 >> Q_6 >> Q_7 >> Q_8;
std::srand(std::time(nullptr));
std::random_device rd;
std::default_random_engine gen(rd());
std::discrete_distribution<> d({Q_1,Q_2,Q_3,Q_4,Q_5,Q_6,Q_7,Q_8});
Read_qual = Qualities[d(gen)];
}
return Read_qual;
}
Проблема в том, что мне приходится многократно использовать эту функцию для создания нескольких таких распределений на основе какого-либо другого ввода. И, насколько я могу прочитать здесь о переполнении стека, я должен использовать .clear() и seekq, чтобы сохранить файл открытым, но все равно использовать его.
int main(int argc,char **argv){
std::ifstream infile("Freq.txt");
std::cout << Qual(infile) << std::endl;
infile.clear();
infile.seekg(0);
std::cout << "-------" << std::endl;
std::cout << Qual(infile);
return 0;
}
Мой вопрос:
Есть ли более идеальное решение для достижения этой цели при использовании c . Как и любые функции, которые, возможно, быстрее. Кто-нибудь может предложить какие-либо предложения?
лучше ли продолжать открывать и закрывать файл?
Комментарии:
1. Ничего плохого в том, что у вас есть, IMO, сохраняйте простоту.
2. Сначала прочитайте данные в коллекцию, а затем используйте эти данные несколько раз.
3. Спасибо, ребята!, поэтому с таким контейнером, как vector (аналогично приведенному ниже), не могли бы вы предложить передать поток ss, а затем случайную выборку из него.? или просто сразу поместить случайную выборку в контейнер.
4. Почему вы должны использовать infile.clear() и infile. seekg(0)? Я полагаю, вы будете повторять этот процесс 150 раз и каждый раз подбирать 8 дублей следующей строки для тестирования дистрибутива. Если вы создаете infile. seekg(0) перед каждым вызовом Qual вы всегда будете читать одно и то же число 8 в первой строке.
5. @ytlu, спасибо за ваш вопрос.! Чтобы было понятно, сам файл состоит из 150 строк, каждая из которых содержит 8 столбцов. Поэтому я создаю для каждой строки случайное распределение этих 8 столбцов, где затем я выбираю один символ с помощью «Read_qual = Качества [d (gen)];», что дает мне 150 значений качества (по одному значению на строку). Я должен повторить этот процесс, скажем, 2000 раз, но для того, чтобы я мог повторить этот процесс, я должен использовать infile.clear() между вызовом функции. Что, по моему мнению, не было идеальным, отсюда и вопрос 🙂
Ответ №1:
Мое предложение:
std::string Qual(double *a)
{
std::string line;
char Qualities[] = {'1', '2', '3', '4' ,'5', '6', '7','8',''};
std::string Read_qual;
std::srand(std::time(nullptr));
std::random_device rd;
std::default_random_engine gen(rd());
std::discrete_distribution<> d({a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]);
Read_qual = Qualities[d(gen)];
return Read_qual;
}
и main()
int main()
{
std::ifstream infile("Freq.txt");
double alldata[150][8];
for (int i=0, i<150; i )
for (int j=0; j<8; j ) infile >> alldata[i][j];
infile.close();
for (int idx = 0; idx < 2000; idx )
{
for (int row = 0; row < 150; row )
std::cout << Qual(alldata[row]) << std::endl;
}
return 0;
}
Ответ №2:
Давайте попробуем кэширование
Полностью непроверенный неполный код
struct row { // your type that goes into the distribution
double Q_1,Q_2,Q_3,Q_4,Q_5,Q_6,Q_7,Q_8;
};
using QualData = std::vector<row>; // typedef
QualData ReadData(std::ifstream amp;infile) {
std::string line;
double Q_1,Q_2,Q_3,Q_4,Q_5,Q_6,Q_7,Q_8;
char Qualities[] = {'1', '2', '3', '4' ,'5', '6', '7','8',''};
std::string Read_qual;
QualData qual;
while (std::getline(infile, line)){
std::stringstream ss(line);
ss >> Q_1 >> Q_2 >> Q_3 >> Q_4 >> Q_5 >> Q_6 >> Q_7 >> Q_8;
qual.emplace_back(Q_1,Q_2,Q_3,Q_4,Q_5,Q_6,Q_7,Q_8);
}
return qual;
}
... do qual
int main(int argc,char **argv){
std::ifstream infile("Freq.txt");
auto qualData = ReadData(infile);
std::cout << Qual(qualData) << std::endl;
std::cout << "-------" << std::endl;
std::cout << Qual(qualData);
return 0;
}
Вы можете представить, что еще нужно изменить.
Комментарии:
1. Спасибо за предложение. поскольку я новичок в c , я должен спросить. Итак, вы создаете вектор, используя структуры для хранения строк. А затем с помощью «QualData ReadData (std:: ifstream amp; infile)» вы вызываете вектор, а затем вставляете строку в конец вектора с помощью emplace_back . Итак, ReadData — это функция с векторным типом? потому что я никогда не видел, чтобы это было написано раньше с использованием QualData = std::vector<строка>;
2. @RAHenriksen это новая форма typedef, ее гораздо легче читать.
3. Я предлагаю прочитать каждую строку, в которой 8 удваивается в main() в массив [8] или вектор <double>(8) , и передать массив в funciton Qual .