1

Тема: Рекурсивне копіювання директорій і папок

Задача: Написати програму, що реалізує копіювання каталогу за вказаним шляхом та всіх його даних у вказане місце.

Ось те, що зробила я:

Прихований текст

#include <iostream>
#include <cstring>
#include <io.h>
#include <direct.h>
#include <Windows.h>
#include <conio.h>

#pragma warning (disable:4996)

using namespace std;

const int MAX_LENGTH = 255;

bool IsFile(char *name)
{
    _finddata_t * file_info = new _finddata_t;
    long done = _findfirst(name, file_info);
    if (done != -1)
    {
        if (file_info->attrib != _A_SUBDIR)
        {
            _findclose(done);
            return true;
        }
    }
    _findclose(done);
    return false;
}

bool PointInName(char *name)
{
    if (name[strlen(name) - 4] == '.')
        return true;

    return false;
}

int PosLastSlash(char *path)
{
    int length = strlen(path);

    int i = length;
    while (i >= 0 && path[i] != '\\')
        ++i;

    if (i != 0)
        return i;
    else
        return -1;
}

char *GetNewName(char *path, int length)
{
    char *temp_name = new char[MAX_LENGTH];
    strncpy(temp_name, "\0", MAX_LENGTH);

    strncpy(temp_name, path, length);
    strcat(temp_name, " - Copy");
    strcat(temp_name, path + length);
    strcat(temp_name, "\0");

    return temp_name;
}

void Copy(char *old_path, char *new_path)
{
    int done, length = 0;
    char *temp_name = NULL;
    long search = 0;

    if (strcmp(old_path, new_path) == 0)
    {
        if (PointInName(old_path))
            length = strlen(old_path) - 4;
        else
            length = strlen(old_path);

        temp_name = GetNewName(new_path, length);

        done = CopyFile(old_path, temp_name, false);
        if (done != 0)
            cout << "\nDONE\n";
        else
            cout << "\nERROR!\n";

        delete []temp_name;
        temp_name = NULL;
    }
    else
    {
        if (IsFile(old_path))
        {
            done = CopyFile(old_path, new_path, false);

            if (done != 0)
                cout << "\nDONE\n";
            else
                cout << "\nERROR!\n";
        }
    }
}

char *NameWithMask(char *path, char *mask)
{
    int size = strlen(path) + strlen(mask) + 1;

    char* temp_path = new char[size];
    strcpy_s(temp_path, size, path);
    strcat_s(temp_path, size, mask);

    return temp_path;
}

void CopyR(char* old_path, char *new_path)
{
    _finddata_t * fileinfo = new _finddata_t;
    
    char *path = NameWithMask(old_path, "\\*");

    long done = _findfirst(path, fileinfo);
    int next = done;
    while (next != -1)
    {
        if (fileinfo->attrib != _A_SUBDIR)
            Copy(old_path, new_path);

        _mkdir(new_path);
        int old_path_length = strlen(old_path) + strlen(fileinfo->name) + 10;

        char* old_path_buff = new char[old_path_length];
        strcpy_s(old_path_buff, old_path_length, old_path);
        strcat_s(old_path_buff, old_path_length, "\\");
        strcat_s(old_path_buff, old_path_length, fileinfo->name);

        int new_path_length = strlen(new_path) + strlen(fileinfo->name) + 10;

        char *new_path_buff = new char[new_path_length];
        strcpy_s(new_path_buff, new_path_length, new_path);
        strcat_s(new_path_buff, new_path_length, "\\");
        strcat_s(new_path_buff, new_path_length, fileinfo->name);

        CopyR(old_path_buff, new_path_buff);

        delete[]old_path_buff;
        delete[]new_path_buff;

        next = _findnext(done, fileinfo);
    }
    delete[]path;

    _findclose(done);

    delete fileinfo;
}

int main()
{
    char cur_path[MAX_LENGTH];
    char new_path[MAX_LENGTH];

    strncpy(cur_path, "C:\\Users\\virynka\\Documents\\ШАГ\\test.copy", MAX_LENGTH);
    strncpy(new_path, "C:\\Users\\virynka\\Documents\\ШАГ\\Програмування\\test.copy", MAX_LENGTH);

    CopyR(cur_path, new_path);
       
    _getch();
    return 0;
}

Але, на жаль, нічого хорошого не виходить. Програма зациклюється і файли не копіюються.
Підкажіть, будь ласка, як можна виправити цю проблему.

2

Re: Рекурсивне копіювання директорій і папок

1. де коментарі ?
2. printf наше все, помилку про копіювання вивести, можна писати ж код з виключними ситуаціями
3. спробуйте  три слеша

"C:\\\Users\\\...
- Поганому трояну фаєрвол заважає
- Ніколи не програмуйте та не пийте пиво
Якщо ви з першого разу написали програму, в якій немає жодної помилки, повідомте про це системного програмісту: він виправить помилки в компіляторі

3

Re: Рекурсивне копіювання директорій і папок

Той гидкий _findfirst:

long done = _findfirst(path, fileinfo);

працює на низькому рівні, він також вписує у fileinfo папки (правильніше, посилання на папки), типу "." - поточний каталог і ".." - надкаталог (батьківський, чи верхній). Відповідно, атрибут покаже, шо то є папка, і до шляху наступного додається крапка чи дві крапки, отака лабуда. Це легко можна виправити - просто потрібно ловити крапку чи дві крапки і пропускати цю ітерацію.

п.с. потрібно користуватися високорівневими лібами, бо тут чорт ногу зломить.

Мій блог про ОС сімейства *nix - http://nixtravelling.blogspot.com/
Подякували: pika19891

4

Re: Рекурсивне копіювання директорій і папок

Нічого гидкого не бачу:

// оо.cpp: определяет точку входа для консольного приложения.
//

#include "stdafx.h"
#include <io.h>
#include <string>

void findfiles(char *Path){
    _finddata64i32_t sr;
    char *s=new char[255];
    memset(s,0,255);
    s=strcpy(s,Path);
    s=strcat(s,"\\*.*");
    intptr_t hFile;
    if( (hFile = _findfirst(s, &sr ) )){
      do{
          if(strcmp(sr.name,".")!=0 && strcmp(sr.name,"..")!=0){
            char *sn=new char[255];
            memset(sn,0,255);
            sn=strcpy(sn,Path);
            sn=strcat(sn,"\\");
            sn=strcat(sn,sr.name);
            if(sr.attrib & _A_SUBDIR) findfiles(sn);
            else printf("%s\n",sr.name);
            delete sn;
          }
      }while(!_findnext(hFile,&sr));    
    }
    delete s;
    _findclose(hFile);
}

int _tmain(int argc, _TCHAR* argv[])
{
    findfiles("d:\\Док");
    system("pause");
    return 0;
}

Робе нормально.

5

Re: Рекурсивне копіювання директорій і папок

Itari, дякую, але я вже розібралась.