2017-01-06 4 views
0

Я хочу открыть случайный файл .txt и поместить данные в некоторые строки. Он работает, если я пишу путь в код.ifstream + открытие случайного txt-файла (c_str)

Я не понимаю, почему это не работает.

#include <iostream> 
#include <fstream> 

using namespace std; 

int main() 
{ 
    string file; 

    ifstream filein(file.c_str()); 

    cout << "Insert Path" << endl; 
    cin >> file; 

    cout << file << endl; 

    filein.open(file.c_str(), ios::in); 

    for (string line; getline(filein, line);) { 
     cout << line << endl; 
    } 

    return 0; 
} 
+1

Когда вы натолкнулись на это в отладчике, что такое 'файл'? Что это должно быть? –

ответ

2

Ваше имя файла строка пуста, потому что std::string по умолчанию пустой.

Вы передаете пустую строку (или строку nul) в конструктор ifstream, что в лучшем случае является неопределенным поведением.

0

Попробуйте написать код так:

#include <iostream> 
#include <fstream> 

int main() 
{ 
    std::string file; 

    std::cout << "Insert Path" << std::endl; 
    std::getline(std::cin, file); 

    std::cout << file << std::endl; 

    std::ifstream filein(file); 

    for (std::string line; std::getline(filein, line);) 
    { 
     std::cout << line << std::endl; 
    } 

    return 0; 
} 

Заметных редактирует включает:

  • Теперь мы построение ifstream объекта только тогда, когда это нужно, после того, как file уже хранили данные, которые означает не более неопределенное поведение, и что мы пытаемся открыть файл только после того, как мы узнаем, что такое путь.
  • Мы извлекаем целую строку при хранении до file вместо первого слова, что имеет решающее значение, если ваш путь содержит любые пробелы.
  • Мы просто используем строку file. Нет необходимости звонить c_str().
  • Мы больше не используем using namespace std;. Есть many, many reasons, почему это плохая практика.

EDIT:

Если у вас есть C++ 17-совместимый компилятор, а я собираюсь предложить вам написать код, который выглядит, как это вместо:

#include <iostream> 
#include <fstream> 
//You may need to write #include <experimental/filesystem> 
#include <filesystem> 
#include <string> 

int main() 
{ 
    std::string input_line; 

    std::cout << "Insert Path" << std::endl; 
    std::getline(std::cin, input_line); 

    //You may need to write std::experimental::filesystem 
    std::filesystem::path file_path{input_line}; 
    //This will print the "absolute path", which is more valuable for debugging purposes 
    std::cout << std::filesystem::absolute(file_path) << std::endl; 

    std::ifstream filein(file_path); 

    for (std::string line; std::getline(filein, line);) 
    { 
     cout << line << endl; 
    } 

    return 0; 
} 

Явное использование path объекты сделают ваш код более читабельным и сделают ошибки более явными, а также предоставят вам доступ к поведению, к которому вы в противном случае не смогли бы получить доступ.

+0

Итак, зачем кому-то писать такой код? Что это делает для ОП? Пожалуйста, отредактируйте свой ответ с разъяснениями, такими как разница между вашим кодом ответа и OP. –

+0

@ThomasMatthews Просто сделал. – Xirema

+0

Почему даже default строил 'ifstream'? Вы можете легко заставить его работать с помощью 'std :: string filename; std :: cin >> filename; std :: ifstream fin (имя файла) '. – NathanOliver

0

первый, что вы открываете? до тех пор, пока строка не содержит ничего ???

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

string file "C:\\MyProject\\data.txt"; // let's say a valid path 

ifstream filein(file.c_str()); 

if(filein.fail()) // the condition fails as long as the opening was successfull 
    cout << "failed to open file!" << endl; 

cout << "Insert Path" << endl; 
cin >> file; // let's say the user enters a valid path again: "C:\\MyProject\\test.txt" 

cout << file << endl; 

filein.open(file.c_str(), ios::in); // fail to correct it: 

filein.close(); 
filein.clear(); // very important 

filein.open(file.c_str(), ios::in); // now it's ok! 

for (string line; getline(filein, line);) { 
    cout << line << endl; 
}