1

我在處理多維數組時遇到了問題。我試圖讓「123」「456」「X123」和「x456」在屏幕上出現使用指針的函數裏面:在C中迭代多維數組而不知道索引

void f(char ***array){ 
    while (**array != '\0'){ 
     while (*array != '\0'){ 
      printf("%s\n",*array);array++; 
     } 
    } 
} 

int main(){ 
    char* arr[50][50]={{"123","456"},{"X123","X456"}}; 
    f(arr); 
    return 0; 
} 

編譯時,我收到了警告passing argument 1 of 'f' from incompatible pointer type在該行f(arr);。並在運行代碼時,我看到:

123 
456 
Segmentation fault 

程序退出。

當我將代碼改成這樣:

void f(char **array){ 
    while (*array != '\0'){ 
     printf("%s\n",*array);array++; 
    } 
} 

int main(){ 
    char* arr[50]={"123","456"}; 
    f(arr); 
    return 0; 
} 

的數字重複罰款,但我寧願我的組數據成組在某些時候更好的組織。爲什麼第一組具有多維數組的代碼不能正確執行?

+2

三顆星?重新思考代碼的時間,但無法找到相關鏈接,除非http://stackoverflow.com/questions/10087113/how-many-levels-of-pointers-can-we-have –

+0

C多維數組* * *與指向數組的指針數組一樣。你需要寫'void f(const char * array [] [50]){...}'。或者,使用GNU非編譯時常量多維數組維度:void f(const int cols,const char * array [] [cols]){...}。自從我這樣做以來已經有一段時間了,但我認爲這是有效的。無論是或者你的函數內部,你都必須將'array'轉換爲指向該類型數組的指針。 –

+1

@PeterCordes作爲參數的尺寸是C99的一部分。 – Jason

回答

0

很難說出你正在嘗試做什麼,但是如果我理解正確,你似乎有一個不需要的額外數組維度。您到達第5個字符串後即刻測試未初始化的值(導致您的段錯誤)。要糾正它,你可以這樣做:

#include <stdio.h> 

void f(char **array){ 
    while (*array != '\0'){ 
     // while (*array != '\0'){ 
     printf("%s\n",*array);array++; 
     //} 
    } 
} 

int main(){ 
    char *arr[50]={"123","456","X123","X456",NULL}; 
    f(arr); 
    return 0; 
} 

輸出

$ ./bin/func_f 
123 
456 
X123 
X456 

注:明確NULL用作定點停止迭代時,數據被用盡。有很多方法可以解決這個問題,這只是一個。

2

首先,爲什麼三顆星?你試圖完成什麼? 顯而易見的解決方案是創建一個二維字符數組,然後將該字符串存儲在數組中,每行一個。請看下面的例子:

char arr[][ 6 ] = { "123", "456", "X123", "X456" }; 

注意,我們被允許省略arr陣列中的行數,但C要求我們指定的列數。不幸的是,並非所有的字符串都足夠長以填充整行數組,所以C用空字符填充它們。 (請注意,有一點浪費的空間陣列中)

 0  1  2  3  4  5 
    +-----+-----+-----+-----+-----+-----+ 
0 | 1 | 2 | 3 | '\0'| '\0'| '\0'| 
    +-----+-----+-----+-----+-----+-----+ 
1 | 4 | 5 | 6 | '\0'| '\0'| '\0'| 
    +-----+-----+-----+-----+-----+-----+ 
2 | X | 1 | 2 | 3 | '\0'| '\0'| 
    +-----+-----+-----+-----+-----+-----+ 
3 | X | 4 | 5 | 6 | '\0'| '\0'| 
    +-----+-----+-----+-----+-----+-----+ 

如果在你的代碼有三顆星是你想要的東西,那麼你將不得不增加一個額外的元素,它始終爲NULL。 (順便說一句,爲什麼你不想使用數組的長度?)

另一種方法是使用一個衣衫襤褸的數組。 C沒有提供「粗糙的數組類型」,但它確實爲我們提供了模擬其中的工具。 (只是創建一個數組,其元素是指向字符串),請看下面的例子:

#define N 4 

int main(int argc, const char * argv[]) { 

    char *str[] = { "123", "456", "X123", "X456" }; 

    for (char **p = &str[ 0 ]; p < str + N; ++p) { 
     puts(*p); 
    } 

    return EXIT_SUCCESS; 
} 

要訪問字符串中的一個,我們需要的是下標arr陣列。

希望這會有所幫助..

0

您通常不應該互換使用指針和數組。常識是他們是一樣的,但他們不是。對於多維數組尤其如此。

多維數組必須在內存中線性佈局,因爲地址是線性的。有幾種方法可以做到這一點,但C使用行主排序。這意味着最後一個指數隨着地址的增加而增長最快。

例如,二維陣列

int x[rows][cols]; 

兩個語句將相當於

x[row][col] = y; 
*(x + (row * cols) + col) = y; 

這意味着,爲了訪問自己的多維陣列的元件在一個功能,該功能需要至少知道可以有效訪問的較高維度的大小。

void f(int rows, int cols, char* array[rows][cols]){ 
    for (int i = 0; i < rows; i++) { 
    for (int j = 0; j < cols; j++) { 
     printf("%s\n", array[i][j]); 
    } 
    } 
} 

int main(){ 
    char* arr[50][50]={{"123","456"},{"X123","X456"}}; 
    f(50, 50, arr); 
    return 0; 
} 

但是,如果有必要不知道尺寸迭代,你可以把內存佈局的優勢,有效地迭代的行和列(領域,更高層次)。儘管如此,這增加了陣列中輸入信號的必要性(例如NULL)。除了使代碼更復雜外,它還會增加內存開銷,因爲通常必須分配最後一行包含NULL

#include <stdio.h> 

void f(char** array){ 

    while (*array) 
    printf("%s\n", *(array++)); 
} 

int main(){ 

    char* arr[][2] = { {"123","456"}, {"X123","X456"}, {NULL, NULL} }; 

    f((char**) arr); 

    return 0; 
} 
+0

你最後的代碼是一個想法,但我仍然''在編譯時從'不兼容的指針類型''傳遞'f'的參數1,並且在執行時傳遞段錯誤。也許我的問題沒有真正的答案,因爲每個人都建議我只使用單一維度。 – Mike

+0

@Mike我寫的最後一個版本太快了,看到上面的變化。這是交換使用指針和數組不好的原因之一。 – Jason