Cần góp ý về thuật toán và cách viết code cho người mới học C

Em mới học C, có 1 bài toán đặt ra với yêu cầu như dưới, mọi người xem giúp phần thuật toán e viết như vậy cần cải tiến chỗ nào ạ.

Và yêu cầu phần sau, khi mở rộng phạm vi của m và n thì nó khác nhau như thế nào ạ. Mong nhận được góp ý của mọi người.

Đề bài như sau: Cho một mảng một chiều với n phần tử được đánh thứ tự từ 1 đến n và có giá trị khởi tạo ban đầu
của mỗi phần tử bằng 0. Với mỗi cặp số (x, y) (0 < x <= y <= n) được cho trước, ta thực hiện việc tăng giá trị các phần tử của mảng từ phần tử thứ x đến phần tử thứ y lên 1 đơn vị. Sau một số bước thực hiện việc tăng giá trị như trên, hãy in ra giá trị tất cả các phần tử của mảng.

  • Dữ liệu đầu vào được lưu trong file “input.txt”.

  • Dòng đầu tiên gồm 2 số nguyên n và m với n là kích thước của mảng một chiều và m là số cặp số (x, y) được cho bên dưới. m dòng tiếp theo từ dòng 2 đến dòng m+1, trên mỗi dòng là 2 số nguyên tương ứng với m cặp số (x, y).

  • Kết quả là giá trị của tất cả các phần tử của mảng sau khi thực hiện xong các bước tăng giá trị và được in ra vào file “output.txt”. Mỗi phần tử của mảng được in trên 1 dòng.

Ví dụ:

Input.txt

7 4
1 5
4 7
2 3
5 6

Output.txt

1
2
2
2
3
2
1

Chương trình có sự phân chia thành các hàm con thực hiện các chức năng cụ thể.

Hãy cố gắng tìm ra thuật toán tốt nhất có thể nhưng trước hết phải ưu tiên cho việc hoàn thành chương trình.
Thực hiện công việc với giá trị n và m nhỏ hơn 10000. Mở rộng với giá trị n và m nhỏ hơn 100000


Đây là code của em

#include <stdio.h>
#define inp "input.txt"
#define outp "output.txt"
void main()
{
    int i,j,m,n,dau,cuoi, kq[100]= {};
    FILE *in,*out;
    in=fopen(inp,"r");
    fscanf(in,"%d%d", &n, &m);
    if(n<=0||m<=0) printf("Du lieu dau vao khong dung, vui long kiem tra lai\n");
    //bat dau xu ly
    for(i=1; i<=m; i++)
    {
        fscanf(in,"%d %d", &dau, &cuoi);
        if(dau>cuoi||dau<1||dau>n) printf("Du lieu vao ko hop le\n");
        else for(j=dau; j<=cuoi; j++) kq[j-1]++;
    }
    fclose(in);
    //xuat ket qua ra file output.txt
    out=fopen(outp,"w");
    for(i=0; i<n; i++)fprintf(out,"%d \n", kq[i]);
    fclose(out);
}

Anh góp ý sơ sơ về trinh bày nhé, em trình bày ẹ quá. Cái tiêu đề cần chỉnh lại đấy, nên hỏi cụ thể hơn là góp ý chỗ nào.

Về code của em thì anh có góp ý thế này

Macro nên viết hoa, sửa

#define inp "input.txt"
#define outp "output.txt"

Thành

#define IN "input.txt"
#define OUT "output.txt"

Đừng đặt tên biến một ký tự, trừ phi là biến i dùng để đếm trong vòng for, hoặc biến n dùng để chỉ số lượng. Viết tắt của chữ number. Hoặc một số rất hiếm các trường hợp khác.

Nên sử dụng int main thay cho void main Xem video ở đây

Không nên viết 2 dòng lệnh trên 1 dòng, trừ phi muốn che giấu tội lỗi gì đấy :smiley:

Nên kiểm tra xem việc mở file có thành công hay không, bằng cách kiểm tra con trỏ file. Con trỏ file nên để chữ f vào. Ví dụ: fin thay vì in

5 Likes

hehe, cảm ơn anh, anh soi kỹ và góp ý kỹ thế này thì còn gì bằng, em sẽ xem lại cách viết và trình bày của mình ạ :smiley:

1 Like

Đây là đoạn em viết lại, anh cho ý kiến ạ :slight_smile:

#include <stdio.h>
#include <stdlib.h>
#define INP "input.txt"
#define OUTP "output.txt"
void main()
{
    system("color 1E");
    int i,j,m,n,dau,cuoi, kq[10000]={};
    FILE *fin,*fout;
    fin=fopen(INP,"r");
    if(fin==NULL)
       {
                printf("Khong tim thay file input.txt \n\nVui long kiem tra lai\n\n");
                system("pause");
                exit(EXIT_SUCCESS);
        }
    else
    {
        fseek(fin, 0L, SEEK_END);
        if (!ftell(fin))
        {
                printf("File rong, vui long kiem tra lai\n\n");
                system("pause");
                exit(EXIT_SUCCESS);
        }
    }
    fclose(fin);fin=fopen(INP,"r");
    fscanf(fin,"%d%d", &n, &m);
    if(n<=0||m<=0)
        {
                printf("Du lieu dau vao khong dung, vui long kiem tra lai\n\n");
                system("pause");
                exit(EXIT_SUCCESS);
        }
    //bat dau xu ly
    for(i=1;i<=m;i++)
        {
                fscanf(fin,"%d %d", &dau, &cuoi);
                if(dau>cuoi||dau<1||dau>n||cuoi>n)
                    {
                        printf("\nCap (%d %d) o hang thu %d khong hop le\n\nVui long kiem tra lai\n\n",dau,cuoi,i+1);
                        system("pause");
                        exit(EXIT_SUCCESS);
                    }
                else for(j=dau;j<=cuoi;j++) kq[j-1]++;
        }
    fclose(fin);
    //xuat ket qua ra file output.txt
    fout=fopen(OUTP,"w");
    for(i=0;i<n;i++)fprintf(fout,"%d \n", kq[i]);
    fclose(fout);
    printf("Xu ly thanh cong\n\nDu lieu ra nam trong file output.txt\n\ndat cung thu muc voi file thuc thi, vui long kiem tra ket qua.\n\n");
    system("pause");
}

Bạn có mở rộng n ra bao nhiêu thì m cũng phải luôn nhỏ hơn hoặc bằng n.
Thế thì số lần bạn thực hiện phép cộng tối đa cũng là n*m lần thôi.

1 Like

Em xem cách post code ở đây nhé, em post 2 lần rồi vẫn sai :frowning:

P/S: Đã sửa cho em luôn rồi :cry:

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