2010-11-04 69 views
3

我正在做的家庭作業項目使用靜態和動態數組。然而,我還沒有實現動態數組,這是一個奇怪的差異,試圖獲得我的靜態數組的長度。試圖避免分段錯誤,但我的輸出看起來很奇怪(C++)

我用了一系列的cout語句,試圖找出什麼是給我一個分段錯誤,因爲該過程看起來簡單。我發現在我的驅動程序中,它正在計算正確的範圍和長度,但是一旦我將該數組傳遞到用戶定義的類函數中,在同一個數組上執行的相同語句就會得到不同的結果。

我的司機功能:

using namespace std; 

#include <iostream> 
#include "/user/cse232/Projects/project07.string.h" 

int main() 
{ 
    const char string1[] = {'a', 'b', 'c', 'd', 'e', 'f'}; 
    String test1(); 
    cout << "Size of array: " << sizeof(string1) << endl; 
    cout << "Size of item in array: " << sizeof(char) << endl; 
    cout << "Length of array: " << (sizeof(string1)/sizeof(char)) << endl; 
    cout << "Range of array" << (sizeof(string1)/sizeof(char))-1 << endl << endl; 

    String test2(string1); 
} 

在運行的時候,我從驅動器的輸出:

Size of array: 6 
Size of item in array: 1 
Length of array: 6 
Range of array5 

我的支持文件:

/* Implementation file for type "String" */ 

using namespace std; 

#include <iostream> 
#include "/user/cse232/Projects/project07.string.h" 

String::String(const char Input[]) 
{ 

    cout << "Size of array: " << sizeof(Input) << endl; 
    cout << "Size of item in array: " << sizeof(char) << endl; 
    cout << "Length of array: " << (sizeof(Input)/sizeof(char)) << endl; 
    cout << "Range of array" << (sizeof(Input)/sizeof(char))-1 << endl << endl; 

/* Bunch of reallocation stuff that is commented out 
for the time being, unimportant*/ 
} 

String::~String() 
{ 
    Capacity = 0; 
    Length = 0; 
    Mem = NULL; 
} 

這裏是輸出I從支持文件中獲得,

Size of array: 4 
Size of item in array: 1 
Length of array: 4 
Range of array3 

這顯然是不正確的。如果有幫助,這是頭文件(省略未實現的函數)。它是不可改變的:

/****************************************************************************** 
    Project #7 -- Interface file for type "String" 
******************************************************************************/ 

#ifndef STRING_ 
#define STRING_ 

using namespace std; 

#include <iostream> 

class String 
{ 
    private: 

    unsigned Capacity; // Number of memory locations reserved 
    unsigned Length; // Number of memory locations in use 
    char * Mem;   // Pointer to memory to hold characters 

    public: 

    // Construct empty string 
    // 
    String() 
    { 
     Capacity = 0; 
     Length = 0; 
     Mem = NULL; 
    } 

    // Destroy string 
    // 
    ~String(); 

    // Construct string by copying existing string 
    // 
    String(const String&); 

