Avatar billede nph12 Nybegynder
04. september 2005 - 16:34 Der er 224 kommentarer og
1 løsning

Hjælp til programmering af programmer

Hej Eksperten
Jeg har nogle programidéer, som jeg håber, at der en nogen som vil hjælpe mig med. Jeg kender ikke det store til C++, men vil meget gerne lære det.

Mine programidéer håber jeg kan blive til "rigtige" programmer med en pæn GUI og progressbar og det hele. Jeg regner med det er et projekt som vi kan arbejde på i de næste halve til hele år.

I første omgang er det "bare" at lave selve programmet, hvor du måske kan lave en del og give mig en lille programdel for som skal programmeres. Jeg vil meget gerne står for testningen af programmet. Mine programidéer kan selvfølgelig skrives mere detaljeret. Jeg regner med, at vi kan udforme en sådan liste i fællesskab. Projektet er ulønnet!

Er du interesseret i projektet kan du skrive til mig på nph12@hotmail.com   


Første program

Programmet tjekker om mapper og filer på ens USB-nøgle (eller et bibliotek) allerede findes på computeren.

Der skal laves en status-side, hvor der bliver vist:
1)    Findes mapper (med indhold) eller filer allerede
2)    Hvis de findes på computeren, hvor ligger de
3)    Hvilken version er nyest
4)    Mulighed for at kopiere eller synkronisere mapper og filer

Andet program

Programmet kopierer billeder fra ens medie f.eks. memory stick (eller et bibliotek) over til biblioteket med ens billeder.

Programmet skal kunne følgende:

1)    Undersøge som billederne allerede lægger på computeren (med samme indhold, men kan godt hedde noget forskelligt)
2)    Kopiere kun nye billeder over på computeren
3)    Lægge billeder i mapper efter forskellige kriterier som f.eks. dato. Alle billeder med en bestemt dato bliver lagt i samme mappe f.eks. 22-08-2005 (eller hvilket andet format man ønsker at mappe skal hedde)
4)    Gennemløbe alle ens billeder og navngive dem efter dato f.eks. DSC00001, DSC00002 osv     

Bemærkning
Det var måske en idé at samme de to programmer til et, hvis man kan….
Avatar billede bertelbrander Novice
04. september 2005 - 20:03 #1
Det lyder som nogle glimrende begynder programmer.
Jeg kan godt hjælpe med specifikke spørgsmål, men jeg gider ikke lave det.
Avatar billede nph12 Nybegynder
04. september 2005 - 22:12 #2
Det lyder godt:-)

Hvis vi kan dele programmerne op i små bidder, så det er til at overskue vil det være en meget stor hjælp. Hvis jeg laver en detaljeret liste over hvad programmer skal kunne, at vi nok mere planlægge hvad der skal laves. Lad os tage en programbid af gangen og så bygge videre på det.

Kan vi tilføje en GUI med tilhørende progressbar til programmerne, når vi er færdige med programmerne?

Skal vi skrive sammen på mailen?
Avatar billede bertelbrander Novice
04. september 2005 - 23:27 #3
Jeg synes at du skal starte med at lave et program der kan vise hvilke filer der ligger et bestem sted, også i undermapper.
Der er nogle eksempler som du kan starte med her:
http://home20.inet.tele.dk/midgaard/sample.html#listfiles

Du skal også lave en funktion til checke om to filer en ens. Her bliver du nok nød til at åbne filerne på vanlig vis og læse dem byte for byte. Du kan evt bruge stat() til at finde ud af hvor store de er.

Til at kopiere filer kan du bruge CopyFileEx(), den kan kobles sammen med en progress bar.

Har du arbejdet med GUI før?
Hvilken kompiler bruger du?

Jeg foretrækker at besvare spørgsmål her. Bemærk at jeg ikke ønsker at være direkte involveret i at lave programmerne, kun besvare spørgsmål.
Avatar billede nph12 Nybegynder
05. september 2005 - 14:36 #4
Som sagt har jeg ikke det store kendskab til C++, så hvis vi kan starte helt fra bunden vil det være at foretrække.

Jeg har købt et C++ hæfte fra IDG
http://www.libris.dk/default.asp?loadside=/Vis_produkt.asp?ISBN=87-7843-265-0

Jeg overvejer at købe Grundlæggende Programmering i C++
http://www.globe.dk/Default.asp?action=detail&vare=FG225-0&section=&la=action%3Dsearch%26pg%3D2%26pgs%3D20%26searchstr%3Dc%252B%252B%26des%3D%26section%3D

Jeg har kigget på nogle af dine eksempler og kigget på de programmer som du lavede til mig på et tidspunkt (checkdup og filedate).
http://www.eksperten.dk/spm/401308

Jeg kender lidt til GUI (fra java), men har ikke arbejdet med GUI i C++ (vil gerne lære det, når jeg er kommet så langt).

Hvad skal jeg bruge af teksteditor og kompiler (bruger textpad til html og til tider java)?

Jeg overvejer at lave de to programmer som et program. Jeg har tænkt mig, at slette punkt tre for det "andet program" og punkt fire for det "andet program" skal enten laves som et selvstædigt program eller være en funktion i det nye program.

Jeg har tænkt mig, at det nye program skal gøre det samme som det "første program", men både for billeder (tjekker som indholdet er det samme) og for andre type filer (tjekker filnavn og hvilke et som er det nyeste).

Man skal som det første vælge hvilke drev/biblioteker som skal holdes op imod hinanden (lave en GUI, hvor man kan vælge drev/biblitek, men til at starte med kan man bare skrive selve stien).

Så kommer selve status-siden, hvor indholdet på ens USB-nøgle bliver hold op imod indholdet på ens computer. Alle mapper og filer bliver listede op med størrelse, filnavn, filtype (evt. med icon af filtypen), antal filer i mappen og om mapper/filer findes på computeren i nyere version. Hvis de findes i nyere version, skal man synronisere både USB-nøgle og computer, så den ligger begge steder. Jeg prøver lige at arbejde lidt videre med idéen, hvordan programmet skal se ud!

Her til sidst vil jeg bare lige sige, at ALLE ER MERE END VELKOMMEN TIL AT KOMME MED FORSLAG OG BIDRAG SOM KAN HJÆLPE MED AT GØRE PROGRAMMERNE SÅ GODE SOM MULIGT!
Avatar billede bertelbrander Novice
05. september 2005 - 19:44 #5
Her vil jeg forslå følgende editor: http://www.codeblocks.org/ Der følger en kompiler (mingw) med.

Der er links til et par begynder tutorials og en om Windows programmering på min hjemmeside, det kunne være et udemærket sted at starte.
Avatar billede nph12 Nybegynder
06. september 2005 - 20:33 #6
Jeg har installeret programmet og er begyndt at lege med lidt kode.

Hvad er forskellen mellem c og c++?
Avatar billede bertelbrander Novice
06. september 2005 - 20:58 #7
C er C++ uden class'er, templates, namespace, og nogle få andre ting.
Ren C bliver mest brugt på små indlejrede systemer, hardware drivere og til at lave kerner (f.ex. Linux) i.
C er delvist en forløber for C++, men der bliver stadig udviklet kode i C.
Til dit formål bør du konsentrere dig om C++
Avatar billede nph12 Nybegynder
07. september 2005 - 20:40 #8
Findes der en c++ dokumentation (ligesom Java API)?
Avatar billede bertelbrander Novice
07. september 2005 - 20:56 #9
Nej, der findes ikke ét dokument.

Til standard C++ bibliotekerne:
http://www.cppreference.com/
http://www.cplusplus.com/ref/
http://www.sgi.com/tech/stl/stl_index.html

GUI er ikke en del af standard biblioteket.
Du kan slå op på MSDN, eller du kan downloade Win32Api dokumentationen som en .hlp fil her (scroll lidt ned og find "Windows API documentation"):
http://www.cs.virginia.edu/~lcc-win32/
Avatar billede nph12 Nybegynder
12. september 2005 - 16:52 #10
Jeg har kigget lidt på det, men jeg bliver nok nød til at få noget mere hjælp. Jeg forstår det meste af koden i eksemplerne, men det er noget andet selv at skrive koden (ved ikke rigtigt, hvor jeg skal starte).
Avatar billede bertelbrander Novice
12. september 2005 - 20:23 #11
Start med at lave logikken, så kikker vi på GUI senere.

Start med at lave en funktion der kan gemme navnet og størrelse på alle filer i en given mappe og undermapper i en std::vector.

Lav et program der beder brugeren om navnet på to mapper/drev og derpå laver listen fra før for hver af de to mapper.

Derpå sammenligner du størrelser for alle filer på de to placeringer. Så skriver programmet alle de filer der:
1: Kun ligger på A
2: Kun ligger på B
3: Ligger på både A og B

Derpå udvider du testen af størrelser så den åbner filerne og sammenligner byte/char for byte/char.

Det lyder måske som en stor mundfuld. Men med de links jeg har givet burde du kunne starte.

Senere kan vi så kikke på en GUI til dette.
Avatar billede nph12 Nybegynder
14. september 2005 - 18:36 #12
Jeg har fået min C++ som er til en del hjælp. Jeg har også kigget på de links som du har henvist til. Jeg har printet ListFiles, ADir, checkdup og filedate ud, så jeg kan kigge koden lidt igennem. 

Jeg har taget udgangspunkt i checkdup, som langt hen af vejen, kan det som det nye program skulle kunne.

Valg af input: enten skal program kun finde dubletter et sted på computer eller skal der gennemsøges to steder fx to biblioteker eller en USB-nøgle og et bibliotek. Der ud over skal man kunne vælge parametre som man kan i checkdup.

[sti1] [parametre]
[sti1] [sti2] [parametre]

Programmet skal lede efter dubletter og nyere version er filen. Ligesom checkdup finder dubletter ved at sammenligne indholdet af to filer skal det nye program også. Derudover kunne det være en god idé, at finde nyere version af en fil ved at bruge dele af ADir. Hvis to filer hedder det samme kigger programmet som indholdet er det samme eller som en af filerne er nyere end den anden. Dette gøres ved, at se hvilken en af filerne som sidst er rettet i.

Nu skal man enten slette dubletterne, så man har en tilbage eller skal man synkronisere begge stier ved, at overskrive den gamle version er filen.

Da checkdup er skrevet i C får jeg ikke lov til at køre det som C++ (der er fejl i linie 68 og 196). Filedate er også skrevet i C. Kan man ikke få det til at køre i C++?

Det er måske lidt af en stor mundfuld jeg har kastet mig ud i og da jeg ikke har programmeret i C++ før var det måske en idé, at jeg lavede en ”oversættelse” af checkdup og ADir? Det vil sikkert også hjælpe mig til at forstår, hvordan jeg skal lave det nye program.
Avatar billede bertelbrander Novice
14. september 2005 - 19:45 #13
Med hensyn til de to fejl. De skyldes at man i C++ ikke automatisk konverterer fra void pointere til vilkårlige andre pointere.
De kan løses ved at de to linier til:
FileSize = (int *)malloc(NumFile * sizeof(int));
FileName = (void **)realloc(FileName, sizeof(char *) * NumAlloc );

Men det kunne være en god idé at "oversætte" programmerne til C++, dvs:
Bruge new og delete i stedet for malloc og free.
Bruge std::vector i stedet for char **FileName; og int *FileSize;
Bruge cout og cerr i stedet for printf
Bruge ifstream og ofstrem i stedet for FILE *
Bruge std::string i stedet for char xxx[...]
Måske bruge en class eller to.
Avatar billede nph12 Nybegynder
15. september 2005 - 17:37 #14
Når jeg prøver at rette checkdup, ved at indsætte de nye linier, bliver den første fejl rettet, men ikke den anden.
Avatar billede bertelbrander Novice
15. september 2005 - 19:02 #15
FileName er en char **, det skal derfor være:
FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc );
Avatar billede nph12 Nybegynder
16. september 2005 - 11:06 #16
Nu kører checkdup i C++:-) Jeg har lavet en lille oversættelse. Jeg kan godt gå mere i dybden, hvis det er. Kan jeg ud fra checkdup få de nye program til at tage imod to input (et eller to drev/stier)?

/*importere klasser*/
#include <dir.h>       
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>

/*Erklære variabler*/
char **FileName;
int  NumAlloc;
int  NumFile;
int  *FileSize;

int GetFileSize(const char *fn);
int CheckDup(const char *fn1, const char *fn2);
void Scan(char *dir, const char *pattern, int sub);
void Usage(const char *ProgramName);
void Cleanup(void);
void ToDos(char *dest, char *src);
void DeleteFile(const char *fn, const char *dn);
int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024], line[256];
  int i, DoSub = 0, FoundPattern = 0, DoAsk = 0, j;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        case 'a':
          DoAsk = 1;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  atexit(Cleanup);
  for(i = 1; i < argc; i++)
  {
    if(argv[i][0])
    {
      Scan(Dir, argv[i], DoSub);
      FoundPattern = 1;
    }
  }
  if(!FoundPattern)
    Scan(Dir, "*.*", DoSub);
  printf("Found: %d %s\n", NumFile, NumFile != 1 ? "files" : "file");
  FileSize = (int *)malloc(NumFile * sizeof(int));

  for(i = 0; i < NumFile; i++)
    FileSize[i] = GetFileSize(FileName[i]);

  for(i = 0; i < NumFile - 1; i++)
  {
    printf("\rChecking: %d", i + 2);
    for(j = i + 1; j < NumFile; j++)
    {
      if(FileSize[i] == FileSize[j])
      {
        if(FileName[j][0] && FileName[i][0] && CheckDup(FileName[j], FileName[i]))
        {
          char name_1[256];
          char name_2[256];
          ToDos(name_1, FileName[j]);
          ToDos(name_2, FileName[i]);
          fprintf(stdout, "\nSame: %s %s", name_1, name_2);
          if(DoAsk)
          {
            printf("\n");
            fprintf(stdout, "1: Delete %s\n", name_1);
            fprintf(stdout, "2: Delete %s\n", name_2);
            fgets(line, sizeof(line), stdin);
            if(line[0] == '1')
            {
              DeleteFile(FileName[j], name_1);
              FileName[j][0] = 0;
            }
            else if(line[0] == '2')
            {
              DeleteFile(FileName[i], name_2);
              FileName[i][0] = 0;
            }
          }
          else
          {
            printf(", deliting %s\n", name_2);
            DeleteFile(FileName[i], name_2);
            FileName[i][0] = 0;
          }
        }
      }
    }
  }
  printf("\n");
  return EXIT_SUCCESS;
}

/*Henter filstørrelse*/
int GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

