在像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)。这是一个非常陈旧和停产的产品。
答案 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
字节。如果不这样做,将导致意外问题,包括变量损坏,运行时错误或更糟(例如数据执行)。