P.S. Люди спрашивали, если это домашнее задание ... Это не так - разработчики в моей компании хотят использовать это для отладки выходных данных своего проекта.
Если это не домашняя работа, и это под Linux, почему бы не использовать включенную "sort" программу?
например:.
% printf 'D\x00C\x00\x00B\x00A' | sort -z | od -c
0000000 \0 A \0 B \0 C \0 D \0
0000011
FSF / GNU sort предлагает опцию -z:
-z, --zero-terminated
end lines with 0 byte, not newline
Изменено, чтобы добавить:
Хорошо, учитывая, как вы все еще хотите свой собственный код ...
И, учитывая, как никто еще не опубликовал подход, основанный на STL.
Обратите внимание на использование struct FUNCTOR для сравнения (через stl :: sort ()). И, если хотите, вы всегда можете использовать ostream_iterator (cout, "\ n") вместо этого, чтобы сделать вещи немного более понятными для человека ..
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
/* ifstream won't set EOF-state until we try to read past the end-of-file.*/
/* (Makes for lots of grief trying to read in files...) */
inline bool
IsStreamStillGood( istream & theStream )
{
return theStream && (theStream . peek() != EOF);
}
template<class TYPE> inline void DELETE( TYPE * x)
{
delete x;
x = (TYPE *) NULL;
}
struct FUNCTOR
{
bool operator()(const string & x, const string & y) { return x < y; }
};
int
main(int argc, char **argv)
{
istream * stream;
vector<string> v;
UASSERT( argc, >, 1 );
const int recordSize = atoi( argv[1] );
char buffer [ recordSize + 1 ];
UASSERT( recordSize, >, 0 );
if ( argc > 2 )
stream = new ifstream( argv[2] );
else
stream = & cin;
while ( IsStreamStillGood( * stream ) )
{
stream-> read( buffer, recordSize );
v.push_back( string( buffer, stream->gcount() ) );
}
UASSERT( v.back().size(), ==, size_t(recordSize) );
FUNCTOR functor;
sort( v.begin(), v.end(), functor );
copy( v.begin(), v.end(), ostream_iterator<string>(cout) );
if ( argc > 2 )
DELETE(stream);
}
Изменено (еще раз), чтобы добавить:
Вопрос относительно использования строк в вашем подходе STL: так как на входе есть потенциально нулевые символы ('\ 0'), не перепутаются ли строки из-за этого? Кто-то предложил использовать char [], но я подозреваю, что возникнет та же проблема
Если у меня есть char c [10]; , я могу сказать: c [0] = '\ 0'; . То же самое для c [1] или c [9] . Я могу иметь столько нулевых символов в этом массиве, сколько захочу. (Конечно, в зависимости от размера массива.)
Теперь, когда используется c в качестве c-строки, возникает вопрос о том, как долго это будет. Это 1 символ в длину или 9? Обычно в Си это определяется тем, где появляется первый символ NULL.
Такие вещи, как printf (% s) , scanf (% s) , strncat () , strncpy () , strncmp () и т. Д. Не очень довольны символами NULL ('\ 0'), встроенными в наш массив двоичных данных.
Но C ++ std :: string самостоятельно отслеживает длину. По крайней мере, кажется, и это разрешает такие вещи, как: myString.append (10, '\ 0');
Итак, используя stream-> read (buffer, recordSize) , мы читаем в заданном количестве символов (байтов). Нам действительно все равно, являются ли они пустыми ('\ 0') или нет. Все хорошо. Просто дайте мне recordSize количество байтов.
Создавая с помощью v.push_back (string (buffer, stream-> gcount ())) , мы отталкиваем новую строку, содержащую stream-> gcount () chars ( байт). И снова нам все равно, являются ли они пустыми ('\ 0') или нет. Нам просто нужны все stream-> gcount () байтов.
Сортировка использует functor, который использует operator <(const string &, const string &), который использует string :: compare (), который снова будет использовать длину строки и не заботится о том, какие данные на самом деле содержатся в строка. Нули ('\ 0') просто отлично. </p>
Теперь, если мы попытаемся использовать v.back (). C_str (), тогда у нас нет длины, поэтому нулевые значения приведут нас в замешательство. Но пока мы используем строковый объект (например, v.back ()), содержащий как данные, так и длину, у нас все хорошо.
Что приводит нас к выводу. И снова мы выводим строку, а не myString.c_str (), поэтому все символы в строке печатаются. Нули ('\ 0') включены.