ФАЙЛ * и istream: соединить два?

@Ketan

... повышает пропущенную деталь относительно намерения по сравнению с производительностью. Существуют времена, когда мы хотим использовать проход ++ вместо ++ проход.

, Очевидно, сообщение и преинкремент имеют различную семантику, и я уверен, что все соглашаются, что, когда результат используется, необходимо использовать соответствующий оператор. Я думаю, что вопрос - то, что должно каждый делать, когда результат отбрасывается (как в for циклы). Ответ на этот вопрос (по моему скромному мнению), состоит в том, что, так как соображения производительности незначительны в лучшем случае необходимо сделать то, что является более естественным. Для меня ++i является более естественным, но мой опыт говорит мне, что я нахожусь в меньшинстве, и использование i++ вызовет меньше металла наверху для большинство люди, читающие Ваш код.

, В конце концов, это - причина, которой язык не называют" ++C ". [*]

[*] Вставляют обязательное обсуждение [приблизительно 114] являющиеся более логическим именем.

8
задан skaffman 20 January 2011 в 13:56
поделиться

3 ответа

Стандартного способа не существует, но если вам нужно быстрое решение, вы можете получить дескриптор файла с помощью fileno (), а затем использовать Josuttis ' fdstream . Могут быть подобные попытки, но я использовал это в далеком прошлом, и он работал нормально. По крайней мере, это должна быть очень хорошая карта для реализации вашего собственного.

4
ответ дан 5 December 2019 в 09:26
поделиться

Sure there's a way, implement your own istream that can be constructed from a FILE*.

If you're asking whether there is a standard way to do this, then no.

1
ответ дан 5 December 2019 в 09:26
поделиться

Вы можете уйти, создав классы std :: basic_streambuf или std :: streambuf.
Что-то вроде этого:

#include <stdio.h>
#include <iostream>

#define BUFFER_SIZE     1024

class popen_streambuf : public std::streambuf {
public:
    popen_streambuf() : fp(NULL) {
    }
    ~popen_streambuf() {
        close();
    }
    popen_streambuf *open(const char *command, const char *mode) {
        fp = popen(command, mode);
        if (fp == NULL)
            return NULL;
        buffer = new char_type[BUFFER_SIZE];
        // It's good to check because exceptions can be disabled
        if (buffer == NULL) {
            close();
            return NULL;
        }
        setg(buffer, buffer, buffer);
        return this;
    }
    void close() {
        if (fp != NULL) {
            pclose(fp);
            fp = NULL;
        }
    }
    std::streamsize xsgetn(char_type *ptr, std::streamsize n) {
        std::streamsize got = showmanyc();
        if (n <= got) {
            memcpy(ptr, gptr(), n * sizeof(char_type));
            gbump(n);
            return n;
        }
        memcpy(ptr, gptr(), got * sizeof(char_type));
        gbump(got);

        if (traits_type::eof() == underflow()) {
            return got;
        }
        return (got + xsgetn(ptr + got, n - got));
    }
    int_type underflow() {
        if (gptr() == 0) {
            return traits_type::eof();
        }
        if (gptr() < egptr()) {
            return traits_type::to_int_type(*gptr());
        }
        size_t len = fread(eback(), sizeof(char_type), BUFFER_SIZE, fp);
        setg(eback(), eback(), eback() + (sizeof(char_type) * len));
        if (0 == len) {
            return traits_type::eof();
        }
        return traits_type::to_int_type(*gptr());
    }
    std::streamsize showmanyc() {
        if (gptr() == 0) {
           return 0;
        }
        if (gptr() < egptr()) {
            return egptr() - gptr();
        }
        return 0; 
    }
private:
    FILE *fp;
    char_type *buffer;
};

int main(int argc, char *argv)
{
    char c;
    popen_streambuf sb;
    std::istream is(&sb);

    if (NULL == sb.open("ls -la", "r")) {
        return 1;
    }

    while (is.read(&c, 1)) {
        std::cout << c;
    }

    return 0;
}
13
ответ дан 5 December 2019 в 09:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: