2010-11-03 24 views
6
Bu şimdiye kadar ancak başarılı denedim budur

:kullanarak bir dizeye kısmi dosya akışı Okuma yineleyiciler

std::string ReadPartial(std::ifstream& _file, int _size) 
{ 
    std::istreambuf_iterator<char> first(_file); 
    std::istreambuf_iterator<char> last(_file); 
    std::advance(last, _size); 
    return std::string(first, last); 
} 

Ben tüm dosyayı okumak için biliyorum.

std::string Read(std::ifstream& _file) 
{ 
    std::istreambuf_iterator<char> first(_file); 
    std::istreambuf_iterator<char> last(); 
    return std::string(first, last); 
} 

Ama bu yapmak istediğim şey değil. Boş bir ip alıyorum. İlk ve bir hata ayıklayıcısına baktığımda std :: advanceden sonra bile aynı şeyi işaret ederler.

+0

size görüyor musun? Ayrıca, kullandığınız * gerçek * kodu lütfen gönderin. Yukarıdaki kod bile derlenmiyor (DÜZENLEME: Charles düzeltmeden önce…). –

+0

Tamam, derleme hatasını düzelttim.Çok kötüyüm. Kafamın dışına yazıyordum. –

+0

HTML kullanmanıza gerek yok, işaretleme harika çalışıyor. –

cevap

5

Yineleyicileri kullanmak istediğiniz belirli bir neden var mı? Sadece tek bir seferde bayt okuyabilir:

std::string s(_size, '\0'); 
_file.read(&s[0], _size); 

gerçekten yineleyicinızı kullanarak okumak istiyorsanız

, bunu yapabilirdi:

std::string ReadPartial(std::ifstream& _file, int _size) 
{ 
    std::istreambuf_iterator<char> first(_file); 
    std::istreambuf_iterator<char> last; 
    std::string s; 
    s.reserve(_size); 
    while (_size-- && first != last) s += *first++; 
    return s; 
} 
+0

Hayır gerekli değil. Ama mümkün olup olmadığını bilmek isterim. –

+2

'file.read (& s [0], boyut)' cevabı için teşekkürler, portatif olmayan ve güvensizdir. basic_string, vektörün bitişik depolama garantisine sahip değildir. –

+0

@Steve: Hangi uygulama için bu doğrudur? –

5
std::istreambuf_iterator<char> first(_file); 
std::istreambuf_iterator<char> last(_file); 
std::advance(last, _size); 

istreambuf_iterators Girdi Iterators vardır. En son ilerledikçe, diğer yineleyici de değiştirilir. Onları, bir yineleyici kopyalayabilmeniz, ilerleyebilmeniz, ilerleyebilmeniz ve daha sonra kopyayı ilerleterek aynı diziye sahip olmaları özelliğine sahip İleri İteratörler olarak davranıyorsunuz. Genel durum için

:

template<class InIter, class Size, class OutIter> 
void copy_n(InIter begin, InIter end, Size n, OutIter dest) { 
    for (; begin != end && n > 0; ++begin, --n) { 
    *dest++ = *begin; 
    } 
} 

//... 
std::string ReadPartial(std::istream& file, int size) { 
    std::string result; 
    copy_n(istreambuf_iterator<char>(file), istreambuf_iterator<char>(), 
     size, back_inserter(result)); 
    return result; 
} 

Ancak bu durumda, & sonucu içine IStream :: doğrudan okumak kullanarak, dize boyutlandırma daha iyi olurdu [0] ve son olarak okumak olmadığını kontrol istenen karakter sayısı.

+0

Ancak, yineleyicileri kullanarak benzer bir şey yapmanın bir yolu var mı, yoksa bu konuda bir ifstream'den ileri bir iteratör almak için mi? –

+0

@Allen_SM: Yineleyicileri kullanabileceğinden eminim, daha önce copy_n içerdim. Forward Iterator olan istyonlar için bir iteratör tipi yazabilirsiniz (istyonlar bir seekg metoduna sahip olduğundan), fakat gerek yoktur. –

1

Orada burada yardımcı olabilir standart algoritma, ancak kullanabilirsiniz bu bir:

Bu böyle ReadPartial ile kullanılabilir
template< class InputIterator, class OutputIterator> 
OutputIterator copy_n(InputIterator from, 
         size_t n, 
         OutputIterator to) 
{ 
    while (n) 
    { 
     *to = *from; 
     ++from; 
     ++to; 
     --n; 
    } 
    return to; 
} 

:

gerçek sonuç nedir
std::string ReadPartial(std::ifstream& _file, int _size) 
{ 
    std::istreambuf_iterator<char> first(_file); 
    std::string result; 

    copy_n(first, _size, std::back_inserter(result)); 
    return result; 
} 
İlgili konular