[英]Why can't write full length string (char[]) in a binary file in Turbo C++
在像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個字符。
我是否應該始終將所需大小的1個額外大小。
我的編譯器是Turbo C ++(可能是3.0)。 這是非常古老且已停產的產品。
C樣式的字符串(字符數組)以null結尾。 您無需在文件中存儲空終止符,但是在打印字符串時需要它。
在您的示例中,您使用strcpy
將10個字符的字符串復制到char[10]
。 這是未定義的行為,因為strcpy
將空終止符附加到目標字符串。 您需要使用char[11]
。
在您的示例中,您從文件中讀取了10個字符,然后使用cout
打印它們。 cout
通過空終止符確定字符串的長度。 由於您沒有,因此cout
會讀取字符串末尾的內容。 這也是未定義的行為,但是在大多數情況下通過從結構的下一個字段讀取字符來實現。 您需要在此數組上使用一個空終止符,這意味着您也需要為此將數組大小增加到11。
C / C ++中的字符指針必須以null終止。 這意味着您必須在末尾分配另一個值為'\\ 0'的字符。
還要注意, strcpy
函數會將所有字符從一個字符串復制到另一個字符串,直到遇到\\0
,除非它是一個在編譯過程中存儲為“ hello world \\ 0”的const字符串(例如“ 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] = '\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();
}
字符串文字"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
字節。 否則,將導致意外的問題,包括變量損壞,運行時錯誤或更糟的情況(例如,數據執行)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.