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

Why can't write full length string (char[]) in a binary file in Turbo C++

本文关键字:字符串 char Turbo C++ 二进制文件 为什么      更新时间:2023-10-16

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

我在我的class中有一个char mobile[10]变量,我在这个变量中存储了正好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个字符,当更具体地使用二进制文件处理文件时…?

我应该总是带一个额外的尺寸…??

我的编译器是Turbo c++(可能是3.0)。

c风格的字符串(char数组)以空结束。您不需要在文件中存储空终止符,但是在打印字符串时需要它。

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

在您的示例中,您从文件中读取10个字符并使用cout打印它们。cout通过空终止符确定字符串的长度。因为你没有一个,cout读取超过字符串的结束。这也是未定义的行为,但在大多数情况下,通过从结构体中的下一个字段读取字符来工作。在这个数组上需要一个空终止符,这意味着您还需要将数组大小增加到11。

C/c++中的

字符指针必须以空结束。这意味着您必须在末尾分配另一个值为''的字符。

还请注意,strcpy函数将所有字符从一个字符串复制到另一个字符串,直到遇到,除非它是一个const字符串(例如"hello world"),在编译期间存储为"hello world"。

试试这个代码:

#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] = '';
    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();
}

字符串字面值"1234567890"占用11字节,而不是10!

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

这是因为编译器在字符串字面值的末尾静默地添加了一个字符——字符串结束标记。该标记用于各种字符串操作函数,包括strcpy

现在,下面一行:

strcpy(t.mobile, "1234567890");

尝试将字符串(10个字符加上)复制到t.mobile。由于t.mobile是10字节长,将溢出到其他变量使用的空间(或者更糟)。

在你的例子中:

  • strcpy(t.mobile, "1234567890")按预期复制字符串,但溢出到t.address
  • 使用的空间。
  • strcpy(t.address, "Mumbai")按预期复制字符串,被覆盖
  • 打印t.mobile的结果应该是"1234567890Mumbai"

这个故事的寓意:当使用C字符串函数时,总是考虑字节。如果不这样做,将导致意想不到的问题,包括变量损坏,运行时错误,或者更糟(例如数据执行)。

相关文章: