2012-03-26 3 views
1

Я пытаюсь ввести данные из текстового файла в 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

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

+1

Вы должны быть в состоянии использовать seekg (если я правильно помню). Вы считали, что используете только вектор? – Corbin

+0

Если «input the data» вы хотите записать значения в этот файл, тогда вам понадобится поток вывода, открытый с соответствующими разрешениями. – AJG85

+0

@Corbin - 'seekg' не очистит' eofbit'. –

ответ

5

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

Q: Как я могу прочитать во всех строках файла, если я дону Не знаете, сколько строк есть?

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() в замкнутом контуре. Это почти всегда приводит к ошибкам кода, как в вашем случае. Вместо этого предпочитайте использовать функцию ввода в условии, как я уже делал выше.

+0

Как я не очень разбираюсь в использовании векторов, как я могу передать значения, которые я читал в массивы, не зная размер этих массивов? Не следует ли мне сначала привязать память к этим массивам? –

+0

Вы не можете передавать значения в массивы, зная сначала размер массива. Если вы новый программист на C++, ** не используйте массивы **. Массивы должны учитываться только для расширенного использования. Начните с гораздо более безопасного и простого в использовании 'std :: vector'. –

+0

Большое спасибо за советы и помощь. Я буду смотреть в векторы сразу. –

2

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

Вот Reference

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

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

+0

Но это оставляет набор 'eofbit'. Если он использует 'seekg', он должен сначала сначала называть' ios :: clear() '. Кроме того, ваш код (и его) будет увеличивать счетчик на один раз слишком много, если файл заканчивается пробелом. –

+0

@ Robᵩ: Исправлен мой ответ. –

+0

@ Robᵩ Только что заметил, если вы вызываете filein >> временный >> wc; то не будет проблем с чтением файла, поскольку касается чтения лишних белых линий. –

2

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

В типичном случае, однако, два числа в строке будут связаны друг с другом, и вы обычно хотите сохранить их таким образом, чтобы показать эту связь напрямую. Например, они могут быть Х и 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); 
+1

+1 для отображения правильной идиомы для чтения данных - 'std :: istream_iterator <>' и пользовательского 'operator >>'. –