friendship in multiple files

I followed the advice in this article: http://cplusplus.com/forum/articles/10627/ , before anyone asks.
I am, however, getting the following errors in the project:

'fobject' has incomplete type
forward declaration of 'struct filemanip'
invalid use of incomplete type 'struct filemanip'
'fmanip' has incomplete type 


Here are the files:

filemanip.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef FILEMANIP_H
#define FILEMANIP_H

class filemanip
{
    private:
        std::string str,dirstr,path,ext;
        std::vector <std::string> files, oldfiles;
        WIN32_FIND_DATA fd;
        HANDLE h;
        int c;
        int result;
        void findfiles(std::string,std::string);
        void filerename(std::string);
    public:
        filemanip();
        filemanip(std::string);
        void PressEnterToContinue();
        friend class directorytree;
};  //end class

#endif // FILEMANIP_H 


filemanip.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <stdio.h>
#include <vector>
#include <windows.h>
#include "filemanip.h"

using namespace std;

filemanip::filemanip()
{
    c = 0;
    result = 0;
    path = "";
    str = "";
    ext = "";
    dirstr = "";
}   //end null constructor

filemanip::filemanip(string subdir)
{
    str = subdir;
}   //end constructor

void filemanip::PressEnterToContinue()
{
    printf( "Press ENTER to continue... " );
    fflush( stdout );
    do
        c = getchar();
    while ((c != '\n') && (c != EOF));
}
void filemanip::findfiles(string param, string ext)
{
    path = str+'/';
    dirstr = path+"*"+param+"*."+ext;
    h = FindFirstFile(dirstr.c_str(), &fd);
    if (h!=INVALID_HANDLE_VALUE)
    {
        do
        {
            oldfiles.push_back(path+fd.cFileName);
        }   //end do
        while (FindNextFile(h, &fd));
        FindClose(h);   //close the handle
    }   //end if
    else
    {
        cout<<"File with extension ."<<ext<<" and containing a "<<'"'<<param<<'"'<<" in the filename was not found in "<<str<<" folder."<<endl;
    }   //end else
    for (unsigned x=0; x<oldfiles.size(); x++)
    {
        cout<<"oldfiles["<<x<<"] == "<<oldfiles[x]<<endl;
    }   //end for
}   //end findfiles

void filemanip::filerename(string param)
{
    if (!oldfiles.empty())
    {
        for (unsigned x = 0; x<oldfiles.size(); x++)
        {
            files.push_back(oldfiles[x]);   
            for (size_t pos = (files[x]).find(param); pos != (files[x]).npos; pos = (files[x]).find(param, pos+1))
            {
                (files[x]).replace(pos,param.length()," ");
            }   //end inner for
            cout<<"files["<<x<<"] == "<<files[x]<<endl;
            result = rename((oldfiles[x]).c_str(), (files[x]).c_str());
            if (result != 0)
            {
                perror("This error occurred: ");
                PressEnterToContinue();
            }   //end if
        }   //end for
        oldfiles.erase(oldfiles.begin(), oldfiles.end());
        files.erase(files.begin(), files.end());
    }   //end if
}   //end filerename 


directorytree.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ifndef DIRECTORYTREE_H
#define DIRECTORYTREE_H

class filemanip;

struct node
{
    std::string value;
    std::vector <node *> subnodes;
};   //end node

class directorytree
{
    private:
        std::stack <HANDLE> hstack;
        std::stack <WIN32_FIND_DATA> fdstack;
        HANDLE h;
        WIN32_FIND_DATA fd;
        node thenode;
        std::string directory;
        void createtree(node*, std::string);
        void preorder(node *, filemanip);
        void deletetree(node *, node *);
        DWORD size;
        TCHAR name[257];
        //bool defined;
        std::string undesired[3];
        std::string extensions[4];
    public:
        directorytree();
        directorytree(node, std::string);
        void classmain(filemanip);
};  //end directorytree

#endif // DIRECTORYTREE_H 


directorytree.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <iostream>
#include <windows.h>
#include <cstring>
#include <new>
#include <vector>
#include <stack>
#include "directorytree.h"

using namespace std;

directorytree::directorytree()
{
    size = 257;
    directory = "";
    undesired[0] = "+";
    undesired[1] = "%2B";
    undesired[2] = "%20";
    extensions[0] = "doc";
    extensions[1] = "docx";
    extensions[2] = "ppt";
    extensions[3] = "pptx";
}   //end default constructor

directorytree::directorytree(node n, string d)
{
    thenode = n;
    if (GetUserName((TCHAR *)name, &size))
    {
        directory = "C:/Users/" + (string)name + '/' + d;
    }   //end if
}   //end constructor

