Есть ли способ сбросить файл в исходное состояние? - PullRequest
1 голос
/ 26 марта 2012

Я пытаюсь ввести данные из текстового файла на C ++.Текстовый файл имеет следующий формат:

4 15
3 516
25 52 etc.

Каждая строка содержит два целых числа.Я не знаю, сколько строк в файле, поэтому я могу связать достаточно памяти, и вот как я решил это:

ifstream filein;
filein.open("text.txt",ios::in);
int count=0;

while (!filein.eof())
    {
        count++;
        filein>>temporary;
    }
count=count/2; // This is the number of lines in the text file.

Моя проблема в том, что я не могувыяснить способ сброса

filein

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

Ответы [ 3 ]

5 голосов
/ 26 марта 2012

Вместо того, чтобы отвечать на вопрос, который вы задали, я собираюсь ответить на вопрос, который вы не задавали, а именно:

В: Как я могу прочитать все строки файла, еслиЯ не знаю, сколько там строк?

A: Используйте std::vector<>.

Если вы хотите прочитать все числа независимо от их спаривания:

// all code fragments untested. typos are possible
int i;
std::vector<int> all_of_the_values;
while(filein >> i)
    all_of_the_values.push_back(i);

Если вы хотите прочитать все числа, поместите чередующиеся числа в разные структуры данных:

int i, j;
std::vector<int> first_values;
std::vector<int> second_values;
while(filein >> i >> j) {
    first_values.push_back(i);
    second_values.push_back(j);

Если вы хотите прочитать все числа, сохраните их вкакая-то структура данных:

int i, j;
struct S {int i; int j;};
std::vector<S> values;
while(filein >> i >> j) {
    S s = {i, j};
    values.push_back(s);
}

Наконец, если вы хотите читать файл по очереди, сохраняя первые два числа из каждой строки, отбрасывая оставшуюся часть каждой строки и сохраняя ихопределяемая пользователем структура данных:

std::vector<MyClass> v;
std::string sline;
while(std::getline(filein, sline)) {
  std::istringstream isline(sline);
  int i, j;
  if(isline >> i >> j) {
    values.push_back(MyClass(i, j));
  }
}

В сторону : никогда не используйте eof() или good() в условном цикле.Это почти всегда приводит к ошибочному коду, как в вашем случае.Вместо этого предпочитайте вызывать функцию ввода в условии, как я это делал выше.

2 голосов
/ 26 марта 2012

Я думаю, что у @ Robᵩ почти правильная идея - вместо того, чтобы читать все данные просто для подсчета количества строк, а затем снова читать весь файл, чтобы фактически прочитать данные, используя что-то вроде std::vector ( или std::deque), который будет расширяться по мере необходимости при чтении данных.

В типичном случае, однако, два числа в строке будут связаны друг с другом, и вы, как правило, хотите хранить их таким образом, чтобы непосредственно показать эту связь. Например, они могут быть координатами X и Y точек, в этом случае вы хотите прочитать точки:

class point { 
    int x, y;
};

std::istream &operator>>(std::istream &is, point &p) { 
     return is >> p.x >> p.y;
}

std::ifstream in("myfile.txt");

// create the vector from the data in the file:
std::vector<point> points((std::istream_iterator<point>(in)), 
                           std::istream_iterator<point>());

На несколько другой ноте: даже если вы решите использовать явный цикл, , пожалуйста, не используйте while (!whatever.eof()), чтобы сделать это - это почти наверняка даст сбой. Вы хотите проверить, что чтение данных прошло успешно, поэтому (например), используя класс point выше, вы можете использовать что-то вроде:

 point p;
 while (infile >> p)
     points.push_back(p);
2 голосов
/ 26 марта 2012

Функция: filein.seekg (0, ios::beg);

Вот Ссылка

Вы также должны использовать filein.clear() для сброса бита eof в файле, если вы делаете это таким образом.

И, конечно, если вам нужен лучший метод для того, что вы в конечном итоге пытаетесь сделать, ответ Робо будет гораздо лучше, хотя и более сложным.

...