/*Tjekker for dubletter*/
int CheckDup(const char *fn1, const char *fn2)
{
  FILE *f1, *f2;
  int c1, c2;

  f1 = fopen(fn1, "rb");
  if(!f1)
  {
    fprintf(stderr, "Unable to open: %s\n", fn1);
    if(!access(fn1, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  f2 = fopen(fn2, "rb");
  if(!f2)
  {
    fclose(f1);
    fprintf(stderr, "Unable to open: %s\n", fn2);
    if(!access(fn2, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }

  do
  {
    c1 = fgetc(f1);
    c2 = fgetc(f2);
    if(c1 != c2)
    {
      fclose(f1);
      fclose(f2);
      return 0;
    }
  }
  while(c1 != EOF && c2 != EOF);
  fclose(f1);
  fclose(f2);
  return 1;
}

/*Scanner dir*/
void Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        if(NumFile >= NumAlloc)
        {
          NumAlloc += 256;
          FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc );
        }
        FileName[NumFile++] = strdup(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}

/*Ryder op*/
void Cleanup(void)
{
  int i;
  for(i = 0; i < NumFile; i++)
    free(FileName[i]);
  if(FileName)
    free(FileName);
  if(FileSize)
    free(FileSize);
}

/*Tilføjer danske karaktere*/
void ToDos(char *dest, char *src)
{
  static unsigned char dos_map[] = {0x91, 0x9B, 0x86, 0x92, 0x9D, 0x8F};
  static unsigned char win_map[] = {"æøåÆØÅ"};
  char *s, *n;

  strcpy(dest, src);
  for(n = dest; *n; n++)
    if((s = strchr((char *)win_map, *n)) != 0)
      *n = (char )dos_map[s - (char *)win_map];
}

/*Sletter filer*/
void DeleteFile(const char *fn, const char *dn)
{
  if(remove(fn))
  {
    struct stat s;
    stat(fn, &s);
    if(!DelReadOnly || s.st_mode & 0x80)
    {
      printf("Failed to delete %s\n", dn);
      printf("Status: %s, %04X\n", errno == EACCES ? "Read-Only" : errno == ENOENT ? "File-Not-Found" : "unknown", (unsigned short )s.st_mode);
      return;
    }
    if(chmod(fn, S_IREAD | S_IWRITE))
    {
      printf("Failed to remove Read-Only attribute for %s\n", dn);
      printf("Status: %s, %04X\n", errno == EACCES ? "Read-Only" : errno == ENOENT ? "File-Not-Found" : "unknown", (unsigned short )s.st_mode);
    }
    else if(remove(fn))
    {
      struct stat s;
      stat(fn, &s);
      if((s.st_mode & 0x100) || !DelReadOnly)
      {
        printf("Failed to delete %s after REad-Only Attribute removed\n", dn);
        printf("Status: %s, %04X\n", errno == EACCES ? "Read-Only" : errno == ENOENT ? "File-Not-Found" : "unknown", (unsigned short )s.st_mode);
      }
    }
  }
}
/* EOF */
Avatar billede bertelbrander Novice
17. september 2005 - 00:53 #17
Du skal bruge to af hver af de fire variabler i starten. Så put dem ind i en class, som du laver to instanser af.

Du kan læse en til sti med:
  char Str[1024];
  std::cin.getline(Str, sizeof(Str));

Du skal så gøre det to gange, og læse filnavnene ind i hver af de to class instanser.

Du kan overveje at bruge CharToOem() (eller er det OemToChar() ?) i ToDos(), så får du alle tegn med.
Avatar billede nph12 Nybegynder
19. september 2005 - 21:26 #18
Ja, jeg er stadigvæk meget usikker på at programmere i C++, da jeg ingen erfaring har med dette. Kan vi ikke tage det i små bidder?

Hvilke klasser skal jeg importere?
Jeg skal bruge disse variabler?
char **FileName;
int  NumAlloc;
int  NumFile;
int  *FileSize;

så skal jeg lave en klasse, hvor jeg laver to instanser af denne klasse. Hvordan gør jeg det helt præcis?
Avatar billede bertelbrander Novice
19. september 2005 - 22:03 #19
Start med at lave en class:

class DirInfoClass
{
public:
  char **FileName;
  int  NumAlloc;
  int  NumFile;
  int  *FileSize;
  void AddFile(const char *aName, int aFileSize);
};

AddFile funktionen skal tilføje en fil til listen. Det vil måske være handy at lave flere funktioner i class'en senere.

Fjern så de fire globale variable og erstat dem med:
DirInfoClass DirInfo;

Lav så programmet om så det stadig virker.

Derpå laver du det om så du har:
DirInfoClass DirInfo[2];

Så laver du programmet om så du gemmer alt i DirInfo[0].

Næste (og mest besværlige) skridt er så at lave det om så du læser fra to steder (DirInfo[0] og DirInfo[1]).
Avatar billede nph12 Nybegynder
21. september 2005 - 18:54 #20
Jeg har gjort følgende:

1)

class DirInfoClass
{
public:
  char **FileName;
  int  NumAlloc;
  int  NumFile;
  int  *FileSize;
  void AddFile(const char *aName, int aFileSize);
};

2)

class DirInfoClass
{
  DirInfoClass DirInfo;
  void AddFile(const char *aName, int aFileSize);
};


3)

class DirInfoClass
{
  DirInfoClass DirInfo;
  DirInfoClass DirInfo[2];
  void AddFile(const char *aName, int aFileSize);
};
Avatar billede bertelbrander Novice
21. september 2005 - 20:09 #21
1 er rigtig (men vel også blot et kopi af min ?)

2 og 3 er IKKE rigtige. En class kan ikke have members af sin egen type.

Jeg tror at det er på tide at du kikker på en tutorial:
http://cplus.about.com/od/beginnerctutorial/l/blcplustut.htm
http://www.cprogramming.com/tutorial.html
Avatar billede nph12 Nybegynder
21. september 2005 - 21:00 #22
Okay. Jeg kigger lige på de to tutorials de næste par dage.

Hvis punkt et er udgangspunktet, så skal jeg i punkt to:

Fjern så de fire globale variable og erstat dem med:
DirInfoClass DirInfo;

hvis det jeg har gjort ikke er rigtigt, er jeg ikke helt med:-( Jeg skal fjerne de fire variabler, så har jeg dette:

class DirInfoClass
{
  void AddFile(const char *aName, int aFileSize);
};

hvorfor skal variablerne fjernes? Hvis jeg ikke skal tilføje DirInfoClass DirInfo;
hvad skal jeg så?
Avatar billede bertelbrander Novice
21. september 2005 - 21:04 #23
Det jeg mener er at du skal lave en class:
class DirInfoClass
{
public:
  char **FileName;
  int  NumAlloc;
  int  NumFile;
  int  *FileSize;
  void AddFile(const char *aName, int aFileSize);
};

Fjerne de globale variable FileName, NumAlloc, ... og så lave en/to varable af typen DirInfoClass:

DirInfoClass DirInfo;
eller:
DirInfoClass DirInfo[2];

De sidste skal være globale variable, ikke members af DirInfoClass.
Avatar billede nph12 Nybegynder
22. september 2005 - 16:40 #24
Jeg kigger lige på det igen i morgen. Er jeg på rette vej?

class DirInfoClass
{
  public:
  void AddFile(const char *aName, int aFileSize);
};
DirInfoClass DirInfo[2];
Avatar billede bertelbrander Novice
22. september 2005 - 19:52 #25
FileName, NumAlloc, ... skal være members af DirInfoClass
Avatar billede nph12 Nybegynder
23. september 2005 - 18:19 #26
Noget i stil med dette?

class DirInfoClass
{
  char **FileName;
  int  NumAlloc;
  int  NumFile;
  int  *FileSize;

  public:
  void AddFile(const char *aName, int aFileSize);
};
DirInfoClass DirInfo[2];
Avatar billede bertelbrander Novice
23. september 2005 - 20:04 #27
Ja, du skal nok lave (nogle af) variablerne public, eller lave funktioner til at tilgå dem.
Avatar billede nph12 Nybegynder
26. september 2005 - 18:58 #28
class DirInfoClass
{
  public:
  Skal jeg indsætte variablerne her?
  void AddFile(const char *aName, int aFileSize);
};
DirInfoClass DirInfo[2];
Avatar billede bertelbrander Novice
26. september 2005 - 19:36 #29
Ja.
Avatar billede nph12 Nybegynder
27. september 2005 - 16:24 #30
Sådan? Ellers må du lige vise mig, hvordan det skal skrives.

class DirInfoClass
{
  public:
  char FileName;
  int  FileSize;

  void AddFile(const char *aName, int aFileSize);
};
DirInfoClass DirInfo[2];
Avatar billede bertelbrander Novice
27. september 2005 - 23:31 #31
Det var min mening at én instans af DirInfoClass skulle kunne indeholde en liste af filnavne og størrelser.

Derfor skal FileSize være et array, med et element for hver fil.

FileName skal være en pointer til char, for at kunne indeholde en streng, og en pointer til pointer, for at kunne indeholde en liste af strenge.

Du får også brug for NumAlloc og NumFile for at vide hvor mange der er i listen, og for at vide hvor mange du har afsat (allokeret) plads til.

Du skal bruge 2 lister derfor skal du have to instanser af DirInfoClass.
Avatar billede nph12 Nybegynder
03. oktober 2005 - 17:28 #32
Det forstår det du har skrevet, men det met pointere har jeg ikke helt styr på.

Jeg bliver nød til at få noget mere hjælp, da jeg ellers ikke kommer videre. Kan vi ikke i fællesskab (gerne linie for linie) lave den delt af programmet som indlæser filerne i array´et (som er en forudsætning for resten af programmet)?

Jeg har kigget i tutorialen og min C++ bog, men er bare blevet mere forvirret.
Avatar billede bertelbrander Novice
03. oktober 2005 - 23:17 #33
Jeg har udvidet DirInfoClass:
class DirInfoClass
{
  char **FileName;
  int  NumAlloc;
  int  NumFile;
  int  *FileSize;
  int GetFileSize(const char *fn);
public:
  const char *GetFileName(int n) { return FileName[n]; }
  int GetFileSize(int n) { return FileSize[n]; }
  int GetNumFile() { return NumFile; }
  void AddFile(const char *aName);
};

På denne måde kan man ikke få fat i class'ens members direkte, men skal tilgå dem gennem funktionerne. Det har den store fordel at man kan laver om på strukturen unden at andre kan se det, f.ex. lave om så man gemmer i en std::vector og/eller i std::string.

AddFile() kunne se sådan ud:
void DirInfoClass::AddFile(const char *aName)
{
  if(NumFile >= NumAlloc)
  {
      NumAlloc += 256;
      FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc);
      FileSize = (int *)realloc(FileSize, sizeof(int) * NumAlloc);
  }
  FileName[NumFile] = strdup(aName);
  FileSize[NumFile] = GetFileSize(aName);
  NumFile++;
}

GetFileSize() er det der før var en global funktion, der blot er blevet en member funktion.

Man bør for en god ordens skyld lave en construktor og en destructor til DirInfoClass.

Jeg har ændret programmet så det gemmer ét dir (og underdirs) i DirInfo[0] når det har læst filnavne, udskriver programmet filnavne og størrelser:

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>

/*Erklære variabler*/
class DirInfoClass
{
  char **FileName;
  int  NumAlloc;
  int  NumFile;
  int  *FileSize;
  int GetFileSize(const char *fn);
public:
  const char *GetFileName(int n) { return FileName[n]; }
  int GetFileSize(int n) { return FileSize[n]; }
  int GetNumFile() { return NumFile; }
  void AddFile(const char *aName);
};

void DirInfoClass::AddFile(const char *aName)
{
  if(NumFile >= NumAlloc)
  {
      NumAlloc += 256;
      FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc);
      FileSize = (int *)realloc(FileSize, sizeof(int) * NumAlloc);
  }
  FileName[NumFile] = strdup(aName);
  FileSize[NumFile] = GetFileSize(aName);
  NumFile++;
}

/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0, FoundPattern = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0])
    {
      Scan(Dir, argv[i], DoSub);
      FoundPattern = 1;
    }
  }
  if(!FoundPattern)
    Scan(Dir, "*.*", DoSub);
  printf("Found: %d %s\n", DirInfo[0].GetNumFile(), DirInfo[0].GetNumFile() != 1 ? "files" : "file");

  for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    std::cout << DirInfo[0].GetFileName(i) << " " << DirInfo[0].GetFileSize(i) << std::endl;

  return EXIT_SUCCESS;
}

/*Scanner dir*/
void Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        DirInfo[0].AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}

Du kan prøve at lave det så det læser fra to sti'er og gemmer den anden sti i DirInfo[1].

Du kan også lave en constructor og destructor til DirInfoClass.

Når du har det på plads kan du prøve at begynde at sammenligne filer. Start med at sammenligne størrelser, og udskriv dem der har samme størrelse.

Du må også meget gerne lave om så man ikke bruger printf, men std::cout.
fprintf til stderr kan udskiftes med std::cerr
Avatar billede nph12 Nybegynder
05. oktober 2005 - 21:02 #34
Inden jeg sammenligner filerne fra de to drev, så skal jeg også havde "Ændret" med.

Sammenligner programmet filer med samme indhold (ligesom checkdup gør)?

Nu undersøger programmet om filerne er:

Ens (samme indhold, evt. andet filnavn)
Samme filnavn (undersøger hvilke af filerne som sidst er rettet)

Jeg prøver, om jeg kan hente "Ændret" fra filerne. Det kan godt være jeg skal have noget hjælp, men prøver lige selv i først omgang.
Avatar billede bertelbrander Novice
05. oktober 2005 - 21:27 #35
Funktionen CheckDup checker to filer, byte for byte om de er ens.

Jeg ved ikke rigtigt hvad du mener med "ændret", er det tidspunkt?
Avatar billede nph12 Nybegynder
06. oktober 2005 - 09:19 #36
Så jeg skal bruge funktionen Checkdup fra programmet Checkdup?

Ja, det jeg mener med "ændret" er, hvornår filen sidst er ændret (ligesom ADIR).
Avatar billede bertelbrander Novice
06. oktober 2005 - 19:45 #37
structuren stat der bruges i kaldet til stat() har en st_mtime der fortæller hvornår filen sidst er modificeret.

Men hvorfor er det at du vil kende den?
Avatar billede nph12 Nybegynder
06. oktober 2005 - 20:35 #38
Jeg vil godt kende hvornår en given fil sidst er modificeret, da man kan se hvilken fil som er nyest. Et eksempel kunne være, at man er ved at lave en opgave som man gemmer på sin computer med navnet "opgave.doc". Man kopiere opgaven over på sin USB-nøgle for at arbejde videre på den. Nu hedder begge filer "opgave.doc", men hvilken en af dem er nu den man arbejder med? Det er selvfølgelig den som sidst er rettet!
Avatar billede nph12 Nybegynder
10. oktober 2005 - 20:19 #39
Hvad skal jeg tilføje/rette før at programmet kan de nævnte ting? Hvad skal jeg starte med?
Avatar billede bertelbrander Novice
10. oktober 2005 - 20:55 #40
Jeg synes at du skal start med: "Du kan prøve at lave det så det læser fra to sti'er og gemmer den anden sti i DirInfo[1]."
Avatar billede nph12 Nybegynder
15. oktober 2005 - 18:06 #41
Jeg har godt se, at jeg stadigvæk er på begynderstadiet (er jo også lige startet med at programmere i C++).

Jeg har læst en del i "Grundlæggende programmering i C++", men mangler at få lavet øvelserne og hermed få erfaringen og forståelsen for, hvordan man programmere i C++.

Kan vi ikke gøre det sådan, at du en bid af gangen, så jeg kan følge med i hvordan koden skal skrives. Altså hvordan man i først omgang læser fra de to stier og gemmer det i et array. Gerne med en forklaring, hvorfor man gør det på den måde.

Jeg er nok bedre til at få idéer til programmer end at selv at programmere dem på nuværende tidspunkt. Håber vi kan lave programmet, da det er et som jeg vil have stor gavn af (der jeg ikke er specielt god til, at holde styr på mine filer). Måske kan du hjælpe mig med at bygge videre på de øvelser som står i bogen (når jeg er kommet så langt)?
Avatar billede nph12 Nybegynder
15. oktober 2005 - 18:13 #42
Er Visual C++ 2005 Express Edition Beta 2 er god C++ editor? Kan jeg bruge den i stedet for CodeBlocks eller skal jeg vente lidt til jeg har fået noget mere erfaring?
Avatar billede bertelbrander Novice
15. oktober 2005 - 20:01 #43
Jeg synes at du skal starte med at lave nogle øvelser. Start med dem fra bogen.

Jeg har ikke rigtig lyst til at lave hele programmet med kommentarter.

VisualC++ er sikkert en god editor, men det er lettere at bruge Code::Blocks.
Avatar billede nph12 Nybegynder
16. oktober 2005 - 16:29 #44
OK. Jeg beholder Code::Blocks og laver øvelserne i bogen.

Jeg vil godt kigge på programmet her i efterårsferien, men skal nok have noget hjælp. Jeg skal vide helt præcis hvad jeg skal lave. Her tænker jeg på, hvor jeg skal rette og hvor jeg skal tilføje noget (gerne hvilke linier eller afsnit).

"Du kan prøve at lave det så det læser fra to sti'er og gemmer den anden sti i DirInfo[1]." Hvad er det helt præcis gøre? Jeg ved godt, at du har beskrevet det 27/09-2005 23:31:37, men skal lige have lidt hjælp i den rette retning. Jeg skal oprette et array, hvordan gør jeg det?

Jeg skal bruge NumAlloc og NumFile til at vide, hvor stort array´et skal være. Hvordan får jeg filerne gemt i array´et? Jeg skal vel køre en løkke?
Avatar billede bertelbrander Novice
16. oktober 2005 - 23:21 #45
Scan funktionen gemmer navnene på filerne.

Hvis du ændrer Scan funtionen til:
void Scan(char *dir, const char *pattern, int sub, int idx)

Og bruger det sidste (det nye) argument til at fortælle funktionen i hvilken index af DirInfo (0, 1) den skal gemme i, kan du lave main om til:

int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int Idx;
  for(i = 1, Idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        Scan(Dir, argv[i], DoSub, Idx);
        Idx++;
      }
  }

Så skal du angive to stier på kommandolinien.

Den sidste del af main() kan du putte ind i en for-loop så den udskriver info for både index 0 og 1.

I Scan(...) skal alle DirInfo[0]. laves om til DirInfo[idx].
Avatar billede nph12 Nybegynder
17. oktober 2005 - 17:24 #46
Jeg har prøve at rette de steder, hvor der skulle rettes, men der er stadigvæk en del fejlmeddelelser. Hvad mangler jeg før det virker?


#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>


/*Erklære variabler*/
class DirInfoClass
{
  char **FileName;
  int  NumAlloc;
  int  NumFile;
  int  *FileSize;
  int GetFileSize(const char *fn);
public:
  const char *GetFileName(int n) { return FileName[n]; }
  int GetFileSize(int n) { return FileSize[n]; }
  int GetNumFile() { return NumFile; }
  void AddFile(const char *aName);
};

void DirInfoClass::AddFile(const char *aName)
{
  if(NumFile >= NumAlloc)
  {
      NumAlloc += 256;
      FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc);
      FileSize = (int *)realloc(FileSize, sizeof(int) * NumAlloc);
  }
  FileName[NumFile] = strdup(aName);
  FileSize[NumFile] = GetFileSize(aName);
  NumFile++;
}

/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub, int idx);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
 
  int Idx;
  for(i = 1, Idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        Scan(Dir, argv[i], DoSub, Idx);
       
        Idx++;
      }

  if(!FoundPattern)
    Scan(Dir, "*.*", DoSub);
  printf("Found: %d %s\n", DirInfo[idx].GetNumFile(), DirInfo[idx].GetNumFile() != 1 ? "files" : "file");

  for(i = 0; i < DirInfo[idx].GetNumFile(); i++)
    std::cout << DirInfo[idx].GetFileName(i) << " " << DirInfo[idx].GetFileSize(i) << std::endl;

  return EXIT_SUCCESS;
  }
}


/*Scanner dir*/
void Scan(char *dir, const char *pattern, int sub, int idx)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        DirInfo[idx].AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
17. oktober 2005 - 19:58 #47
Denne del skal ikke bruges, så du kan slette disse linier:
  if(!FoundPattern)
    Scan(Dir, "*.*", DoSub);

Idx og idx er ikke det samme, i main har du Idx, så idx skal ændres til Idx.

Scan kalder sig selv, så du skal overføre idx parametren i dette kald til Scan:
          Scan(sub, pattern, 1, idx);

Disse linier er ikke korrekte:
  printf("Found: %d %s\n", DirInfo[idx].GetNumFile(), DirInfo[idx].GetNumFile() != 1 ? "files" : "file");

  for(i = 0; i < DirInfo[idx].GetNumFile(); i++)
    std::cout << DirInfo[idx].GetFileName(i) << " " << DirInfo[idx].GetFileSize(i) << std::endl;

Du skal putte dem ind i:
  int i;
  for(i = 0; i < 2; i++)
  {
    Kode her
  }
Og bruge i og ikke idx som index til DirInfo, meningen er jo at udskrive informationen for begge lister, dvs DirInfo[0] og DirInfo[1]
Avatar billede nph12 Nybegynder
17. oktober 2005 - 22:35 #48
Nu er jeg kommet noget længere...

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>

/*Erklære variabler*/
class DirInfoClass
{
  char **FileName;
  int  NumAlloc;
  int  NumFile;
  int  *FileSize;
  int GetFileSize(const char *fn);
public:
  const char *GetFileName(int n) { return FileName[n]; }
  int GetFileSize(int n) { return FileSize[n]; }
  int GetNumFile() { return NumFile; }
  void AddFile(const char *aName);
};

void DirInfoClass::AddFile(const char *aName)
{
  if(NumFile >= NumAlloc)
  {
      NumAlloc += 256;
      FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc);
      FileSize = (int *)realloc(FileSize, sizeof(int) * NumAlloc);
  }
  FileName[NumFile] = strdup(aName);
  FileSize[NumFile] = GetFileSize(aName);
  NumFile++;
}

/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub, int idx);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        Scan(Dir, argv[i], DoSub, idx);
        idx++;
      }
 
      int i;
      for(i = 0; i < 2; i++)
      {
        printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

        for(i = 0; i < DirInfo[i].GetNumFile(); i++)
        std::cout << DirInfo[i].GetFileName(i) << " " << DirInfo[i].GetFileSize(i) << std::endl;
      }
  }
  return EXIT_SUCCESS;
}

/*Scanner dir*/
void Scan(char *dir, const char *pattern, int sub, int idx)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        DirInfo[idx].AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1, idx);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
17. oktober 2005 - 22:54 #49
Hvis du prøver at ændre den sidste del (fra "int idx;") af main til:
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        Scan(argv[i], "*", DoSub, idx);
        idx++;
      }

  }
  for(i = 0; i < 2; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << std::endl;
  }
  return EXIT_SUCCESS;
}

Så burde det virke.
Bemærk at du i den sidste loop brugte i til to ting -> det går galt.

Jeg har også ændret kaldet til Scan.
Avatar billede nph12 Nybegynder
18. oktober 2005 - 13:45 #50
Nu kører det hvis som det skal:-) Nu henter vi filer fra to stier, men kan man vælge kun at tjekke en sti?

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>

/*Erklære variabler*/
class DirInfoClass
{
  char **FileName;
  int  NumAlloc;
  int  NumFile;
  int  *FileSize;
  int GetFileSize(const char *fn);
public:
  const char *GetFileName(int n) { return FileName[n]; }
  int GetFileSize(int n) { return FileSize[n]; }
  int GetNumFile() { return NumFile; }
  void AddFile(const char *aName);
};

void DirInfoClass::AddFile(const char *aName)
{
  if(NumFile >= NumAlloc)
  {
      NumAlloc += 256;
      FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc);
      FileSize = (int *)realloc(FileSize, sizeof(int) * NumAlloc);
  }
  FileName[NumFile] = strdup(aName);
  FileSize[NumFile] = GetFileSize(aName);
  NumFile++;
}

/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub, int idx);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        Scan(argv[i], "*", DoSub, idx);
        idx++;
      }

  }
  for(i = 0; i < 2; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void Scan(char *dir, const char *pattern, int sub, int idx)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        DirInfo[idx].AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1, idx);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
18. oktober 2005 - 13:49 #51
Hvis du udskifter:
  for(i = 0; i < 2; i++)
med
  for(i = 0; i < idx; i++)

vil den kun checke det antal stier som man har angivet på kommandolinien (det går dog galt hvis man skriver mere end 2).
Avatar billede nph12 Nybegynder
18. oktober 2005 - 14:45 #52
Det er hermed rettet. Det er også helt perfekt, at man enten kan vælge en eller to stier (mere har jeg heller ikke brug for).

Hvad er det næste der skal laves? Det er vel status-siden eller hvad?
Avatar billede bertelbrander Novice
18. oktober 2005 - 16:11 #53
Jeg synes at du skal lave et par små ting om først, også som en øvelse.

Prøv at lave Scan om til at være en funktion i DirInfoClass, så det kommer til at se sådan ud:
class DirInfoClass
{
  ...
public:
  void Scan(char *dir, const char *pattern, int sub);
  ...
};

Og du vil så kalde den med:
DirInfo[idx].Scan(...);

sub parametren burde egentlig være bool (true/false)

Du kan også prøve at lave disse:
  char **FileName;
  int  *FileSize;
Om til:
  std::vector<std::string >FileName;
  std::vector<int >FileSize;
Så behøver du ikke:
  int  NumAlloc;
  int  NumFile;
Du kunne også lave det om til:
  class FileEntryClass
  {
  public:
    std::string FileName;
    int FileSize;
  };
  std::vector<FileEntryClass> FileEntry;

Du kan læse om std::vector her:
http://www.sgi.com/tech/stl/Vector.html
http://home20.inet.tele.dk/midgaard/tipc20050114.html

Du kunne også lave en funktion i DirInfoClass der udskriver det der nu bliver udskrevet til slut i main.
Avatar billede nph12 Nybegynder
20. oktober 2005 - 18:35 #54
Ok. jeg har lavet første del:
class DirInfoClass
{
  ...
public:
  void Scan(char *dir, const char *pattern, int sub);
  ...
};

Så skal jeg kalde den med denne linie:
DirInfo[idx].Scan(...);

Hvordan gør jeg det helt præcis?
Avatar billede bertelbrander Novice
21. oktober 2005 - 00:47 #55
I main, der hvor du kalder Scan laver du det om til:
        DirInfo[idx].Scan(argv[i], "*", DoSub);
Der hvod du kalder Scan fra Scan, fjerner du blot sidste argument i kaldet.

Alle steder i Scan hvor du nu har noget i stil med:
  DirInfo[idx].AddFile(sub);
laver du det om til:
  AddFile(sub);
Da AddFile er en memberfunktion.
Avatar billede nph12 Nybegynder
21. oktober 2005 - 10:19 #56
Nu har jeg prøvet at rette i programmet, men jeg får en del fejl. Hvad gør jeg forkert?

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>

/*Erklære variabler*/
class DirInfoClass
{
 
  std::vector<std::string >FileName;
  std::vector<int >FileSize;
  int GetFileSize(const char *fn);
public:
  const char *GetFileName(int n) { return FileName[n]; }
  int GetFileSize(int n) { return FileSize[n]; }
  int GetNumFile() { return NumFile; }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

void DirInfoClass::AddFile(const char *aName)
{
  if(NumFile >= NumAlloc)
  {
      NumAlloc += 256;
      FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc);
      FileSize = (int *)realloc(FileSize, sizeof(int) * NumAlloc);
  }
  FileName[NumFile] = strdup(aName);
  FileSize[NumFile] = GetFileSize(aName);
  NumFile++;
}

/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void Scan(char *dir, const char *pattern, int sub)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
21. oktober 2005 - 12:12 #57
Du skal inkludere vector og string for at kunne bruge std::vector og std::string:
#include <vector>
#include <string>

GetFileName skal rettes, det letteste er at lade den returnere en reference til en std::string, da FileName er en std::strig:
  std::string &GetFileName(int n) { return FileName[n]; }

Scan er nu en member af DirInfoClass, så du skal skrive DirInfoClass foran selve funktionen:
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)

Da du ikke har nogen NumFile variabel i class'en kan du finde ud af hvor mange filnavne der er i listen vha. FileName.size() (i funktionen GetNumFile()).

Derudover skal du rette AddFile så den tilføjer til en vector, det er ret simpelt, så prøv at læse lidt på vectorer (du skal bruge funktionen push_back).
Avatar billede nph12 Nybegynder
21. oktober 2005 - 19:33 #58
De sidste to punkter skal jeg have lidt mere hjælp til. Jeg har kigget lidt på funktionen push_back:
http://www.sgi.com/tech/stl/BackInsertionSequence.html
Hvad skal jeg helt præcis gøre?

Er der ellers rigtigt det jeg har lavet indtil videre?
#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>


/*Erklære variabler*/
class DirInfoClass
{
  std::vector<std::string >FileName;
  std::vector<int >FileSize;
  int GetFileSize(const char *fn);
public:
  std::string &GetFileName(int n) { return FileName[n]; }
  int GetFileSize(int n) { return FileSize[n]; }
  int GetNumFile() { return NumFile; }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

void DirInfoClass::AddFile(const char *aName)
{
  if(NumFile >= NumAlloc)
  {
      NumAlloc += 256;
      FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc);
      FileSize = (int *)realloc(FileSize, sizeof(int) * NumAlloc);
  }
  FileName[NumFile] = strdup(aName);
  FileSize[NumFile] = GetFileSize(aName);
  NumFile++;
}

/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
21. oktober 2005 - 23:06 #59
Du kan også læse om std::vector her:
http://home20.inet.tele.dk/midgaard/tipc20050114.html

I GetNumFile() skal du blot retrunere FileName.size() i stedet for NumFile
Avatar billede nph12 Nybegynder
22. oktober 2005 - 15:03 #60
Jeg har læst om std::vector. Jeg har prøvet mig lidt frem, men der er stadigvæk mange fejl!

Jeg er lidt forvirret over, hvad jeg skal med funktionen push_back

Kan du ikke skrive trin for trin, hvad jeg skal?
Avatar billede bertelbrander Novice
22. oktober 2005 - 15:43 #61
std::vector har en push_back funktion der tilføjer et element i slutningen af vectoren.

I AddFile har du netop brug for at tilføje et element til FileName og FileSize, som begge er en vector.
Det fil-navn du skal tilføje til FileName er argumentet til AddFile.
Fil-størrelsen der skal tilføjes til FileSize får du med GetFileSize()

Alt i alt gør det at du kan lave AddFile som to gange push_back, en for hver vector.
Avatar billede nph12 Nybegynder
22. oktober 2005 - 18:08 #62
Jeg tror, at jeg er ved at være med på den. Jeg tror, at jeg har forstået hvad det skal gøres, men hvordan jeg gør det helt præcis er jeg stadigvæk lidt usikker på.

Er det disse linier som skal rettes?
FileName = (char **)realloc(FileName, sizeof(char *) * NumAlloc);
FileSize = (int *)realloc(FileSize, sizeof(int) * NumAlloc);
Avatar billede bertelbrander Novice
22. oktober 2005 - 18:17 #63
Alt det der er i AddFile skal væk, du skal dog stadig have et kald til GetFileSize.
Avatar billede nph12 Nybegynder
23. oktober 2005 - 13:39 #64
Er det noget i denne stil?

void DirInfoClass::AddFile(const char *aName)
{
    FileName.push_back[NumFile](*aName);
    FileSize.push_back[NumFile](GetFileSize());
    FileSize[NumFile] = GetFileSize(aName);
    NumFile++;
}
Avatar billede bertelbrander Novice
23. oktober 2005 - 13:47 #65
Næsten.

Vi skal have afskafftet NumFile.
push_back putter til enden på vectoren, så der skal ikke være nogen [] på push_back.

FileName indeholder std::string, så det der skal push's skal være en std::string. Compileren kan selv finde ud af at lave en "const char *" om til en std::string, så for FileName bliver det til:
FileName.push_back(aName);
Eller vi kan lave konverteringen for compileren:
std::string T(aName);
FileName.push_back(T);
Eller (det samme skrevet på en anden måde):
FileName.push_back(std::string(aName));

Det samme for FileSize
Avatar billede nph12 Nybegynder
23. oktober 2005 - 14:05 #66
Sådan?

void DirInfoClass::AddFile(const char *aName)
{
    FileName.push_back(std::string(aName));
    FileSize.push_back(int (GetFileSize(aName)));
}
Avatar billede bertelbrander Novice
23. oktober 2005 - 16:18 #67
Ja.

Med hensyn til FileSize er det ikke nødventigt med int(...) GetFileSize returnerer en int.

Prøv at lave en løsning hvor fil-navn og file-size er i en class for sig selv, som beskrevet 18/10-2005 16:11:59 med FileEntryClass.
Avatar billede nph12 Nybegynder
23. oktober 2005 - 17:12 #68
Sådan?

class FileEntryClass
{
public:
  std::string FileName;
  int FileSize;
};
  std::vector<FileEntryClass> FileEntry;


void DirInfoClass::AddFile(const char *aName)
{
    FileName.push_back(std::string(aName));
    FileSize.push_back(GetFileSize(aName));
}
Avatar billede bertelbrander Novice
23. oktober 2005 - 19:45 #69
Ja, men du skal fjerne FileName og FileSize vectorene.
Og lave en push_back på FileEntry (jeg går ud fra at det er en member i FileInfoClass).
Avatar billede nph12 Nybegynder
23. oktober 2005 - 22:21 #70
Denne del var rigtigt?
void DirInfoClass::AddFile(const char *aName)
{
    FileName.push_back(std::string(aName));
    FileSize.push_back(GetFileSize(aName));
}

Så skal jeg fjerne FileName og FileSize vectorene
class FileEntryClass
{
public:
  std::string FileName;
  int FileSize;
};
  std::vector<FileEntryClass> FileEntry;

altså:

class FileEntryClass
{

};
  std::vector<FileEntryClass> FileEntry;

og lave en push_back på FileEntry (lige som jeg gjorde med vectorerne i addFile)?

FileEntry skal være member i FileInfoClass, mener du ikke DirInfoClass?
Avatar billede bertelbrander Novice
23. oktober 2005 - 23:25 #71
Jo, FileEntry skal være member af DirInfoClass.

Men du skal så ikke bruge FileName og FileSize vectorene.

Du skal oprette en FileEntryClass object og push'e den på FileEntry.

Og rette GetFileName og GetFileSize.
Avatar billede nph12 Nybegynder
29. oktober 2005 - 15:01 #72
Kan vi ikke tage hvert af punkterne fra 23/10-2005 23:25:40 og forklar mig præcis hvad jeg skal? Hvad skal jeg gøre for, at FileEntry er member af DirInfoClass og næste punkt osv.
Avatar billede bertelbrander Novice
29. oktober 2005 - 17:12 #73
Start med FileEntryClass:
class FileEntryClass
{
public:
  std::string FileName;
  int FileSize;
};

DirInfoClass ændres til:
class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
  int GetFileSize(const char *fn);
public:
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile();
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

I AddFile skal vi oprette et FileEntryClass object, sætte dens member-variable, og push'e den på vectoren. Du skal selv kode det der svarer til de to kommentarer:

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry;
  Entry.FileName = aName;
  // Entry.FileSize skal også sættes
  // Og Entry skal push'es på FileEntry med push_back
}

Nu skal vi lave GetFileSize(int n), for at få det n'te element i FileEntry bruges[], det vi får er så en FileEntryClass object, vi får FileSize med . operatoren;

int FileInfoClass GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

GetFileName laves på samme måde.

GetNumFile skal ændres så den returnerer størrelsen på FileEntry vectoren (size())
Avatar billede nph12 Nybegynder
30. oktober 2005 - 17:47 #74
Noget i denne stil? Jeg kan ikke få programmet til at køre, da der er fejl i programmet.

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>


/*Erklære variabler*/
class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
  int GetFileSize(const char *fn);
public:
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile(size());
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

class FileEntryClass
{
public:
  std::string FileName;
  int FileSize;
};

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry;
  Entry.FileName = aName;
  Entry.FileSize = Entry;
  FileEntry.push_back(Entry); 
}

int FileInfoClass GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

int FileInfoClass GetFileName(int n)
{
  return FileEntry[n].FileName;
}

/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
30. oktober 2005 - 19:55 #75
Du skal erklære FileEntryClass inden DirInfoClass.

Jeg har rettet disse linier:
  int GetNumFile() { return FileEntry.size(); } 

  Entry.FileSize = GetFileSize(aName);

int DirInfoClass::GetFileSize(int n)

std::string &DirInfoClass::GetFileName(int n)

Og så virker det.
Avatar billede nph12 Nybegynder
30. oktober 2005 - 21:26 #76
OK. Nu virker det også her:-)

Hvad er det næste vi skal lave? Kan man få programmet til at understøtte æ,ø,å ?
Avatar billede bertelbrander Novice
30. oktober 2005 - 23:21 #77
Du kan få det til at udskrive æøå (og andre specielle tegn) ved at oversætte med OemToChar (eller er det CharToOem?). Men hvis det er meningen at det skal ende med at være et windows program (hvor problemet ikke opstår) er det måske ikke umagen værd.

Du kan starte med at tilføje en feature der også gemmer tidspunkt for hver fil til FileEntryClass, og lave en GetFileTime funktion til DirInfoClass. Du får fat i tidspunkt med stat:
http://www.hmug.org/man/2/stat.php

Næste opgave kunne være at få programmet til at undersøge forskellen på filer i de to lister.
Avatar billede nph12 Nybegynder
31. oktober 2005 - 09:08 #78
Ja, det skal ende med at programmet bliver et windows program.

Kan du ikke lave en gennemgang ligesom du gjorde d. 29/10-2005 17:12:22, så kan jeg bedre forstår, hvad det er jeg skal.
Avatar billede bertelbrander Novice
31. oktober 2005 - 20:22 #79
Start med at lave en GetFileTime funktion i DirInfoClass:
  time_t GetFileTime(const char *aName);

Det burde være trivielt, der er en bedre beskrivelse af stat(...) her:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__stat.2c_._wstat.2c_._stati64.2c_._wstati64.asp
Du bør bruge st_mtime fra strukturen.

Så tilføjer du en:
  time_t FileTime;
Til FileEntryClass.

I AddFile kalder du GetFileTime, og sætter FileTime i FileEntry.

På siden jeg linker til kan du se hvordan man kan bruge ctime(...) til at udskrive fil-tiden med. Det kan måske være en ide at lave en:
  std::string GetFileTime(int n);
i DirInfoClass, der bruger ctime til at lave en std::string, som så kan udskrives.

Når du kommer til at lave sammenligningen bør du starte med at lave en pseudo-kode beskrivlse af hvordan du vil gøre det.
Avatar billede nph12 Nybegynder
01. november 2005 - 17:17 #80
Jeg behøver lidt hjælp, da jeg er gået lidt i stå. Jeg er stadigvæk ikke hel med på, hvordan jeg skal bruge st_mtime.

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>

class FileEntryClass
{
public:
  std::string FileName;
  int FileSize;
  time_t FileTime;
};

/*Erklære variabler*/
class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
  int GetFileSize(const char *fn);
public:
  time_t GetFileTime(const char *aName);
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry;
  Entry.FileName = aName;
  Entry.FileSize = GetFileSize(aName);
  FileEntry.push_back(Entry);
  Entry.FileTime = GetFileTime(aName);
  FileEntry(FileTime);
 
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}


/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
01. november 2005 - 20:10 #81
Du skal lave en:
time_t DirInfoClass::GetFileTime(const char *aName)
{
...
}
I denne skal du kalde stat(...)
I koden fra "16/09-2005 11:06:04" kan du se hvordan det gøres.
I kaldet til stat(...) bruges "struct stat s;" s har st_mtime det er den der skal returneres fra GetFileTime.

I din AddFile(...) har du "FileEntry(FileTime);", det giver ikke rigtigt mening, du skal sætte FileEntry.FileTime på samme måde som du sætter FileEntry.FileSize.
Og det skal gøres inden du kalder push_back, da den laver et kopi.

Når du har det på plads skal du lave
std::string DirInfo::GetFileTime(int n)
Du skal bruge ctime(...) til at lave en "char Data[50]", og så lave en std::string fra dette, som returneres.

Til slut skal du bruge GetFileTime(j) i loopen i enden af main til at udskrive tiden på filen sammen med navnet og størrelsen.
Avatar billede nph12 Nybegynder
02. november 2005 - 20:43 #82
Jeg mangler lidt hjælp til dette:

Når du har det på plads skal du lave
std::string DirInfo::GetFileTime(int n)
Du skal bruge ctime(...) til at lave en "char Data[50]", og så lave en std::string fra dette, som returneres.

Ellers har jeg styr på resten (tror jeg nok).
Avatar billede bertelbrander Novice
02. november 2005 - 20:48 #83
Jeg huskede forkert, du skal ikke bruge en "char Data[50]", kun en char *:

std::string DirInfoClass::GetFileTime(int n)
{
  char *Str = ctime(&FileEntry[n].FileTime);
  return std::string(Str);
}
Avatar billede nph12 Nybegynder
02. november 2005 - 21:31 #84
Nu kører det vist:-)

Er vi kommet til sammenlignen nu?

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>

class FileEntryClass
{
public:
  std::string FileName;
  int FileSize;
  time_t FileTime;
};

/*Erklære variabler*/
class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
  int GetFileSize(const char *fn);
public:
  time_t GetFileTime(const char *aName);
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry;
  Entry.FileName = aName;
  Entry.FileSize = GetFileSize(aName);
  Entry.FileTime = GetFileTime(aName);
  FileEntry.push_back(Entry); 
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *Str = ctime(&FileEntry[n].FileTime);
  return std::string(Str);
}

time_t DirInfoClass::GetFileTime(const char *aName)
{
    struct stat s;
    s.st_mtime;
}



/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
02. november 2005 - 22:02 #85
Der er lige et par ting som jeg vil foreslå at vi laver om først.

Først flytte GetFileSize(const char *xx) og GetFileTime(const char *xx) til FileEntryClass, og lave en constructor til FileEntryClass som tager en "const char *aName) som argument.

Derved kommer vores class'er til at se sådan ud:
class FileEntryClass
{
  int GetFileSize(const char *fn);
  time_t GetFileTime(const char *aName);
public:
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  time_t FileTime;
};

class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

AddFiles kommer så til at se såden ud:
void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

Du skal så selv lave:
FileEntryClass::FileEntryClass(const char *aName)

Den skal sætte FileName, FileSize ved at kalde GetFileSize og FileTime ved at kalde GetFileTime.

Du må også gerne fjerne argumenterne til GetFileSize(const char *) og GetFileTime(const char *), da navnet er en member i class'en.

Dernæst vil jeg gerne have flyttet disse:
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
Til FileEntryClass også.

Din version af GetFileTime virker ikke. Du skal kalde stat(...) og returnere s.st_mtime
Avatar billede nph12 Nybegynder
03. november 2005 - 12:12 #86
Jeg har lige hurtig kigget på det, men er gået lidt i stå. Hvis du lige kan sige, hvad der er rigtigt og hvad som skal rettes, så kigger jeg på det i aften.

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>

class FileEntryClass
{
public:
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  time_t FileTime;
};

FileEntryClass::FileEntryClass(const char *aName)
{
        FileName();
        FileTime = GetFileSize();
        FileTime = GetFileTime();
       
}
/*Erklære variabler*/
class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *Str = ctime(&FileEntry[n].FileTime);
  return std::string(Str);
}

time_t DirInfoClass::GetFileTime(const char *aName)
{
    struct stat s;
    return s.st_mtime;
}

/*Henter filstørrelse*/
int DirInfoClass::GetFileSize(const char *fn)
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
03. november 2005 - 20:40 #87
Start med dette:

class FileEntryClass
{
public:
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  int GetFileSize();
  time_t GetFileTime();
  time_t FileTime;
};

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileTime = GetFileSize();
  FileTime = GetFileTime();
}

class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

Du skal så ændre FileEntryClass::GetFileSize() så den bruger FileName og ikke fn.
fopen, access og printf skal bruge en "const char *", du laver en fra en std::string med: FileName.c_str()

GetFileTime() er stadig ikke rigtig.
Avatar billede nph12 Nybegynder
03. november 2005 - 23:09 #88
Jeg forstår ikke rigtigt dette:

Du skal så ændre FileEntryClass::GetFileSize() så den bruger FileName og ikke fn.
fopen, access og printf skal bruge en "const char *", du laver en fra en std::string med: FileName.c_str()

Jeg kan ikke finde FileEntryClass::GetFileSize()...

Er GetFileTime() rigtigt nu?

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}
Avatar billede bertelbrander Novice
03. november 2005 - 23:28 #89
Det der før var DirInfoClass::GetFileSize(const char *) skal laves om til FileEntryClass::GetFileSize()

FileEntryClass::GetFileTime() skal kalde stat(...).
Avatar billede nph12 Nybegynder
04. november 2005 - 16:02 #90
Jeg ved godt, at det langt fra er rigtigt, men jeg kører bare rundt i det nu. Jeg mangler lige at få styr på det grundlæggende, så jeg læser lige i min C++ bog her i weekend.

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>

class FileEntryClass
{
public:
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  int GetFileSize();
  time_t GetFileTime();
  time_t FileTime;
};


FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

/*Erklære variabler*/
class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *Str = ctime(&FileEntry[n].FileTime);
  return std::string(Str);
}

time_t DirInfoClass::GetFileTime(const char *aName)
{
    struct stat s;
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede nph12 Nybegynder
06. november 2005 - 13:28 #91
Skal vi fortsætte fra 04/11-2005 16:02:01? Hvad skal jeg rette?

Jeg tror at "problemet" er, at jeg mister overblikket og derfor ikke ved rigtigt, hvad jeg skal gøre. Alt nyt er svært, men jeg er indstillet på at lære at programmere i C++.
Avatar billede bertelbrander Novice
06. november 2005 - 15:18 #92
Så vidt jeg kan se mangler du kun:

// Skal være FileEntryClass::GetFileTime()
// Skal kalde stat(...)
time_t DirInfoClass::GetFileTime(const char *aName)
{
    struct stat s;
    return s.st_mtime;
}

//Skal bruge FileName.c_str() i stedet for fn
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(fn, "rb");
  if(!f)
  {
    fprintf(stderr, "Unable to open: %s\n", fn);
    if(!access(fn, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

Derpå: Lav printf om til cout <<
Avatar billede nph12 Nybegynder
06. november 2005 - 18:06 #93
Sådan, men der er stadigvæk mange fejl

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>

class FileEntryClass
{
public:
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  int GetFileSize();
  time_t GetFileTime();
  time_t FileTime;
};


FileEntryClass::FileEntryClass::GetFileSize()
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

/*Erklære variabler*/
class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *Str = ctime(&FileEntry[n].FileTime);
  return std::string(Str);
}

// Skal være FileEntryClass::GetFileTime()
// Skal kalde stat(...)
time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    return s.st_mtime;
}


/*Henter filstørrelse*/
//Skal bruge FileName.c_str() i stedet for fn
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    fcout <<(stderr, "Unable to open: %s\n", FileName.c_str());
    if(!access(FileName.c_str(), 0))
      fcout <<(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
06. november 2005 - 19:42 #94
Denne linie:
FileEntryClass::FileEntryClass::GetFileSize()
Skal være:
FileEntryClass::FileEntryClass(const char *aName)

For at skrive til stderr bruger man std::cerr:
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

Når man bruger ctime() til at lave en time_t om til en streng putter den et linieskift på i enden af strengen. Det er ikke så smart, prøv om du kan fjerne den, læs om std::string her:
http://www.sgi.com/tech/stl/basic_string.html
Avatar billede bertelbrander Novice
06. november 2005 - 23:16 #95
Du kalder stadig ikke stat(...) i:
time_t FileEntryClass::GetFileTime()
Avatar billede nph12 Nybegynder
07. november 2005 - 21:04 #96
Det ekstra linieskift som skal fjernes og kaldet til stat(...) i: time_t FileEntryClass::GetFileTime()driller mig.

Kan vi ikke tage trin for trin, hvad der sker i de to klasser? Det vil være en rigtigt god måde, hvis jeg forstod hvad de forskellige ting gør (så vil jeg måske også kunne se, hvad jeg mangler før det virker). Det vil være en godt hjælp, hvis jeg fik at vide, at der mangler det og det og hvor det mangler.
Avatar billede bertelbrander Novice
07. november 2005 - 21:38 #97
Jeg har ændret det så det hele virker. Prøv at sammenligne dette med din seneste udgave af koden.

Jeg tror at du får mest ud af at beskrive koden selv. Prøv at skrive nogle liniers kommentar for hver funktion og blok i funktion. Hvis der er dele du ikke forstår så spørg.

Der er to funktioner der hedder GetFileSize og der er også to funktioner der hedder GetFileTime, det forvirrer måske. Prøv at give et andet navn til dem i FileEntryClass.

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>

class FileEntryClass
{
public:
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  int GetFileSize();
  time_t GetFileTime();
  time_t FileTime;
};

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

/*Erklære variabler*/
class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

// Skal være FileEntryClass::GetFileTime()
// Skal kalde stat(...)
time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
//Skal bruge FileName.c_str() i stedet for fn
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          fprintf(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    printf("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}


/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)

{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  fprintf(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  fprintf(stderr, "  -s  Scan thru subdirectories\n");
  fprintf(stderr, "  -a  Ask before delete\n");
  fprintf(stderr, "  -r  Delete Read-Only files\n");
  fprintf(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede nph12 Nybegynder
09. november 2005 - 20:05 #98
Jeg kigger lige på det og vender tilbage her en af dagene.
Avatar billede nph12 Nybegynder
11. november 2005 - 15:41 #99
Hvad er det næste som skal laves?
Avatar billede bertelbrander Novice
11. november 2005 - 23:23 #100
1: Fjern de sidste printf og fprintf.

2: Put FileEntryClass og DirInfoClass i en .h fil og inkluder den i din cpp fil.

3: Beskriv hvilket problem du nu ønsker at løse, dvs. hvad skal programmet kunnne som det næste.
Avatar billede nph12 Nybegynder
15. november 2005 - 20:44 #101
Skal jeg ændre printf og fprintf til std::cout?

Jeg skriver #include <main.h> i starten af min main.cpp og flytter FileEntryClass og DirInfoClass til en .h fil som jeg passende kunne kalde main.h

Vi skal lave en status side som viser navn, størrelse og hvornår filen sidst er ændret. Status siden skal finde følgende filer:

Filer med samme indhold
Filer med samme navn (skal finde den nyeste fil)
Avatar billede bertelbrander Novice
16. november 2005 - 01:26 #102
"Skal jeg ændre printf og fprintf til std::cout?"
>Ja

"Jeg skriver #include <main.h> i starten af min main.cpp og flytter FileEntryClass og DirInfoClass til en .h fil som jeg passende kunne kalde main.h"
> Foretrækker #include "main.h" til filer der er ens egne og som ligger i samme mappe. main.h er måske ikke det bedste navn.

Du kan derpå lave en funktion der sammenligner to FileEntryClass objecter/filer. Start med at checke om de har samme størrelse, så kan vi lave resten senere.

Og så laver du en loop der sammenligner alle filer i to lister (DirInfoClass) og udskriver resultatet af hver sammenligning.
Avatar billede nph12 Nybegynder
18. november 2005 - 10:04 #103
Nu er jeg ændret printf og fprintf til std::cout<<.

Jeg har flyttet FileEntryClass og DirInfoClass til header.h filen. Jeg kan godt compile, men jeg får to warnings:

Project  : Console application
Compiler  : GNU GCC Compiler (called directly)
Directory : D:\CPP\checkdup2\
--------------------------------------------------------------------------------
Switching to target: default
Compiling: main.cpp
In file included from main.cpp:12:
header.h:22:3: warning: no newline at end of file
main.cpp:192:2: warning: no newline at end of file
Linking console executable: D:\CPP\checkdup2\console.exe
Process terminated with status 0 (0 minutes, 1 seconds)
0 errors, 2 warnings

Jeg prøver, at kigge på resten her en af dagene. God weekend:-)
Avatar billede bertelbrander Novice
18. november 2005 - 20:10 #104
Du manger blot et linieskift i enden af filerne
Scroll helt ned til enden & tryk på enter.
Avatar billede nph12 Nybegynder
22. november 2005 - 18:00 #105
Jeg mangler det sidste fra 16/11-2005 01:26:58. Kan vi ikke tage det sidste linie for linie? Hvordan laver jeg en funktion som sammeligner to FileEntryClass objecter/filer?
Avatar billede bertelbrander Novice
22. november 2005 - 23:14 #106
Man kunne starte med at tilføje en funktion til FileEntryClass:
  bool Compare(const FileEntryClass& aOther);

Den kunne se sådan ud:
bool FileEntryClass::Compare(const FileEntryClass& aOther)
{
  if(FileSize != aOther.FileSize)
      return false;
  if(FileTime != aOther.FileTime)
      return false;
  return true;
}
Hvis den returnerer true er filerne ens.
Men det checker kun om filerne har samme størrelse (hvilket er ok) og om de er fra samme tid (hvilket ikke er nogen god idé).
I stedet bør man åbne filerne og læse dem byte for byte for at se om de er ens, CheckDup() fra den oprindelige kode gør netop det.
Avatar billede nph12 Nybegynder
26. november 2005 - 11:17 #107
Jeg kan godt compile filerne, men det ser ikke rigtigt ud, når man kører filen.

header.h

class FileEntryClass
{
public:
  bool Compare(const FileEntryClass& aOther);
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  int GetFileSize();
  time_t GetFileTime();
  time_t FileTime;
};

class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
};

main.cpp

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

bool FileEntryClass::Compare(const FileEntryClass& aOther)
{
  if(FileSize != aOther.FileSize)
      return false;
  if(FileTime != aOther.FileTime)
      return false;
  return true;
}


void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          std::cout<<(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout<<("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}

/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  std::cout<<(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        std::cout<<(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    std::cout<<(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          std::cout<<(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  std::cout<<(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
  std::cout<<(stderr, "  -s  Scan thru subdirectories\n");
  std::cout<<(stderr, "  -a  Ask before delete\n");
  std::cout<<(stderr, "  -r  Delete Read-Only files\n");
  std::cout<<(stderr, "  pattern  e.g. *.* *.jpg adir.*\n");
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
26. november 2005 - 15:47 #108
Du har nogle af disse:
  chat temp[1023];
  std::cout<<(temp, "%s\\%s", dir, pattern);

I dette tilfælde var det en sprintf, den skal du lave om til:
std::string temp:
temp = dir:
temp += "\\";
temp += pattern;
og så bruge temp.c_str() efterfølgende

Der hvor du udskriver til cout of cerr står der f.ex:
std::cout<<(stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]\n", ProgramName);
Det skal være:
std::cerr << "Usage: " << ProgramName << "[-s] [-a] [-q] [pattern1 [pattern2 [...]]]" << std::endl;
Avatar billede nph12 Nybegynder
29. november 2005 - 19:18 #109
Du skriver, at jeg har nogle af disse, men er der ikke kun en?
char sub[1024];
std::cout<<(sub, "%s\\%s", dir, fileinfo.name);

Jeg har prøvet at ændre denne ene, men får det ikke rigtigt til at køre. Hvis jeg sletter de to linier og indsætter disse:
std::string temp:
temp = dir:
temp += "\\";
temp += pattern;

Hvad skal jeg så gøre med temp.c_str()? Er der ander jeg skal?




#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

bool FileEntryClass::Compare(const FileEntryClass& aOther)
{
  if(FileSize != aOther.FileSize)
      return false;
  if(FileTime != aOther.FileTime)
      return false;
  return true;
}


void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          std::cout<<(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout<<("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}

/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  std::cout<<(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        std::cout<<(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    std::cout<<(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          std::cout<<(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  std::cerr<< "Usage: " << ProgramName << "[-s] [-a] [-q] [pattern1 [pattern2 [...]]]" << std::endl;
  std::cout<< "  -s  Scan thru subdirectories\n" << std::endl;
  std::cout<< "  -a  Ask before delete\n" << std::endl;
  std::cout<< "  -r  Delete Read-Only files\n" << std::endl;
  std::cout<< "  pattern  e.g. *.* *.jpg adir.*\n" << std::endl;
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
29. november 2005 - 20:06 #110
Du har en med temp[1024] og en med sub[1024].

De steder hvor du bruger temp (f.ex _findfirst) og sub forventes en c-type streng (char *) for at lave en sådan fra en std::string bruger man .c_str()
Avatar billede nph12 Nybegynder
30. november 2005 - 10:15 #111
Nu kører det næsten, men jeg får to fejl i linie 186

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

bool FileEntryClass::Compare(const FileEntryClass& aOther)
{
  if(FileSize != aOther.FileSize)
      return false;
  if(FileTime != aOther.FileTime)
      return false;
  return true;
}


void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          std::cout<<(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout<<("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}

/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  std::string temp;
  temp = dir;
  temp += "\\";
  temp += pattern;
  std::cout<<(temp.c_str(), "%s\\%s", dir, pattern);
  handle = _findfirst(temp.c_str(), &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        std::string sub;
        sub = dir;
        sub += "\\";
        sub += pattern;
        std::cout<<(sub.c_str(), "%s\\%s", dir, fileinfo.name);
        AddFile(sub.c_str());
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    std::cout<<(temp.c_str(), "%s\\*.*", dir);
    handle = _findfirst(temp.c_str(), &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          std::string sub;
          sub = dir;
          sub += "\\";
          sub += pattern;
          std::cout<<(sub.c_str(), "%s\\%s", dir, fileinfo.name);
          Scan(sub.c_str(), pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  std::cerr<< "Usage: " << ProgramName << "[-s] [-a] [-q] [pattern1 [pattern2 [...]]]" << std::endl;
  std::cout<< "  -s  Scan thru subdirectories\n" << std::endl;
  std::cout<< "  -a  Ask before delete\n" << std::endl;
  std::cout<< "  -r  Delete Read-Only files\n" << std::endl;
  std::cout<< "  pattern  e.g. *.* *.jpg adir.*\n" << std::endl;
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
30. november 2005 - 19:44 #112
Øv! _findfirst forventer en char * og ikke en const char *

Jeg foreslår at du laver dem tilbage til sprintf, men retter cout << og cerr, f.ex:
          std::cout<<(stderr, "Unknown switch: %s\n", argv[i]);
Avatar billede nph12 Nybegynder
01. december 2005 - 18:07 #113
Skal jeg tilbage til 29/11-2005 19:18:44 og så rette temp[1024] og sub[1024] med det du beskriver 30/11-2005 19:44:51? Skal jeg rette parametrene tilbage?

Hvad skal jeg f.eks. rette disse linier til?
char sub[1024];
std::cout<<(sub, "%s\\%s", dir, fileinfo.name);
Scan(sub, pattern, 1);
Avatar billede bertelbrander Novice
01. december 2005 - 19:43 #114
Du skal tilbage til fra før du lavede sub og temp om til std::string og du skal bruge sprintf

Men alle printf og fprintf skal laves om til cout << og cerr
Avatar billede nph12 Nybegynder
04. december 2005 - 17:35 #115
Jeg er gået tilbage til 29/11-2005 19:18:44. Hvad skal jeg så?
Avatar billede nph12 Nybegynder
05. december 2005 - 19:58 #116
Jeg ved ikke, hvad jeg skal fortsætte med....
Avatar billede nph12 Nybegynder
09. december 2005 - 16:01 #117
Hvad skal jeg rette? Hvad er det næste jeg skal lave?

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

bool FileEntryClass::Compare(const FileEntryClass& aOther)
{
  if(FileSize != aOther.FileSize)
      return false;
  if(FileTime != aOther.FileTime)
      return false;
  return true;
}


void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          std::cout<<(stderr, "Unknown switch: %s\n", argv[i]);
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout<<("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}

/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  std::cout<<(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        std::cout<<(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    std::cout<<(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          std::cout<<(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  std::cerr<< "Usage: " << ProgramName << "[-s] [-a] [-q] [pattern1 [pattern2 [...]]]" << std::endl;
  std::cout<< "  -s  Scan thru subdirectories\n" << std::endl;
  std::cout<< "  -a  Ask before delete\n" << std::endl;
  std::cout<< "  -r  Delete Read-Only files\n" << std::endl;
  std::cout<< "  pattern  e.g. *.* *.jpg adir.*\n" << std::endl;
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
10. december 2005 - 18:11 #118
Du skal have rettet disse:
          std::cout<<(stderr, "Unknown switch: %s\n", argv[i]);
Til
          std::cerr <<stderr, "Unknown switch: " << argv[i] << std::endl;

Der er en del af dem, også f.ex:
    std::cout<<("Found: %d %s\n", DirInfo[i].GetNumFile(), DirInfo[i].GetNumFile() != 1 ? "files" : "file");

Det er muligt at det kompilerer, men det virker ikke.

Når du har det på plads kan du begynde at sammenligne filer i to lister.
Avatar billede nph12 Nybegynder
12. december 2005 - 09:23 #119
Jeg har prøvet at rette i programmet, men der er masser af fejl som jeg ikke ved, hvad jeg skal gøre med.

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

bool FileEntryClass::Compare(const FileEntryClass& aOther)
{
  if(FileSize != aOther.FileSize)
      return false;
  if(FileTime != aOther.FileTime)
      return false;
  return true;
}


void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          std::cerr <<stderr, "Unknown switch: " << argv[i] << std::endl;
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout<< "Found: " << DirInfo[i].GetNumFile() << DirInfo[i].GetNumFile() <<!= 1 ? "files" : "file" << std::endl;

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}

/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  std::cout<<temp << dir << pattern << std::endl;
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        std::cout<<sub <<dir <<fileinfo.name <<std::endl;
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    std::cout<<temp << dir <<std:endl;
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          std::cout<<sub <<dir <<fileinfo.name << std::endl;
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  std::cerr<<stderr, "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]", ProgramName <<std::endl;
  std::cerr<<stderr, "  -s  Scan thru subdirectories" <<std::endl;
  std::cerr<<stderr, "  -a  Ask before delete" <<std::endl;
  std::cerr<<stderr, "  -r  Delete Read-Only files" <<std::endl;
  std::cerr<<stderr, "  pattern  e.g. *.* *.jpg adir.*" <<std::endl;
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
12. december 2005 - 23:02 #120
Jeg har fixet de sidste småfejl, prøv at sammenligne de linier der ender på OLD med linien efter.

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

bool FileEntryClass::Compare(const FileEntryClass& aOther)
{
  if(FileSize != aOther.FileSize)
      return false;
  if(FileTime != aOther.FileTime)
      return false;
  return true;
}


void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          // std::cerr <<stderr, "Unknown switch: " << argv[i] << std::endl; OLD
          std::cerr << "Unknown switch: " << argv[i] << std::endl;
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    // std::cout << "Found: " << DirInfo[i].GetNumFile() << DirInfo[i].GetNumFile() <<!= 1 ? "files" : "file" << std::endl; OLD
    std::cout << "Found: " << DirInfo[i].GetNumFile() << (DirInfo[i].GetNumFile() != 1 ? "files" : "file") << std::endl;

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
  return EXIT_SUCCESS;
}

/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  std::cout<<temp << dir << pattern << std::endl;
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        std::cout<<sub <<dir <<fileinfo.name <<std::endl;
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    // std::cout<<temp << dir <<std:endl; OLD
    std::cout<<temp << dir <<std::endl;
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          std::cout<<sub <<dir <<fileinfo.name << std::endl;
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  // std::cerr<< "Usage: %s [-s] [-a] [-q] [pattern1 [pattern2 [...]]]", ProgramName <<std::endl; OLD
  std::cerr<< "Usage: " << ProgramName  << " [-s] [-a] [-q] [pattern1 [pattern2 [...]]]"  <<std::endl;
  std::cerr<< "  -s  Scan thru subdirectories" <<std::endl;
  std::cerr<< "  -a  Ask before delete" <<std::endl;
  std::cerr<< "  -r  Delete Read-Only files" <<std::endl;
  std::cerr<< "  pattern  e.g. *.* *.jpg adir.*" <<std::endl;
  exit(EXIT_FAILURE);
}

Du bør nok lige checke op på std::cout og ?: operatoren
Avatar billede nph12 Nybegynder
20. december 2005 - 11:00 #121
Jeg har kigget lidt på de to linier. Hvad er det næste jeg skal og hvordan laver jeg det?
Avatar billede bertelbrander Novice
20. december 2005 - 20:05 #122
Prøv at kikke under "22/11-2005 23:14:57"
Avatar billede nph12 Nybegynder
28. december 2005 - 12:41 #123
Jeg har kigget på det, men jeg behøver lidt mere hjælp til at få det til at virke.
Avatar billede bertelbrander Novice
28. december 2005 - 14:24 #124
Så vis hvad du har lavet, så arbejder vi videre derfra.
Avatar billede nph12 Nybegynder
28. december 2005 - 14:53 #125
Jeg har ikke lavet andet kode end det som jeg har lavet 12/12-2005 23:02:49 (udover at fjerne OLD linierne).

Der er tilføjet det som også er beskrevet 22/11-2005 23:14:57. Jeg kan godt se, at jeg skal have fat i noget kode fra det oprindelige checkdup program, men ved ikke helt, hvor jeg skal starte.
Avatar billede bertelbrander Novice
29. december 2005 - 00:42 #126
Vi har allerede en compare function i FileEntryClass, den er ikke færdig, men kan bruges om en begyndelse.

Vi starter med at lave den const (den modificerer ikke objektet).
I header.h tilføjer vi const efter funktionen:
  bool Compare(const FileEntryClass& aOther) const;
også i .cpp filen:
bool FileEntryClass::Compare(const FileEntryClass& aOther) const

Derpå laver vi en [] operator i DirInfoClass:
  const FileEntryClass& operator [] (size_t aIdx) const {return FileEntry[aIdx]; }

Så kan vi lave en loop i enden af main():
  if(idx == 2)
  {
    int i, j;
    for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
          if(DirInfo[0][i].Compare(DirInfo[1][j]))
          {
              std::cout << "These files seems to be the same: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
          }
        }
    }
  }

Den vil så udskrive navnene på de filer der har samme størrelse og er fra samme tidspunkt.

Når du har det til at spille kan du forbedre compare funktionen:
1: At to filer har forskellige tidsstempler gør dem ikke forskellige.
2: Hvis to filer har samme størrelse bør man åbne dem, og sammenligne dem byte for byte. Du kan se hvordan i den oprindelige kode.
Avatar billede nph12 Nybegynder
02. januar 2006 - 19:44 #127
Jeg kan ikke få det til at køre. Hvad gør jeg forkert?


#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

bool FileEntryClass::Compare(const FileEntryClass& aOther)
{
  if(FileSize != aOther.FileSize)
      return false;
  if(FileTime != aOther.FileTime)
      return false;
  return true;
}


void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;
const FileEntryClass& operator [] (size_t aIdx) const {return FileEntry[aIdx]; }


/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          // std::cerr <<stderr, "Unknown switch: " << argv[i] << std::endl; OLD
          std::cerr << "Unknown switch: " << argv[i] << std::endl;
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout << "Found: " << DirInfo[i].GetNumFile() << (DirInfo[i].GetNumFile() != 1 ? "files" : "file") << std::endl;

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
 
  if(idx == 2)
  {
    int i, j;
    for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
          if(DirInfo[0][i].Compare(DirInfo[1][j]))
          {
              std::cout << "These files seems to be the same: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
          }
        }
    }
  }
  return EXIT_SUCCESS;
}

/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  std::cout<<temp << dir << pattern << std::endl;
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        std::cout<<sub <<dir <<fileinfo.name <<std::endl;
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    std::cout<<temp << dir <<std::endl;
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          std::cout<<sub <<dir <<fileinfo.name << std::endl;
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  std::cerr<< "Usage: " << ProgramName  << " [-s] [-a] [-q] [pattern1 [pattern2 [...]]]"  <<std::endl;
  std::cerr<< "  -s  Scan thru subdirectories" <<std::endl;
  std::cerr<< "  -a  Ask before delete" <<std::endl;
  std::cerr<< "  -r  Delete Read-Only files" <<std::endl;
  std::cerr<< "  pattern  e.g. *.* *.jpg adir.*" <<std::endl;
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
02. januar 2006 - 19:58 #128
Der skal const til slut i denne linie:
bool FileEntryClass::Compare(const FileEntryClass& aOther) const

Denne linie skal stå i header.h:
const FileEntryClass& operator [] (size_t aIdx) const {return FileEntry[aIdx]; }

inden for:
class DirInfoClass
{
...

};

i public delen.
Avatar billede nph12 Nybegynder
03. januar 2006 - 12:51 #129
Det kan godt compilie nu, men jeg er ikke sikker på, at det virker som det skal.

class FileEntryClass
{
public:
  bool Compare(const FileEntryClass& aOther) const;
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  int GetFileSize();
  time_t GetFileTime();
  time_t FileTime;
};

class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
  const FileEntryClass& operator [] (size_t aIdx) const {return FileEntry[aIdx]; }
};
----------------------------------------------------------------



#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

bool FileEntryClass::Compare(const FileEntryClass& aOther) const
{
  if(FileSize != aOther.FileSize)
      return false;
  if(FileTime != aOther.FileTime)
      return false;
  return true;
}


void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;


/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          // std::cerr <<stderr, "Unknown switch: " << argv[i] << std::endl; OLD
          std::cerr << "Unknown switch: " << argv[i] << std::endl;
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout << "Found: " << DirInfo[i].GetNumFile() << (DirInfo[i].GetNumFile() != 1 ? "files" : "file") << std::endl;

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
 
  if(idx == 2)
  {
    int i, j;
    for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
          if(DirInfo[0][i].Compare(DirInfo[1][j]))
          {
              std::cout << "These files seems to be the same: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
          }
        }
    }
  }
  return EXIT_SUCCESS;
}

/*Scanner dir*/
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  std::cout<<temp << dir << pattern << std::endl;
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        std::cout<<sub <<dir <<fileinfo.name <<std::endl;
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    std::cout<<temp << dir <<std::endl;
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          std::cout<<sub <<dir <<fileinfo.name << std::endl;
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  std::cerr<< "Usage: " << ProgramName  << " [-s] [-a] [-q] [pattern1 [pattern2 [...]]]"  <<std::endl;
  std::cerr<< "  -s  Scan thru subdirectories" <<std::endl;
  std::cerr<< "  -a  Ask before delete" <<std::endl;
  std::cerr<< "  -r  Delete Read-Only files" <<std::endl;
  std::cerr<< "  pattern  e.g. *.* *.jpg adir.*" <<std::endl;
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
03. januar 2006 - 20:27 #130
Har du prøvet at køre det?
Hvad sker der?
Avatar billede nph12 Nybegynder
04. januar 2006 - 12:27 #131
Ja, jeg har prøvet at køre programmet. Jeg har to mapper som er næsten 100% undtagen to filer som jeg har tilføjet backup2. Det er var jeg får, når jeg kører programmet:

C:\>console c:\backup c:\backup2 -s
id:\backup*
id:\backup
id:\backup2*
id:\backup2
Found: 0files
Found: 0files
Avatar billede bertelbrander Novice
04. januar 2006 - 20:05 #132
Scan funktionen skal se sådan ud:
void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    std::cout<<temp << dir <<std::endl;
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          std::cout<<sub <<dir <<fileinfo.name << std::endl;
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

Det er de to cout << der er lavet om til sprintf.
Så bør du kunne ændre det så den udskriver filer der ikke er ens.
Avatar billede nph12 Nybegynder
04. januar 2006 - 20:40 #133
Det ser stadigvæk ikke helt rigitgt ud. Burde programmet ikke undersøge alle undermapper? Jeg har kopieret mappen backup over til backup2 (samt tilføjet en ekstra fil)

C:\>console c:\backup c:\backup2 -s
c:\backup\*c:\backup
¼c:\backupDocuments and Settings
¼\*¼
c:\backup2\*c:\backup2
¼c:\backup2Documents and Settings
¼\*¼
Found: 1file
c:\backup\Backup.txt 106287 Tue Dec 27 11:44:13 2005
Found: 2files
c:\backup2\Backup.txt 106287 Tue Dec 27 11:44:13 2005
c:\backup2\Ny Bitmapbillede.bmp 0 Wed Dec 28 12:40:50 2005
These files seems to be the same: c:\backup\Backup.txt, c:\backup2\Backup.txt
Avatar billede bertelbrander Novice
04. januar 2006 - 20:45 #134
Ups, der er et par cout << mere i scan(...) der skal laves om til sprintf.
Prøv at ændre dem på samme måde om dem jeg har ændret.
Avatar billede nph12 Nybegynder
05. januar 2006 - 17:10 #135
Jeg har rettet det sidste. Nu ser det ud som om det virker:-)

Hvad sortere vi filerne efter? Jeg vil gerne finde filer som er 100% identiske og filer som optræder i flere versioner fx et Word-dokument.

1) 100 % identiske filer skal bare tjekkes ligesom i checkdup byte for byte.

2) Hvad gør vi her? Er det noget med filnavn, hvornår filen er oprettet og hvornår filen sidst er ændret? Man kan ikke bruge byte for byte metoden her? Altså udregne hvor identiske dokumenterne er fx. 85% identisk
Avatar billede bertelbrander Novice
05. januar 2006 - 20:55 #136
At checke for 100% er ikke noget problem, det synes jeg du skal lave først.

Med stat() kan man få tiden for hvornår en fil er oprettet, jeg ved ikke om den kan bruges.
Det er ret svært at finde ud af om to filer en næsten ens, hvis man putter nogle få ekstra bytes i den ene vil det umiddelbart se ud somom de er meget forskellige, det samme hvis man flytter rundt på to afsnit.
Du kan prøve at sammenligne to næsten ens word dokumenter byte for byte og se hvor meget det er forskellige.
Avatar billede nph12 Nybegynder
06. januar 2006 - 10:55 #137
OK. Jeg skal bruge den del fra checkdup som tjekker for dubletter. Hvordan får jeg det til at køre med resten af programmet? Hvad skal jeg gøre?

Fra checkdup:

/*Tjekker for dubletter*/
int CheckDup(const char *fn1, const char *fn2)
{
  FILE *f1, *f2;
  int c1, c2;

  f1 = fopen(fn1, "rb");
  if(!f1)
  {
    fprintf(stderr, "Unable to open: %s\n", fn1);
    if(!access(fn1, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  f2 = fopen(fn2, "rb");
  if(!f2)
  {
    fclose(f1);
    fprintf(stderr, "Unable to open: %s\n", fn2);
    if(!access(fn2, 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }

  do
  {
    c1 = fgetc(f1);
    c2 = fgetc(f2);
    if(c1 != c2)
    {
      fclose(f1);
      fclose(f2);
      return 0;
    }
  }
  while(c1 != EOF && c2 != EOF);
  fclose(f1);
  fclose(f2);
  return 1;
}
Avatar billede bertelbrander Novice
06. januar 2006 - 20:38 #138
Du kan putte funktionen CheckDup ind i FileEntryClass og kalde den fra Compare funktionen.
Du skal bruge c_str() til at lave om fra en std::string til en const char *
Avatar billede nph12 Nybegynder
12. januar 2006 - 17:32 #139
Jeg tror, at jeg skal have lidt mere hjælp. Kan du ikke beskrive hvad jeg skal, ligesom du gjorde 02/01-2006 19:58:43? Jeg forstår det bedre på den måde:-)
Avatar billede nph12 Nybegynder
15. januar 2006 - 13:37 #140
Jeg kan godt mærke, at det er det her jeg ikke helt forstår endnu.

1) Jeg sætter Checkdup (06/01-2006 10:55:39) ind efter klassen int FileEntryClass::GetFileSize()

2) Så skal jeg kalde den fra Compare funktionen. Er det denne linie jeg skal bruge bool Compare(const FileEntryClass& aOther) const;?

3) Hvordan laver jeg  en std::string til en const char *?
Avatar billede bertelbrander Novice
15. januar 2006 - 15:04 #141
Jeg lavede en kommentar for et par dage siden, men den er fursvundet :-(

Jeg foreslår at vi laver en == operator der sammenligner to FileEntryClass objekter.

Så du skal:
1: Fjerne Compare funktionen fra header.h og .cpp filen.

2: Indsætte en prototype for operatoren i header.h, den skal se sådan ud:
bool operator == (const FileEntryClass& lhs, const FileEntryClass& rhs);
Put den ind i til slut i header.h

3: Så sætter du CheckDup funktionen ind, og ændrer linien:
int CheckDup(const char *fn1, const char *fn2)
til:
bool operator == (const FileEntryClass& lhs, const FileEntryClass& rhs)
I operatoren skal du så bruge lhs.FileName.c_str() i stedet for fn1 og rhs.FileName.c_str() i stedet for fn2

4: Så sætter du disse to linier ind, de checker om de to filer har samme størrelse:
  if(lhs.FileSize != rhs.FileSize)
      return false;

5: For den første fil (f1) skal du ændre koden til:
  FILE *f1, *f2;

  f1 = fopen(lhs.FileName.c_str(), "rb");
  if(!f1)
  {
    fprintf(stderr, "Unable to open: %s\n", lhs.FileName.c_str());
    if(!access(lhs.FileName.c_str(), 0))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
Det samme for f2.

6: Nu kan du bruge operatoren til at sammenligne to filer, i main hvor du før kaldte Compare skal du ændre koden til:
          if(DirInfo[0][i] == DirInfo[1][j])
          {
              std::cout << "These files seems to be the same: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
          }

7: Når du har det til at spille kan du lave nogle små forbedringer:
a: operatoren skal returnere false eller true, ikke 0 eller 1
b: Det er nok ikke nogen god ide at afslutte programmet (exit()) hvis der er en fil den ikke kan åbne.
c: Bruge cout << og cerr << i stedet for printf og fprintf
d: Bruge std::ifstream istedet for FILE, husk at åbne som binær fil.
Avatar billede nph12 Nybegynder
15. januar 2006 - 19:49 #142
Jeg har fået en del rettet nu, men der er nogle småting som driller. Kan du se, hvad jeg gør forkert?

header.h
-----------------------------------------------
class FileEntryClass
{
public:
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  int GetFileSize();
  time_t GetFileTime();
  time_t FileTime;
};

class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
  const FileEntryClass& operator [] (size_t aIdx) const {return FileEntry[aIdx]; }
  bool operator == (const FileEntryClass& lhs, const FileEntryClass& rhs);
};

main.cpp
---------------------------------------------
#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    exit(EXIT_FAILURE);
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

/*Tjekker for dubletter*/
bool operator == (const FileEntryClass& lhs, const FileEntryClass& rhs)
{
  if(lhs.FileSize != rhs.FileSize)
      return false;

  FILE *f1, *f2;
  int c1, c2;

  f1 = fopen(lhs.FileName.c_str(), "rb");
  if(!f1)
  {
    fprintf(stderr, "Unable to open: %s\n", lhs.FileName.c_str());
    if(!access(lhs.FileName.c_str(), false))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }

  f2 = fopen(rhs.FileName.c_str(), "rb");
  if(!f2)
  {
    fprintf(stderr, "Unable to open: %s\n", rhs.FileName.c_str());
    if(!access(rhs.FileName.c_str(), false))
      fprintf(stderr, "The file seems to be there\n");
    exit(EXIT_FAILURE);
  }
  do
  {
    c1 = fgetc(f1);
    c2 = fgetc(f2);
    if(c1 != c2)
    {
      fclose(f1);
      fclose(f2);
      return false;
    }
  }
  while(c1 != EOF && c2 != EOF);
  fclose(f1);
  fclose(f2);
  return true;
}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;


/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          // std::cerr <<stderr, "Unknown switch: " << argv[i] << std::endl; OLD
          std::cerr << "Unknown switch: " << argv[i] << std::endl;
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout << "Found: " << DirInfo[i].GetNumFile() << (DirInfo[i].GetNumFile() != 1 ? "files" : "file") << std::endl;

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
 
  if(idx == 2)
  {
    int i, j;
    for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
        if(DirInfo[0][i] == DirInfo[1][j])
          {
              std::cout << "These files seems to be the same: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
          }

        }
    }
  }
  return EXIT_SUCCESS;
}

void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\%s", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}


/*Parametre*/
void Usage(const char *ProgramName)
{
  std::cerr<< "Usage: " << ProgramName  << " [-s] [-a] [-q] [pattern1 [pattern2 [...]]]"  <<std::endl;
  std::cerr<< "  -s  Scan thru subdirectories" <<std::endl;
  std::cerr<< "  -a  Ask before delete" <<std::endl;
  std::cerr<< "  -r  Delete Read-Only files" <<std::endl;
  std::cerr<< "  pattern  e.g. *.* *.jpg adir.*" <<std::endl;
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
15. januar 2006 - 23:01 #143
operatoren er global, ikke member af nogen class, så den skal flyttes ud af DirInfoClass, derved kommer header.h til at se sådan ud:

class FileEntryClass
{
public:
  FileEntryClass(const char *aName);
  std::string FileName;
  int FileSize;
  int GetFileSize();
  time_t GetFileTime();
  time_t FileTime;
};

class DirInfoClass
{
  std::vector<FileEntryClass> FileEntry;
public:
  std::string GetFileTime(int n);
  std::string &GetFileName(int n);
  int GetFileSize(int n);
  int GetNumFile() { return FileEntry.size(); }
  void AddFile(const char *aName);
  void Scan(char *dir, const char *pattern, int sub);
  const FileEntryClass& operator [] (size_t aIdx) const {return FileEntry[aIdx]; }
};

bool operator == (const FileEntryClass& lhs, const FileEntryClass& rhs);


Der er et problem med den sprintf der er lige efter kommentaren /* Then parse all sub directories */
Der er to gange %s, men kun et argument. Den skal laves om til:
sprintf(temp, "%s\\*.*", dir);
Avatar billede nph12 Nybegynder
16. januar 2006 - 11:12 #144
Nu kører det:-) Hvad er det næste vi skal lave?
Avatar billede bertelbrander Novice
16. januar 2006 - 19:49 #145
Jeg synes at du skal lave punkt 7b, 7c og 7d fra "15/01-2006 15:04:54"

Derpå skal du bestemme dig for hvad der skal ske når den finder to filer der er ens, så laver vi det.
Avatar billede nph12 Nybegynder
21. januar 2006 - 23:31 #146
Jeg skal nok have lidt mere hjælp til 7b og 7d. Jeg har lavet 7c. Jeg finder lige ud af, hvad der helt præcis skal ske, når vi har fundet to filer som er ens.
Avatar billede bertelbrander Novice
22. januar 2006 - 00:28 #147
7b: Jeg ville nok bare udskrive en warning, og lade somom de to filer ikke er ens.

7d: Start med at læse om iostreams her: http://www.cppreference.com/cppio/
Du skal bruge open, read, og close.
Avatar billede nph12 Nybegynder
28. januar 2006 - 17:56 #148
Jeg har kigget på det, men ved stadigvæk ikke helt, hvad jeg skal. Kan vi ikke starte med 7b? Hvordan udskriver jeg en warning?
Avatar billede bertelbrander Novice
28. januar 2006 - 22:04 #149
At udskrive en warning betyder blot at udskrive en advarsel til brugeren, i dette tilfælde at filen whatever.ext ikke kunne åbnes.

Med hensyn til 7d. Det er ikke nødvendigt at lave det nu, men det kunne være en god øvelse. Jeg vil foreslå at du som en øvelse laver et lille program der bruger std::ifstream til at sammenligne to filer, i programmet læser du blot filerne én byte af gangen med read.
Avatar billede nph12 Nybegynder
10. februar 2006 - 14:34 #150
Både i koden til Henter filstørrelse og Tjekker for dubletter afslutter programmet med exit(EXIT_FAILURE);

Der bliver da skrevet en advarsel ud til brugeren her eller hvad?
std::cerr << "Unable to open: " << FileName << std::endl;

Hvad skal jeg med exit(EXIT_FAILURE);? Skal jeg bare slette dem?

Jeg regner med at kigge på 7d her i weekenden eller starten af næste uge.
Avatar billede bertelbrander Novice
11. februar 2006 - 00:02 #151
Ja, der bliver udskrevet en advarsel, det er ok.
I stedet for exit(...) skal du i == operatoren returnere false, for at indikere at filerne ikke er ens.
I "int FileEntryClass::GetFileSize()" er problemet lidt større. Den pæne måde kunne være at indikere en fejl, så filen bliver ignoreret, ellers er man nok nødt til at sætte en "tilfældig" filstørrelse, problemet med den løsning er ikke så stor - det bør ikke ske.
Avatar billede nph12 Nybegynder
16. februar 2006 - 18:01 #152
"I stedet for exit(...) skal du i == operatoren returnere false, for at indikere at filerne ikke er ens." Hvad er det præcis jeg skal her?

Skal jeg slette exit(EXIT_FAILURE);?
Hvordan får jeg == operatoren til at returnere false?
Avatar billede bertelbrander Novice
16. februar 2006 - 19:49 #153
I stedet for
exit(EXIT_FAILURE);
skriver du bare:
return false;
Avatar billede nph12 Nybegynder
17. februar 2006 - 18:35 #154
OK. Er hermed rettet!
Avatar billede nph12 Nybegynder
18. februar 2006 - 11:43 #155
Hvad er det næste som skal laves?
Avatar billede bertelbrander Novice
18. februar 2006 - 14:36 #156
Opgav du at bruge iostream og read i stedet for FILE og fgetc i == operatoren?

Det næste der skal ske er vel at der skal gøres noget med de filer der er ens, hvad?
Avatar billede nph12 Nybegynder
20. februar 2006 - 12:25 #157
Jeg har lidt svært ved, at få taget hul på iostream delen. Jeg læst om iostreams på: http://www.cppreference.com/cppio/ og læst i min C++ bog, men jeg forstår det ikke helt. Jeg forstår godt, at vi skal åbne, læse og lukke filen, men resten driller!

Jeg har nok brug for lidt hjælp her. Hvad skal jeg helt præcis gøre for at åbne filen?

Hvordan skal jeg forstå dette: http://www.cppreference.com/cppio/open.html
Avatar billede bertelbrander Novice
20. februar 2006 - 19:54 #158
Et lille eksempel der åbner test.dat og læser én byte af gangen og skriver den ud (som et tal):

#include <iostream>
#include <fstream>

int main()
{
  std::ifstream File("test.dat", std::ios::binary);
  if(!File)
  {
      std::cerr << "You failed to provide a readable test.dat file!" << std::endl;
      return 0;
  }
  char x;
  while(File.read(&x, 1))
  {
      std::cout << int (x) << std::endl;
  }
}

Det bør kunne bruges som en start.
Avatar billede nph12 Nybegynder
25. februar 2006 - 16:49 #159
Jeg forstår det stadigvæk ikke helt:-(

Kan du ikke lave hele iostream som den skal være? Er du ikke sød, at forklar hvilke elementer som indgår i koden, så jeg kan lære lidt af det?
Avatar billede bertelbrander Novice
25. februar 2006 - 17:22 #160
I den oprindelige kode har vi:
  f1 = fopen(lhs.FileName.c_str(), "rb");
Det svarer til:
  std::ifstream File(lhs.FileName.c_str(), std::ios::binary);

For at checke om filen blev åbnet bruge vi:
  if(!f1)

Det oversættes til:
  if(!File)

Derpå læste vi en byte/char fra hver fil med:
    c1 = fgetc(f1);

Det skal oversættes til:
  File.read(&x1, 1)
I den gamle kode var det vi læste en int, det skal laves om til en char

I den gamle kode læste man EOF når man nåede til enden (dvs c1 blev EOF), med det nye vil File.read(&x1, 1) returnere false når den når til enden.

Så hele loopen bør kunne laves med (ikke testet):
  std::ifstream File1(lhs.FileName.c_str(), std::ios::binary);
  if(!File1)
  {
      std::cerr << "Failed ...." << std::endl;
      return false;
  }
  std::ifstream File2(rhs.FileName.c_str(), std::ios::binary);
  if(!File2)
  {
      std::cerr << "Failed ...." << std::endl;
      return false;
  }

  char x1, x2;
  while(File1.read(&x1, 1) && File.read(&x2, 1))
  {
    if(x1 != x2)
        return false;
  }
  return true;

Det er ikke nødvendigt at lukke filerne, de bliver lukket af ifstream's destructor.
Avatar billede nph12 Nybegynder
01. marts 2006 - 14:19 #161
Sådan. Jeg synes ikke rigtigt, at den sammenligner filerne nu! 

#include <dir.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <sys\stat.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <time.h>
#include "header.h"

FileEntryClass::FileEntryClass(const char *aName)
{
  FileName = aName;
  FileSize = GetFileSize();
  FileTime = GetFileTime();
}

void DirInfoClass::AddFile(const char *aName)
{
  FileEntryClass Entry(aName);
  FileEntry.push_back(Entry);
}

int DirInfoClass::GetFileSize(int n)
{
  return FileEntry[n].FileSize;
}

std::string &DirInfoClass::GetFileName(int n)
{
  return FileEntry[n].FileName;
}

std::string DirInfoClass::GetFileTime(int n)
{
  char *s = ctime(&FileEntry[n].FileTime);
  std::string Str(s);
  std::string::size_type pos = Str.rfind('\n');
  if(pos != std::string::npos)
    Str = Str.substr(0, pos);
  return Str;
}

time_t FileEntryClass::GetFileTime()
{
    struct stat s;
    stat(FileName.c_str(), &s);
    return s.st_mtime;
}

/*Henter filstørrelse*/
int FileEntryClass::GetFileSize()
{
  int len;
  FILE *f = fopen(FileName.c_str(), "rb");
  if(!f)
  {
    std::cerr << "Unable to open: " << FileName << std::endl;
    if(!access(FileName.c_str(), 0))
      std::cerr << "The file seems to be there" << std::endl;
    return false;
  }
  fseek(f, 0, SEEK_END);
  len = ftell(f);
  fclose(f);

  return len;
}

/*Tjekker for dubletter*/
bool operator == (const FileEntryClass& lhs, const FileEntryClass& rhs)
{
  if(lhs.FileSize != rhs.FileSize)
      return false;

  FILE *f1, *f2;
  char c1, c2;

  std::ifstream File(lhs.FileName.c_str(), std::ios::binary);
  if(!File)
  {
    std::cerr << "Unable to open: %s\n" << lhs.FileName.c_str() << std::endl;
    if(!access(lhs.FileName.c_str(), false))
      std::cerr << "The file seems to be there\n" << std::endl;
    return false;
  }

  std::ifstream File2(rhs.FileName.c_str(), std::ios::binary);
  if(!File2)
  {
    std::cerr << "Unable to open: %s\n" << rhs.FileName.c_str() << std::endl;
    if(!access(rhs.FileName.c_str(), false))
      std::cerr << "The file seems to be there\n" << std::endl;
    return false;
  }
 
  char x1, x2;
  while(File.read(&x1, 1) && File.read(&x2, 1))
  {
    if(x1 != x2)
    return false;
  }
  return true;

}


DirInfoClass DirInfo[2];

static void Scan(char *dir, const char *pattern, int sub);
static void Usage(const char *ProgramName);
static int  DelReadOnly = 0;


/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          std::cerr << "Unknown switch: " << argv[i] << std::endl;
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout << "Found: " << DirInfo[i].GetNumFile() << (DirInfo[i].GetNumFile() != 1 ? "files" : "file") << std::endl;

    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
 
  if(idx == 2)
  {
    int i, j;
    for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
        if(DirInfo[0][i] == DirInfo[1][j])
          {
              std::cout << "These files seems to be the same: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
          }

        }
    }
  }
  return EXIT_SUCCESS;
}

void DirInfoClass::Scan(char *dir, const char *pattern, int sub)
{
  struct _finddata_t fileinfo;
  long handle;
  char temp[1024];

  /* First parse any files in this directory */
  sprintf(temp, "%s\\%s", dir, pattern);
  handle = _findfirst(temp, &fileinfo);
  if(handle != -1)
  {
    do
    {
      if(!(fileinfo.attrib & _A_SUBDIR))
      {
        char sub[256];
        sprintf(sub, "%s\\%s", dir, fileinfo.name);
        AddFile(sub);
      }
    }
    while(_findnext(handle, &fileinfo) == 0);
    _findclose(handle);
  }
  if(sub)
  {
    /* Then parse all sub directories */
    sprintf(temp, "%s\\*.*", dir);
    handle = _findfirst(temp, &fileinfo);
    if(handle != -1)
    {
      do
      {
        if((fileinfo.attrib & _A_SUBDIR) && strcmp(fileinfo.name, ".") && strcmp(fileinfo.name, ".."))
        {
          char sub[1024];
          sprintf(sub, "%s\\%s", dir, fileinfo.name);
          Scan(sub, pattern, 1);
        }
      }
      while(_findnext(handle, &fileinfo) == 0);
      _findclose(handle);
    }
  }
}

/*Parametre*/
void Usage(const char *ProgramName)
{
  std::cerr<< "Usage: " << ProgramName  << " [-s] [-a] [-q] [pattern1 [pattern2 [...]]]"  <<std::endl;
  std::cerr<< "  -s  Scan thru subdirectories" <<std::endl;
  std::cerr<< "  -a  Ask before delete" <<std::endl;
  std::cerr<< "  -r  Delete Read-Only files" <<std::endl;
  std::cerr<< "  pattern  e.g. *.* *.jpg adir.*" <<std::endl;
  exit(EXIT_FAILURE);
}
Avatar billede bertelbrander Novice
01. marts 2006 - 20:11 #162
Der var en fejl i min kode, den har du gentaget i en lidt anden form:
  char x1, x2;
  while(File.read(&x1, 1) && File.read(&x2, 1))
  {
    if(x1 != x2)
    return false;
  }

Du læser alle tegn fra samme fil.

Det skal være:
  while(File.read(&x1, 1) && File2.read(&x2, 1))

Det var nok mest logisk om de hed File1 og File2
Avatar billede nph12 Nybegynder
01. marts 2006 - 21:05 #163
Nu kører det:-)

Det er vel dette vi skal lave nu:

Vi skal lave en status side som viser navn, størrelse og hvornår filen sidst er ændret. Status siden skal finde følgende filer:

Filer med samme indhold
Filer med samme navn (skal finde den nyeste fil)
Avatar billede bertelbrander Novice
01. marts 2006 - 23:21 #164
Vil du selv forsøge at lave en sådan "status side"?

Du kan begynde med at skrive til std::cout, så kan vi altid lave det om til at blive skrevet i en fil, på en windows app, eller hvor du nu vil have det hen.
Avatar billede nph12 Nybegynder
02. marts 2006 - 09:38 #165
Jeg vil godt forsøge mig med en "status side".

Nu tjekker vi om filerne er 100 % identiske, men finder vi også filer som optræder i flere versioner fx et Word-dokument.
Avatar billede bertelbrander Novice
02. marts 2006 - 20:38 #166
Vi checker kun om filer er 100% ens, man kunne godt skrive navnet på filer der har samme navn. Men det er ret svært at finde dokumenter der er "næsten" ens.

Der er iøvrigt en fejl i denne linie:
std::cerr << "Unable to open: %s\n" << rhs.FileName.c_str() << std::endl;

Også den anden linie der ligner.
Avatar billede nph12 Nybegynder
02. marts 2006 - 21:37 #167
Nu tjekker vi om filerne er 100% ens, ligesom checkdup gør det. Hvis vi kan lave nogle flere søgekriterier vil det være super:-)

Det med at søge på navnet på filen er oplagt.

Hvis man opretter et word-dokument og gemmer dette på harddisken og derefter kopiere det til fx. ens usb-nøgle, så har begge dokumenter samme "Ændret" dato (se egenskaber for dokumentet). Dokumentet hedder også det samme, hvis dokumentet gemmes et andet sted end originalen ellers kommer dokumentet til at hedde "kopi af....".

Jeg ser om der er behov for andre søgekriterier og vender tilbage, hvis der er. 

Jeg kan ikke lige se fejlen i denne linje:
std::cerr << "Unable to open: %s\n" << rhs.FileName.c_str() << std::endl;
Avatar billede bertelbrander Novice
02. marts 2006 - 22:30 #168
Prøv at lave et lille testprogram og se hvad det skriver.

(hint: %s bruges til som format-specifier til printf, men ikke med cout)
Avatar billede nph12 Nybegynder
03. marts 2006 - 21:05 #169
Linierne skal vel skrives på samme som i /*Henter filstørrelse*/

/*Tjekker for dubletter*/
bool operator == (const FileEntryClass& lhs, const FileEntryClass& rhs)
{
  if(lhs.FileSize != rhs.FileSize)
      return false;

  FILE *f1, *f2;
int c1, c2;

  std::ifstream File1(lhs.FileName.c_str(), std::ios::binary);
  if(!File1)
  {
    std::cerr << "Unable to open: " << lhs.FileName.c_str() << std::endl;
    if(!access(lhs.FileName.c_str(), false))
      std::cerr << "The file seems to be there" << std::endl;
    return false;
  }

  std::ifstream File2(rhs.FileName.c_str(), std::ios::binary);
  if(!File2)
  {
    std::cerr << "Unable to open: " << rhs.FileName.c_str() << std::endl;
    if(!access(rhs.FileName.c_str(), false))
      std::cerr << "The file seems to be there" << std::endl;
    return false;
  }
 
  char x1, x2;
  while(File1.read(&x1, 1) && File2.read(&x2, 1))
  {
    if(x1 != x2)
    return false;
  }
  return true;

}
Avatar billede bertelbrander Novice
03. marts 2006 - 21:34 #170
Ja, det ser rigtigt ud.

Det er ikke nødvendigt at konvertere std::string's til c-strenge når man udskriver med cout (det er det med printf).

Så du kunne skrive:
std::cerr << "Unable to open: " << lhs.FileName << std::endl;
Avatar billede nph12 Nybegynder
05. marts 2006 - 19:16 #171
OK. Det retter jeg lige.

Skal vi kigge lidt mere på søgekriterierne inden vi laver status siden?
Avatar billede nph12 Nybegynder
06. marts 2006 - 18:15 #172
Skal vi starte med at finde filer som hedder det samme? Jeg vil godt kunne finde filer som beskrevet d. 02/03-2006 21:37:08, hvis det er muligt.
Avatar billede nph12 Nybegynder
10. marts 2006 - 11:28 #173
Hvordan får jeg programmet til at finde filer med samme navn?
Avatar billede bertelbrander Novice
13. marts 2006 - 13:53 #174
Hvis du starter med at tilføje en variabel til FileEntryClass der indeholder filnavnet uden stinavn, du kunne kalde den BaseName kunne du udskrive navnet på filer der er ens med:
  if(idx == 2)
  {
    int i, j;
    for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
        if(DirInfo[0][i].BaseName == DirInfo[1][j].BaseName)
          {
              std::cout << "These files seems to be the same: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
          }

        }
    }
  }

Du kan bruge funktionen splitpath fra FileEntryClass's constructor (FileEntryClass::FileEntryClass) til at finde BaseName eller overføre det som parameter, da det er kendt i Scan(...) (fileinfo.name).
Avatar billede nph12 Nybegynder
14. marts 2006 - 19:08 #175
Koden skal vel bare sætte ind i sidst i main-metoden? Jeg har tilføjet variablen std::string BaseName; i FileEntryClass.

Jeg er ikke helt med på splitpath tingen. Hvad skal jeg helt præcis gøre?
Avatar billede bertelbrander Novice
14. marts 2006 - 19:41 #176
Ja, det burde kunne puttes ind sidst i main.

Det letteste er nok at overføre "BaseName" i constructoren til FileEntryClass.
Avatar billede nph12 Nybegynder
15. marts 2006 - 18:44 #177
Hvad skal jeg skrive i constructoren?

Så skal jeg vel lave en metode til at få filnavnene uden drev angivelse? Hvordan gør jeg det?
Avatar billede bertelbrander Novice
15. marts 2006 - 20:41 #178
Hvis du laver constructoren af FileEntryClass om til:

FileEntryClass(const char *aName, const char *aBaseName);
Og i denne gemmer aBaseName i BaseName (en std::string)

Og lave DirInfoClass::AddFile om til:
void DirInfoClass::AddFile(const char *aName, const char *aBaseName)

Og kalder AddFile med:
AddFile(sub, fileinfo.name);

Har hver FileEntry både filnavn med path (FileName) og filnavn uden sti (BaseName).
Avatar billede nph12 Nybegynder
16. marts 2006 - 17:01 #179
Jeg tror det kører nu, men sortere programmet ikke nu både på indhold og filnavn samtidigt?

Kan vi ikke starte med at lave en simpel oversigt? Oversigten kunne evt. vise; hvor mange filer der er på de to steder der bliver læst fra, hvilke filer som har samme indhold, og hvilke filer som har samme filnavne.

Jeg er stadigvæk lidt i tvivl om, hvordan vi fanger f.eks. Word-dokumenter som findes i flere version (se evt. 02/03-2006 21:37:08. Det er typisk, når man laver gruppearbejde, at man lige pludselig har flere versioner af et Word-dokument.

Indeholder et Word-dokument et "fingeraftryk" som man kan bruge til at samle de forskellige dokumenter, og på en eller anden måde finde det nyeste?
Avatar billede bertelbrander Novice
16. marts 2006 - 23:47 #180
Jo, programmet vil udskrive både navnet på filer der er ens og filer med samme indhold.

Vil du selv prøve at lave oversigten? Så vidt jeg ved har du den information der skal til, det skal blot udskrivs på den rigtige måde.

Jeg kender ikke formatet på word dokumenter, og jeg ved ikke om der er nogen metode til at vide om det er samme fil, i en anden udgave.
Avatar billede nph12 Nybegynder
17. marts 2006 - 09:47 #181
Skal main-metoden se sådan ud?

/*main-metode*/
int main(int argc, char *argv[])
{
  char Dir[1024];
  int i, DoSub = 0;

  getcwd(Dir, sizeof(Dir));

  for(i = 1; i < argc; i++)
  {
    if(argv[i][0] == '-')
    {
      switch(argv[i][1])
      {
        case 's':
          DoSub = 1;
          argv[i][0] = 0;
          break;
        case 'r':
          DelReadOnly = 1;
          argv[i][0] = 0;
          break;
        default:
          std::cerr << "Unknown switch: " << argv[i] << std::endl;
          /* No break; */
        case 'h':
          Usage(argv[0]);
          break;
      }
    }
  }
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout << "Found: " << DirInfo[i].GetNumFile() << (DirInfo[i].GetNumFile() != 1 ? "files" : "file") << std::endl;

    //int j;
    //for(j = 0; j < DirInfo[i].GetNumFile(); j++)
    //  std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
 
  if(idx == 2)
  {
    int i, j;
    for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
        if(DirInfo[0][i] == DirInfo[1][j])
          {
              std::cout << "These files seems to be the same: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
          }

        }
    }
  }
 
  //BaseName
  if(idx == 3)
  {
    int i, j;
    for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
        if(DirInfo[0][i].BaseName == DirInfo[1][j].BaseName)
          {
              std::cout << "These files seems to be the same: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
          }

        }
    }
  }

  return EXIT_SUCCESS;
}

Jeg synes, at det sidste ser forkert ud. Jeg kigger lige på nettet om Word dokumenter indeholder et "fingeraftryk" som vi kan sortere på.
Avatar billede bertelbrander Novice
17. marts 2006 - 20:49 #182
Jeg synes at den sidste del ser ok ud, virker det ikke?
Du skal måske ændre teksten til:
std::cout << "These files has the same name: " << DirInfo[0].GetFileName(i) << ", " <<  DirInfo[1].GetFileName(j) << std::endl;
Avatar billede nph12 Nybegynder
19. marts 2006 - 17:23 #183
Det virker hvis nu:-)

Udover navnet på filen, kan vi så ikke finde størrelsen og hvornår den sidst er ændret?
Avatar billede bertelbrander Novice
19. marts 2006 - 19:56 #184
Avatar billede nph12 Nybegynder
23. marts 2006 - 13:33 #185
Jeg er kommet lidt længere nu:-)

Jeg har fået lavet status-siden, så den viser:

Time of creation
Time of last modification
Time of last access

Hvordan får jeg vist hvilke stier som bliver igennemsøgt? Jeg vil godt havde vist stierne som følgende eksempel:

Path: C:\Mappe1\
Found: 287 files

Path D:\Mappe2\
Found: 224 files

Hvad skal jeg tilføje her for at få vist stierne?

for(i = 0; i < idx; i++)
  {
    std::cout << "Found: " << DirInfo[i].GetNumFile() << (DirInfo[i].GetNumFile() != 1 ? "files" : "file") << std::endl;
   
    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << std::endl;
  }
Avatar billede bertelbrander Novice
23. marts 2006 - 23:40 #186
Det letteste er at skrive den information ud i scan funktionen.
Hvis ikke det kommer til at stå det rigtige sted, kan du lade scan gemme det i et array af en struct med dir-navn og antal, og så skrive det ud i main funktionen.

Problemet er at DirInfo kan indholde informationer fra mange undermapper, jeg ud fra at du vil have vist informationen for alle mappe? (hvis ikke kan du bruge argv[] og DirInfo.FileEntry.size())
Avatar billede nph12 Nybegynder
24. marts 2006 - 20:58 #187
Det er måske en idé, at inddele filerne i undermapper. I første omgang vil jeg bare havde vist, hvilke stier der bliver indlæst fra (de stier som bliver brugt som parametre til programmet).
Avatar billede bertelbrander Novice
24. marts 2006 - 21:07 #188
Du kan gemme stierne i DirInfoClass, gem dem på det tidspunkt hvor du kalder scan i main.
Så kan du udskrive sti og antal når du ønsker.
Avatar billede nph12 Nybegynder
25. marts 2006 - 13:42 #189
Jeg skal have noget mere hjælp, da jeg ikke kan se, hvordan jeg får gemt stierne. Kan vi ikke tage det trin for trin?
Avatar billede bertelbrander Novice
25. marts 2006 - 14:04 #190
Start med at tilføje en std::string til DirInfo class:
  std::string RootDir;

Der hvor du kalder Scan fra main tilføjer du:
        DirInfo[idx].RootDir = argv[i];

Og så kan du udskrive:
    std::cout << "Found " << DirInfo[i].GetNumFile() << " files in " << DirInfo[i].RootDir << std::endl;

Alt i alt bliver det til disse linier i main:
  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].RootDir = argv[i];
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }
  for(i = 0; i < idx; i++)
  {
    std::cout << "Found " << DirInfo[i].GetNumFile() << " files in " << DirInfo[i].RootDir << std::endl;
    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << " " << DirInfo[i].GetFileSize(j) << " " << DirInfo[i].GetFileTime(j) << std::endl;
  }
