загрузить файл из 1 и 0 в char ** построчно

У меня есть файл, в конце каждой строки, возможно, есть новая строка:

111\n
100\n
101

person imonaboat    schedule 02.12.2015    source источник
comment
Почему вы не используете std::string и std::vector? И учитывая, что вы их не используете, почему вы используете malloc вместо new?   -  person Cheers and hth. - Alf    schedule 03.12.2015
comment
что идет не так. Также вы используете С ++, если это действительно С ++, есть гораздо лучшие способы (например, строка std :: vector)   -  person pm100    schedule 03.12.2015
comment
sizeof(int) должно быть sizeof(char*). Почему здесь используется int?   -  person Cheers and hth. - Alf    schedule 03.12.2015
comment
sizeof(char) равно 1 по определению.   -  person Cheers and hth. - Alf    schedule 03.12.2015
comment
Это может помочь: Исправление ошибок сегментации в C ++   -  person emlai    schedule 03.12.2015
comment
Мне нужны данные в виде символа **. Спасибо за помощь. Мне нужно было бы переписать большую часть моего кода, если std::string и std::vector - единственные решения, я написал файл, прочитанный в последнюю очередь, думая, что это будет легко. Но каждый раз возникает несовместимость.   -  person imonaboat    schedule 03.12.2015


Ответы (1)


В C ++ вы можете загружать строки файла в массив байтовых строк следующим образом:

auto lines_from( istream& is )
    -> vector<string>
{
    string line;
    vector<string> result;
    while( getline( is, line ) )
    {
        result.push_back( line );
    }
    return result;
}

auto main() -> int
{
    vector<string> const lines = lines_from( cin );
    // Use it.
}

Здесь string - это std::string из заголовка <string>, getline - это std::getline из того же заголовка, а vector - это std::vector из заголовка <vector>. Я решил использовать описательное имя для функции lines_from. Однако обычно его называют readall.


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

class C_strings
{
private:
    vector<string>  buffers_;
    vector<char*>   pointers_;
    int             bufsize_;

    C_strings( C_strings const& ) = delete;
    auto operator=( C_strings const& ) -> C_strings& = delete;

public:
    auto pointer() -> char** { return pointers_.data(); }
    auto bufsize() const -> int { return bufsize_; }

    C_strings( vector<string> const& strings, int const bufsize )
        : buffers_( strings )
        , bufsize_( bufsize )
    {
        pointers_.reserve( buffers_.size() + 1 );
        for( string& s : buffers_ )
        {
            s.reserve( bufsize );
            if( s.empty() or s.back() != '\0' ) { s += '\0'; }
            pointers_.push_back( &s[0] );
        }
        pointers_.push_back( nullptr );
    }

    C_strings( C_strings&& other )
        : buffers_( move( other.buffers_ ) )
        , pointers_( move( other.pointers_ ) )
    {}
};

Предположим, вы хотите вызвать функцию с двойной звездочкой, например:

void doublestarfunc( char** const lines )
{
    using std::cout;
    for( char** pps = lines; *pps != nullptr; ++pps )
    {
        if( strlen( *pps ) < 40 ) { strcat( *pps, " < Oh la la!" ); }
        cout << *pps << '\n';
    }
    cout << '\n';
}

Сделать это очень просто:

using namespace std;        // cin, cout
int const columns           = 80;
int const cstring_bufsize   = columns + 1;

auto c_strings = C_strings( lines_from( cin ), cstring_bufsize );
doublestarfunc( c_strings.pointer() );

Но разве это хорошая идея? Нет, за исключением случаев, когда вам нужно иметь отношение к существующему API в стиле C. Для кода C ++ лучше реструктурировать его, чтобы использовать C ++ std::string во всем.

person Cheers and hth. - Alf    schedule 02.12.2015
comment
Мне нужны данные в виде символа **. Спасибо за ваш код. Я постараюсь проверить, совпадают ли константные линии vector ‹string› и char **. В противном случае мне нужно переписать большую часть моего кода, я считал файл последним, думая, что это будет легко. - person imonaboat; 03.12.2015
comment
@imonaboat: Вам следует исправить другой код. Это означает, что char** не используется. Однако для полноты картины я добавляю информацию о том, как получить char**. - person Cheers and hth. - Alf; 03.12.2015
comment
Ух ты, Альф, ты очень много сделал, чтобы помочь. Что я могу сказать? Большое спасибо. Похоже, что C ++ многое добавляет к C, и вы используете последнюю версию C ++ (так говорит мой компилятор). - person imonaboat; 03.12.2015
comment
Ваш более длинный ответ действительно полезен. Он показывает, как правильно перейти с C на C ++. Что было частью вопроса. Теперь я решил свою проблему, посмотрев на ваш комментарий sizeof () и мое собственное обновление вопроса. scanf действительно работает с файлами, я добавляю код к своему вопросу. - person imonaboat; 03.12.2015