Разбор строки с переменным количеством записей в C или C ++ (без повышения) - PullRequest
2 голосов
/ 25 июня 2010

У меня есть файл , содержащий строки вида,

double mass, string seq, int K, int TS, int M, [variable number of ints]
688.83       AFTDSK      1      1       0       3384 2399 1200
790.00       MDSSTK      1      3       1       342 2

Мне нужен (желательно простой) способ анализа этого файла без повышения. Если бы число значений в строке было постоянным, я бы использовал решение здесь .

Каждая строка станет объектом класса Peptide:

class Peptide {
    public:
        double mass;
        string sequence;
        int numK;
        int numPTS;
        int numM;
        set<int> parents;
 }

Первые три целых имеют конкретные имена переменных в объекте, в то время как все следующие целые числа должны быть вставлены в набор.


Мне посчастливилось получить два действительно потрясающих ответа, но различия во времени выполнения сделали реализацию C лучшим для меня.

Ответы [ 2 ]

10 голосов
/ 25 июня 2010

Если вы хотите использовать C ++, используйте C ++:

std::list<Peptide> list;
std::ifstream file("filename.ext");

while (std::getline(file, line)) {

    // Ignore empty lines.
    if (line.empty()) continue;

    // Stringstreams are your friends!
    std::istringstream row(line);

    // Read ordinary data members.
    Peptide peptide;
    row >> peptide.mass
        >> peptide.sequence
        >> peptide.numK
        >> peptide.numPTS
        >> peptide.numM;

    // Read numbers until reading fails.    
    int parent;
    while (row >> parent)
        peptide.parents.insert(parent);

    // Do whatever you like with each peptide.
    list.push_back(peptide);

}
3 голосов
/ 25 июня 2010

Лучший способ разобрать текстовый файл ascii, который я знаю, - читать его построчно и использовать strtok. Это функция C, но она разделит ваш ввод на отдельные токены для вас. Затем вы можете использовать функции синтаксического анализа строк atoi и strtod для анализа ваших числовых значений. Для указанного вами формата файла я бы сделал что-то вроде этого:

  string line;
  ifstream f(argv[1]);
  if(!f.is_open()) {
    cout << "The file you specified could not be read." << endl;
    return 1;
  }

  while(!f.eof()) {
    getline(f, line);
    if(line == "" || line[0] == '#') continue;

    char *ptr, *buf;
    buf = new char[line.size() + 1];
    strcpy(buf, line.c_str());

    Peptide pep;
    pep.mass     = strtod(strtok(buf, " "), NULL);
    pep.sequence = strtok(NULL, " ");
    pep.numK     = strtol(strtok(NULL, " "), NULL, 10);
    pep.numPTS   = strtol(strtok(NULL, " "), NULL, 10);
    pep.numM     = strtol(strtok(NULL, " "), NULL, 10);
    while(ptr = strtok(NULL, " "))
      pep.parents.insert(strtol(ptr, NULL, 10));

    cout << "mass: " << mass << endl
         << "sequence: " << sequence << endl
         << "numK: " << numK << endl
         << "numPTS: " << numPTS << endl
         << "numM: " << numM << endl
         << "parents:" << endl;

    set<int>::iterator it;
    for(it = parents.begin(); it != parents.end(); it++)
      cout << "\t- " << *it << endl;
  }
  f.close();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...