为什么不能在Turbo C ++中的二进制文件中写入全长字符串(char [])

时间:2012-12-31 20:24:28

标签: c++ binaryfiles file-handling turbo-c++

在像int a[5]这样的数组中,我们可以存储从[0]到[4]的5个值。不是这个..?

我的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();
}

我的假设是正确的,在处理更具体二进制文件的文件时,我无法在char[n]这样的数组中存储n个字符。

我是否应该总是需要1个额外尺寸的所需尺寸.. ??

我的编译器是Turbo C ++(可能是3.0)。这是一个非常陈旧和停产的产品。

3 个答案:

答案 0 :(得分:3)

C样式字符串(char数组)以null结尾。您不需要在文件中存储空终止符,但在打印字符串时需要它。

在您的示例中,您使用strcpy将10个字符的字符串复制到char[10]。这是未定义的行为,因为strcpy将空终止符附加到目标字符串。您需要使用char[11]

在您的示例中,您从文件中读取10个字符,然后使用cout进行打印。 cout通过null终止符确定字符串的长度。由于您没有,cout读取字符串的结尾。这也是未定义的行为,但在大多数情况下通过从结构中的下一个字段读取字符来实现。你需要在这个数组上使用null终止符,这意味着你需要将数组大小增加到11。

答案 1 :(得分:2)

C / C ++中的字符指针必须以null结尾。这意味着您必须在结尾分配另一个值为'\ 0'的字符。

另请注意,strcpy函数将所有字符从一个字符串复制到另一个字符串,直到遇到\0,除非它是一个const字符串(例如“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 :(得分:1)

字符串文字"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"

故事的道德:使用C字符串函数时始终考虑\0字节。如果不这样做,将导致意外问题,包括变量损坏,运行时错误或更糟(例如数据执行)。