binaryfiles — Почему нельзя записать строку полной длины (char []) в двоичный файл в переполнении Turbo Stack

В массиве вроде int a[5] мы можем хранить 5 значений от [0] до [4]. не это..?

у меня есть char mobile[10] переменная в моем class и я хранил ровно 10 символов строки в этой переменной. Но когда я читаю его из файла, несколько символов из следующей переменной (объявленной сразу после этой переменной в классе) добавляются в переменную mobile, Потребовались часы, чтобы выяснить, что не так.

Я перепробовал все, что мог, изменив порядок переменных и т. Д.

Наконец я бы установил размер mobile до 11 (char mobile[11]), а затем сохранить его в двоичном файле. Тогда все идет хорошо.

Здесь я создал демонстрационную программу, которая может продемонстрировать мое исследование:

#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <fstream.h>
#include <stdio.h>

class Test
{
public:
char mobile[10], address[30];
};

void main()
{
clrscr();
Test t;
// uncoment below to write to file
/*strcpy(t.mobile, "1234567890");
strcpy(t.address, "Mumbai");

fstream f("_test.bin", ios::binary | ios::out | ios::app);
f.write((char*)&t, sizeof(t));*/

// uncomment below to read from file
/*fstream f("_test.bin", ios::binary | ios::in);
f.read((char*)&t, sizeof(t));
cout << t.mobile << "\t" << t.address;*/

f.close();

getch();
}

Верно ли мое предположение, что я не могу хранить n символов в массиве char[n] при работе с файлами более конкретно с двоичными файлами ..?

Должен ли я всегда брать 1 дополнительный размер необходимого размера .. ??

Мой компилятор — Turbo C ++ (может быть 3.0). Это очень старый и снятый с производства продукт.

0

Решение

символьные указатели в C / C ++ должны заканчиваться нулем. Это означает, что вы должны выделить другой символ со значением ‘\ 0’ в конце.

Также обратите внимание, strcpy Функция копирует все символы из одной строки в другую, пока \0 встречается, если только не является константной строкой (например, «hello world»), которая хранится как «hello world \ 0» во время компиляции.

Попробуйте этот код:

#include <iostream.h>
#include <conio.h>
#include <string.h>
#include <fstream.h>
#include <stdio.h>

class Test
{
public:
char mobile[11], address[30];
};

void main()
{
clrscr();
Test t;
// uncoment below to write to file
strcpy(t.mobile, "1234567890");
strcpy(t.address, "Mumbai");
t.address[10] = '\0';
fstream f("_test.bin", ios::binary | ios::out | ios::app);
f.write((char*)&t, sizeof(t))

// uncomment below to read from file
fstream f("_test.bin", ios::binary | ios::in);
f.read((char*)&t, sizeof(t));
cout << t.mobile << "\t" << t.address;

f.close();

getch();
}
2

Другие решения

Строки в стиле C (массивы символов) заканчиваются нулем. Вам не нужно хранить нулевой терминатор в вашем файле, но он вам нужен при печати строки.

В вашем примере вы используете strcpy скопировать 10-символьную строку в char[10], Это неопределенное поведение, потому что strcpy добавляет нулевой терминатор к строке назначения. Вам нужно использовать char[11],

В вашем примере вы читаете 10 символов из файла и распечатываете их, используя cout, cout определяет длину строки нулевым терминатором. Так как у вас его нет, cout читает за концом вашей строки. Это также неопределенное поведение, но в большинстве случаев работает, считывая символы из следующего поля в структуре. Вам нужен нулевой терминатор для этого массива, что означает, что вам также нужно увеличить размер массива до 11 для этого.

3

Строковый литерал "1234567890" занимает 11 байтов, а не 10!

printf("%d", sizeof("1234567890"));
// 11

Это потому, что компилятор молча добавляет \0 символ — конец строкового маркера — в конце строковых литералов. Этот маркер используется различными функциями для работы со строками, в том числе strcpy,

Теперь следующая строка:

strcpy(t.mobile, "1234567890");

пытается скопировать строку — 10 символов плюс \0 — в t.mobile, поскольку t.mobile длиной 10 байт, \0 переполнится в пространство, используемое пространством других переменных (или хуже).

В вашем примере:

  • strcpy(t.mobile, "1234567890") копирует строку, как и ожидалось, но \0 перетекает в пространство, используемое t.address
  • strcpy(t.address, "Mumbai") копирует строку, как и ожидалось, \0 перезаписывается
  • Результат печати t.mobile должно быть "1234567890Mumbai"

Мораль истории: всегда учитывайте \0 байт при использовании строковых функций Си. Невыполнение этого требования приведет к неожиданный проблемы, включая повреждение переменных, ошибки во время выполнения или хуже (например, выполнение данных).

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector