01/10/2018, 08:19

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 ạ

#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("
");
    }
}

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

*grab popcorn* viết 10:35 ngày 01/10/2018

Sai ở đây:

    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);

&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

Long Dragon viết 10:32 ngày 01/10/2018

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

Ẹ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 ?

*grab popcorn* viết 10:35 ngày 01/10/2018

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

Được chứ
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

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

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

Long Dragon viết 10:24 ngày 01/10/2018

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

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

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 ?

*grab popcorn* viết 10:28 ngày 01/10/2018

Đú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à đủ

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

Long Dragon viết 10:29 ngày 01/10/2018

thì giá trị của p = 123456.

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

Ở 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à đủ

Có lẽ …

Long Dragon viết 10:28 ngày 01/10/2018

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 ?

*grab popcorn* viết 10:32 ngày 01/10/2018

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

Long Dragon viết 10:31 ngày 01/10/2018

è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 :((

*grab popcorn* viết 10:27 ngày 01/10/2018

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

Ideone.com

Ideone.com

Ideone is something more than a pastebin; it's an online compiler and debugging tool which allows to compile and run code online in more than 40 programming languages.

Long Dragon viết 10:20 ngày 01/10/2018

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ì

Nguyen Trong Dung viết 10:29 ngày 01/10/2018

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:

Long Dragon viết 10:24 ngày 01/10/2018

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

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

rogp10 viết 10:22 ngày 01/10/2018

Trong C ko có tham chiếu 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.

Long Dragon viết 10:26 ngày 01/10/2018

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.

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ỏ =))

rogp10 viết 10:25 ngày 01/10/2018

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.

Bài liên quan
0