2012-02-23 3 views
0

Я хочу, чтобы иметь возможность читать в файле с именем doc.txt произвольной длины и не получить seg-ошибку, я знаю, что мне приходится выделять кучу, но у меня возникают проблемы с этим. я хочу притворяться, как будто у меня нет способа узнать размер файла или получить размер файла, просто прочитайте, как много там есть и выложите кучу, я хочу, чтобы единственным ограничением был размер физической машины памяти.выделите кучу

#include <iostream> 
#include <string> 
#include <fstream> 

using namespace std ; 

int main() { 

    char *file_name = "doc.txt" ; 

    ifstream fin ; 
    fin.open(file_name) ; 

    if(! fin) { 
     cout << "Problems opening " << file_name << endl ; 
     return -1 ; 
    } 

    const unsigned MAX = 100 ; 
    string doc[MAX] ; 

    unsigned word_count = 0 ; 
    //while(fin >> doc[ word_count++ ]) ; 

    while(fin >> doc[ word_count ]) { 
     cout << doc[ word_count ] << endl ; 
     word_count ++ ; 
    } 
    fin.close() ; 

    return 0 ; 
} 
+0

Должно быть ** const ** 'char * file_name =" doc.txt ";'. – iammilind

+0

Как насчет использования std :: vector ? –

+1

Почему вы хотите притвориться, что вы не можете найти размер файла? 'malloc' хотел бы, чтобы вы узнали. – Dave

ответ

0

Лучше всего, вероятно, использовать STL контейнер как vector. Они позволяют динамически распределять память по мере необходимости.

vector<string> doc; 
string word; 

while (!fin.eof()) 
{ 
    fin >> word; 
    doc.push_back(word); 
    cout << word << end; 
} 
+2

Мэтт имеет правильную идею здесь. Хорошее эмпирическое правило при написании C++ должно быть таким же ленивым, насколько возможно. Каждый раз, когда у вас возникает вопрос об архитектуре вашего кода, ваша первая мысль должна быть посмотрите на STL (и, в меньшей степени, Boost), чтобы узнать, не разрешил ли кто-то другой проблему. – pg1989

+2

Этот метод тестирования для 'eof' - это плохая практика. [Пожалуйста, прочтите это.] (http: // stackoverflow .com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-accepted-wrong) – Blastfurnace

+0

Я хочу использовать связанный список и предположить, что я не знаю размер размера – ourmando

2

Хорошо, если я понимаю, что вы здесь делаете, вы читаете массив, называемый doc. Однако, поскольку массивы должны быть распределены статически, вы не выполняете свою задачу, чтобы это было более динамичным. Есть способы сделать это, например, использовать vector, как и

vector<string> doc; 
string newestInput; 
while(fin >> newestInput) { 
    cout << newestInput << endl ; 
    doc.push_back(newestInput); 
} 
+0

Почему вы отказали мне в ответе? Пожалуйста, предложите некоторое обоснование. – jozefg

+1

Я отдал тебе верх. Ваш код правильно обрабатывает условие 'eof', в отличие от другого опубликованного ответа. – Blastfurnace

+0

@ Blastfurnace вы могли бы объяснить это? 'ios :: eof()' существует именно по этой причине, см., например, соответствующий раздел [здесь] (http://www.cplusplus.com/doc/tutorial/files/) –

0

Вы можете использовать std::vector и хранить слова/строки в там, что, как вы не имеют знать размер.

Это хорошая справочная статья по файлу I/O here. При чтении текстового файла, они читают построчно в while(myFile.good()) петли и получить текущую строку, используя getline(myFile, line) где myFile ваш объект ifstream и line является строкой, которую вы хотите сохранить текущую строку в.

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

И, просто из любопытства, для чего вы используете оператор >>? Не удалось ли достичь этого с помощью getline()?

1

Нераспределяя все пространство заранее, имеет смысл только в том случае, если вы не намерены читать весь файл. Если это действительно так, то у вас есть несколько вариантов:

  • Прочитайте файл в куски (либо заданной длины, или линии) и хранить их в std::list<std::string>. Вы также можете использовать std::vector<std::string>, но это переназначает память по мере ее роста, что может привести к нехватке памяти раньше, чем это необходимо (из-за фрагментации и необходимости сохранения как старого, так и нового блока памяти «живым» при одном и том же время, пока элементы копируются).
  • Под Windows, используйте VirtualAlloc в резерв объем памяти, равным размеру файла, а затем совершить его страницу за страницей, как вы читаете файл. Таким образом, вы никогда не будете совершать больше, чем вам действительно нужно.
  • Под Windows используйте файл с отображением памяти.

Кстати, вы можете получить размер файла в (в основном) переносимым способом, используя функцию _stat (читать st_size поле).

+0

+1 для поднятия некоторых хороших аспектов. Re list vs vector-list также может отнимать память, поскольку каждый узел распределяется из кучи, что влечет за собой накладные расходы на управление и часто округление размера (возможно, до следующей мощности 2). Таким образом, не такой четкий разрез, который может потерпеть неудачу сначала, как может показаться. Отдельно, большинство ОС, включая UNIX/Linux, также имеют файлы с отображением памяти и способы получения размера файла: http://stackoverflow.com/questions/5840148/how-can-i-get-a-files-size -в-с –