SORU
22 Mayıs 2011, Pazar


Std :: LF, CR, CRLF?işlemek için ifstream

Özellikle istream& getline ( istream& is, string& str ); ilgileniyorum. Orada '\n' kaputun altında? tüm yeni satır kodlamaları dönüştürmek için söylemek ifstream yapıcı bir seçenektir getline Ara ve incelikle tüm Satır sonları işlemek için mümkün olmak istiyorum.

GüncellemeAçıklık, hemen hemen her yerde derler ve hemen hemen her yerden giriş alacak bir kod yazmak istiyorum. Ender dosyalar dahil '\r' '\n'. Yazılımın tüm kullanıcılar için rahatsızlık en aza indirmek.

Kolay sorun için çözüm değil, ama standart doğru yol için, esnek bir şekilde tüm metin dosya biçimleri ele olarak hala merak ediyorum.

Tam bir çizgi getline okur, bir '\n', bir dizeye. '\N' akış tüketilen, ama getline dize dahil değil. Şimdiye kadar idare etti, ama olabilir '\r' önce '\n' bu dize içine dahil olur.

three types of line endings metin dosyaları görülen vardır: '\n' geleneksel sona Unıx makineleri, '\r' (sanırım) eski Mac işletim sistemleri ve Windows kullanan bir çift, '\r' izleyerek '\n'.

Sorun getline '\r' dize sonunda. bırakmasıdır

ifstream f("a_text_file_of_unknown_origin");
string line;
getline(f, line);
if(!f.fail()) { // a non-empty line was read
   // BUT, there might be an '\r' at the end now.
}

Editf.good() benim istediğim şey değil bu işaret için Neil için teşekkürler. !f.fail() istiyorum.

Windows metin dosyaları için kolay olan bu elle ben de bu soruyu Düzenle çıkarın, ben. Ama birisi bir dosya sadece içeren yem olacak diye korkuyorum '\r'. Bu durumda, getline bütün dosya, tek bir hat olduğunu düşünerek tüketir herhalde!

.. ve hatta Unicode düşünüyor :-)

.. belki de Destek metin dosyası herhangi bir türü için bir satır aynı anda tüketmek için iyi bir yol var mı?

EditBu, Windows dosyalarını işlemek için kullanıyorum, ama yine de gerek yok hissediyorum! Ve bunun için çatal olmayacak '\r'-sadece dosyaları.

if(!line.empty() && *line.rbegin() == '\r') {
    line.erase( line.length()-1, 1);
}

CEVAP
22 Mayıs 2011, Pazar


Neil, "C çalışma zamanı doğru hat sözleşmesi biten belirli bir platform için ne olursa olsun çözmeli." belirttiği gibi

Ancak, insanlar farklı platformlar arasında metin dosyaları taşıyın, bu yeterli değil. Burada üç Satır sonları işleyen bir işlev ("\r", "\n" ve "\r\n"):

std::istream& safeGetline(std::istream& is, std::string& t)
{
    t.clear();

    // The characters in the stream are read one-by-one using a std::streambuf.
    // That is faster than reading them one-by-one using the std::istream.
    // Code that uses streambuf this way must be guarded by a sentry object.
    // The sentry object performs various tasks,
    // such as thread synchronization and updating the stream state.

    std::istream::sentry se(is, true);
    std::streambuf* sb = is.rdbuf();

    for(;;) {
        int c = sb->sbumpc();
        switch (c) {
        case '\n':
            return is;
        case '\r':
            if(sb->sgetc() == '\n')
                sb->sbumpc();
            return is;
        case EOF:
            // Also handle the case when the last line has no line ending
            if(t.empty())
                is.setstate(std::ios::eofbit);
            return is;
        default:
            t  = (char)c;
        }
    }
}

Ve burada bir test programı

int main()
{
    std::string path = ...  // insert path to test file here

    std::ifstream ifs(path.c_str());
    if(!ifs) {
        std::cout << "Failed to open the file." << std::endl;
        return EXIT_FAILURE;
    }

    int n = 0;
    std::string t;
    while(!safeGetline(ifs, t).eof())
          n;
    std::cout << "The file contains " << n << " lines." << std::endl;
    return EXIT_SUCCESS;
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • BioHunta

    BioHunta

    28 Mayıs 2006
  • Chuck Testa

    Chuck Testa

    14 AĞUSTOS 2011
  • GavinMichaelBooth

    GavinMichael

    26 AĞUSTOS 2006