2014-06-18 86 views
0

我有一個2維字符數組char** field。我有一個方法get_field()它使這個字符數組的副本,並返回此副本。額外的垃圾值外部尺寸字符陣列

char** Game::get_field() { 
    char** copy = new char*[this->width_field]; 
    for (unsigned int i = 0; i < this->width_field; i++) 
     copy[i] = new char[this->length_field]; 

    for (unsigned int i = 0; i < this->width_field; i++) { 
     for (unsigned int j = 0; j < this->length_field; j++) 
      copy[i][j] = this->field[i][j]; 
    } 

    return copy; 
} 

當我將副本的值輸出到控制檯時,我在每行之後都會得到一些垃圾值。然而,char數組的每一行都包含'\ 0'字符來標記字符串的結尾。經過對調試器的一些調查後,我發現在get_field()方法中,當聲明數組時,額外的垃圾值會增加以外的尺寸。 enter image description here

length_field等於52我得到了51破折號加上'\ 0'字符就像在圖像和之後,一些額外的垃圾值。這些垃圾值從哪裏來,我如何擺脫它們?

[編輯:] 這是做輸出到控制檯的代碼:

char** field = game->get_field(); 
    for (unsigned int i = 0; i < 13; i++) { 
     cout << field[i] << endl; 
    } 

這是代碼的初始場是如何設置:

this->field = new char*[this->width_field]; 
    for (unsigned int i = 0; i < this->width_field; i++) 
     this->field[i] = new char[this->length_field]; 


    this->setup_field(); 


void Game::setup_field(){ 
    this->field[0] = "---------------------------------------------------\n\0"; 
    this->field[1] = "|      |      |\n\0"; 
    this->field[2] = "|      |      |\n\0"; 
    this->field[3] = "|      |      |\n\0"; 
    this->field[4] = "|----     |     ----|\n\0"; 
    this->field[5] = "| |     -|-     | |\n\0"; 
    this->field[6] = "| |    | | |    | |\n\0"; 
    this->field[7] = "| |     -|-     | |\n\0"; 
    this->field[8] = "|----     |     ----|\n\0"; 
    this->field[9] = "|      |      |\n\0"; 
    this->field[10] = "|      |      |\n\0"; 
    this->field[11] = "|      |      |\n\0"; 
    this->field[12] = "---------------------------------------------------\n\0"; 
} 
+0

首先想到的是長度和寬度你認爲他們是什麼? – Ben

+0

是的。用調試器檢查它。 –

+0

有趣的代碼是將數據輸出到控制檯(以及初始化它)的代碼。 – Deduplicator

回答

4

無論是C++標準微軟的實施也不保證不屬於你的內存。

以任何理由訪問它是未定義的行爲=>任何事情都可能發生。

如果你把一個char*不指向一個0結尾的字符串給一個期望的函數,它將訪問超出界限的內存直到它找到一個0或以某種方式崩潰。
這應該足以解釋你的「添加垃圾」。

旁註:是否有任何理由不能在一個塊中分配所有需要的內存?

正如您稍後在提示後添加的那樣,您的複製行是而不是以0結尾的
任何線路的全尺寸:長度+ 1:51可印刷+ 1個換行+ 1終結

提示:如果您無法使用strdup和/或memdup,定義它們自己。

+0

這就是要點。每個char *以'\ 0'結尾,所以我不明白爲什麼在'\ 0'之後並且在數組的維度之外添加了垃圾。 –

+1

@tim_a爲什麼你甚至在數組的維度之外尋找?當然,陣列外部會有垃圾。 –

+0

我不是。但是當做'cout << field [i] << endl'時,垃圾被打印在控制檯中。我得到'length_field'字符,然後添加垃圾。 –

0

你真的不想這樣做。試試這個:

#include <vector> 
#include <string> 

std::vector<std::string> Game::get_field() { 
    std::vector<std::string> copy(this->width_field); 

    for (unsigned int i = 0; i < this->width_field; i++) { 
     for (unsigned int j = 0; j < this->length_field; j++) { 
      copy[i].push_back(this->field[i][j]); 
     } 
    } 

    return copy; 
} 
+0

感謝您的回答。我知道使用STL容器和使用std :: string更容易,但代碼是一個賦值的一部分,它特別提到我必須使用2維char數組。 –

+2

請注意,您正在使用2D字符指針數組。一個二維字符數組只會是'字段[10] [20]',這將是非常簡單的工作。 – uesp

2

當長度域等於52我得到了51個破折號加上 '\ 0' 字符

實際上,你有你的Game::setup_field()串54個字符:

  • 51破折號
  • One \ n
  • One \ 0
  • 一個隱含\ 0結束串

因此,在您的Game::get_field()方法時只複製52個字符(在\ n暫停),你不要複製導致一個未終止字符串\ 0字符。

更好地使用vector<string>,或者在初始化或複製事物時更仔細/明確數組長度。