Avatar billede nph12 Nybegynder
25. marts 2006 - 16:25 #191
Nu kører det. Nu har vi en metode som finder filer med samme indhold og en metode som finder filer med samme navn. Kan man ikke samle det i en metode? Man kan jo godt have filer som både har samme indhold og hedder det samme.

Hvis man finder dette match kunne man skrive "These files seems to be the same" og "These files has the same name".
Avatar billede bertelbrander Novice
25. marts 2006 - 18:05 #192
Hvis du laver en class i stil med følgende i header.h:
class EqualFilesClass
{
public:
  std::string FirstFile;
  std::string SecondFile;
  bool SameName;
  bool SameContent;
};
Kan du lave en liste af disse (i .cpp filen):
std::vector<EqualFilesClass> EqualFilesList;

Hvis du så laver loopen så det starter med at finde filer filer med samme navn, kan du hver gang du finder sådanne, lave et nyt EqualFilesClass objekt og putte ditte i listen (EqualFilesList.push_back). Inden du putter det i listen sætter du navnene på de to filer (fuld sti) og sætter SameName flaget
Derpå checker du om de to filer har samme indhold (skal gøres uanset om de har samme navn), hvis de har samme indhold og de havde samme navn skal du sætte SameContent flaget i det object du lige tilføjede til listen, ellers skal du lave et nyt object, sætte SameContent flaget og putte objektet i listen.

