У меня есть файл, в конце каждой строки, возможно, есть новая строка:
111\n
100\n
101
У меня есть файл, в конце каждой строки, возможно, есть новая строка:
111\n
100\n
101
В 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
во всем.
char**
не используется. Однако для полноты картины я добавляю информацию о том, как получить char**
.
- person Cheers and hth. - Alf; 03.12.2015
std::string
иstd::vector
? И учитывая, что вы их не используете, почему вы используетеmalloc
вместоnew
? - person Cheers and hth. - Alf   schedule 03.12.2015sizeof(int)
должно бытьsizeof(char*)
. Почему здесь используетсяint
? - person Cheers and hth. - Alf   schedule 03.12.2015sizeof(char)
равно 1 по определению. - person Cheers and hth. - Alf   schedule 03.12.2015std::string
иstd::vector
- единственные решения, я написал файл, прочитанный в последнюю очередь, думая, что это будет легко. Но каждый раз возникает несовместимость. - person imonaboat   schedule 03.12.2015