Запуск функции с ifstream и stringstream несколько раз

#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 .