void directorytree::createtree(node * a, string dir)
{
    if (a != 0)
    {
        a->value = dir;
        h = FindFirstFile((a->value + "/*.").c_str(), &fd);
        while ((((string)fd.cFileName == ".") || ((string)fd.cFileName == "..")) && (FindNextFile(h,&fd)))
        {

        }   //end while
        if (((string)fd.cFileName != ".") && ((string)fd.cFileName != ".."))
        {
            if (fd.dwFileAttributes != 16)
            {
                a->subnodes.push_back(0);
                createtree(a->subnodes[0], dir);
            }   //end if
            else
            {
                hstack.push(h);
                fdstack.push(fd);
                do
                {
                    dir = a->value + '/' + (string)((fdstack.top()).cFileName);
                    a->subnodes.push_back(new(nothrow)node);
                    createtree(a->subnodes.back(), dir);
                }   //end do
                while (FindNextFile(hstack.top(), &(fdstack.top())));
                hstack.pop();
                fdstack.pop();
            }   //end else
        }   //end if
        else
        {
            a->subnodes.push_back(0);
            createtree(a->subnodes[0], dir);
        }   //end else
    }   //end if
}   //end createtree

void directorytree::preorder(node * a, filemanip fobject)
{
    if (a != 0)
    {
        cout << a->value << endl;
        fobject = filemanip(a->value);
        for (int s = 0; s < 3; s++)
        {
            for (int t = 0; t < 4; t++)
            {
                fobject.findfiles(undesired[s], extensions[t]);
            }   //end inner for
            fobject.filerename(undesired[s]);
        }   //end outer for
        for (unsigned pos = 0; pos < a->subnodes.size(); pos++)
        {
            preorder(a->subnodes[pos],fobject);
        }   //end for
    }   //end if
}   //end preorder

void directorytree::deletetree(node * a, node * parent)
{
    if (a != 0)
    {
        for(unsigned pos = 0; pos < a->subnodes.size(); ++pos)
        {
            deletetree(a->subnodes[pos], parent);
        }   //end for
        if (a != parent)
        {
            cout << "The node for "<<a->value << " got deleted."<<endl;
            delete a;
        }   //end if
    }   //end if
}   //end deletetree

void directorytree::classmain(filemanip fmanip)
{
    createtree(&thenode, directory);
    preorder(&thenode, fmanip);
    deletetree(&thenode, &thenode);
}   //end classmain 


main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <windows.h>
#include <cstring>
#include <new>
#include <vector>
#include <stack>
#include "directorytree.h"
#include "filemanip.h"

using namespace std;

int main()
{
    const string ctor[] = {"Desktop", "Documents", "Downloads"};
    node * nodes = new (nothrow) node[3];
    filemanip * f = new (nothrow) filemanip [3];
    directorytree * dirtree = new directorytree [3];
    for (int y = 0; y < 3; y++)
    {
        dirtree[y] = directorytree(nodes[y], ctor[y]);
        dirtree[y].classmain(f[y]);
    }   //end for
    delete [] dirtree;
    delete [] nodes;
    delete [] f;
    return 0;
}   //end main 


Just when I thought I could look up how to programmatically make new folders, add to the tree, move "duplicate" files to the new folder (to change their names), move them back to their original folders, and delete the temporary folders!

cout << "sigh" << endl;
Last edited on
File directorytree.cpp has no definition of class filemanip but its functions access this class.
I take it that what you are saying is that I should forward-declare filemanip in directorytree.cpp, too?
No. You should include filemanip.h in directorytree.cpp. The compiler needs the definition of the class.
Last edited on
I do that, and the result is a disaster. It throws no errors, yet QUICKLY eats up the memory. I'm amazed I was able to catch it before it crashed the system (if it was going to).
1
2
3
4
5
6
void directorytree::preorder(node * a, filemanip fobject)
{
    if (a != 0)
    {
        cout << a->value << endl;
        fobject = filemanip(a->value);
¿why do you ask for an argument if you are not going to use it?
Maybe you are suggesting that instead of calling the constructor (with declaration, which could work but doesn't make immediate sense), I should just have a setter function. I will try this.
Last edited on
No. I'm saying that your function is not dependant on your parameter, so it shouldn't be a parameter to your function.
My function uses BOTH PARAMETERS in its body. How is this not dependency?
Last edited on
1
2
3
4
void foo(int n){
   n = 42;
   cout << n << ' ';
}
¿is that function using the parameter?
I can call `foo()' with any number, the result will be the same. So there is no dependency.

Your function has the same issue. I can construct `fobject' in any way, you will discard its state.
I took my suggestion (which was based on yours): I eliminated the parametric constructor and substituted it with a setter. I then called the setter instead. It crashes, but at a slower rate. Still, the fact remains that it crashes and I must do something about it. The directory tree works, but nothing prints out. Analyzing the call stack points the problem at the directory tree being made, but the tree works, and so does the original program (which I am trying to update with the tree)!

EDIT: Problem solved. It was a series of glorified data problems (all programming problems are like this!) The program is working now!! Now I should focus on implementing my idea!!
Last edited on
Topic archived. No new replies allowed.