Xử lý Mảng và Chuỗi bằng C

  1. Tìm giá trị lớn nhất và nhỏ nhất trong mảng
#include <stdio.h>
#define KICH_THUOC 5

void nhapDuLieu(int mang[], int n);
void xuatDuLieu(int mang[], int n);
void timMinMax(int mang[], int n, int* pmin, int* pmax);

int main() {
    int a[KICH_THUOC];
    int min, max;

    printf("Nhập %d số nguyên:\n", KICH_THUOC);
    nhapDuLieu(a, KICH_THUOC);

    printf("Dữ liệu đã nhập: \n");
    xuatDuLieu(a, KICH_THUOC);

    printf("Đang xử lý dữ liệu...\n");
    timMinMax(a, KICH_THUOC, &min, &max);

    printf("Kết quả:\n");
    printf("Giá trị nhỏ nhất = %d, giá trị lớn nhất = %d\n", min, max);

    return 0;
}

void nhapDuLieu(int mang[], int n) {
    int i;

    for (i = 0; i < n; ++i)
        scanf("%d", &mang[i]);
}

void xuatDuLieu(int mang[], int n) {
    int i;

    for (i = 0; i < n; ++i)
        printf("%d ", mang[i]);
    printf("\n");
}

void timMinMax(int mang[], int n, int* pmin, int* pmax) {
    int i;

    *pmin = *pmax = mang[0];

    for (i = 0; i < n; ++i)
        if (mang[i] < *pmin)
            *pmin = mang[i];
        else if (mang[i] > *pmax)
            *pmax = mang[i];

Câu hỏi 1: Hàm timMinMax có chức năng gì? Câu trả lời: Hàm này tìm giá trị lớn nhất và nhỏ nhất trong mảng số nguyên.

Câu hỏi 2: Tại sao pmin và pmax đều được gán giá trị của phần tử đầu tiên? Câu trả lời: Vì chúng ta cần một điểm khởi đầu để so sánh với các phần tử khác trong mảng.

  1. Trả về địa chỉ của phần tử lớn nhất
#include <stdio.h>
#define KICH_THUOC 5

void nhapDuLieu(int mang[], int n);
void xuatDuLieu(int mang[], int n);
int* timMax(int mang[], int n);

int main() {
    int a[KICH_THUOC];
    int* pmax;

    printf("Nhập %d số nguyên:\n", KICH_THUOC);
    nhapDuLieu(a, KICH_THUOC);

    printf("Dữ liệu đã nhập: \n");
    xuatDuLieu(a, KICH_THUOC);

    printf("Đang xử lý dữ liệu...\n");
    pmax = timMax(a, KICH_THUOC);

    printf("Kết quả:\n");
    printf("Giá trị lớn nhất = %d\n", *pmax);

    return 0;
}

void nhapDuLieu(int mang[], int n) {
    int i;

    for (i = 0; i < n; ++i)
        scanf("%d", &mang[i]);
}

void xuatDuLieu(int mang[], int n) {
    int i;

    for (i = 0; i < n; ++i)
        printf("%d ", mang[i]);
    printf("\n");
}

int* timMax(int mang[], int n) {
    int chiSoMax = 0;
    int i;

    for (i = 0; i < n; ++i)
        if (mang[i] > mang[chiSoMax])
            chiSoMax = i;

    return &mang[chiSoMax];

Câu hỏi 1: Hàm timMax có chức năng gì? Câu trả lời: Hàm này trả về địa chỉ của phần tử có giá trị lớn nhất trong mảng.

Câu hỏi 2: Có thể viết hàm này để trả về giá trị thay vì địa chỉ không? Câu trả lời: Có thể, nhưng việc trả về địa chỉ cho phép người gọi có thể sửa đổi giá trị trực tiếp nếu cần.

  1. Truy cập mảng hai chiều bằng con trỏ
#include <stdio.h>

int main() {
    int x[2][4] = { {1, 9, 8, 4}, {2, 0, 4, 9} };
    int i, j;
    int* conTroPhanTu;     // Con trỏ trỏ đến phần tử đơn
    int(*conTroMang)[4]; // Con trỏ trỏ đến mảng 4 phần tử

    printf("Cách 1: Truy cập trực tiếp bằng tên mảng và chỉ số\n");
    for (i = 0; i < 2; ++i) {
        for (j = 0; j < 4; ++j)
            printf("%d ", x[i][j]);
        printf("\n");
    }

    printf("\nCách 2: Sử dụng con trỏ conTroPhanTu để truy cập gián tiếp\n");
    for (conTroPhanTu = &x[0][0], i = 0; conTroPhanTu < &x[0][0] + 8; ++conTroPhanTu, ++i) {
        printf("%d ", *conTroPhanTu);

        if ((i + 1) % 4 == 0)
            printf("\n");
    }

    printf("\nCách 3: Sử dụng con trỏ conTroMang để truy cập gián tiếp\n");
    for (conTroMang = x; conTroMang < x + 2; ++conTroMang) {
        for (j = 0; j < 4; ++j)
            printf("%d ", *(*conTroMang + j));
        printf("\n");
    }

    return 0;
}

Câu hỏi 1: ConTroPhanTu là loại con trỏ gì? Câu trả lời: Đây là con trỏ trỏ đến một phần tử đơn (int).

Câu hỏi 2: ConTroMang là loại con trỏ gì? Câu trả lời: Đây là con trỏ trỏ đến một mảng có 4 phần tử int.

  1. Thay thế ký tự trong chuỗi
#include <stdio.h>
#define KICH_THUOC 80

void thayThe(char* chuoi, char kyTuCu, char kyTuMoi); // Khai báo hàm

int main() {
    char vanBan[KICH_THUOC] = "Lập trình có khó hay không, đó là một câu hỏi.";

    printf("Văn bản gốc: \n");
    printf("%s\n", vanBan);

    thayThe(vanBan, 'i', '*'); // Gọi hàm

    printf("Văn bản sau khi xử lý: \n");
    printf("%s\n", vanBan);

    return 0;
}

// Định nghĩa hàm
void thayThe(char* chuoi, char kyTuCu, char kyTuMoi) {
    int i;

    while (*chuoi) {
        if (*chuoi == kyTuCu)
            *chuoi = kyTuMoi;
        chuoi++;
    }
}

Câu hỏi 1: Hàm thayThe làm gì? Câu trả lời: Hàm này thay thế tất cả các ký tự kyTuCu trong chuỗi bằng kyTuMoi.

Câu hỏi 2: Hàm này có thể thay thế nhiều ký tự khác nhau cùng lúc không? Câu trả lời: Không, mỗi lần gọi hàm chỉ thay thế một loại ký tự duy nhất.

  1. Cắt chuỗi tại ký tự đầu tiên xuất hiện
#include <stdio.h>
#define KICH_THUOC 80

char* catChuoi(char* chuoi, char kyTu);

int main() {
    char chuoi[KICH_THUOC];
    char kyTu;

    while (printf("Nhập chuỗi: "), gets(chuoi) != NULL) {
        printf("Nhập một ký tự: ");
        kyTu = getchar();

        printf("Đang cắt chuỗi...\n");
        catChuoi(chuoi, kyTu);         // Gọi hàm

        printf("Chuỗi sau khi cắt: %s\n\n", chuoi);
        getchar();
    }

    return 0;
}

// Định nghĩa hàm catChuoi
// Chức năng: Cắt chuỗi tại ký tự đầu tiên xuất hiện và các ký tự sau đó
char* catChuoi(char* chuoi, char kyTu) {
    char* p = chuoi;
    while (*p != '\0') {
        if (*p == kyTu) {
            *p = '\0';
            break;
        }
        p++;
    }
    return chuoi;
}

Câu hỏi: Tại sao cần có lệnh getchar() sau khi nhập ký tự? Câu trả lời: Để đọc ký tự xuống dòng còn lại trong bộ đệm nhập, tránh ảnh hưởng đến lần nhập tiếp theo.

  1. Kiểm tra định dạng số CMND
#include <stdio.h>
#include <string.h>
#define KICH_THUOC 5

int kiemTraCCCD(char* str); // Khai báo hàm

int main()
{
    char* cccd[KICH_THUOC] = { "31010120000721656X",
                              "3301061996X0203301",
                              "53010220051126571",
                              "510104199211197977",
                              "53010220051126133Y" };
    int i;

    for (i = 0; i < KICH_THUOC; ++i)
        if (kiemTraCCCD(cccd[i])) // Gọi hàm
            printf("%s\tHợp lệ\n", cccd[i]);
        else
            printf("%s\tKhông hợp lệ\n", cccd[i]);

    return 0;
}

// Định nghĩa hàm
// Chức năng: Kiểm tra định dạng chuỗi số CMND
// Hợp lệ, trả về 1, không hợp lệ, trả về 0
int kiemTraCCCD(char* str) {
    // Kiểm tra độ dài
    int doDai = strlen(str);
    if (doDai != 18)
        return 0;

    // Kiểm tra 17 ký tự đầu
    for (int i = 0; i < 17; i++) {
        if (!isdigit(str[i]))
            return 0;
    }
    
    // Kiểm tra ký tự cuối
    if (!(isdigit(str[17]) || str[17] == 'X'))
        return 0;
    
    return 1;
}
  1. Mã hóa và giải mã chuỗi
#include <stdio.h>
#include <ctype.h>
#define KICH_THUOC 80
void maHoa(char* chuoi, int n); // Khai báo hàm
void giaiMa(char* chuoi, int n); // Khai báo hàm

int main() {
    char tu[KICH_THUOC];
    int n;

    printf("Nhập văn bản tiếng Anh: ");
    gets(tu);

    printf("Nhập n: ");
    scanf("%d", &n);

    printf("Văn bản đã mã hóa: ");
    maHoa(tu, n);      // Gọi hàm
    printf("%s\n", tu);

    printf("Văn bản đã giải mã: ");
    giaiMa(tu, n); // Gọi hàm
    printf("%s\n", tu);

    return 0;
}

/*Định nghĩa hàm maHoa
Chức năng: Mã hóa chuỗi s
Quy tắc:
Với ký tự a~z hoặc A~Z, thay bằng ký tự đứng sau nó n vị trí; các ký tự khác giữ nguyên
*/
void maHoa(char* chuoi, int n){
    // Thực hiện mã hóa
    while (*chuoi != '\0') {
        if (islower(*chuoi)) {
            *chuoi = 'a' + (*chuoi - 'a' + n) % 26;
        }
        else if (isupper(*chuoi)) {
            *chuoi = 'A' + (*chuoi - 'A' + n) % 26;
        }
        chuoi++;
    }
}

/*Định nghĩa hàm giaiMa
Chức năng: Giải mã chuỗi s
Quy tắc:
Với ký tự a~z hoặc A~Z, thay bằng ký tự đứng trước nó n vị trí; các ký tự khác giữ nguyên
*/
void giaiMa(char* chuoi, int n) {
    // Thực hiện giải mã
    while (*chuoi != '\0') {
        if (islower(*chuoi)) {
            *chuoi = 'a' + (*chuoi - 'a' - n + 26) % 26;
        }
        else if (isupper(*chuoi)) {
            *chuoi = 'A' + (*chuoi - 'A' - n + 26) % 26;
        }
        chuoi++;
    }
}
  1. Sắp xếp chuỗi từ dòng lệnh
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int soSanhChuoi(const void* a, const void* b) {
    return strcmp(*(const char**)a, *(const char**)b);
}

int main(int argc, char* argv[]) {
    if (argc > 1) {
        // Sắp xếp các chuỗi từ vị trí thứ 2 trở đi
        qsort(argv + 1, argc - 1, sizeof(char*), soSanhChuoi);
        
        // In ra các chuỗi đã sắp xếp
        for (int i = 1; i < argc; ++i) {
            printf("Xin chào, %s\n", argv[i]);
        }
    }
    return 0;
}

Thẻ: C con trỏ mạng chuỗi xử lý chuỗi

Đăng vào ngày 22 tháng 7 lúc 15:58