Code nhập/xuất array 2d bị lỗi

E có đoạn code sau để nhập/xuất 2D array những bị lỗi khi run, nhờ mọi người giúp ạ :blush:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void InOutArray(int ***arr, int *rows, int *columns)
{
    printf("Type the number of row: ");
    scanf("%d", &rows);
    printf("Type the number of column: ");
    scanf("%d", &columns);
    *arr = (int **)calloc(*rows, sizeof(int *));
    for (int i = 0; i < *rows; ++i)
        (*arr)[i] = (int *)calloc(*columns, sizeof(int));
    for (int i = 0; i < *rows * *columns; ++i) {
        *(*((*arr) + i / *columns) + i % *columns) = 1 + rand() % 100;
        printf("%4d", (*arr)[i / *columns][i % *columns]);
        if ((i + 1) % *columns == 0)
            printf("\n");
    }
}

int main()
{
    srand(time(NULL));
    int rows, columns;
    int **arr;
    InOutArray(&arr, &rows, &columns);
    for (int i = 0; i < rows; ++i)
        free(arr[i]);
    free(arr);
    return 0;
}

P/S: Do thầy bắt ko dc dùng C++ nên e ko thể dùng tham chiếu được :cry:

Sai ở đây:

&rows -> truyền vào địa chỉ của con trỏ rows.
-> tức khi bạn input 10 -> rows = 10
-> *rows = *(10) = ???
Tương tự cho column

Còn fix như thế nào thì bạn thử nghĩ xem :smile:

3 Likes

Ẹc, trước giờ e cứ tưởng nhập giá trị cho con trỏ dùng & vẫn dc chứ anh ?

Vậy em để scanf("%d", rows);scanf("%d", columns); được ko anh ?

Được chứ :smiley:
Nhưng lúc dereference bị sai nếu ko nhập đúng địa chỉ or địa chỉ bị block ko cho truy cập -> bị lỗi lúc run-time

:)) Thử đi là biết.

1 Like

E fix lại thì có vẻ là ok rồi, vậy là đúng rồi hả anh ? :slight_smile:

Em chưa hiểu lắm @@
Tức là nhập giá trị cho con trỏ thông qua hàm thì không để & hay sao anh ?

:smiley: Đúng r đó

Hàm scanf nhận vào 1 con trỏ là vì để nó gán giá trị thông qua địa chỉ của biến ta muốn nhập. Nên khi ra khỏi hàm ta giá trị đó vẫn được giữ nguyên.

Biến con trỏ đặc biệt ở chỗ, giá trị của nó đc xem là 1 địa chỉ. Tức như int a = 10 -> Giá trị của a = 10. -> printf("%d", a) = 10
Nhưng int *p = &a (giả sử &a = 123456) thì giá trị của p = 123456.
Tức khi ra in printf("%d", p) thì ta nhận được 123456. Và *p lúc này mới = 10.

Ở hàm trên bạn dùng scanf cho con trỏ (rows, column), tức đang nhập giá trị cho con trỏ này (tức là đang nhập địa chỉ cho nó trỏ tới luôn), nếu muốn nó ko lỗi thì phải nhập vào là 1 địa chỉ được phép truy cập.
Nhưng bạn nhập test có thể rows w column giá trị < 100 thì vùng nhớ này có thể là vùng được hệ điều hành chiếm giữ nên ko cho phép ai truy cập vào -> Nó quăng ra lỗi not responding gì gì đó và dừng ct luôn. Nếu trên linux sẽ gặp được lỗi segmentation fault.

Vậy nếu muốn nhập giá trị cho biến đang được trỏ bởi con trỏ kia, thì bạn chỉ cần truyền vào giá trị của con trỏ là đủ :grin:

Hơi dài dòng xíu nhưng hy vọng bạn hiểu.

3 Likes

hình như cái này thầy em gọi là “miền giá trị của p” thì phải :grin:

Có lẽ … :grin:

1 Like

Anh @drgnz cho em hỏi là nếu muốn nhập giá trị vào phần tử đầu tiên của mảng array thì để scanf("<đặc tả>", array); là được đúng không a ?

:)) Bạn cứ thử, test thấy đúng kq là biết mà \ :v /
Ngại gì mà ko thử? :kissing:

2 Likes

èo lười lắm :))
code html/css có editor online còn test nhanh chứ c/c++ thì bé VS chạy chậm rì mà đứt ruột :((

1 Like

:~ Thích online thì đây luôn:
http://rextester.com/l/c_online_compiler_visual

2 Likes

Hì ~~
em mới thử thì thấy nếu nhập giá trị cho con trỏ mà để scanf("%d", &pointer) là nó lỗi ngay, để scanf("%d", pointer) thì ko có gì :smiley:

cái này nghĩa là j vậy ? mình chỉ biết có int *p thôi chứ chưa từng thấy cái này luôn á. Bạn chỉ mình với.
thêm cái này nữa:

@BacNinh mấy cái đó mình làm màu xíu cho đẹp thôi bạn :stuck_out_tongue:

vì mình muốn code thuần theo C (ko sử dụng tham chiếu) nên khi cấp phát bộ nhớ cho con trỏ cấp 2 thông qua hàm phải tăng nó lên con trỏ cấp 3, và trong hàm đó phải thêm 1 dấu * trước mỗi tên mảng.
nhưng cũng vì đó mà mình lại bị sai cái lỗi ngớ ngẩn này đây :sob:

Trong C ko có tham chiếu :smiley: nếu muốn truyền tham chiếu một tham số s thì phải ghi tham số hình thức là *s (tức là truyền vào con trỏ đến s). scanf theo nguyên tắc này sẽ nhận s (trong hàm) chứ không phải &s do ta đã có con trỏ đến s (bên ngoài) rồi.

Ví dụ cụ thể: để truyền tham chiếu 1 con trỏ cấp n thì tham số hình thức phải là con trỏ cấp n+1.

1 Like

Dạ ^^
Code C trên VS riết quen giờ qua Codeblocks nó ko cho dùng tham chiếu, thế là nổ não với con trỏ =))

VS chỉ có trình biên dịch C++ chứ không có C, nó chỉ hỗ trợ đến C89 với ba cái gì đâu nữa là hết.

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?