簡體   English   中英

為什么在Turbo C ++中不能在二進制文件中寫入全長字符串(char [])

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM