好吧,這是顯而易見的,你需要幫助使用/引用動態分配的內存來克服C的第一部分,所以讓我們看看基本知識。但是,在我們看代碼之前,讓我們先談談你將如何編譯它。您需要在編譯時啓用警告,然後在您考慮完成代碼之前取消所有警告。警告會幫助你。至少你想在使用gcc
時啓用-Wall -Wextra
,你可以檢查其他編譯器的等價物。你的編譯字符串將類似於:
gcc -Wall -Wextra -g -o square square.c
的-g
將生成調試符號與gcc
。當您完成調試時,您將需要用您想要的優化級別0
(零,默認值)或1, 2, 3, fast
替換-g
。您指定的首選項爲-O
(哦,不爲零)(例如-O3
或-Ofast
(gcc 4.6及更新版本))。
現在知道你將如何構建你的代碼,讓我們看看如何編寫它。首先,在C中,有沒有二維數組。只有方法可以模擬二維數組的索引。當使用一個數組指針的輸入(例如Square **matrix
),以模擬2D陣列的方法是聲明和分配指針數組鍵入Square
:
Square **matrix = NULL;
matrix = calloc (ROWS, sizeof *matrix);
這將聲明ROWS
數目的指向類型爲Square*
的矩陣的指針。然後,每個指針,你分配的內存塊持有struct Square
所需數量:
for (row = 0; row < ROWS; row++)
{
matrix[row] = malloc (COLS * sizeof **matrix);
...
}
您現在已經宣佈ROWS
數指針到COLS
數量型Square
的陣列。這允許你模擬一個二維數組,即使沒有要求任何數組在內存中是連續的。
注意:calloc
被用來分配指針。 calloc
都分配並初始化爲NULL
(或0
)。每當你分配一塊內存時,你需要驗證分配成功。您可以通過檢查malloc
,calloc
或realloc
- 的返回來完成此操作,每次都檢查。例如: -
matrix = calloc (ROWS, sizeof *matrix);
if (!matrix) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
您可以創建一個輔助函數來分配/檢查,並返回一個指向新的內存塊,以保持你的代碼整潔。
注2:你分配和驗證的內存塊後,它是你的責任到(1)保存一個指向內存中,以便(2)該塊的起始地址當您不再需要時,可以釋放該內存塊。
對於你的1D
數組,事情要簡單得多,你只需要爲需要的Square
類型的數量分配存儲空間。例如爲:
matrix = calloc (ROWS * COLS, sizeof *matrix);
可以通過簡單地創建邏輯,允許2D陣列類型的索引來指代任何位置連續陣列內模擬從該分配的2D陣列,以及。 (它看起來像matrix[row*ROWS+col]
,其中0 <= row < ROWS
)。雖然不是下面的示例中的一部分,如果你是想從您matrix2
模擬二維數組,然後爲了完整起見如下你可以實現打印部件號:
void print1DMatrixAs2DNumbers (Square *matrix)
{
if (!matrix) return;
int row, col;
printf ("\n simulated 2D array numbers are:\n\n");
for (row = 0; row < ROWS; row++) {
for (col = 0; col < COLS; col++)
printf (" %4d", matrix[row * ROWS + col].i);
putchar ('\n');
}
putchar ('\n');
}
什麼(1) in 備註2是什麼意思?這意味着你必須特別注意不要做類似如下:
while (1) {
...
matrix++;
}
當您使用的循環中完成,道出了什麼的內存塊的開始您最初分配的?沒有。如果您沒有起始地址,則該內存不能再被釋放。如果您發現自己處於這種情況,請創建一個指向矩陣的指針並在循環中使用它。 (例如Square *p = matrix;
,然後while (1) {... p++;}
)
這些是做你正在做的事情的基礎知識。其餘部分僅僅是語法和整理你的程序邏輯。是的,我知道你也需要幫助。
下面是一個例子,暗示你的代碼。它旨在告訴你如何把這些作品放在一起,而不是爲你做。 C是一種非常優雅和靈活的低級語言,可以爲機器提供強大的動力和控制力,除了彙編程序以外,幾乎沒有哪種語言可以提供。有與任何語言相關的學習曲線,C沒有什麼不同。但是,與其他更高級別的語言不同,C可以靈活地執行語法允許的任何操作。沒有任何保護功能可以在數組結束後防止寫入,或在嘗試分配失敗後寫入內存區域。學習C,責任在於你學習C到那個水平,以防止可怕的問題,而不是你賦予你的權力。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROWS 8
#define COLS 8
typedef struct square
{
int i;
char c;
} Square;
Square **initializeMatrix (void);
void printMatrixNumbers (Square**);
void printMatrixLetters (Square**);
void shuffleMatrix (Square**);
Square *initialize1DMatrix (void);
void print1DMatrixLetters (Square*);
void print1DMatrixNumbers (Square*);
void shuffle1DMatrix (Square*);
int main (void)
{
srand (time (NULL));
Square **matrix = initializeMatrix();
while (1)
{
int choice;
printf ("\nPrint which set?: \n\n"
" 1. letters\n"
" 2. numbers\n"
" 3. shuffle matrix\n"
" 4. move to 1D matrix\n"
" > ");
scanf ("%d", &choice);
if(choice == 1) printMatrixLetters (matrix);
else if(choice == 2) printMatrixNumbers (matrix);
else if(choice == 3) shuffleMatrix (matrix);
else if(choice == 4) break;
else printf("Didn't understand that input. Try again\n");
}
Square *matrix2 = initialize1DMatrix();
printf ("\nNow for the 1D array:\n\n");
while (1)
{
int choice;
printf ("\nPrint which set?: \n\n"
" 1. letters\n"
" 2. numbers\n"
" 3. shuffle matrix\n"
" 4. quit\n"
" > ");
scanf ("%d", &choice);
if(choice == 1) print1DMatrixLetters (matrix2);
else if(choice == 2) print1DMatrixNumbers (matrix2);
else if(choice == 3) shuffle1DMatrix (matrix2);
else if(choice == 4) break;
else printf("Didn't understand that input. Try again\n");
}
/* free simulated 2D matrix */
size_t i;
for (i = 0; i < ROWS; i++)
free (matrix[i]);
free (matrix);
/* free matrix2 */
free (matrix2);
return 0;
}
Square **initializeMatrix()
{
/* unless you can't have a null-terminator, this is fine */
char letters[] = "abcdefghijklmnopqrstuvwxyz";
int row, col;
Square **matrix = NULL;
/* allocate ROWS number of pointers to struct Square
* 'calloc' allocates and initializes NULL, you must then
* validate your allocation by checking the return.
*/
matrix = calloc (ROWS, sizeof *matrix);
if (!matrix) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
/* allocate COLS number of struct Square and validate */
for (row = 0; row < ROWS; row++)
{
matrix[row] = malloc (COLS * sizeof **matrix);
if (!matrix) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n",
__func__);
exit (EXIT_FAILURE);
}
for (col = 0; col < COLS; col++)
{
/* fill i with random number between 0 - 999 */
matrix[row][col].i = rand() % 1000;
/* fill c with random letter 'a-z' */
matrix[row][col].c = letters[rand() % 26];
}
}
return matrix;
}
Square *initialize1DMatrix()
{
/* unless you can't have a null-terminator, this is fine */
char letters[] = "abcdefghijklmnopqrstuvwxyz";
int i;
Square *matrix = NULL;
/* allocate memory for ROWS * COLS struct Square
* and validate
*/
matrix = calloc (ROWS * COLS, sizeof *matrix);
if (!matrix) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n",
__func__);
exit (EXIT_FAILURE);
}
for (i = 0; i < ROWS * COLS; i++)
{
/* fill i with random number between 0 - 999 */
matrix[i].i = rand() % 1000;
/* fill c with random letter 'a-z' */
matrix[i].c = letters[rand() % 26];
}
return matrix;
}
void printMatrixNumbers (Square **matrix)
{
if (!matrix) return;
int row, col;
printf ("\n simulated 2D array numbers are:\n\n");
for (row = 0; row < ROWS; row++) {
for (col = 0; col < COLS; col++)
printf (" %4d", matrix[row][col].i);
putchar ('\n');
}
putchar ('\n');
}
void printMatrixLetters (Square **matrix)
{
if (!matrix) return;
int row, col;
printf ("\n simulated 2D array letters are:\n\n");
for (row = 0; row < ROWS; row++) {
for (col = 0; col < COLS; col++)
printf (" %4c", matrix[row][col].c);
putchar ('\n');
}
putchar ('\n');
}
void shuffleMatrix (Square **matrix)
{
if (!matrix) return;
fprintf (stderr, "%s() warning: not yet implemented.\n", __func__);
}
void print1DMatrixNumbers (Square *matrix)
{
if (!matrix) return;
size_t i;
printf ("\n matrix2 numbers are:\n\n");
for (i = 0; i < ROWS * COLS; i++)
printf (" matrix2[%2zu] : %4d\n", i, matrix[i].i);
putchar ('\n');
}
void print1DMatrixLetters (Square *matrix)
{
if (!matrix) return;
size_t i;
printf ("\n matrix2 letters are:\n\n");
for (i = 0; i < ROWS * COLS; i++)
printf (" matrix2[%2zu] : %c\n", i, matrix[i].c);
putchar ('\n');
}
void shuffle1DMatrix (Square *matrix)
{
if (!matrix) return;
fprintf (stderr, "%s() warning: not yet implemented.\n", __func__);
}
編譯
gcc -Wall -Wextra -o bin/square square.c
使用/輸出
$ ./bin/square
Print which set?:
1. letters
2. numbers
3. shuffle matrix
4. move to 1D matrix
> 2
simulated 2D array numbers are:
180 468 335 205 480 606 40 276
360 581 824 731 59 827 573 708
837 18 557 109 234 348 255 54
527 479 60 174 891 799 868 922
35 230 867 335 406 375 660 629
416 243 670 948 123 377 607 48
943 291 617 263 14 37 419 565
126 664 578 357 712 44 738 17
Print which set?:
1. letters
2. numbers
3. shuffle matrix
4. move to 1D matrix
> 1
simulated 2D array letters are:
l a f q l e x y
x p y w p w c t
u c h g l q a t
n m a p v s f l
i d l l x j r z
q u t j x p p e
s o s e c q s c
d c k p p p j c
Print which set?:
1. letters
2. numbers
3. shuffle matrix
4. move to 1D matrix
> 4
Now for the 1D array:
Print which set?:
1. letters
2. numbers
3. shuffle matrix
4. quit
> 2
matrix2 numbers are:
matrix2[ 0] : 371
matrix2[ 1] : 844
matrix2[ 2] : 287
matrix2[ 3] : 69
matrix2[ 4] : 98
matrix2[ 5] : 327
matrix2[ 6] : 125
matrix2[ 7] : 706
matrix2[ 8] : 54
matrix2[ 9] : 400
...
matrix2[59] : 504
matrix2[60] : 655
matrix2[61] : 604
matrix2[62] : 583
matrix2[63] : 597
Print which set?:
1. letters
2. numbers
3. shuffle matrix
4. quit
> 1
matrix2 letters are:
matrix2[ 0] : f
matrix2[ 1] : h
matrix2[ 2] : u
matrix2[ 3] : r
matrix2[ 4] : a
matrix2[ 5] : u
matrix2[ 6] : b
matrix2[ 7] : f
matrix2[ 8] : y
matrix2[ 9] : e
...
matrix2[60] : a
matrix2[61] : u
matrix2[62] : z
matrix2[63] : h
Print which set?:
1. letters
2. numbers
3. shuffle matrix
4. quit
> 4
內存泄漏/錯誤檢查
在任何C在您的寫入動態分配內存時,您必須使用內存錯誤檢查程序。對於Linux valgrind
是正常的選擇。濫用一塊可能導致真正問題的內存塊有很多微妙的方法,這樣做是沒有藉口的。每個平臺都有類似的內存檢查器。它們使用簡單。通過它運行你的程序。
$ valgrind ./bin/square
==9866== Memcheck, a memory error detector
==9866== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==9866== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==9866== Command: ./bin/square
==9866==
Print which set?:
1. letters
2. numbers
3. shuffle matrix
4. move to 1D matrix
> 2
simulated 2D array numbers are:
299 713 762 909 504 705 697 846
600 735 239 2 870 258 998 155
819 88 649 688 921 890 3 657
418 52 761 739 17 612 159 664
340 264 454 848 49 345 179 359
747 958 523 845 398 259 928 240
380 963 808 561 253 614 613 733
442 222 740 209 228 697 743 777
<snip>
Print which set?:
1. letters
2. numbers
3. shuffle matrix
4. quit
> 4
==9866==
==9866== HEAP SUMMARY:
==9866== in use at exit: 0 bytes in 0 blocks
==9866== total heap usage: 10 allocs, 10 frees, 1,088 bytes allocated
==9866==
==9866== All heap blocks were freed -- no leaks are possible
==9866==
==9866== For counts of detected and suppressed errors, rerun with: -v
==9866== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
看[**上的2D陣列C **使用的realloc](http://stackoverflow.com/questions/33007171/using-realloc-on-a-2d-array-c/33011568# 33011568)。你可以添加字母。 –
沒有二維數組aka矩陣。 'Square **'是**不是**數組! – Olaf