Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 10 của 10
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Mã : Liệt kê tất cả các tập tin theo 1 đuôi mở rộng trong 1 ổ đĩa

    Mã này mình viết đã lâu rồi, nay post lên nhờ anh em tham khảo. Bạn nào giúp mình khử đệ quy cho mã tốt hơn không ? Cám ơn.

    Mã:
    #include<windows.h>                     // Cần thiết cho lập trình Windows#include<time.h>                        // Cần cho hàm srand()#include<shlwapi.h>                     // Window Shell#include"resource.h"                    // Icon và Hộp thoại#pragma comment(lib,"shlwapi.lib")      // Phân giải cho Shelltypedef struct                          // Cấu trúc truyền thông tin giữa cửa sổ và luồng việc{    HWND    hDlg;    HWND    hList,hStatic;    CHAR    szDrive[3];    CHAR    szExt[5];    DWORD   dwCount;}PARAM,*PPARAM; void EnumFile(PCHAR szFolder,PPARAM pParam){    WIN32_FIND_DATA     wfd;    CHAR                szFind[MAX_PATH*2];    HANDLE              hFind;     wsprintf(szFind,"%s\\*.*",szFolder);                                        // Tìm tất cả    if(INVALID_HANDLE_VALUE != (hFind = FindFirstFile(szFind,&wfd)))    {        do        {            if(wfd.cFileName[0] != '.')                                         // Không xét thư mục cha và thư mục gốc            {                wsprintf(szFind,"%s\\%s",szFolder,wfd.cFileName);                if(PathIsDirectory(szFind))                                     // Chuỗi tìm thấy là thư mục                    EnumFile(szFind,pParam);                                    // Gọi đệ quy vào sâu trong thư mục con                else if(lstrcmpi(PathFindExtension(szFind),pParam->szExt) == 0) // Nếu là tập tin có đuôi đang tìm kiếm                {                    // Ghi vào listbox và hiển thị cập nhật số tập tin đã tìm được vào static label                    SendMessage(pParam->hList,LB_SETCURSEL,SendMessage(pParam->hList,LB_ADDSTRING,0,(LPARAM)szFind),0);                    wsprintf(szFind,"%d",++pParam->dwCount);                    SetWindowText(pParam->hStatic,szFind);                }            }        }        while(FindNextFile(hFind,&wfd));                                        // Tìm tên kế tiếp        FindClose(hFind);                                                       // Chấm dứt tìm trong thư mục này    }}DWORD WINAPI StartThread(PVOID pVoid){    PPARAM      pParam = (PPARAM)pVoid;     SendMessage(pParam->hList,LB_RESETCONTENT,0,0);    SetWindowText(pParam->hStatic,"0");    EnumFile(pParam->szDrive,pParam);    SendMessage(pParam->hDlg,WM_USER,0,0);                                      // Gởi thông báo hoàn thành tới cửa sổ chính    return 0;}BOOL CALLBACK DlgProc(HWND hDlg,UINT message,WPARAM wparam,LPARAM lparam){    static  HANDLE      hThread;    static  HWND        hList,hCombo,hEdit,hStatic;    static  HBRUSH      hbrBack;                            // But vẽ nền của hộp thoại    static  PARAM       param;                              // Biến tham số cho luồng việc    UINT                uDrive;    char                root[3] = " :";                     // Chuỗi thư mục gốc    char                szExt[5];                           // Chuỗi đuôi mở rộng cho tìm kiếm    char                c;    int                 iLen;     switch(message)    {    case WM_INITDIALOG:        // Nạp Icon cho cửa sổ hộp thoại        SetClassLong(hDlg,GCL_HICON,(LONG)LoadIcon((HINSTANCE)lparam,MAKEINTRESOURCE(IDI_ICON1)));        srand(time(NULL));        hbrBack = CreateSolidBrush(RGB(rand()&255,rand()&255,rand()&255));        hEdit = GetDlgItem(hDlg,IDC_EDIT1);        hCombo = GetDlgItem(hDlg,IDC_COMBO1);        hList = GetDlgItem(hDlg,IDC_LIST1);        hStatic = GetDlgItem(hDlg,IDC_STATIC1);        SetWindowText(hEdit,"exe");        for(c='C';c<='Z';c++)        {            root[0] = c;            uDrive = GetDriveType(root);            if(uDrive == DRIVE_REMOVABLE || uDrive == DRIVE_FIXED || uDrive == DRIVE_CDROM || uDrive == DRIVE_RAMDISK)                SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)root);            else                break;        }        SendMessage(hCombo,CB_SETCURSEL,0,0);        return TRUE;    case WM_USER:                                               // Nhận thông báo hoàn thành từ luồng việc        hThread = NULL;        EnableWindow(GetDlgItem(hDlg,IDOK),TRUE);               // Cho phép nút Start        return TRUE;    case WM_COMMAND:        switch(LOWORD(wparam))        {        case IDC_BUTTON1_STOP:                                  // Nút Stop được nhấn            if(hThread)            {                TerminateThread(hThread,0);                     // Chấm dứt luồng việc                hThread = NULL;            }            EnableWindow(GetDlgItem(hDlg,IDOK),TRUE);           // Cho phép nút Start            return TRUE;        case IDOK:                                              // Nút Start được nhấn            iLen = GetWindowTextLength(hEdit);            if(iLen < 1 || iLen > 3)            {                MessageBox(hDlg,"Ext id invalid","ListFile",0);                return TRUE;            }            ZeroMemory(&param,sizeof(PARAM));            GetWindowText(hEdit,szExt,GetWindowTextLength(hEdit)+1);            wsprintf(param.szExt,".%s",szExt);            param.hStatic = hStatic;            param.hList = hList;            param.dwCount = 0;            param.hDlg  = hDlg;            GetWindowText(hCombo,param.szDrive,GetWindowTextLength(hCombo)+1);            hThread = CreateThread(NULL,0,StartThread,&param,0,NULL);           // Tạo ra luồng việc mới            EnableWindow(GetDlgItem(hDlg,IDOK),FALSE);                          // Không cho phép nút Start            return TRUE;        case IDCANCEL:                                          // Nút Close được nhấn            SendMessage(hDlg,WM_CLOSE,0,0);            return TRUE;        }        break;    case WM_CTLCOLORDLG:                                        // Thông điệp yêu cầu bút vẽ để vẽ nền hộp thoại        return (int)hbrBack;    case WM_CLOSE:        if(hThread)            TerminateThread(hThread,0);        DeleteObject(hbrBack);        EndDialog(hDlg,0);        return TRUE;    }    return FALSE;}int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE  hPrev,LPSTR lp,int nShow){    DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,DlgProc,(LPARAM)hInstance);    return 0;}
    Tài nguyên cho chương trình này chỉ đơn giản gồm:
    _ Icon: IDI_ICON1
    _ Dialog : IDD_DIALOG1
    _ Listbox : IDC_LIST1(NoSort), Combobox : IDC_COMBO1(DropList,NoSort), Edit : IDC_EDIT1, Static : IDC_STATIC1, Button : IDC_BUTTON1
    Được sắp xếp như hình bên dưới khi thực thi


  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    cái mã này là dùng thư viện đồ họa j vậy bạn?

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi binhln
    cái mã này là dùng thư viện đồ họa j vậy bạn?
    Đây là hộp thoại bình thường trong Windows, không có thêm bất cứ thư viện đồ họa nào.

  4. #4
    Ngày tham gia
    Sep 2015
    Đang ở
    89 Tam Trinh - Hoàng Mai - Hà Nội
    Bài viết
    0
    Trích dẫn Gửi bởi Van8Hien62
    soạn thảo bên ngoài VS rồi lưu với đuôi *.c, sau đó có thể biên dịch bằng command line (command prompt).
    //
    cl /? - for help (VC)
    //
    bcc32 - for Borland C
    OK, bạn làm được, tôi làm được, nhưng nhìn vào mã của binhIn, bạn có cảm nhận gì không? Cảm nhận của tôi là bạn ấy chưa rành rẽ để biện dịch theo dòng lệnh. Vậy thì chỉ hướng nào gần nhất để hoàn thành - Hơn là đánh đố - Biết đâu vài năm sau, chúng ta lại là người cần chỉ dẫn thêm đấy.

  5. #5
    Ngày tham gia
    Sep 2015
    Đang ở
    24 Rạch Bùng Binh , P10,Q3 , HCM
    Bài viết
    0
    Dùng BB Code cho dễ đọc (xem reply #1)
    //
    IDE nó highLight, đánh số dòng, ...
    //
    Bắt người khác đánh vần, đọc từng chữ, ... đọc xong đã mệt còn sức đâu giúp ai.

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    soạn thảo bên ngoài VS rồi lưu với đuôi *.c, sau đó có thể biên dịch bằng command line (command prompt).
    //
    cl /? - for help (VC)
    //
    bcc32 - for Borland C

  7. #7
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    @Van8Hien62 : Cám ơn bạn đã chia sẻ.

    Quay trở lại với vấn đề của binhIn. Có vài nhận xét :
    _ Mã của bạn hơi lủng củng và hơi khó đồng bộ, bạn muốn ghi vào tập tin nhưng lại tìm kiếm tập tin trong dữ liệu lưu trên bộ nhớ.
    _ Với các chuỗi thì bạn không thể gán từ chuỗi này sang chuỗi khác (chỉ có thể gán địa chỉ thôi) mà phải copy bộ nhớ như dùng hàm memcpy chẳng hạn, trong mã của bạn thì có thể dùng wsprintf cũng được.
    _ Viết mã hơi lẫn lộn : nếu printf thì không cout và ngược lại. Dẫn tới định dạng chuỗi không chính xác.

    Mã bên dưới viết tạm cho bạn tham khảo, khi duyệt thì nó lưu vào bộ nhớ, khi tìm thì nó tìm từ bộ nhớ. Bạn nhớ thêm mã kiểm tra nhập liệu từ người sử dụng, mã còn nhiều thiếu sót, nhờ các bạn khác xem dùm.


    Mã:
    #define _CRT_SECURE_NO_WARNINGS#include "stdafx.h"#include <Windows.h>#include <shlwapi.h>#include <iostream>#include <vector>#pragma comment(lib,"Shlwapi.lib")using namespace std; typedef struct{    CHAR    szName[MAX_PATH / 2];   // Lưu tên file    CHAR    szPath[MAX_PATH * 2];   // Lưu đường dẫn file} DATA, *PDATA; // szFolder : [in] thư mục đang duyệt tìm các thư mục con và tập tin// pVector : [in] biến vector chứa dữ liệu// nLevel : [in] độ sâu đệ quy - cũng là xác định khoảng cách canh lềvoid find(PCHAR szFolder, vector<PDATA> &pVector, int nLevel){    WIN32_FIND_DATA     w;    CHAR                szFind[MAX_PATH * 2];    HANDLE              hFind;      wsprintf(szFind, "%s\\*.*", szFolder);    hFind = FindFirstFile(szFind, &w);     if (hFind != INVALID_HANDLE_VALUE)    {        do        {            if (w.cFileName[0] != '.')            {                for (int i = 0; i < nLevel; i++)            // Chừa các khoảng trắng phân cấp cho độ sâu, 2 space cho 1 cấp                    cout << "  ";                    //printf(" ");                wsprintf(szFind, "%s\\%s", szFolder, w.cFileName);                if ((PathIsDirectory(szFind)))                {                    cout << "+ " << w.cFileName << "
    ";    // Dấu + đại diện cho thư mục                    find(szFind, pVector, nLevel + 1);                }                else            // Là tập tin                {                    cout << "- " << w.cFileName << "
    ";    // Dấu - đại diện cho tập tin                     PDATA   pData = new DATA;                    wsprintf(pData->szName, w.cFileName);                    wsprintf(pData->szPath, szFolder);                    pVector.push_back(pData);               // Lưu vào Vector                }            }         } while (FindNextFile(hFind, &w));        FindClose(hFind);    }} // Tìm tập tin lưu trữ trong Vectorvoid searchname(vector<PDATA> &pVector, PCHAR szName){    PDATA       pData;    int         iIndex = 0;    for (vector<PDATA>::iterator iter = pVector.begin(); iter != pVector.end(); ++iter)    {        pData = *iter;        if (!_strcmpi(szName, pData->szName))            cout << ++iIndex << ": " << pData->szPath << "\\" << pData->szName << "
    ";    }    if (!iIndex)        cout << "Khong co file can tim
    ";} int main(){    vector<PDATA>   Vector;    int             select;    char            name[50];    int             bFind = 0;     cout << "Chuong trinh tim kiem file";    do    {        if(bFind)            cout << "
    2: Search
    0: Exit
    ";        else            cout << "
    1: Quet File
    0: Exit
    ";        cin >> select;                  // Chưa kiểm tra nhập         switch (select)        {        case 0:            return 0;        case 1:            // Khi thử nghiệm chỉ nên duyệt 1 ổ đĩa ít dữ liệu.            //find("C:", Vector, 0);            find("D:", Vector, 0);            //find("E:", Vector, 0);            bFind = 1;                  // Đã có duyệt các tập tin            break;        case 2:            if (!bFind)            {                cout << "================== Quet File ??? ======================";                break;            }            cout << "Nhap ten file can tim : ";            cin >> name;                // Chưa kiểm tra nhập            searchname(Vector, name);            break;        default:            cout << "Nhap sai so ";            break;        }    } while (cin.get() != '0');    return 0;}
    Khi tìm nó có thể tìm thấy nhiều tập tin chứ không phải chỉ 1 đâu nhé bạn.

  8. #8
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi MHoang
    Chú ý nữa là Console có thể cắt bỏ bớt các dòng hiển thị nếu nó quá lớn, nên đừng thắc mắc tại sao nó luôn hiển thị tới cuối mà các dòng đầu lại không thấy.

    OK, bạn làm được, tôi làm được, nhưng nhìn vào mã của binhIn, bạn có cảm nhận gì không? Cảm nhận của tôi là bạn ấy chưa rành rẽ để biện dịch theo dòng lệnh. Vậy thì chỉ hướng nào gần nhất để hoàn thành - Hơn là đánh đố - Biết đâu vài năm sau, chúng ta lại là người cần chỉ dẫn thêm đấy.
    Bạn có thể thay bộ đệm (cache) và độ rộng, cao của command prompt (cmd.exe):


    Để biên dịch theo mode command prompt, bạn cần biết cách thiết lập biến, đường dẫn (Environment Variables). Nó dài dòng nên không tiện trình bày ở đây.
    Với Ms Microsoft Visual Studio X, nó là cl.exe
    a - đọc hướng dẫn, trong MsDN là khá đầy đủ
    b - trong command prompt, gõ : >\CL.exe /?

    Đâu phài lúc nào cũng phụ thuộc vào IDE, chỉ biết cắm đầu trong chuồng, một không gian nhỏ mà thành lập trình giỏi được.

  9. #9
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn : Bạn có thể thay bộ đệm (cache) và độ rộng, cao của command prompt (cmd.exe)

    Ờ, cái này mình chưa từng tìm hiểu vì cũng it khi đụng tới nó. Cho tìm hiểu thêm chút :

    1. Hộp thoại trên là từ chương trình bạn viết hay là của Windows, máy mình dùng Windows8 nên không có trang tab Layout, hoặc mình không biết tìm nó ở chỗ nào.
    2. Theo như hộp thoại trên thì chiều cao (số dòng mà buffer lưu lại) tối đa là bao nhiêu. Theo mình nhớ không lầm thì điều khiển Up-Down giữ giá trị mà hiển thị trên Edit là một số int và như vậy số dòng có trong cửa sổ cmd vẫn là hữu hạn. Như vậy, kể cả trong trường hợp đã nhấc bộ đệm lên cao nhất, gặp các điều kiện không thuận lợi, cmd vẫn không thể không cắt bớt mà nó vẫn cứ phải cuốn chiếu và loại trừ những dòng ở phía đầu phải không ? Cần hiểu thêm về cái này. (Theo mình thấy ổ đĩa chủ của một máy có thể có tổng số thư mục và tập tin là lớn hơn giới hạn của số int thì cũng không phải là chuyện lạ)

    Vấn đề biên dịch bằng dòng lệnh, liên kết bằng dòng lệnh, rất dài dòng như bạn nói, nên nếu có thảo luận, chúng ta hãy mở một đề tài khác. Chúng ta không cần phụ thuộc vào IDE khi đúng mục đích, khi mục tiêu chưa phải là biên dịch dòng lệnh thì IDE vẫn là công cụ thuận lợi nên có gì phải từ chối nó (?!).

  10. #10
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    1 - Tôi dùng Win7, ở Title Bar của cmd.exe, right-click menu.Propertes
    2 - buffer max là 9999 lines. Nó hữu hạn và chưa đủ lớn cho các log, trong trường hợp đó tôi xuất ra file (text file lớn mờ bằng notepad của chính Windows không hiệu quả, chậm, nặng; nên mở bằng notepad++):

    abc.exe opts >toFile.dat

    Biên dịch bằng dòng lệnh không thay thế IDE, nhất là các bạn mới làm quen với lập trình. Nó cho bạn biết có một công cụ khác, mà thực sự IDE gọi và lấy kết quả từ đó. Nó mạnh mẽ hơn IDE, làm được những cái trong IDE không hỗ trợ.

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •