【问题标题】:load a file of 1's and 0's into a char** line by line将 1 和 0 的文件逐行加载到 char** 中
【发布时间】:2016-03-07 07:07:48
【问题描述】:

我有一个文件,在每一行的末尾可能有一个换行符:

111\n
100\n
101

【问题讨论】:

  • 你为什么不使用std::stringstd::vector?鉴于您没有使用它们,为什么要使用malloc 而不是new
  • 出了什么问题。你也在使用 c++ ,如果这真的是 c++ 有很多更好的方法(例如 std::vector 字符串)
  • sizeof(int) 应该是 sizeof(char*)。为什么在这里使用int
  • sizeof(char) 按定义为 1。
  • 这可能会有所帮助:Fixing Segmentation faults in C++

标签: c++ arrays file char istream


【解决方案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 是来自&lt;string&gt; 标头的std::stringgetline 是来自同一个标头的std::getlinevector 是来自&lt;vector&gt; 标头的std::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() );

但这是个好主意吗?不,除非您必须与现有的 C 风格 API 相关联。对于 C++ 代码,最好将其重构为始终使用 C++ std::string

【讨论】:

  • 我需要 char** 中的数据。谢谢你的代码。我将尝试查看 vector const lines 和 char** 是否相同。否则我需要重写我的大部分代码,我最后做了文件读取,认为这很容易。
  • @imonaboat:建议您修复其他代码。这意味着,不使用char**。但是,为了完整起见,我添加了有关如何获取 char** 的信息。
  • 哇,阿尔夫,你帮了很多忙。我能说什么?太感谢了。看起来 c++ 为 C 增加了很多,而且你使用的是最新的 c++(我的编译器这么说)。
  • 你更长的答案真的很有帮助。它展示了如何正确地从 C 迁移到 C++。这是问题的一部分。现在我通过查看您的 sizeof() 评论和我自己的问题更新解决了我的问题。 scanf 确实适用于文件,我将代码添加到我的问题中。
猜你喜欢
  • 1970-01-01
  • 2011-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多