0

在像我们这样的数组中,int a[5]我们可以存储从 a[0] 到 a[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)。这是非常古老且已停产的产品。

4

3 回答 3

3

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

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

在您的示例中,您从文件中读取 10 个字符并使用cout. cout通过空终止符确定字符串的长度。由于您没有,cout请阅读字符串的末尾。这也是未定义的行为,但在大多数情况下,通过从结构中的下一个字段读取字符恰好可以工作。您需要在此数组上使用空终止符,这意味着您还需要将数组大小增加到 11。

于 2012-12-31T20:26:19.223 回答
2

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

另请注意,strcpy函数将所有字符从一个字符串复制到另一个字符串,直到\0遇到,除非它是一个 const 字符串(例如“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();
}
于 2012-12-31T20:26:42.757 回答
1

字符串文字"1234567890"占用 11 个字节,而不是 10 个!

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

这是因为编译器在字符串文字的末尾默默地添加了一个\0字符 - 字符串标记的结尾。此标记由各种字符串操作函数使用,包括strcpy.

现在,以下行:

strcpy(t.mobile, "1234567890");

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

在您的示例中:

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

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

于 2012-12-31T21:19:01.567 回答