У меня проблема, и я не знаю, как ее решить. Проблема заключается в следующем:
char * ary = new Char[];
ifstream fle;
fle.open(1.txt, ios_base::binary);
fle.seekg(fle.end);
long count = fle.tellg();
fle.seek(fle.beg);
вот в чем проблема: Файл 1.txt содержит: Hello world !.
когда я выполняю:
ary = new char(count);
fle.read(ary, count);
ари заполнили вот так: Привет, мир! @T # ^ @$ @FF (мусор)
Файл ничего не содержит в нем ничего, что выше.
Платформа: Win 7, VS 2012
Любая идея, как решить эту проблему. (Раскрыты)
(Проблема 2) Теперь я столкнулся с другой проблемой: fle.read иногда читает больше, чем размер, который я дал. Например, если я прошел как fle.read(buffer, 1000), он заканчивается в некоторых случаях (strlen (buffer) = 1500. Как я могу это решить?
С Уважением,
Я думаю, что ваша проблема заключается не в том, что ваш массив содержит мусор, а в том, что вы забыли положить символ нулевого терминатора в конце, а ваш оператор печати не знает, когда остановиться.
Кроме того, вы написали new char(count)
вместо new char[count]
. В первом случае, вы только экземпляр один char
со значением count
в то время как во втором случае вы создаете буфер count
символов.
Попробуй это:
ary = new char[count+1];
fle.read(ary, count);
ary[count] = '\0';
char [] -strings в C обычно заканчиваются нулем. Они являются одним байтом дольше, чем необходимо, а последний байт установлен в 0x00
. Это необходимо, потому что C не имеет возможности рассказать длину массива.
Когда вы читаете двоичные данные из файла, в строку не считывается завершающий нулевой символ. Это означает, что функция типа printf, которая работает с char-массивами неизвестной длины, выведет массив и любые данные, которые происходят после него в памяти, пока не встретит нулевой символ.
Решение: выделите char [] -buffer на один байт дольше, чем длина данных, и установите последний байт в 0
вручную.
Лучшее решение: не используйте char-массивы C-стиля. Сделайте это объектно-ориентированным способом и используйте класс std :: string для представления строк.
Наилучшая проблема заключается в том, что вы выделяете с помощью new char(count)
, который выделяет один char
, инициализированный count
. То, что вы, вероятно, пытались сделать, это new char[count]
. Что вам действительно нужно:
std::vector<char> arr( count );
fle.read( &arr[0], count );
Или, может быть, count + 1
в распределении, если вы хотите получить '\0'
в буфере.
РЕДАКТИРОВАТЬ:
Поскольку у вас все еще есть проблемы: fle.read
никогда не будет читать больше, чем fle.read
. Что fle.gcount()
после чтения?
Если вы это сделаете:
std::vector<char> arr( count );
fle.read( &arr[0], count );
arr.resize( fle.gcount() );
вы должны иметь вектор с точно количеством char
которое вы прочитали. Если вы хотите, чтобы они были строкой, вы можете построить ее из arr.begin(), arr.end()
или даже использовать std::string
вместо std::vector<char>
.
Если вам нужна строка с завершением '\0'
(для интерфейса с устаревшим программным обеспечением), тогда просто создайте свой вектор с размером count + 1
вместо count
, а &arr[0]
будет вашей строкой '\0'
.
Не пытайтесь использовать new char[count]
здесь. Это очень сложно сделать правильно. (Например, для этого потребуется блок try и catch.)
Большинство других ответов пропускают очень важный момент: когда вы делаете ary = new char(count);
вы выделяете A SINGLE CHARACTER, инициализированный символом с count
кода ASCII. Вы должны написать это: ary = new char[count + 1];
char
- это просто другой тип малого целого числа, и вы инициализируете его интегральным значением count
(конечно, преобразованным в char
). И то, что он должен написать, больше похоже на std::vector<char> ary( count + 1);
,
char(32)
вы получите пробел внутри, потому что 32 - это код ASCII для пробела, не так ли?
Мы должны угадать немного здесь, но, скорее всего, это сводится к проблеме с вашей отладкой. Буфер заполнен правильно, но вы неправильно проверяете его содержимое.
Теперь, ary
объявлен как char*
и я подозреваю, что при попытке проверить содержимое ary
вы используете некоторый метод печати, который ожидает массив с нулевым завершением. Но вы не завершаете нулевой массив. И у вас есть переполнение буфера.
Если бы у вас были только напечатанные count
, вы бы не переполнили. И вы не могли бы, если бы у вас был нуль-завершенный массив, не забывая выделять дополнительный символ для нулевого терминатора.
Вместо использования сырых массивов и new
, было бы гораздо разумнее прочитать буфер в std::string
. Вы должны стараться избегать строк с нулевым завершением как можно больше. Вы используете их при взаимодействии с библиотеками, отличными от С++.
Вы читаете символы count
для файла, вам нужно выделить один дополнительный символ, чтобы указать ограничитель строки (\0
).
ary = new char[count + 1];
ary[count] = '\0';
char
. (Что ему действительно нужно, так это std::vector<char> ary( count + 1 );
)
Попробуй это
ary = new char[count + 1];
fle.read(ary,count);
ary[count] = '\0';
Конечный нулевой символ отсутствовал - его нет в файле, его нужно добавить потом
ary[count-1] = '\0'
, вы потеряете последний байт.