Code xóa comment trong file code

Không anh, lỡ rồi giải cho xong rồi mai ngủ cả ngày :slight_smile:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUF_SIZE 64 

int main(int argc, char **argv)
{
	FILE *inFilePtr;
    char fileName[BUF_SIZE];
    char previous_char = ' ';
    char current_char;
    int is_quote_opening = 0; 
    puts("Enter file name for checking comments: "); 
    scanf("%s", &fileName);
    int line = 1; //Mục đích là để xuất ra vị trí bắt đầu của comment trong trường hợp không đóng comment
    
    if((inFilePtr = fopen(fileName, "r")) != NULL)
    {
        
        FILE *outFilePtr;
        
        if((outFilePtr = fopen("result.txt", "w")) != NULL)
        {
            while((current_char = fgetc(inFilePtr)) != EOF)
            {
                if(current_char = '"')
                {
                    fputc(current_char, outFilePtr);
                    while((current_char = fgetc(inFilePtr)) != '"')
                    {
                        fput(current_char, outFilePtr);
                        if(current_char == EOF)
                        {
                            puts("Error");
                        }
                    }
                }
                else if(current_char == '*' && previous_char = '/')
                {
                    
                }
                else
                {
                    fputc(current_char, outFilePtr);
                }
            }
        }
        else
        {
            
        }
    }
    else
    {
        //Báo lỗi
    }
               
}

Hướng giải hiện tại của em, em không biết biến tín hiệu có cần thiết không

Bỏ bớt mấy while lồng bên trong if đi :pouting_cat:

Người ta phát minh ra 2 biến kiểm tra is_..._opening để làm code trong sáng hơn đó :pouting_cat: Code rối 1 nùi rồi đến lúc lỗi lầm thì lại chẳng biết tại sao.

2 Likes

Ý anh là bỏ hẳn cái while đi?

Bỏ hẳn while trong if đi :pouting_cat: bớt làm mấy việc thừa. 1 vòng while đọc current_char chưa đủ mệt hay sao mà còn phải làm trò mèo bên trong if :pouting_cat:

2 Likes

Code này xử lý rất tiện ở chỗ trường hợp các kí tự còn lại, nếu 1 quote hay 1 comment block đang mở thì current_char chắc chắn nằm trong đó, muốn làm gì cũng được.