    // Construct string by copying C-style character string 
    // 
    String(const char[]); 

#endif 

我最大的問題是爲什麼我得到兩個單獨的輸出。第一個是我在分配內存時需要使用的一個;否則我會遇到分段錯誤。任何人都可以提供意見

+0

我測試的另一件事是打印輸入在Input [0],Input [1]等支持文件中,它識別出Input [5] ='f',但它並沒有計算出與驅動文件中的數組長度相同的長度和範圍,即使數組相等 – user212562 2010-11-04 17:54:08

+0

請注意,'String test1()'不會**創建​​一個String對象,它反而會向前聲明一個返回String的函數,並且不會接受任何參數。 String test1;'。 – 2010-11-04 18:26:55

回答

10

你的功能實際上是做一些你沒有意識到 - 它衰變你進入一個指向第一個元素的數組。

基本上你的函數簽名:String::String(const char Input[])將相當於簽名String::String(const char *input)

所以當你做sizeof時,你實際上得到的大小是char *,而不是數組的大小。

您不能直接傳遞數組給函數,並期望能夠得到數組的大小。如果你必須使用這樣的原始數組,你可以改變你的函數,這樣你就可以用它傳遞數組的大小。如果你不能修改簽名,那麼你可以做的另一件事是放入一個哨兵值(如\0字節),並使用循環來計算數組的大小。

編輯

我覺得你真的想了解是C-style strings,而不是僅僅使用字符數組是不是空終止。這確實符合你的任務似乎希望你做的模型,並且允許你避免操縱這些不可變的標題。

+2

你正在搜索的詞是「衰變」。 – 2010-11-04 17:59:29

+0

@Konrad,謝謝! – birryree 2010-11-04 18:00:18

+0

有沒有一種方法可以將整個數組傳遞給函數,而不僅僅是指向第一個元素的指針? – user212562 2010-11-04 18:02:02

4

一旦你傳遞一個數組到一個函數,編譯器不再知道它的大小

調用的函數只是看到

foo(char[]) 

它不知道它有多大,該陣列已經成爲一個指針當你要求一個指針的大小你得到4(32位機器上)

的在陣列中不包含其長度的內存中的表示。這是衆所周知的,棘手的問題,其原因的std ::矢量存在

+0

我可以將數組傳遞給一個函數嗎?它可以識別整個數組? – user212562 2010-11-04 18:03:10

+1

如果你的任務不允許使用像std :: vector這樣的奇特C++的東西,那麼你不能,你必須通過長度作爲第二個參數 – pm100 2010-11-04 18:14:27

1

不幸的是你不能傳遞這樣的數組。當你有這樣的功能:

String::String(const char Input[]) 

你只傳入一個指向第一個元素的指針。您還需要將數組的大小傳遞給構造函數。

+0

我不認爲我能夠傳遞兩個參數,因爲.h文件聲明「String(const char []);」。我無法更改.h文件,所以我必須確定一種方法來測量輸入傳遞給函數的長度。 – user212562 2010-11-04 18:00:17

+0

您必須傳遞兩個參數,或者定義一個可以識別最後一個元素的約定。例如,C「字符串」使用NUL(\ 0)字符的約定來標記數組的末尾。 – 2010-11-04 18:02:25

1

其他人已經回答了你的問題,所以我只是補充一點點的想法 - 有一種方式,你可以傳遞一個數組到一個函數,而不會腐爛成一個指針。

const size_t SIZE = 6; //Or whatever other array size you want to pass. 
String::String(const char (&Input)[SIZE]) 
{ 
    //TODO 
} 

因爲它是不容易總是指望你的陣列的尺寸,更好的機制是這樣的 -

template<size_t N> 
String::String(const char (&Input)[N]) 
{ 
    //TODO 
} 

如果你不知道什麼size_t手段,姑且認爲它類似於到int現在,你會最終了解更多(無論是通過自學,還是在一些教科書中,可能是前者)。

的有些怪異的參數功能 -

const char (&Input)[SIZE] 

意味着要傳遞

  • 這就是所謂的Input
  • 這是一個參考的基準(由&表示)到一個由const char組成的數組(注意:如果我已經把&在圓括號之外,如下所示:const char & Input[SIZE],那麼它將被視爲一個數組const char&'s - 因此需要引入圓括號以確保引用是針對數組本身,而不是數組中的每個元素)
  • 數組的大小爲SIZE,其中SIZE必須是常數。

如果你不能確定template線是怎麼一回事,這可能超出範圍的討論:-)

這一切都將只對真正的陣列工作,對於其尺寸是可以在編譯時計算的恆定值。否則,它不會工作,你將不得不使用一個哨兵值(如'\0',並通過循環內容動態計算'數組'的長度。

+0

我只能通過這個大小的數組?如果我想在一個大小爲6的數組和一個大小爲3的數組上使用它,該怎麼辦? – user212562 2010-11-04 18:45:04

+0

是的,第一個版本迫使你,程序員計算數組大小並將其放在那裏。第二個(模板)版本會爲你做這件事,它會在編譯時計算數組的大小(編譯時它必須可計算才能工作),所以你不必這樣做。 – Vatsan 2010-11-04 18:52:56