Sự khác biệt giữa mảng kí tự và mảng con trỏ kiểu kí tự

#include <stdio.h>

const char * msg[] = {"Để ghi dữ liệu vào file, chúng ta có các hàm đã được định nghĩa sẵn trong thư viện cstdio như sau:\n",
    "\tHàm fputc sẽ ghi ký tự có mã ASCII là c vào file được trỏ đến bởi con trỏ f. Giá trị trả về là EOF nếu ghi dữ liệu thất bại, trả về mã ASCII của kí tự được ghi vào nếu thực hiện thành công.\n",
    "\tHàm fputs ghi một C-Style string vào file được trỏ đến bởi con trỏ f cho đến khi gặp kí tự \\0. \n",
    "\tHàm fprintf tương tự hàm printf trong ngôn ngữ C. Tuy nhiên, hàm printf được mặc định liên kết với đối tượng FILE có tên là stdout nên sử dụng hàm printf sẽ ghi nội dung ra màn hình.\n"};

void writeToFile(FILE* file);

int main(int argc, const char * argv[]) {
    const char *filePath = "/Users/hunghoang/Desktop/my_document.txt";
    FILE* file;
    file = fopen(filePath, "w");
    if(!file)
        printf("Can not open this file\n");
    else
        printf("File is opened\n");
    writeToFile(file);
    fclose(file);
    return 0;
}

void writeToFile(FILE* file)
{
    int c = 0;
    while (c<4){
        fprintf(file, msg[c]);              // tuong tu printf
        c++;
    }
}

Mình có chương trình như trên, mong muốn ghi đoạn text vào một file đang tồn tại. Mình đang thắc mắc rằng ở phần khai báo biến msg thì phải dùng con trỏ thay vì khai báo msg như một mảng thông thường. Tại sao lại dùng như vậy ?
Xin cảm ơn mọi người.

có ai giúp mình với ạ

Tại vì khi bạn làm như vậy. Bạn phải khao báo mảng msg ntn

char msg[][] = {
 {'Đ', 'ể', ' ', 'g', 'h', 'i', ' ', ...},
 {'\t', 'H', 'à', 'm', ...},
 ...
}

:penguin:

4 Likes

Bởi vì khi bạn khai báo const char * msg[] , thì msg là một mảng chứa các con trỏ, mỗi con trỏ trỏ đến 1 mảng kí tự:

msg[0] = "Để ghi dữ liệu vào file, chúng ta có các hàm đã được định nghĩa sẵn trong thư viện cstdio như sau:\n"
msg[1] = "\tHàm fputc sẽ ghi ký tự có mã ASCII là c vào file được trỏ đến bởi con trỏ f. Giá trị trả về là EOF nếu ghi dữ liệu thất bại, trả về mã ASCII của kí tự được ghi vào nếu thực hiện thành công.\n"
.....

Nếu muốn khai báo mảng thông thường , đây là chuỗi nên nếu dùng mảng 2 chiều bạn cần chỉ ra cho nó kích thước line lớn nhất , đoạn text trên có 4 line và line có size lớn nhất là khoảng 200 , nên có thể khai báo :

const char  msg[4][210] = ...;

HOặc dùng mảng 1 chiều:

const char msg[1000] = " ... "; // tuy nhiên phải sửa lại logic hàm writeToFile()
3 Likes

Nếu mình sử dụng mảng 1 (hoặc kể cả 2 chiều) thì mỗi phần tử là một kí tự đơn phải không bạn ?

Mảng 2 chiều thì mỗi phần tử là một chuỗi
Mảng 1 chiều thì mỗi phần tử là một kí tự.
Nhưng nhớ là char chỉ có 1 byte

2 Likes

Mảng 1 chiều hay mảng 2 chiều thì mỗi phần tử trong no cũng chỉ là 1 kí tự đơn ( nếu là mảng kí tự )
Ví dụ Arr[10][10] = {…} thì Arr[0][0] = ‘A’ hay Arr[6][6] = ‘B’ …đều chỉ là 1 phần tử trong mảng, chứa 1 ký tự đơn. Trong mảng 2 chiều các phần tử được lưu trữ tuần tự tương tự mảng 1 chiều trong ram : lưu từ Arr[0][0] -> Arr[0][9] , tiếp theo là Arr[1][0] -> Arr[1][9] …
Còn nếu viết Arr[0] thì đây là con trỏ trỏ đến chuỗi ( Arr[0][0] -> Arr[0][9] ) , thực chất nó là địa chỉ của Arr[0][0] , tương tự Arr[1] là con trỏ trỏ đến chuỗi ( Arr[1][0] -> Arr[1][9] ) … Code của hàm writeToFile sử dụng cái này.

Mọi người đã trả lời khá đầy đủ thắc mắc của bạn. Nhưng mình muốn bổ sung thêm về: quan hệ giữa mảng và con trỏ

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