if((inFilePtr = fopen(fileName, "r")) != NULL)
    {
        
        FILE *outFilePtr;
        
        if((outFilePtr = fopen("result.txt", "w")) != NULL)
        {
            while((current_char = fgetc(inFilePtr)) != EOF)
            {
                if(current_char == '"' || is_quote_opening == 1)
                {
                    is_quote_opening = 1; 
                    fputc(current_char, outFilePtr);
                   
                }
                else if(current_char == '*' && previous_char == '/')
                {
                    
                }
                else
                {
                    fputc(current_char, outFilePtr);
                }

Có đúng hướng chưa anh, nếu đúng thì em còn phải xử lý ngoại lệ quote hoặc comment không đóng lại nữa

Hơi sai logic rồi.

if (current_char == '"') {
    // chỉ xử lý trường hợp current_char và các điều kiện đi kèm nó,
    // KHÔNG xét điều kiện or.
    if (is_quote_opening == 1) {
        // đóng quote lại
    }
    else if (is_comment_block_opening == 0) {
        // mở quote ra
    }
}
1 Like
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUF_SIZE 64 

int main(int argc, char **argv)
{
	FILE *inFilePtr;
    char fileName[BUF_SIZE];
    char previous_char = ' ';
    char current_char;
    int is_quote_opening = 0; 
    int is_comment_opening = 0;
    puts("Enter file name for checking comments: "); 
    scanf("%s", &fileName);
    int line = 1; //Mục đích là để xuất ra vị trí bắt đầu của comment trong trường hợp không đóng comment
    
    if((inFilePtr = fopen(fileName, "r")) != NULL)
    {
        
        FILE *outFilePtr;
        
        if((outFilePtr = fopen("result.txt", "w")) != NULL)
        {
            while((current_char = fgetc(inFilePtr)) != EOF)
            {
                if(current_char == '"')
                {
                   if(is_quote_opening == 0)
                   {
                       fputc(current_char, outFilePtr);
                       is_quote_opening = 1; 
                   }
                   else if(is_quote_opening == 1)
                   {
                       fputc(current_char, outFilePtr);
                       is_quote_opening = 0;
                   }
                   
                }
                else if(current_char == '*' && previous_char == '/')
                {
                    
                }
                else
                {
                    fputc(current_char, outFilePtr);
                }
            }
        }
        else
        {
            
        }
    }
    else
    {
        //Báo lỗi
    }
               
}

OK, bước đầu vậy là ổn, code các trường hợp tiếp đi thôi. Từ từ thêm các điều kiện cho chính xác hơn.

2 Likes

Giờ có xài được while thoải mái chưa anh? Hay vẫn if else thôi ạ?

Đừng có xài while linh tinh nữa :pouting_cat: toy mất bao công để chỉ cho code trong sáng mà giờ lại thích đâm đầu vào bụi rậm nữa à :pouting_cat:

2 Likes
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUF_SIZE 64 

int main(int argc, char **argv)
{
	FILE *inFilePtr;
    char fileName[BUF_SIZE];
    char previous_char = ' ';
    char current_char;
    int is_quote_opening = 0; 
    int is_comment_opening = 0;
    puts("Enter file name for checking comments: "); 
    scanf("%s", &fileName);
    int line = 1; //Mục đích là để xuất ra vị trí bắt đầu của comment trong trường hợp không đóng comment
    
    if((inFilePtr = fopen(fileName, "r")) != NULL)
    {
        
        FILE *outFilePtr;
        
        if((outFilePtr = fopen("result.txt", "w")) != NULL)
        {
            while((current_char = fgetc(inFilePtr)) != EOF)
            {
                if(current_char == '"')
                {
                   if(is_quote_opening == 0)
                   {
                       fputc(current_char, outFilePtr);
                       is_quote_opening = 1; 
                   }
                   else if(is_quote_opening == 1)
                   {
                       fputc(current_char, outFilePtr);
                       is_quote_opening = 0;
                   }
                   
                }
                else if(current_char == '*' && previous_char == '/')
                {
                    is_comment_opening == 1;
                }
                else if(current_char == '/' && previous_char == '*')
                {
                    is_comment_opening = 0;
                }
                else
                {
                    fputc(current_char, outFilePtr);
                }
                
                previous_char = current_char;
            }
            
            if(is_quote_opening == 1)
            {
                puts("Error, quotes doesn't close");
            }
            if(is_comment_opening == 1)
            {
                puts("Error, comments doesn't close");
            }
        }
        else
        {
            
        }
    }
    else
    {
        //Báo lỗi
    }
               
}

Test thử: /* “abc” */ --> Kết quả: / “abc” *
Đầu em không nảy chữ được nữa luôn :>

Tại cái else này vẫn chưa phân biệt được comment block có đang mở hay không đó :pouting_cat:

Mình đã nói rồi, xét điều kiện cho kỹ vào, hơi chút là đăng code mà không chịu nhìn lại 1 chút hả :pouting_cat:

2 Likes

Em vừa định nói thấy rồi xong anh nói luôn :))
Nói thật giờ em code theo hệ tâm linh thôi, ông bà bảo sao làm đó.
Để em check lại lần cuối :>

Test case mới:

a / b
a " b
a /* b
a /* b *
3 Likes

Em đã test thử 4 case mới, để em test tất cả mấy cái cũ xem sao.
Em comment trước để anh biết em chưa ngủ :slight_smile: :frowning:
Ai đi qua đọc comment hãy thả tim cho sự cố gắng của em với chứ sao thả mình MOD dị :frowning:

2 Likes
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUF_SIZE 64 

int main(int argc, char **argv)
{
	FILE *inFilePtr;
    char fileName[BUF_SIZE];
    char previous_char = ' ';
    char current_char;
    int is_quote_opening = 0; 
    int is_comment_opening = 0;
    puts("Enter file name for checking comments: "); 
    scanf("%s", &fileName);
    int line = 1; //Mục đích là để xuất ra vị trí bắt đầu của comment trong trường hợp không đóng comment
    
    if((inFilePtr = fopen(fileName, "r")) != NULL)
    {
        
        FILE *outFilePtr;
        
        if((outFilePtr = fopen("result.txt", "w")) != NULL)
        {
            while((current_char = fgetc(inFilePtr)) != EOF)
            {
                if(current_char == '"' && is_comment_opening == 0)
                {
                   if(is_quote_opening == 0)
                   {
                       fputc(current_char, outFilePtr);
                       is_quote_opening = 1; 
                   }
                   else if(is_quote_opening == 1)
                   {
                       fputc(current_char, outFilePtr);
                       is_quote_opening = 0;
                   }
                   
                }
                else if(current_char == '*' && previous_char == '/')
                {
                    is_comment_opening = 1;
                  
                }
                else if(current_char == '/' && previous_char == '*')
                {
                    is_comment_opening = 0;
                    
                }
                else
                {
                    if(is_quote_opening == 1)
                    {
                        fputc(current_char, outFilePtr);
                    }
                    else if(is_comment_opening == 1)
                    {
                        //Don't do anything
                    }
                    else
                    {
                        fputc(current_char, outFilePtr);
                    }
                }
                
                previous_char = current_char;
            }
            fclose(outFilePtr);
            if(is_quote_opening == 1)
            {
                puts("Error, quotes doesn't close");
            }
            if(is_comment_opening == 1)
            {
                puts("Error, comments doesn't close");
            }
            fclose(inFilePtr);
        }
        else
        {
            
        }
    }
    else
    {
        //Báo lỗi
    }
               
}

Hiện tại em test thử some/* crazy */ stuff và ra KQ some/ stuff thì phải, em nghĩ mình sai ở chỗ mối liên hệ giữa current và previous char. Lí do?
Em nghĩ bởi vì khi current char là / và previous là e thì nó sẽ đẩy qua trường hợp else. Vì thế em nghĩ trong cái else có nên xét đến kí tự next nữa để avoid case này không?

time
Kỷ lục thức khuya nhất của em :frowning:
Xin phép đầu hàng đợi khi nào em tỉnh giải quyết tiếp chứ nhìn không nổi nữa rồi hic

1 Like

Bạn có thể xét nếu current_char == '/' thì không in ngay, ở lần lặp tiếp theo nếu previous_char (== '/')current_char không tạo thành 1 kí hiệu mở comment block (/*, lưu ý kiểm tra cả biến is_comment_block_opening) thì in previous_char ra trước khi in current_char.

Đại loại là

// các else if khác
else {
    if (current_char == '/') {
        // tạm thời bỏ qua
    } else {
        if (previous_char == '/') {
            // in previous_char trước
        } 
        // in current_char
    }
}
1 Like

Hello @hellokenta,
Rất hoan nghênh tinh thần học hỏi của bạn. Khá hiếm bạn trẻ mới học code ở DNH post code của bản thân và theo đuổi 1 solution tới cùng như bạn để giải quyết vấn đề. Tinh thần học tập rất tốt.

Quay trở lại vấn đề, hướng tiếp cận ban đầu của bạn cũng khá ổn cho người mới. Tuy nhiên, khi đi sâu vào các trường hợp hiếm (corner cases) thì sẽ không thể dễ dàng giải quyết được. Khi đó đòi hỏi bạn phải điều chỉnh code, thêm các điều kiện if/else ngặt nghèo. Mỗi lần thêm 1 cụm if/else nhỏ, code sẽ càng rối và phức tạp đến mức ngay cả bạn cũng không biết phải làm gì tiếp theo. Mình có thể gọi đó là đâm đầu vào ngõ cụt :smiley: . Dẫu vậy, đôi khi chúng ta vẫn cố chấp để hoàn thành nó, vì đã đạt được 99% rồi, chỉ 1% nữa là xong, không muốn từ bỏ…

Một cách đúng đắn và rõ ràng hơn đã được @noname00 trình bày:

Bạn thử tạm gác lại code hiện tại của mình, xem như phần code đó hoàn thành 99% và đã hoàn thành sứ mạng của nó. Thử nhìn 1 chút qua cái hình này, bạn có hiểu nó không đã?

Mình có thể giải thích nhẹ, automata là một đồ thị trạng thái, mà nếu bạn làm theo các bước của nó với input của bạn thì chắc chắn bạn sẽ có kết quả mong muốn. Có 2 loại kết quả:

  • Nếu bạn vào trạng thái cuối cùng (số 4 ở trên) thì nghĩa là input (ví dụ string, text file) của bạn thỏa mãn điều kiện đề bài.
  • Nếu toàn bộ input của bạn đã được xử lý (ví dụ string, text file) mà bạn vẫn đang nằm ở các trạng thái khác (0,1,2,3) thì input của bạn không thỏa mãn đề bài.

Sau khi đã hiểu về đồ thị trạng thái ở trên, bạn hiện thực nó bằng switch case nhé.

Giải thích sơ về đồ thị ở trên: Bắt đầu ở 0, nếu ký tự tiếp theo là / thì vào trạng thái 1. Nếu ký tự tiếp theo là * thì vào trạng thái 2. Nghĩa là ta đã check /* rồi.
Nếu ký tự tiếp theo ở bước 0 và 1 không thỏa mãn bước chuyển thì reset về 0.
Tương tự bạn tự nghiệm ra nhé.

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