2010-04-29 94 views
8

下面是代碼:既然我們說加NULL(因爲我們在最後一個NULL字符,沒有在迭代問題)如何使用整數指針操作時確定整數數組的末尾?

char myChar[] ={ 'A', 'B', 'C', 'D', 'E', '\0' }; 
char *myCharPtr = &myChar[0]; 
while(*myCharPtr != NULL) 
{ 
    cout<<*myCharPtr<<endl; 
    myCharPtr++; 
} 

Output: ABCDE 

我的問題是:

int myInt[] ={ 1, 2, 3, 4, 5 }; 
int *myIntPtr = &myInt[0]; 
while(*myIntPtr != NULL) 
{ 
    cout<<*myIntPtr<<endl; 
    myIntPtr++; 
} 

Output: 12345....<junks>.......... 

字符數組字符作爲字符串的結尾,我們排除了這些問題! 如果萬一,規則是將0加到整數數組的末尾,我們可以避免這個問題。說啥?

回答

10

C字符串約定是char *由'\ 0'字符完成。對於數組或任何其他C++容器,還有其他可以應用的習慣用法。接下來如下我的喜好

,反覆序列​​的最好辦法是使用基於範圍環路列入的C++ 0x

int my_array[] = {1, 2, 3, 4, 5}; 
for(int& x : my_array) 
{ 
    cout<<x<<endl; 
} 

如果你的編譯器不提供此還,使用迭代

for(int* it = std::begin(array); it!=std::end(array); ++it) 
{ 
    cout<<*it<<endl; 
} 

如果你不能使用既不的std ::開始/結束

for(int* it = &array[0]; it!=&array[sizeof(array)]; ++it) 
{ 
    cout<<*it<<endl; 
} 

PS加速。 Foreach在C++ 98編譯器上模擬基於範圍的for-loop

+0

std :: begin/end定義在哪裏?它是否帶有C++ 0x? – 2010-04-29 10:46:15

+0

@克里斯蒂安:是的,還是有助力。 – UncleBens 2010-04-29 12:00:17

+0

@Christian是的,這是與Range有關的C++的一個新特性。 Boost.Range包含了這個以及更多,簡化了很多序列上的算法。 – 2010-04-29 14:35:59

11

在C++中,最好的解決方案是使用std :: vector,而不是數組。向量隨身攜帶它們的大小。使用零(或任何其他值)作爲結束標記的問題當然不能出現在數組中的其他位置。這對於字符串來說並不是什麼大問題,因爲我們很少想用代碼0打印字符,但是在使用int數組時它是個問題。

+0

我很喜歡在這裏使用std :: vector。我有一個一般性問題。如何在向量中,他們能夠確定整數數組的大小? – AKN 2010-04-29 09:29:00

+0

@AKN它們將大小作爲某種單獨的值進行傳輸。 – 2010-04-29 09:34:14

+0

@AKN std:vector不僅僅是一個數組,它可能是一個包含數組和長度可能更多的int的結構。 – phkahler 2010-04-29 11:21:42

3

你當然可以決定在你自己的"sentinel" value存儲在你的整數數組的末尾。例如,如果您的整數總是非負的,您可以使用-1作爲標記數組末尾的標記值。

int myInt[] ={ 1, 2, 3, 4, 5, -1 }; 
int *myIntPtr = &myInt[0]; 
while(*myIntPtr >= 0) 
{ 
    cout<<*myIntPtr<<endl; 
    myIntPtr++; 
} 
1

char值0具有特殊含義,按照慣例和慣例標準化。 int值不是0,所以這不是一個通用規則。如果它適用於您的特定情況,您可以隨它一起使用。但是,通常最好是單獨跟蹤整數數組的長度,因爲這是普遍適用的。或使用std::vector或類似的容器來處理你的工作。

0

使用std :: vector,就像Neil說的那樣。

或者做迭代方式:

有關使用的sizeof
int myInt[] ={ 100, 200, 300, 400, 500 }; 
int *myIntPtr = &myInt[0]; 
int *myIntPtr_end = myIntPtr + 5; 
while(myIntPtr != myIntPtr_end) 
    { 
    cout<<*myIntPtr<<endl; 
    ++myIntPtr; 
    } 
+0

在這裏,我們看到'5',並且是我們可以直接使用的長度的權利! :) – AKN 2010-04-29 09:27:34

+0

int * myIntPtr_end = myIntPtr + 5;指針* myIntPtr_end在最後一個值之後指向SOME_JUNK_VALUE。 (即)500以後。由於這個設計缺陷,我覺得這是不可取的。說啥? – AKN 2010-04-29 09:47:28

+0

只要不取消引用指針,它就指向垃圾並不重要。 至於數組的長度 - 你顯然在你的例子中有它。如果你正在討論關於數組的指針,而沒有關於長度的信息,那麼你需要添加到你的問題/描述中。 – 2010-04-29 11:57:51

3
+0

因爲沒有這種東西 - 你在考慮sizeof。一旦數組衰減到指針,就不能使用它。 – 2010-04-29 10:02:12

+0