Når du så er færdig med at sammenligne, kan du udskrive al information fra listen.

Det er måske en idé at lave en constructor til EqualFilesClass.

Det er en lidt stor mundfuld, men prøv at starte, så tager vi problemerne hen ad vejen.
Avatar billede nph12 Nybegynder
26. marts 2006 - 17:07 #193
1) Jeg har lavet class EqualFilesClass i header.h filen.

2) Jeg har lavet listen std::vector<EqualFilesClass> EqualFilesList; i .cpp filen (indsat lige under DirInfoClass DirInfo[2];)

3) Jeg regner med, at loopen du snakker om er denne:

  int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].RootDir = argv[i];
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }

  }

Jeg skal vel lave noget i stil med AddFile metoden, men også kalde scan metoden? Jeg skal nok have noget mere hjælp til at lave det.

Tager vi også højde for, at der kan være flere filer med samme indhold og navn (flere end to)?
Avatar billede bertelbrander Novice
26. marts 2006 - 17:35 #194
Du kan godt lave en AddFile funktion der tilføjer til EqualFilesList, du skal i så fald kalde den fra loopen i main hvor du sammenligner.
Dvs Scan skal køre som nu, og tilføje til DirInfo listerne.

Med hensyn til tre eller flere ens filer; Nej det tager ikke højde for det, men det synes jeg at vi skal lave senere, for ikke at gøre opgaven for stor.
Avatar billede nph12 Nybegynder
26. marts 2006 - 18:04 #195
Forklar mig hellere hvordan du havde tænkt dig, at vi skulle lave det (som du beskev d. 25/03-2006 18:05:59). Hvad skal jeg lave trin for trin?

Det med flere ens filer kigger vi bare på senere.
Avatar billede bertelbrander Novice
26. marts 2006 - 20:04 #196
Dette kunne være delen der tilføjer til EqualFilesList:

    for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
          bool SameName = false;
          if(DirInfo[0][i].FileName == DirInfo[1][j].FileName)
          {
              EqualFilesClass EqualFiles;
              EqualFiles.FirstFile = DirInfo[0].GetFileName(i);
              EqualFiles.SecondFile = DirInfo[1].GetFileName(j);
              EqualFiles.SameName = true;
              EqualFiles.SameContent = false;
              EqualFilesList.push_back(EqualFiles);
              SameName = true;
          }
          if(DirInfo[0][i] == DirInfo[1][j])
          {
              if(SameName)
              { // The files has the same name, just set the SameContent flag:
                EqualFilesList.back().SameContent = true;
              }
              else
              {  // The content of the files are the same but the names are not,
                // we have to add an entry to EqualFilesList
                ...
              }
          }
        }
    }

Denne loop sammenligner hele fil navn, dvs. inklusive path, den skal kun sammenligne selve filnavnet, dvs BaseName.
Du skal selv udfylde ..., husk at sætte de rigtige flag.

Når du har det på plads kan du udskrive fra EqualFilesList
Avatar billede nph12 Nybegynder
27. marts 2006 - 18:36 #197
Hvordan udskriver jeg fra EqualFilesList? Jeg vil godt sidde og lege lidt med EqualFilesList metoden. Det vil hjælpe mig en del, hvis jeg kan se, hvad som ligger i listen.
Avatar billede bertelbrander Novice
27. marts 2006 - 18:46 #198
F.ex:

unsigned int Idx;
for(Idx = 0; Idx < EqualFilesList.size(); Idx++)
  std::cout << EqualFilesList[Idx].FirstFile << ", " << EqualFilesList[Idx].SecondFile << std::endl;
Avatar billede nph12 Nybegynder
27. marts 2006 - 20:21 #199
Hvordan får jeg skrevet, at filerne har samme navn og/eller samme indhold i stedet for 0 eller 1?

unsigned int Idx;
  for(Idx = 0; Idx < EqualFilesList.size(); Idx++)
  {
    std::cout << EqualFilesList[Idx].FirstFile << ", " << EqualFilesList[Idx].SecondFile << std::endl;
    std::cout << EqualFilesList[Idx].SameContent << ", " << EqualFilesList[Idx].SameName << std::endl;
  }

Hvor i EqualFilesList skal jeg tilføje størrelsen på filen, hvornår filen er oprettet, hvornår filen er ændret og hvornår filen har været åbnet?
Avatar billede bertelbrander Novice
27. marts 2006 - 20:57 #200
Du kan f.ex:
if(EqualFilesList[Idx].SameContent)
  std::cout << "Same Content";
else
  std::cout << "Not Same Content";
if(EqualFilesList[Idx].SameName)
  std::cout << "Same Name";
else
  std::cout << "Not Same Name";

Du kan gemme en pointer til det FileEntryClass object som filen peger på, i stedet for FirstFile og SecondFile. Så har du adgang til alle de informationer der er gemt for filen.
Du laver så EqualFilesClass om til:
class EqualFilesClass
{
public:
  FileEntryClass* FirstFile;
  FileEntryClass* SecondFile;
  bool SameName;
  bool SameContent;
};
Der hvor du opretter EqualFilesClass Objekterne og putter dem i listen laver du det om til:
              EqualFiles.FirstFile = &DirInfo[0][i];
              EqualFiles.SecondFile = &DirInfo[1][j];

Det kræver at du tilføjer en [] operator til DirInfoClass:
  FileEntryClass& operator [] (size_t Idx) { return FileEntry[Idx]; }

Når du så skal udskrive filnavn:
std::cout << EqualFilesList[Idx].FirstFile->FileName;
Avatar billede nph12 Nybegynder
28. marts 2006 - 17:48 #201
Når jeg kører programmet, så bliver tingene udskrevet forkert. Programmet udskriver kun en sti (uden drevangivelse) og nogle pointer adresser. Hvad gør jeg forkert?

