2012-04-24 3 views
3

Итак, у меня есть .cpp-файл с функцией, которая получает имя файла, и должна возвращать String с содержимым файла (фактическое измененное содержимое, я модифицировал код, чтобы сделать его более понятным, но у которого нет влияние на мою проблему). Проблема в том, что f.good() возвращает false, и цикл, который читает файл, не работает. КОД:Неужели мой fstream плохой или плохой()?

#include "StdAfx.h" 
#include "Form21.h" 
#include <string> 
#include <fstream> 
#include <iostream> 



    string ReadAndWrite(char* a){ 
    char filename[8]; 
    strcpy_s(filename,a); 
    string output; 
    char c; 
    ifstream f(filename,ios::in); 
    output+= "Example text"; // <-- this writes and returns just fine! 
    c = f.get(); 

    while (f.good()) 
     { 

    output+= c; 
    c= f.get();   
      } 

    return output; 
} 

Кто-нибудь есть идеи о том, почему это происходит? Это связано с тем, что это отдельный .cpp-файл (он даже не выкидывает ошибку при удалении #include <fstream>). Возможно, существует какой-то другой способ создания цикла? Я буду очень рад услышать любые предложения о том, как исправить это или, может быть, другой способ, как достичь моей цели.

ответ

4

Во-первых, нет причин копировать имя файла, которое вы получаете, - вы можете просто использовать его как есть. Во-вторых, почти любая петля вида while (stream.good()), while (!stream.bad()), while (stream) и т. Д., Является почти некорректной ошибкой. То, что вы обычно хотите сделать, это проверить, читают ли некоторые данные.

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

string readfile(std::string const &filename) { 
    std::ifstream f(filename.c_str()); 
    std::string retval; 

    retval << f.rdbuf(); 
    return retval; 
} 

Это прекрасно работает до нескольких десятков килобайт (или так) данных, но начинает замедляться на больших файлов. В таком случае, вы обычно хотите использовать ifstream::read, чтобы получить данные, то вдоль этой общей линии:

std::string readfile(std::string const &filename) { 
    std::ifstream f(filename.c_str()); 

    f.seekg(0, std::ios_base::end); 
    size_t size = f.tellg(); 

    std::string retval(size, ' '); 
    f.seekg(0); 
    f.read(&retval[0], size); 
    return retval; 
} 

Edit: Если необходимо обработать отдельные символы (не только читать их) у вас есть несколько выбор. Один из них - разделить его на фазы, где вы читаете все данные в одну фазу и выполняете обработку в отдельной фазе. Еще одна возможность (если вам просто нужно смотреть на отдельные символы во время обработки) использовать что-то вроде std::transform для чтения данных, сделать обработку, и поместить вывод в строку:

struct character_processor { 
    char operator()(char input) { 
     // do some sort of processing on each character: 
     return ~input; 
    } 
}; 

std::transform(std::istream_iterator<char>(f), 
       std::istream_iterator<char>(), 
       std::back_inserter(result), 
       character_processor()); 
+0

Смотрите, дело в том, что в цикле i фактический должен будет проанализировать каждый символ и изменить некоторые символы на разные, также я добавлю строки. Maby мой ум застрял в моем методе, но я не уверен, что я собираюсь добиться того, что хочу с помощью предлагаемого вами метода. – krishkule

+0

@krishkule: см. Отредактированный ответ. –

0

Я бы установил, что strlen (a) не больше 7 ... Возможно, вы переполнили filename и получили имя файла, которого не существует.

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

string ReadAndWrite(string a) { // string here, if you are into C++ already 
    string filename; // also here 
    filename = a; // simpler 
    string output; 
    char c; 
    ifstream f(filename.c_str()); // no need for ios::in (but needs a char *, not a string 
    output+= "Example text"; // <-- this writes and returns just fine! 
    f >> c; // instead c = f.get(); 

    while (f) // no need for f.good()) 
     { 

     output+= c; 
     f >> c; // again, instead c= f.get();   
     } 

    return output; 
} 
+0

даже если я изменить «имя файла 'со статическим «001.txt», который является необходимым именем файла, он все равно не работает:/ – krishkule

+0

оператор >> это не то же самое, что get(). По умолчанию оператор >> удаляет все пробелы перед выполнением чтения в переменную. –

+0

Это 'while (f)' так же плохо, как 'while (f.good())'. В обычных ситуациях вы не использовали бы ни того, ни другого. –

-3

Может я предлагаю использовать Еореп? http://www.cplusplus.com/reference/clibrary/cstdio/fopen/ Он принимает имя файла и возвращает указатель на файл. С этим вы можете использовать fgets для чтения строки строки по строке http://www.cplusplus.com/reference/clibrary/cstdio/fgets/

+2

Пожалуйста, не надо !!! :-) Потоки C++ гораздо удобнее и безопаснее, автоматически закрываются и т. Д. Это способ сделать это, но нужно знать, как их использовать –

+0

alright then replace fgets with fseek –

+1

Пожалуйста, удалите этот ответ, прежде чем я буду голосовать Это. –

Смежные вопросы