@Neil Butterworth謝謝你,這只是一個厭倦症的情況:)然而,沒有任何關於不能訪問數組的說法。這還可以用來進一步實現像邊界檢查數組模板類這樣的東西。 – 2010-04-29 10:08:32

0
for(i=0; i < sizeof(myInt); i++) 
{ 
    cout<<*myIntPtr<<endl; 
    myIntPtr++; 
} 

如果你是在暗示你的代碼,其中myIntPtr操縱沒有塊大小它所指向的,你要麼必須決定在你的int數組的魔法值,或者調整你的代碼,這樣的想法sizeof(myInt)也可用。

標準C庫函數使用後一種方法:只要需要通過指針傳遞緩衝區,就必須在同一個調用中傳遞它們的大小。

+1

謝謝kostas。但是sizeof(myInt)不會直接給出數組大小。 因此,可以改爲'int nIntArrSize = sizeof(myInt)/ sizeof(int)' – AKN 2010-04-29 10:43:45

1

首先,我們不在字符串的末尾添加「NULL字符」。沒有「NULL字符」這樣的東西。我們添加字符,有時稱爲「NUL字符」。但NULL與它完全無關。 NULL通常在指針上下文中使用,而不是在字符或整數上下文中使用。您的比較如*myCharPtr != NULL*myIntPtr != NULL將會編譯(由於NULL在C++中定義),但實際上沒有意義。如果您正在查找數組中的零個字符,則可以檢查它爲*myCharPtr != '\0'*myCharPtr != 0或簡單地*myCharPtr,但不會將其作爲*myCharPtr != NULL

其次,零字符被稱爲零字符的原因:它等於整數零。畢竟C++中的字符類型只是一個純整數類型。我們可以在字符串上下文中使用零字符作爲特殊的唯一原因是因爲它的含義僅用於特定目的。在一般情況下,在整數上下文中,爲此目的保留零顯然是不可能的,原因很明顯:零與其他整數值一樣有用。但是,如果在特定的應用程序中可以使用整數零作爲保留值,請隨時以這種方式使用它。或者你可以使用任何其他的整數值來達到這個目的。但是在一般情況下,參考標題中提到的問題,有沒有辦法來確定數組的結束。您有責任知道結束位置(通過了解元素的總數或通過以您選擇的保留值或以其他方式標記結尾)。即使使用字符串,也無法確定數組的結尾,因爲您只希望查找字符串的末尾,該字符串不一定是存儲該字符串的數組的末尾。

如果你明確地在你的整數數組的末尾加了一個零,你的第一個週期就會高興地停下來。出於某種原因,您在字符數組末尾添加了\0(並且第二個循環停止),但是您沒有在整數數組末尾添加零(並且第一個循環不停止)。你想知道爲什麼你的第一個週期沒有停止在零?因爲你沒有把那零點放在那裏。這很簡單。

1

ASCII和Unicode標準都將值爲0的字符定義爲NULL字符,而不是數組尾/字符串標記。只有C/C++約定字符串以此字符結尾。 Pascal使用不同的符號。此外,NULL字符不一定表示包含該字符串的數組的末尾。存在使用雙空終止字符串(一個打開文件對話框)幾個Win32 API函數,如下所示:

"one\0two\0three\0" // there's an implicit '\0' appended in C/C++ 

這是有效的C/C++代碼,NULL字符並不意味着該陣列的端部。

要將這個NULL值適應整數數組意味着你必須犧牲你的一個整數值。如果你的數據由整數集合的一個子集組成,那麼這不是一個問題,但是如果你的數據可以包含任何整數值,那麼就沒有辦法確定一個給定的整數是數組尾標記還是一個有效的值。在後一種情況下,您需要有關數組中元素數量的附加信息,可以手動或通過std :: vector自動進行。

0

創建任何數組結束指針的通用方法如下:首先使用sizeof(array)/sizeof(array[0])確定數組中元素的數量。請注意,sizeof會出現兩次,因爲它會以字節爲單位返回項目的大小。所以對於靜態數組,這是數組的大小除以數組中元素的大小。然後,數組的結束指針是array+number_of_elements。所以這應該工作:

int myInt[]={1, 2, 3, 4, 5}; 
int myIntNumElements = sizeof(myInt)/sizeof(myInt[0]); 
int *myIntEnd = myInt + myIntNumElelents; 

for (int *myIntPtr = myInt; myInt != myIntEnd; myIntPtr++) 
    { 
    cout << *myIntPtr << endl; 
    } 

現在的一些注意事項:

  • 結束指針指向的位置就在陣列結束後!所以*myIntPtr返回垃圾,而不是數組中最後一個元素的值。
  • 這僅適用於常規靜態數組!對於容器,請使用beginend成員函數和迭代器。
  • 這種方法適用於任何版本的C++。但是,如果您使用的是C++ - 11或更高版本,建議使用std::beginstd::end功能for語句如下:

    for (int *myIntPtr = std::begin(myInt); myIntPtr != std::end(myIntPtr); myIntPtr++)

  • 這種方法的目的是,除了要考慮其他答案。哪一個最好是一個背景問題。