int idx;
  for(i = 1, idx = 0; i < argc; i++)
  {
      if(argv[i][0])
      {
        DirInfo[idx].RootDir = argv[i];
        DirInfo[idx].Scan(argv[i], "*", DoSub);
        idx++;
      }
  }
 
  for(i = 0; i < idx; i++)
  {
    std::cout << "Found: " << DirInfo[i].GetNumFile() << (DirInfo[i].GetNumFile() != 1 ? "files" : "file")  << DirInfo[i].RootDir<< std::endl;
   
    int j;
    for(j = 0; j < DirInfo[i].GetNumFile(); j++)
      std::cout << DirInfo[i].GetFileName(j) << std::endl;
  }
 
  int j;
  for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
          bool SameName = false;
          if(DirInfo[0][i].BaseName == DirInfo[1][j].BaseName)
          {
              EqualFilesClass EqualFiles;
              EqualFiles.FirstFile = &DirInfo[0][i];
              EqualFiles.SecondFile = &DirInfo[1][j];
              EqualFiles.SameName = true;
              EqualFiles.SameContent = false;
              EqualFilesList.push_back(EqualFiles);
              SameName = true;
          }
          if(DirInfo[0][i] == DirInfo[1][j])
          {
              if(SameName)
              { // The files has the same name, just set the SameContent flag:
                EqualFilesList.back().SameContent = true;
              }
              else
              {  // The content of the files are the same but the names are not,
                // we have to add an entry to EqualFilesList
                EqualFilesList.back().SameName = false;
              }
          }
        }
    }


  unsigned int Idx;
  for(Idx = 0; Idx < EqualFilesList.size(); Idx++)
  {
    std::cout << EqualFilesList[Idx].FirstFile << ", " << EqualFilesList[Idx].SecondFile << std::endl;
    if(EqualFilesList[Idx].SameContent)
      std::cout << "Same Content";
    else
      std::cout << "Not Same Content";
    if(EqualFilesList[Idx].SameName)
      std::cout << "Same Name";
    else
      std::cout << "Not Same Name";
 
    std::cout << EqualFilesList[Idx].FirstFile->FileName;
  }


  return EXIT_SUCCESS;
}
Avatar billede bertelbrander Novice
28. marts 2006 - 20:02 #202
FirstFile og SecondFile er pointere til FileEntryClass objekter. Så du skal lave dette:

std::cout << EqualFilesList[Idx].FirstFile << ", " << EqualFilesList[Idx].SecondFile << std::endl;

Om til:

std::cout << EqualFilesList[Idx].FirstFile->FileName << ", " << EqualFilesList[Idx].SecondFile->FileName << std::endl;
Avatar billede nph12 Nybegynder
28. marts 2006 - 21:01 #203
Hvordan skal -> læses/forståes? Datoen bliver ikke udskrevet rigtigt. Eks.

Same Content
Same Name
67072, 67072
1143559374, 1142714988
1140512269, 1140512269
1164741040, 1164741040

unsigned int Idx;
  for(Idx = 0; Idx < EqualFilesList.size(); Idx++)
  {
    std::cout << EqualFilesList[Idx].FirstFile->FileName << ", " << EqualFilesList[Idx].SecondFile->FileName << std::endl;
    if(EqualFilesList[Idx].SameContent)
      std::cout << "Same Content\n";
    else
      std::cout << "Not Same Content\n";
    if(EqualFilesList[Idx].SameName)
      std::cout << "Same Name\n";
    else
      std::cout << "Not Same Name\n";
    std::cout << EqualFilesList[Idx].FirstFile->FileSize << ", " << EqualFilesList[Idx].SecondFile->FileSize << std::endl; 
    std::cout << EqualFilesList[Idx].FirstFile->FileCreation << ", " << EqualFilesList[Idx].SecondFile->FileCreation << std::endl;
    std::cout << EqualFilesList[Idx].FirstFile->FileModification << ", " << EqualFilesList[Idx].SecondFile->FileModification << std::endl;
    std::cout << EqualFilesList[Idx].FirstFile->FileAccess << ", " << EqualFilesList[Idx].SecondFile->FileAccess << std::endl;
  }
Avatar billede bertelbrander Novice
28. marts 2006 - 22:38 #204
Hvis du har:
class X
{
public:
  int x;
};

Og:
X MyX;
Kan du tilgå MyX's x med:
MyX.x = 123;

Hvis der derimod er tale om en pointer bruger man ->
X *MyX = Something();
MyX->x = 123;

Hvor udskriver du dato? Prøv evt. at poste hele programmet.
Avatar billede bertelbrander Novice
28. marts 2006 - 22:45 #205
Du gemmer tid for filen som en time_t (som er en form for heltal).
For at få det udskrevet som et normalt datoformat kan du bruge ctime, se f.ex:
http://www.cplusplus.com/ref/ctime/ctime.html

Eksemplet er i C, i C++ ville man bruge:
std::cout << "Current date and time are: " << ctime(&EqualFilesList[Idx].FirstFile->FileTime);
Avatar billede nph12 Nybegynder
28. marts 2006 - 23:42 #206
Nu går det bedre med udskrivningen, men det driller stadigvæk lidt.

    std::cout << "FileCreation    : " << ctime(&EqualFilesList[Idx].FirstFile->FileCreation) << ", " << ctime(&EqualFilesList[Idx].SecondFile->FileCreation) << std::endl;
    std::cout << "FileModification: " << ctime(&EqualFilesList[Idx].FirstFile->FileModification) << ", " << ctime(&EqualFilesList[Idx].SecondFile->FileModification) << std::endl;
    std::cout << "FileAccess      : " << ctime(&EqualFilesList[Idx].FirstFile->FileAccess) << ", " << ctime(&EqualFilesList[Idx].SecondFile->FileAccess) << std::endl; 
    std::cout << EqualFilesList[Idx].FirstFile->FileSize << ", " << EqualFilesList[Idx].SecondFile->FileSize << std::endl; 

Jeg kan ikke få det til at stå på samme linie:

FileCreation    : Tue Mar 28 17:22:53 2006
, Tue Mar 28 17:22:53 2006

FileModification: Mon Mar 13 16:35:40 2006
, Mon Mar 13 16:35:40 2006

FileAccess      : Tue Nov 28 23:07:21 2006
, Tue Nov 28 23:07:21 2006

3713, 3713
Avatar billede bertelbrander Novice
29. marts 2006 - 00:36 #207
Problemet er at den streng som ctime returnerer afsluttes med et linie skift, du kan løse problemet med en lille funktion:

std::string FormTime(time_t* aT)
{
  std::string Temp(ctime(aT));
  std::string::size_type pos = Temp.find('\n');
  if(pos != std::string::npos)
    Temp.erase(pos, 1);
  return Temp;
}

Den gør det samme som ctime, men fjerner linieskiftet. Du kalder den i stedet for ctime, på samme måde som ctime.
Avatar billede nph12 Nybegynder
29. marts 2006 - 18:08 #208
Det med datoen er på plads nu.

Hvordan får man filesize vist i KB ligesom under Windows?

Kan vi lave programmet sådan at det nu undersøger for flere ens filer (på indhold og/eller navn)?
Avatar billede nph12 Nybegynder
30. marts 2006 - 21:23 #209
Kan man lave udregningen af filesize på samme måde som FormTime?
Avatar billede bertelbrander Novice
30. marts 2006 - 21:34 #210
Ja, du kan lave en funktion i stil med FormTime, f.ex:
std::string FormSize(int aFileSize)

Med hensyn til flere ens filer; det er en anelse kompliceret. Du kan f.ex. have tre filer der hedder det samme, men kun to af dem er ens. Der kan så være en fjerde fil der indeholder det samme som de to ens filer, men som hedder noget andet, og hvad gør man så?

Du kan starte med at lave EqualFilesClass om til:
class EqualFilesClass
{
public:
  std::vector<FileEntryClass*> FileList;
  bool SameName;
  bool SameContent;
};

Så kan den indeholde mere end to ens filer.
Start med at ændre programmet så det bruge denne EqualFilesClass, så fortsætter vi derfra.
Du bruger push_back til at tilføje til FileList. De to (første) filer kan du så tilgå med FileList[0] og FileList[1]
Avatar billede nph12 Nybegynder
30. marts 2006 - 22:09 #211
Skal jeg udskrive FormSize på samme måde som FormTime?

std::cout << "Filesize        : " << FormSize(&EqualFilesList[Idx].FirstFile->FileSize) << ", " << FormSize(&EqualFilesList[Idx].SecondFile->FileSize) << std::endl; 

Jeg skal nok have lidt hjælp med at lave FormSize. Hvad er det præcis jeg skal lave?

Jeg retter lige det andet til imens. Jeg kan godt se, at det nok bliver lidt kompliceret, men vi skal nok finde en løsning (tænker lige over forskellige løsninger).
Avatar billede bertelbrander Novice
30. marts 2006 - 22:36 #212
Hvis du bare vil have den til at skrive "xxx kbytes":

std::string FormSize(int aFileSize)
{
  std::stringstream ss;
  ss << aFileSize/1024 << " kbytes";
  return ss.str();
}

Husk:
#include <sstream>

Og bruge den med:
std::cout << "Filesize        : " << FormSize(EqualFilesList[Idx].FirstFile->FileSize)

Dvs uden & foran EqualFilesList[Idx].FirstFile->FileSize, FileSize er en int, så der er ingen grund til at overføre en pointer.

Du skal nok overveje om en kilo byte er 1000 eller 1024 bytes.
Avatar billede nph12 Nybegynder
30. marts 2006 - 23:26 #213
Jeg kan godt kompile programmet, men programmet lukker ned, når jeg kører det.

int j;
  for(i = 0; i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
          bool SameName = false;
          if(DirInfo[0][i].BaseName == DirInfo[1][j].BaseName)
          {
              EqualFilesClass EqualFiles;
              EqualFiles.FileList[0] = &DirInfo[0][i];
              EqualFiles.FileList[1] = &DirInfo[1][j];
              EqualFiles.SameName = true;
              EqualFiles.SameContent = false;
              EqualFilesList.push_back(EqualFiles);
              SameName = true;
          }
          if(DirInfo[0][i] == DirInfo[1][j])
          {
              if(SameName)
              { // The files has the same name, just set the SameContent flag:
                EqualFilesList.back().SameContent = true;
              }
              else
              {  // The content of the files are the same but the names are not,
                // we have to add an entry to EqualFilesList
                EqualFilesList.back().SameName = false;
              }
          }
        }
    }


  unsigned int Idx;
  for(Idx = 0; Idx < EqualFilesList.size(); Idx++)
  {
    std::cout << EqualFilesList[Idx].FileList[0]->FileName << ", " << EqualFilesList[Idx].FileList[1]->FileName << std::endl;
    if(EqualFilesList[Idx].SameContent)
      std::cout << "Same Content\n";
    else
      std::cout << "Not Same Content\n";
    if(EqualFilesList[Idx].SameName)
      std::cout << "Same Name\n";
    else
      std::cout << "Not Same Name\n";
    std::cout << "FileCreation    : " << FormTime(&EqualFilesList[Idx].FileList[0]->FileCreation) << ", " << FormTime(&EqualFilesList[Idx].FileList[1]->FileCreation) << std::endl;
    std::cout << "FileModification: " << FormTime(&EqualFilesList[Idx].FileList[0]->FileModification) << ", " << FormTime(&EqualFilesList[Idx].FileList[1]->FileModification) << std::endl;
    std::cout << "FileAccess      : " << FormTime(&EqualFilesList[Idx].FileList[0]->FileAccess) << ", " << FormTime(&EqualFilesList[Idx].FileList[1]->FileAccess) << std::endl; 
    std::cout << "Filesize        : " << FormSize(EqualFilesList[Idx].FileList[0]->FileSize) << ", " << FormSize(EqualFilesList[Idx].FileList[1]->FileSize) << std::endl; 
  }
Avatar billede bertelbrander Novice
31. marts 2006 - 00:36 #214
Du skal lave plads til elementerne i FileList, så disse:
              EqualFiles.FileList[0] = &DirInfo[0][i];
              EqualFiles.FileList[1] = &DirInfo[1][j];
Skal laves om til:
              EqualFiles.FileList.push_back(&DirInfo[0][i]);
              EqualFiles.FileList.push_back(&DirInfo[1][j]);

På dette sted i koden skal du også tilføje et EqualFilesClass object:
              else
              {  // The content of the files are the same but the names are not,
                // we have to add an entry to EqualFilesList
                EqualFilesList.back().SameName = false;

Dvs noget i stil med:
              EqualFilesClass EqualFiles;
              ...
              EqualFilesList.push_back(EqualFiles);
Avatar billede nph12 Nybegynder
31. marts 2006 - 13:09 #215
Nu ser det ud til at køre:-)

Jeg synes, at vi skal udvide FormSize lidt. Vi kan udskrive filesize i KB, MB eller GB (hvor mange cifre skal vi have med efter kommaet?) Eller en anden måde vi kunne gøre det på var, at udskrive det hele i KB og så indsætte et punktum efter hvert tusindende.

Hvad er den bedste måde at lave det på? Hvis man skal sammeligne filer, så er det nok bedst at køre med samme enhed.
Avatar billede bertelbrander Novice
31. marts 2006 - 20:22 #216
Du kan godt fortsætte med at ændre på FormSize. Du bør blive ved med at gemme størrelsen på filen som en int, og så formatere output, f.ex:

std::string FormSize(int aFileSize)
{
  std::stringstream ss;
  ss << aFileSize/1000 << "." << aFileSize%1000 << bytes;
  return ss.str();
}

Som vil udskrive med ét punktum, f.ex: 1.234 bytes

På et tidspunkt skal vi nok lave det om så vi gemmer størrelse i en 64 bits type, så vi kan arbejde med filer der er større en 4G. Til det brug kunne det være gavnligt at kikke på GetFileAttributesEx
Avatar billede nph12 Nybegynder
01. april 2006 - 17:34 #217
Lad os kigge på FormSize senere, det er OK for nu.

Kan vi ikke i første omgang finde flere ens filer? Så må vi kigge på, hvordan vi få skrevet det ud, så man kan sammeligne filerne. Evt. give de fundne filer numre
Avatar billede bertelbrander Novice
01. april 2006 - 19:51 #218
Du kan starte med at finde alle filer der hedder det samme, og lave en liste af disse.
Og derpå lave en liste af ens filer, og lave en liste af disse.
Og til slut finde lighedspunkter mellem de to lister.

Hvis du laver loopen så et entry i EqualFilesList er enten med ens navne ELLER med ens indhold, kan du hver gang du finder to ens filer, checke om en af filerne allerede er i listen, og er ens på samme måde, kan du tilføje den anden fil til samme EqualFilesClass objekt.

Derved har du info om alle filer der er ens, og du kan skrive dem ud.

Når du har det på plads kan du checke om to entries i EqualFilesList indeholder de samme filer, men er ens på de to forskellige måder. Hvis du finder to ens entry kan du sætte begge flag i det ene og slette det andet entry.
Avatar billede nph12 Nybegynder
03. april 2006 - 18:42 #219
Okay, men jeg tror, at vi bliver nød til at dele det op i mindre bidder.

Skal vi beholde det vi har lavet indtil videre?

Jeg vil godt selv prøve, at lave de forskellige lister. Jeg vil godt starte med at lave listen, som finder filer som hedder det samme.
Avatar billede nph12 Nybegynder
04. april 2006 - 14:45 #220
Jeg tror, at jeg har styr på at lave de to lister (filer med samme navn og filer med samme indhold).

Nu når vi kører med to lister og kan sammenligne disse lister, så kunne vi måske også gøre det muligt, at vælge i mellem disse lister (filer med samme navn, filer med samme indhold, filer med sammen navn og/eller samme indhold).

Jeg skal nok have lidt hjælp til at finde lighedspunkter mellem de to lister.
Avatar billede bertelbrander Novice
04. april 2006 - 23:35 #221
Prøv at starte, hvis ikke det kommer til at virke så poste hele koden, så kikker jeg på det.
Avatar billede nph12 Nybegynder
05. april 2006 - 20:58 #222
Jeg forstår ikke helt det sidste, hvor jeg skal sammenligne de to lister. Jeg er ikke helt med på den operator fejl jeg får, når jeg kompiler programmet.

.h fil

class EqualFilesClass
{
public:
  std::vector<FileEntryClass*> FileList;
  bool SameName;
  bool SameContent;
};

class NameFilesClass
{
public:
  std::vector<FileEntryClass*> NameList;
  int GetNumFile() { return NameList.size(); }
};

class ContentFilesClass
{
public:
  std::vector<FileEntryClass*> ContentList;
  int GetNumFile() { return ContentList.size(); }
};

.cpp fil

  int j;
  for(i = 0;  i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
            if(DirInfo[0][i].BaseName == DirInfo[1][j].BaseName)
            {
              NameFilesClass NameFiles;
              NameFiles.NameList.push_back(&DirInfo[0][i]);
              NameFiles.NameList.push_back(&DirInfo[1][j]);
              NameFilesList.push_back(NameFiles);   
            }
        }
    }
 
  for(i = 0;  i < DirInfo[0].GetNumFile(); i++)
    {
        for(j = 0; j < DirInfo[1].GetNumFile(); j++)
        {
            if(DirInfo[0][i] == DirInfo[1][j])
            {
              ContentFilesClass ContentFiles;
              ContentFiles.ContentList.push_back(&DirInfo[0][i]);
              ContentFiles.ContentList.push_back(&DirInfo[1][j]);
              ContentFilesList.push_back(ContentFiles);   
            }
        }
    }
   
    for(i = 0;  i < NameFilesList[0].GetNumFile(); i++)
    {
        for(j = 0; j < ContentFilesList[0].GetNumFile(); j++)
        {
            if(NameFilesList[0][i] == ContentFilesList[0][j])
            {
              EqualFilesClass EqualFiles;
              EqualFiles.FileList.push_back(&DirInfo[0][i]);
              EqualFiles.FileList.push_back(&DirInfo[1][j]);
              EqualFilesList.push_back(EqualFiles);   
            }
        }
    }
Avatar billede bertelbrander Novice
05. april 2006 - 21:05 #223
Prøv lige at poste hele koden, så jeg kan prøve at oversætte.
(Du kan evt. sende den i en email).
Avatar billede nph12 Nybegynder
05. april 2006 - 22:23 #224
Hvis du lige sender en mail til denne mailadresse
nph12@hotmail.com

så sender jeg koden til dig.
Avatar billede nph12 Nybegynder
10. januar 2011 - 15:15 #225
Lukker
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