Avatar billede spiritusanta Nybegynder
14. oktober 2002 - 04:22 Der er 19 kommentarer og
2 løsninger

filnavn til txt fil

Jeg arbejder i C++ Builder

Jeg vil gerne lave et lille program, der kan indlæse navnet på alle filer i en mappe. Programmet skal fungere således:

Læser navn på fil
Skriver navn på fil ind i en textbox
Fortsætter til næste fil i mappen
Når der ikke er flere filer i mappen stopper den med at indlæse.

Har ingen ide om, det er en nem eller svær opgave, derfor er pointe sat lidt højt

Håber der er nogen, der kan hjælpe mig

mvh Spirit
Avatar billede kamikaze Nybegynder
14. oktober 2002 - 09:50 #1
Flg. er godt nok lavet i Visual C++, men funktionen skulle gerne fungere i C++ Builder også:

#include <io.h>
#include <windows.h>
#include <vector>
#include <string>

using namespace std;

typedef struct _FILE_FILTER_T
{
    bool fArchive;
    bool fHidden;
    bool fNormal;
    bool fReadOnly;
    bool fSubDir;
    bool fSystem;
} FILE_FILTER_T;

int SearchDir(char* szDir, char* szText, vector<string> *ResultVector, FILE_FILTER_T* Filter)
{
    int  iCount = 0;
    struct _finddata_t file;
    long handle;
    string Temp;
    char szSearchText[MAX_PATH];
    char szSearchDir[MAX_PATH];
    bool fMatch;

    strcpy(szSearchDir, szDir);
    if (szSearchDir[strlen(szSearchDir) - 1] != '\\' &&
        szSearchDir[strlen(szSearchDir) - 1] != '/')
    {
        strcat(szSearchDir, "/");
    }
    strcpy(szSearchText, szSearchDir);
    strcat(szSearchText, szText);

    handle = _findfirst(szSearchText, &file);
    if (handle != -1)
    {
        do
        {
            fMatch = true;
            if (Filter != NULL)
            {
                if (Filter->fArchive  && (file.attrib & _A_ARCH))  fMatch = false;
                if (Filter->fHidden    && (file.attrib & _A_HIDDEN)) fMatch = false;
                if (Filter->fNormal    && (file.attrib & _A_NORMAL)) fMatch = false;
                if (Filter->fReadOnly  && (file.attrib & _A_RDONLY)) fMatch = false;
                if (Filter->fSubDir    && (file.attrib & _A_SUBDIR)) fMatch = false;
                if (Filter->fSystem    && (file.attrib & _A_SYSTEM)) fMatch = false;
            }
            if (fMatch)
            {
                Temp = szSearchDir;
                Temp += file.name;
                ResultVector->push_back(Temp);
                ++iCount;
            }
        } while (_findnext(handle, &file) == 0);
    }
    _findclose(handle);
    return iCount;
}
Avatar billede kamikaze Nybegynder
14. oktober 2002 - 09:56 #2
Den traverserer en mappe for filnavne (af typer der ikke er filtreret fra)og putter dem i ResultVector.

Fx.:
vector<string> ResVec;
FILE_FILTER_T Filter;
memset(Filter, 0, sizeof(FILE_FILTER_T));
SearchDir("C:/WINNT/System", "*.dll", &ResVec, Filter);
// Her indeholder ResVec navne på ALLE .dll-filer i mappen C:/WINNT/System

// Du kan så gennemgå vectoren og add'e navnene til din listbox
Avatar billede kamikaze Nybegynder
14. oktober 2002 - 16:23 #3
(Hvis du ikke vil filtrere noget fra kan du sende NULL som filter!)
Avatar billede spiritusanta Nybegynder
14. oktober 2002 - 16:40 #4
hmm hvordan skal jeg sætte det op?

Hvor skal det du skrev i indlæg 2 stå?

Når jeg trykker på knappen, skal alle filerne skrives på listen...
Avatar billede kamikaze Nybegynder
15. oktober 2002 - 09:36 #5
Ja, når du trykker på knappen skriver du:

OnClick()
{
  vector<string> ResVec;
  SearchDir("C:/WINNT/System", "*.dll", &ResVec, NULL);
  // Her kan du gennemløbe ResVec (vectoren) og putte alle navne i din listbox
}
Avatar billede kamikaze Nybegynder
15. oktober 2002 - 09:39 #6
(Du skal også lige huske at konvertere fra string til AnsiString når du nu bruger Builder :o)
Avatar billede kamikaze Nybegynder
15. oktober 2002 - 12:17 #7
Hvis du ikke ved hvordan du gennemløber vectoren, så sig til...
Avatar billede spiritusanta Nybegynder
16. oktober 2002 - 02:39 #8
hmm ja ved faktisk ikke hvad vektoren er... og hvordan konvertere man en string til AnsiString... det er vel bare, at kalde String for AnsiString
Avatar billede kamikaze Nybegynder
16. oktober 2002 - 09:07 #9
vector er en datatype i STL (Standard Template Library) som følger med enhver C++ implementation. En vector kan bruges ligesom et array, du behøver bare ikke at allokere et bestemt antal pladser - den udvidder sig jo mere du fylder i (dynamisk allokering). Når du instantierer en vector, skal du fortælle den hvilken type elementer den skal holde, fx. int, char*, string ell. lign. (i dette tilfælde string).

Du itererer igennem en vector ved hjælp af en anden datatype der hedder en iterator:

vector<string> vec; // en vector, der tager string som datatype
vector<string>::iterator itr; // en iterator, der kan bruges på en string-vector

itr = vec.begin(); // Nu peger iteratoren på det første element i vectoren.
while(itr != vec.end()) // så længe vi ikke er nået til det sidste element
{
  cout << (*itr); // skriv elementet ud
  itr++; // gå til næste element
}
Avatar billede kamikaze Nybegynder
16. oktober 2002 - 09:11 #10
Når du skal konvertere string (som også er en STL datatype) til AnsiString, skal du først lave string om til char*. Dette gøres ved at bruge metoden c_str(). Dernæst er der en funktion i Builder der hedder AnsiString, og den laver char* strenge om til AnsiString:

string str = "Hello";
AnsiString astr;
astr = AnsiString(str.c_str()); // her er den konverteret
Avatar billede kamikaze Nybegynder
16. oktober 2002 - 09:14 #11
Husk at du skal fortælle kompileren at du ønsker at bruge STL. Dette kan gøres ved at skrive:

using namespace std;

alternativt kan du skrive std:: foran alle STL datatyper, fx:

std::vector<string> str;
std::vector<string>::iterator itr = str.begin();
Avatar billede kamikaze Nybegynder
18. oktober 2002 - 11:41 #12
Kan det bruges? Fortæl hvis du ikke forstår...
Avatar billede spiritusanta Nybegynder
18. oktober 2002 - 16:47 #13
Hvad gør jeg nu..
Jeg har skrevet det her ind i programmet:

while(itr != vec.end()) // så længe vi ikke er nået til det sidste element
{
  Memo1->Lines->Add(*itr);
  itr++; // gå til næste element
}

Jeg får følgende fejlmeddelse:
[C++ Error] Unit1.cpp(39): E2034 Cannot convert 'string' to 'AnsiString'

Hvad skal jeg skrive i det tilfælde?
Avatar billede spiritusanta Nybegynder
18. oktober 2002 - 16:48 #14
For at konvertere string til AnsiString?
Avatar billede kamikaze Nybegynder
21. oktober 2002 - 10:35 #15
Har ikke builder installeret, men dette her burde virke:

AnsiString astr;
while(itr != vec.end()) // så længe vi ikke er nået til det sidste element
{
  astr = AnsiString((*itr).c_str());
  Memo1->Lines->Add(astr);
  itr++; // gå til næste element
}
Avatar billede kamikaze Nybegynder
21. oktober 2002 - 10:37 #16
eller:

