C ++ мусор в конце файла

0

У меня проблема, и я не знаю, как ее решить. Проблема заключается в следующем:

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. Как я могу это решить?

С Уважением,

Теги:

7 ответов

3
Лучший ответ

Я думаю, что ваша проблема заключается не в том, что ваш массив содержит мусор, а в том, что вы забыли положить символ нулевого терминатора в конце, а ваш оператор печати не знает, когда остановиться.

Кроме того, вы написали new char(count) вместо new char[count]. В первом случае, вы только экземпляр один char со значением count в то время как во втором случае вы создаете буфер count символов.

Попробуй это:

ary = new char[count+1];
fle.read(ary, count);
ary[count] = '\0';
  • 0
    Спасибо. Это сделало то, что я хочу, вместо того, чтобы увеличивать буфер, я просто сделал ary [count -1] = '\ 0', иначе мне придется изменить размер буфера приемника, если я не ошибаюсь.
  • 0
    Если вы выполните ary[count-1] = '\0' , вы потеряете последний байт.
Показать ещё 5 комментариев
5

char [] -strings в C обычно заканчиваются нулем. Они являются одним байтом дольше, чем необходимо, а последний байт установлен в 0x00. Это необходимо, потому что C не имеет возможности рассказать длину массива.

Когда вы читаете двоичные данные из файла, в строку не считывается завершающий нулевой символ. Это означает, что функция типа printf, которая работает с char-массивами неизвестной длины, выведет массив и любые данные, которые происходят после него в памяти, пока не встретит нулевой символ.

Решение: выделите char [] -buffer на один байт дольше, чем длина данных, и установите последний байт в 0 вручную.

Лучшее решение: не используйте char-массивы C-стиля. Сделайте это объектно-ориентированным способом и используйте класс std :: string для представления строк.

2

Наилучшая проблема заключается в том, что вы выделяете с помощью 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.)

2

Большинство других ответов пропускают очень важный момент: когда вы делаете ary = new char(count); вы выделяете A SINGLE CHARACTER, инициализированный символом с count кода ASCII. Вы должны написать это: ary = new char[count + 1];

  • 0
    Два нита (потому что у вас есть правильный ответ, в отличие от всех остальных): нет ASCII участвует здесь. char - это просто другой тип малого целого числа, и вы инициализируете его интегральным значением count (конечно, преобразованным в char ). И то, что он должен написать, больше похоже на std::vector<char> ary( count + 1); ,
  • 0
    @James Почему не участвует ASCII? Когда вы напишите char(32) вы получите пробел внутри, потому что 32 - это код ASCII для пробела, не так ли?
Показать ещё 1 комментарий
1

Мы должны угадать немного здесь, но, скорее всего, это сводится к проблеме с вашей отладкой. Буфер заполнен правильно, но вы неправильно проверяете его содержимое.

Теперь, ary объявлен как char* и я подозреваю, что при попытке проверить содержимое ary вы используете некоторый метод печати, который ожидает массив с нулевым завершением. Но вы не завершаете нулевой массив. И у вас есть переполнение буфера.

Если бы у вас были только напечатанные count, вы бы не переполнили. И вы не могли бы, если бы у вас был нуль-завершенный массив, не забывая выделять дополнительный символ для нулевого терминатора.

Вместо использования сырых массивов и new, было бы гораздо разумнее прочитать буфер в std::string. Вы должны стараться избегать строк с нулевым завершением как можно больше. Вы используете их при взаимодействии с библиотеками, отличными от С++.

0

Вы читаете символы count для файла, вам нужно выделить один дополнительный символ, чтобы указать ограничитель строки (\0).

ary = new char[count + 1];
ary[count] = '\0';
  • 0
    Это все еще только выделяет один char . (Что ему действительно нужно, так это std::vector<char> ary( count + 1 ); )
  • 0
    Правильно. Исправленный.
0

Попробуй это

ary = new char[count + 1];
fle.read(ary,count);
ary[count] = '\0';

Конечный нулевой символ отсутствовал - его нет в файле, его нужно добавить потом

Ещё вопросы

Сообщество Overcoder
Наверх
Меню