while(itr != vec.end()) // så længe vi ikke er nået til det sidste element
{
  Memo1->Lines->Add(AnsiString((*itr).c_str()));
  ++itr;
}
Avatar billede spiritusanta Nybegynder
21. oktober 2002 - 18:30 #17
Hmm ja det virker, men der er stadig en del problemer....
Jeg tror problemet ligger i den stump kode her:
  int SearchDir(char* szDir, char* szText, vector<string> *ResultVector, FILE_FILTER_T* Filter)
      {
      int  iCount = 0;
      struct _finddata_t file;
      long handle;
      string Temp;
      char szSearchText[MAX_PATH];
      char szSearchDir[MAX_PATH];
      bool fMatch;
osv...

Herunder er hele kildekoden

//---------------------------------------------------------------------------

#include <vcl.h>
#include <io.h>
#include <windows.h>
#include <vector>
#include <string>

#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
using namespace std;
typedef struct _FILE_FILTER_T
  {
  bool fArchive;
  bool fHidden;
  bool fNormal;
  bool fReadOnly;
  bool fSubDir;
  bool fSystem;
  } FILE_FILTER_T;

vector<string> vec; // en vector, der tager string som datatype
vector<string>::iterator itr; // en iterator, der kan bruges på en string-vector
itr = vec.begin(); // Nu peger iteratoren på det første element i vectoren.
while(itr != vec.end()) // så længe vi ikke er nået til det sidste element
  {
  Memo1->Lines->Add(AnsiString((*itr).c_str()));
  itr++; // gå til næste element
  }
  int SearchDir(char* szDir, char* szText, vector<string> *ResultVector, FILE_FILTER_T* Filter)
      {
      int  iCount = 0;
      struct _finddata_t file;
      long handle;
      string Temp;
      char szSearchText[MAX_PATH];
      char szSearchDir[MAX_PATH];
      bool fMatch;
      strcpy(szSearchDir, szDir);
      if (szSearchDir[strlen(szSearchDir) - 1] != '\\' &&
      szSearchDir[strlen(szSearchDir) - 1] != '/')
        {
        strcat(szSearchDir, "/");
        }
      strcpy(szSearchText, szSearchDir);
      strcat(szSearchText, szText);
      handle = _findfirst(szSearchText, &file);
      if (handle != -1)
        {
        do
            {
            fMatch = true;
            if (Filter != NULL)
              {
              if (Filter->fArchive  && (file.attrib & _A_ARCH))  fMatch = false;
              if (Filter->fHidden    && (file.attrib & _A_HIDDEN)) fMatch = false;
              if (Filter->fNormal    && (file.attrib & _A_NORMAL)) fMatch = false;
              if (Filter->fReadOnly  && (file.attrib & _A_RDONLY)) fMatch = false;
              if (Filter->fSubDir    && (file.attrib & _A_SUBDIR)) fMatch = false;
              if (Filter->fSystem    && (file.attrib & _A_SYSTEM)) fMatch = false;
              }
            if (fMatch)
              {
              Temp = szSearchDir;
              Temp += file.name;
              ResultVector->push_back(Temp);
              ++iCount;
              }
            }
            while (_findnext(handle, &file) == 0);
        }
      _findclose(handle);
      return iCount;
  }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  vector<string> ResVec;
  SearchDir("C:/WINNT/System", "*.dll", &ResVec, NULL);
  // Her kan du gennemløbe ResVec (vectoren) og putte alle navne i din listbox
}
//---------------------------------------------------------------------------

Men du skal da have tak for hjælpen indtil videre
Avatar billede spiritusanta Nybegynder
21. oktober 2002 - 18:33 #18
I det øverste jeg skrev, hvor der først står "int" efterfølgende af { } dem her, burde det ikke være et eller andet der indleder "{}"?

sådan
int.....
..et eller andet..
{
..
}
Avatar billede soepro Nybegynder
23. oktober 2002 - 13:33 #19
Drop en 'FileListBox' component fra 'Win 3.1' fanen - så får du med det samme en liste over alle filer i det pågældende directory. Du kan loade alle filerne over i en TMemo component vha.:

Memo1->Lines = ListBox1->Items;
Avatar billede spiritusanta Nybegynder
23. oktober 2002 - 13:52 #20
Hehe skulle der virkelig ikke mere til... tak for svaret Soepro :D

Men jeg synes nu også at Kamikaze har gjordt et stort stykke arbejde, derfor får i begge point.

Tak til jer begge
Avatar billede kamikaze Nybegynder
23. oktober 2002 - 14:09 #21
Heh, ja hvorfor lave det selv når det nu findes... :o) Tak for points
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester