Help in my program using Classes

In summary: Case = dirCase(DirV[midPt].element, Dir.lastName); }//End addName void deleteName(int& oldName) { int size, selCase; DirV.pop_back();//Remove the element at position DirV.size() - 1 size = DirV.size();//DirV[midPt].element = midPt; oldName = midPt; int startPt = 0, endPt = size - 2, midPt = (endPt
  • #1
yungman
5,718
241
Hi
I am integrating my program into using different Classes. I have been trouble shooting for a while and I am stuck on this error and I don't understand the problem even reading online. I am using two Specification files with no Implementation files. I just want to make it easier with less files. I have one header file for working with read and write file. Another header file to work with add, sort, delete and display content of the vector DirV[].

This is fileManage.h for read and write to file.
C++:
#ifndef fileManage_H
#define fileManage_H
#include <vector>
#include <fstream>
#include <iostream>
#include "vectorEdit.h"
class fileClass
{   private:
        const static int nameLen = 25, phoneLen = 12;
    public:
        vectorClass vectC;
        bool newF, failOpen;
        std::fstream file;
     bool testFile()//
      { failOpen = false;
        file.open("Directory.dat", std::ios::in | std::ios::binary);
        if (file.fail())//1st attempt to open file
           { file.open("Directory.dat", std::ios::in | std::ios::binary);
              if(file.fail())//2nd attempt to open file
                 { createFile();//file does not exist, create file
                   file.open("Directory.dat", std::ios::in | std::ios::binary);
                   if (file.fail()) failOpen = true;//If fail, there is a problem
                   else failOpen = false;//Successfully created file, no read into DirV[].
                 }//end 2nd attempt
              else { failOpen = false; readFile(); }//else, 2nd attempt successfuel, read into DirV[]
           }//End if 1st attempt.
        else { failOpen = false; readFile(); }//else open file successfully, read into DirV[]
        file.close();
        return failOpen;
      }//End testFile()
    void createFile()
      { file.open("Directory.dat", std::ios::out | std::ios::binary | std::ios::app);
        file.close();
      }
    void readFile()//Assume file is OPEN already
      {while (!file.eof())
         { file.read(reinterpret_cast<char*>(&(vectC.Dir)), sizeof(vectC.Dir));
           if (file.eof()) { break; }
           vectC.DirV.push_back(vectC.Dir);
         }
      }
    void writeFile()//Assume file is closed, open file to write DirV[] into file.
      {
        int ct2 = 0;
        file.open("Directory.dat", std::ios::out | std::ios::binary);
        do//write the updated data in vector DirV into the file before closing
          { file.write(reinterpret_cast<char*>(&vectC.DirV[ct2]), sizeof(vectC.DirV[ct2]));
            ct2++;
          } while (ct2 < vectC.DirV.size());
        file.close();
      }//End of writeFile
};//End of fileClass
#endif
This is vectorEdit.h for add, delete, sort and display content of vector DirV[].
C++:
#ifndef vectorEdit_H
#define vectorEdit_H
#include <vector>
#include <fstream>
#include <iomanip>

class vectorClass
{
  private:
    const static int nameLen = 25, phoneLen = 12;
  public:
    struct Directory
    {
        char lastName[nameLen]; char firstName[nameLen];
        char phone[phoneLen]; int element;
    };
    std::vector<Directory>DirV;
    Directory Dir, Temp; bool newF;
  void addName(int& newName)
  { int size, selCase;
    DirV.push_back(Dir);//Push to next available element of DirV.
    size = DirV.size();// DirV[midPt].element = midPt; newName = midPt;
    int startPt = 0, endPt = size - 2, midPt = (endPt - startPt) / 2;
    if ((size == 1) || ((strcmp(DirV[endPt].lastName, Dir.lastName) <= 0) & (size >= 2)))
        selCase = 0;//Don't have to sort or anything, Dir is in last element already
  //Case 0 for first entry when size = 1 OR when Dir.lastName is
  // >= to last element of DirV(Dir.lastName >= DirV[endPt].lastName.
    else
    { if ((strcmp(Dir.lastName, DirV[startPt].lastName) <= 0) && (size > 1))
       selCase = 1;//If Dir smaller than DirV[0] AND (size >1)
      else
        { startPt = 0, endPt = size - 2; midPt = (endPt - startPt) / 2;
          do { if (strcmp(Dir.lastName, DirV[midPt].lastName) <= 0)
               { endPt = midPt; midPt = (startPt + endPt) / 2;}
              else { startPt = midPt; midPt = (startPt + endPt) / 2; }
             } while (startPt != midPt);
          selCase = 2;
        }//else selCase = 2
    }//End if((strcmp(Dir.lastName, DirV[startPt].lastName) <= 0) && (size > 1))
   switch (selCase)
        //(size = 1)  AND  Dir.lastName => DirV[endPt].lastName
    { case 0: { DirV[size - 1].element = size - 1; newName = size - 1; break; }
      case 1://Dir.lastName <= DirV[0].lastName
        { int i;
          for (i = 1; i <= (size - 1); i++)
           { DirV[size - i] = DirV[size - i - 1];
             DirV[size - i].element = size - i;
             DirV[size - i - 1].element = size - i - 1;
           }//End for
          DirV[size - i] = Dir; newName = size - i;
          DirV[size - i].element = size - i;
          break;
        };//End case 1
      case 2:
        { int j;
          for (j = 1; j <= (size - endPt - 1); j++)
           { DirV[size - j] = DirV[size - j - 1];
             DirV[size - j].element = size - j;
             DirV[size - j - 1].element = size - j - 1;
           }
          DirV[size - j] = Dir; newName = size - j;
          DirV[size - j].element = size - j;
          break;
        };//end case 2
    };//End switch
   }
  void sort_firstName(int& newName)//DirV[newName] is the newly added name.
    { int beginLname = newName, endLname = newName;//start out all equal
      int bubbleDown, bubbleUp;
      Temp = DirV[newName];//Temporary structure variable
      bool doneUp = false, doneDown = false, moveUp = false;
      bubbleUp = newName; bubbleDown = newName;
      while ((bubbleUp > 0) & !doneUp)//Prevent bubbleUp going negative
        {if ((strcmp(DirV[newName].lastName, DirV[newName - 1].lastName) == 0)
            & (strcmp(DirV[newName].firstName, DirV[newName - 1].firstName) < 0))
           { DirV[newName] = DirV[newName - 1]; DirV[newName].element = newName;
             DirV[newName - 1] = Temp; DirV[newName - 1].element = newName - 1;
             newName--; bubbleUp--; moveUp = true;
           }
         else (doneUp = true);
        }//END while((bubbleUp > 0)& !doneUp)
      if (moveUp == false)
       { while ((bubbleDown < (DirV.size() - 1)) & !doneDown)
          { if ((strcmp(DirV[newName].lastName, DirV[newName + 1].lastName) == 0)
                & (strcmp(DirV[newName].firstName, DirV[newName + 1].firstName) > 0))
             { DirV[newName] = DirV[newName + 1]; DirV[newName].element = newName;
               DirV[newName + 1] = Temp; DirV[newName + 1].element = newName + 1;
               newName++; bubbleDown++;
             }
            else doneDown = true;
          }//END while (decrement < bubbleUp)
       }
    }
  void showRange(char selName[25])
  { int size = DirV.size(), stpt = 0, edpt = size - 1;
    int mdpt = (stpt + edpt) / 2, index, comp;
    do //search to within range using 2 characters in selName
     { comp = strncmp(selName, DirV[mdpt].lastName, 2);
       if (comp != 0)
         { if (comp > 0) { stpt = mdpt; mdpt = (stpt + edpt) / 2; }
           else { edpt = mdpt; mdpt = (stpt + edpt) / 2; }
         }
     } while ((comp != 0) && (stpt + 2 <= edpt));//Matching DirV[mdpt]
     for (index = -2; index <= 3; index++)
      { if (((mdpt + index) >= 0) && ((mdpt + index) <= (size - 1)))
        {std::cout << "   Element #" << DirV[mdpt + index].element <<
            "]  is:   Last name: " << std::left << std::setw(10) << DirV[mdpt + index].lastName <<
             " first name: " << std::left << std::setw(10) << DirV[mdpt + index].firstName << "\n\n";
        }
      }//End for loop to display range of names if it is valid.
   }//End showRange
  void deleteName(int numDelete)
  {
    char sure;
    int edpt = DirV.size() - 1;
    std::cout << " Is this what you chose?\n";
    std::cout << "   Element #" << DirV[numDelete].element <<
        "]  is:   Last name: " << std::left << std::setw(10) << DirV[numDelete].lastName <<
        " first name: " << std::left << std::setw(10) << DirV[numDelete].firstName << "\n\n";
    std::cout << " Are you sure you want to delete this:\n\n"; std::cin >> sure;
    if (tolower(sure) == 'y')
    {
        for (int i = 0; i < (edpt - numDelete); i++)
        {   DirV[numDelete + i] = DirV[numDelete + i + 1];
            DirV[numDelete + i].element = numDelete + i;
        }
        DirV.pop_back();
    }
  }
};
#endif
This is the main():
C++:
#include <iostream>
#include <cstring>
#include <vector>
#include <iomanip>
#include "fileManage.h"
#include "vectorEdit.h"
using namespace std;
vectorClass vectC;
fileClass file;

int main()
{
  int newName, index = 0, compSize, numDelete;
  char more, displayAll, choice;
  char selName[25];
  cout << " Welcome to the directory program. You can add name, contact\n";
  cout << " informations and it will store in a file. You can display selected\n";
  cout << " names and choose to delete anyone you want.\n\n";
  file.testFile();
  if (file.testFile() == true)
    { cout << " Problem opening file.\n\n"; return 0;}
  file.readFile();
  do {cout << " Please enter 'a' to add names, 's' to dispay complete list. 'r' to\n";
      cout << " show range of names. 'd' to delete a specific name. 'q' to quit.\n\n";
      cout << " Please enter what you want to do:  "; cin >> choice; cout << "\n\n";
      switch (choice)
       {
        case 'a': //Add new names and sort
         { do {cout << " Enter last name:  "; cin >> vectC.Dir.lastName;
            //std::cout << " Enter first name:  "; cin >> fileC.Dir.firstName;
               vectC.addName(newName);
               vectC.sort_firstName(newName);
               cout << " \n\nDo you want to enter another name?  "; cin >> more;
              } while (tolower(more) == 'y');
          break;
         };//End case 'a'
        case 's': //Display entire list of names and info
         { index = 0;
           if (vectC.DirV.size() > 0)
            {do { cout << "   Element #" << vectC.DirV[index].element <<
                    "]  is:  Last name: " << left << setw(10) << " first name: "
                    << left << setw(10) << vectC.DirV[index].lastName <<
                    vectC.DirV[index].firstName << "\n\n";
                  index++;
                } while (index < vectC.DirV.size());
             }
           else cout << " There is no name in the file.\n\n";
           break;
         };//End case 's'
        case 'r':
         {if (vectC.DirV.size() > 0)
           {cout << " Enter the first 2 character of the last name to search.";
            cin >> selName; cout << "\n\n";
            vectC.showRange(selName);//Display range before and after the name.
           }//End if (fileC.DirV.size() > 0)
          else cout << " There is no name in the file.\n\n";
          break;
         };//End case 'r'
        case 'd'://Delete a name.
          {if (vectC.DirV.size() > 0)
            {vectC.showRange(selName);
             cout << " Enter the Element# of the left to be deleted: ";
             cin >> numDelete;
             vectC.deleteName(numDelete);
            }
           else cout << " There is no name in the file.\n\n";
           break;
          };//End case 'd'
        case 'q': { cout << " Are you sure you want to quit? ";
            cin >> choice; cout << "\n\n"; break;
            };
        default: cout << " Not a valid choice.\n";
        }//End switch
    } while (choice != tolower('q'));//End choice what to do
    file.writeFile();
    return 0;
}//End main()
I have been working on the integration since yesterday. This is really pushing beyond my knowledge. I spent 3 hours troubleshooting just to find I missed a ';' at the very end of the header file! The error showed was "using namespace std;" in main() doesn't work and I had to put std:: on every single cout, cin, setw(), left, right!The error messages are:
Error 11 9.jpg

What is error C3867? I read on line and I don't understand. I don't know what I did wrong.

Please help. Also please comment on how I write the program. First time doing this, no idea whether this is right or not. I know I have to split up the vectorEdit.h as it's very long.

Thanks
 
Last edited:
Technology news on Phys.org
  • #3
On the file class line 20, createFile; should be createFile();
 
  • Like
Likes yungman
  • #4
Thanks guys, I am reading about static and instance method, Wow! Sounds Russian! Let me have a little bit of time to read first. I want to understand what I did wrong. I'll be back.
 
  • #5
Finally found an article that is in English! Why can't all articles written like this one?!
http://heather.cs.ucdavis.edu/~matloff/classvars.html#:~:text=TotEmps, then, must be made,the lack of that keyword.&text=An instance method operates on,pointer points to that object).

I added () to the ones that flagged error and it compiled . I still don't quite get how do I determine my member functions whether it's static of instance. Seems like they ALL should be STATIC as I perform readFile, writeFile, createFile the same way regardless of which member Object. Only the lastName, firstName inside each object are instance as they are different in each of the object. Am I right?

does that mean I put () on all static member functions when called? eg. readFile(), writeFile(), createFile().

Thanks
 
  • #6
yungman said:
Finally found an article that is in English! Why can't all articles written like this one?!
http://heather.cs.ucdavis.edu/~matloff/classvars.html#:~:text=TotEmps, then, must be made,the lack of that keyword.&text=An instance method operates on,pointer points to that object).

I added () to the ones that flagged error and it compiled . I still don't quite get how do I determine my member functions whether it's static of instance. Seems like they ALL should be STATIC as I perform readFile, writeFile, createFile the same way regardless of which member Object. Only the lastName, firstName inside each object are instance as they are different in each of the object. Am I right?

does that mean I put () on all static member functions when called? eg. readFile(), writeFile(), createFile().

Thanks
You'de be better off to not take the advice in that article; it is not very good. But your errors are not exactly to do with it anyways.

You know if a member function is static if you defined it as static.

All functions are called with parenthesis, static or not.

I think that VS mistakenly thought you just wanted to state the address of the function. It's just a sort of bad error message.
 
Last edited:
  • Like
Likes yungman
  • #7
Please help in another issue. The program is now running. The way the program works is I don't write into to file until the program is about to quit. You can see I call writeFile() right before the program quit. Before that, everything is working, I can add names, it will sort to the right order, I can delete, view. Everything is working. This means the main() is working with vectorEdit.h perfectly. But then when the program goes to writeFile() and attempt to read from vector DirV[], it generate this:
Error 11 9.jpg


So I went to debug and put a break point at line 43 of fileManage.h right before it starts copying. Then I use the Immediate window to look at the sizeof(vectC.DirV[0]) it gave me 68, I tried DirV[1] and DirV[2], they are the same 68. BUT then when I try to read vectC.DirV.size, it said it cannot read memory. as shown below:
Error 11 9 1.jpg


I think this is why the program flag the "vector subscript out of range".

Please help me on this. I updated the files in post#1. It should compile and run up to the point of writeFile().

Thanks
 
  • #8
yungman said:
Please help in another issue. The program is now running. The way the program works is I don't write into to file until the program is about to quit. You can see I call writeFile() right before the program quit. Before that, everything is working, I can add names, it will sort to the right order, I can delete, view. Everything is working. This means the main() is working with vectorEdit.h perfectly. But then when the program goes to writeFile() and attempt to read from vector DirV[], it generate this:
View attachment 272384

So I went to debug and put a break point at line 43 of fileManage.h right before it starts copying. Then I use the Immediate window to look at the sizeof(vectC.DirV[0]) it gave me 68, I tried DirV[1] and DirV[2], they are the same 68. BUT then when I try to read vectC.DirV.size, it said it cannot read memory. as shown below:
View attachment 272385

I think this is why the program flag the "vector subscript out of range".

Please help me on this. I updated the files in post#1. It should compile and run up to the point of writeFile().

Thanks
Maybe you corrupted it somewhere before that?

You can write the entire vector of structs in a single line (without a loop).

C:
file.write(
    reinterpret_cast<char*>(vectC.DirV.data()),
    vectC.DirV.size()*sizeof(Directory));
 
Last edited:
  • Like
Likes yungman
  • #9
Jarvis323 said:
Maybe you corrupted it somewhere down the line?

You realize you can write the entire vector of structs in a single line (without a loop) right?

C:
file.write(
    reinterpret_cast<char*>(vectC.DirV.data()),
    vectC.DirV.size()*sizeof(Directory));
No, I don't know that! How?

As you can see, I can read the byte length of DirV[0..2], so I know the DirV.size() should be 3 as I entered 3 entries.

Thanks
 
  • #10
yungman said:
I have a do-while(ct2 < vectC.DirV.size()) encasing the line to write to the end of the vector.

Thanks
Right, but you can more efficiently, and more simply write the data with a single call to write the whole vector at once as I showed in the snippet.

The first parameter to the write function is the start address of memory to write.

The second parameter is how many bytes to write.

The vector of structs is all contiguous in memory (it's just one continuous chunk of memory with number of bytes equal to sizeof(Directory) times how many elements it has in it. The .data() function gives the start address to that memory.
 
  • Like
Likes yungman
  • #11
Some more tips: you should try to declare variables closest to where they are used and isolate their scope to where they are used.

For example, you don't need a member variable vectC.Dir. It is only used as a temporary buffer to read a directory into. Just make a temporary variable in the read function. And assuming the file is open in the read function is also not so great. Your making a more complicated system of dependencies. Just open the file here, and close the file when you're done. In fact it wouldn't hurt to make the file variable a temporary in the function scope itself in my opinion.

C:
    void readFile()//Assume file is OPEN already
    {
        Directory tmp;
        while (!file.eof())
        {
            file.read(reinterpret_cast<char*>(&tmp), sizeof(Directory));
            if (file.eof())
            {
                break;
            }
            vectC.DirV.push_back(tmp);
        }
    }

And the same concept applies with indexing variables.

C:
    index = 0;
           if (vectC.DirV.size() > 0)
            {do { cout << "   Element #" << vectC.DirV[index].element <<
                    "]  is:  Last name: " << left << setw(10) << " first name: "
                    << left << setw(10) << vectC.DirV[index].lastName <<
                    vectC.DirV[index].firstName << "\n\n";
                  index++;
                } while (index < vectC.DirV.size());
             }

Can be replaced with this so that it's self contained. You don't need to worry about what happens to index later on.

C:
for( const Directory & dir : vectC.DirV )
{
        cout << "   Element #" << dir.element
                 << "]  is:  Last name: " << left << setw(10) << " first name: "
                 << left << setw(10) << dir.lastName
                 <<dir.firstName << "\n\n";
}

// or

for(  size_t index = 0; index < vectC.DirV.size(); ++index )
{
        cout << "   Element #" << vectC.DirV[index].element
                 << "]  is:  Last name: " << left << setw(10) << " first name: "
                 << left << setw(10) << vectC.DirV[index].lastName
                 << vectC.DirV[index].firstName << "\n\n";
}
 
  • Like
Likes yungman
  • #12
Wow, Thank you so much, I copy your response down and I have to read it slowly. I'll be back.

thank you.
 
  • #13
yungman said:
Wow, Thank you so much, I copy your response down and I have to read it slowly. I'll be back.

thank you.
It's just better to make things simple and direct. You don't want the behavior of the code you're looking at to depend on more unknowns than necessary. It means you don't want to have to worry about variables being used all over the place, or having to track it down and what happens to it. And you don't want to worry about the state of your system too much before the function is called, or what the function does to the state of the system. The more the different parts depend on each other the more complicated it is, the harder it is to follow and debug, and the easier it is to make a mistake.
 
  • Like
Likes sysprog and yungman
  • #14
It also looks like you close the file in testFile(), so it's closed in readFile, which assumes it's open, and then you never closed the file after calling readFile(), so when you call writeFile(), you assume the file is closed, but it should have been open.

This is the type of problem with manipulating the same variable in lots of different places.
 
Last edited:
  • Like
Likes yungman
  • #15
Jarvis323 said:
It's just better to make things simple and direct. You don't want the behavior of the code you're looking at to depend on more unknowns than necessary. It means you don't want to have to worry about variables being used all over the place, or having to track it down and what happens to it. And you don't want to worry about the state of your system too much before the function is called, or what the function does to the state of the system. The more the different parts depend on each other the more complicated it is, the harder it is to follow and debug, and the easier it is to make a mistake.
Jarvis323 said:
It also looks like you close the file in testFile(), so it's closed in readFile, which assumes it's open, and then you never closed the file after calling readFile(), so when you call writeFile(), you assume the file is closed, but it should have been open.

This is the type of problem with manipulating the same variable in lots of different places.
Thanks so much for the advice, I changed the readFile(). Originally I open the file in the calling function, I even specified file is open when calling readFile() on the comment line. BUT, I like your way better, cleaner. So I change my calling function to close the file before calling readFile(). Then in readFile(), I open, read and close all LOCALLY. This is GOOD advice and I'll take it to heart. Below is the modified readFile(), but I still get error for Temp1 being undeclared.
Error 11 9 2.jpg


On the writeFile(), I still don't get it. I read your explanation. I tried to compile as what you have, it won't compile, so I change according to your description. The starting address of the vector should be &(vectC.DirV[0]), and total length of the vector is (number of elements) X (size of element). So I change it to vectC.DirV.size() * sizeof(vect.DirV[0]). But it still won't compile.

This is the error list:
Error 11 9.jpg

It complain Directory is undeclared, thereby Temp1 is undeclared.

Thanks for your time, this is really above my head at this point. I took a very large bite this time! maybe larger than I can swallow!
EDIT

I change local variable Temp1 to Temp that is declared in vectorEdit.h, I use Temp dedicated for readFile() and not use it anywhere else, that eliminate the error on Directory and Temp1.
 
Last edited:
  • #16
Ahh, because Directory is nested inside vectorClass. So it needs to be vectorClass::Directory. Or just move Directory outside of vectorClass.

.data() is fine, it will be exactly the same result as getting the address of the first element.

http://www.cplusplus.com/reference/vector/vector/data/

You put sizeof(vect.DirV[0]) instead of vectC.
 
Last edited:
  • Like
Likes yungman
  • #17
Jarvis323 said:
Ahh, because Directory is nested inside vectorClass. So it needs to be vectorClass::Directory. Or just move Directory outside of vectorClass.

.data() is fine, it will be exactly the same result as getting the address of the first element.

http://www.cplusplus.com/reference/vector/vector/data/

You put sizeof(vect.DirV[0]) instead of vectC.
That solves the problem of using local Temp1. I really like the idea of keeping it local. I just put vectorClass::Directory Temp;

So adding vectorClass:: with the Scope operator will point to the compiler to look in vectorEdit.h for vectorClass? This is just like how it is used in the Implementation file(if I have it) to bring the member function OUT of the .h file. Which I might do in the next step as the vectorEdit.h is HUGE!

I still have the vectC.DirV[] subscript out of bound error. But I feel a lot more comfortable now that I know it's likely a mistake somewhere rather than some fundamental problem with the program. I'll take a crack using the debugger again to trace through it and see.

BTW, I was too busy to ask you about post #6, you said the article is not accurate. What is wrong in it? I know all I need is to put () and I'll be fine, but I just want to learn more about static vs instance. Too bad if the article is wrong.

Again, thanks for all the help.
 
  • #18
yungman said:
That solves the problem of using local Temp1. I really like the idea of keeping it local. I just put vectorClass::Directory Temp;

So adding vectorClass:: with the Scope operator will point to the compiler to look in vectorEdit.h for vectorClass? This is just like how it is used in the Implementation file(if I have it) to bring the member function OUT of the .h file. Which I might do in the next step as the vectorEdit.h is HUGE!

I still have the vectC.DirV[] subscript out of bound error. But I feel a lot more comfortable now that I know it's likely a mistake somewhere rather than some fundamental problem with the program. I'll take a crack using the debugger again to trace through it and see.

BTW, I was too busy to ask you about post #6, you said the article is not accurate. What is wrong in it? I know all I need is to put () and I'll be fine, but I just want to learn more about static vs instance. Too bad if the article is wrong.

Again, thanks for all the help.
Yeah something like that.

The article on static member variables is not really wrong. He probably has got the technical things right, I just disagree with the author's opinions on coding style and software design.

I wouldn't use a static member variable in an Employee class to keep a count of the number of employees for example.
 
  • Like
Likes yungman
  • #19
Jarvis323 said:
Yeah something like that.

The article on static member variables is not really wrong. He probably has got the technical things right, I just disagree with the author's opinions on coding style and software design.

I wouldn't use a static member variable in an Employee class to keep a count of the number of employees for example.
So the idea of instance variable that are different for different object and static variable is always the same regardless of object is still Correct? That really help me to understand it already.

BTW, while you are still here, I want to hit you on a quick one. So I want to go a step further trying to define in main() vectorClass::Directory Temp2 to make it local variable to main so I don't have to use Dir(declare in header file) everywhere. I need to pass parameter to addName(Temp2, newName). Then in vectorEdit.h, I pick up the parameter using void addName(Directory Dir, newName). But compiler doesn't like it.

Here is the code in main:
C++:
        vectorClass::Directory Temp2, Temp3;
        cout << " Enter last name:  ";
        cin >> Temp2.lastName;
        vectC.addName(Temp2, newName);

In vectorEdit.h:
C++:
  void addName(Directory Dir, int& newName)
  { int size, selCase;
    DirV.push_back(Dir);//Push to next available element of DirV.
.
.
.}

This should work in ordinary passing parameters to function. But compiler doesn't like it. Anything special I need to do in passing from main() to header file? I really like this, I am going to try my best to keep all variables local to keep it clean, just pass parameter over.

Thanks so much.
 
  • #20
I am very close in saying VS is inconsistent again. This happened at least twice last night. Like the last post that I posted: Temp2 as argument to addName() in vectorEdit.h, it FAILED to compile. So I copied the files to a new Temporary program preparing to dissect it this morning. It works!, I went back and open the original program( the one that gave me error) and run it. IT WORK without doing anything to it!

This happened another time also when I posted post#7 here. I don't know how many times I typed in the Immediate Window sizeof(vectC.DirV[0]) and it said it's undeclared or cannot be read. I even type that in post#7 and almost posted it. Then I ran one more time, all of a sudden, it shows the size is 68 bytes! I just chucked it to my mistake that I've been at it for hours. Then this again. I even screen captured that, then I deleted it, too bad. Or else I would have solid proof.

I might be confused, but not that confused. I spent A LOT of time on these two issue. Something is really funky. I did Rebuilt Solution. I even exit the VS and opened again. I even restarted my laptop on the first issue. I did all I can already. This is starting to be distressing.

But I feel good though, meaning it works that I can change to all local variables as much as I can. I want to keep vector DirV[] global instead of copying over and over. This has be very educational, I even give up my own schedule of studying and just flow with it. Nothing like rubber hitting the road writing a bigger program like this. Things I thought I know that I don't, I spent a few hours looking online and worked on easy things like how to reject character input that is not specified in switch-case. I even thought about using enumerator and all...Just to realize I forgot about the DEFAULT statement! Live and learn! Things I studied and forgot.
 
Last edited:
  • #21
The thread took a detour after post#7. Now I am back to the original issue. This is what I got in debug showing in the Immediate Window. Something is wrong as shown:
size 0.jpg


1) I added one line in main() to cout the vectC.DirV.size() and is shown in A that shows there is 5 elements. Also you can see in the cmd window I read out 5 elements labeled. Theses are READ from vectC.DirV[].

2) in the Immediate Window after I stepped the writeFile to the out of bound error, vectC.DirV.size() = 0. There is nothing done to DirV[] between A to B.

I think the problem is in writeFile(), since vectC.DirV.size()=0, anything is out of bound.

Can anyone help? I have no idea why vectC.DirV.size() change from 5 in main() to 0 in vectorEdit.h.

Thanks
 
  • #22
I'm just glancing now. Is the vecC in main the same one in your file object

In main shouldn't you use file.vecC ?
 
  • Like
Likes yungman
  • #23
Jarvis323 said:
I'm just glancing now. Is the vecC in main the same one in your file object?
I edit this post. I declared std::vector<Directory>DirV; in line 17 of vectorEdit.h, this should make DirV[] global. I should be able to use vectC.DirV in main() and fileManage.h.

Thanks a million.
 
Last edited:
  • #24
yungman said:
I am very close in saying VS is inconsistent again. This happened at least twice last night. Like the last post that I posted: Temp2 as argument to addName() in vectorEdit.h, it FAILED to compile.
If your program fails to compile, it's because you have an error. VS and other compilers are consistent in notifying you that your code is incorrect. The easiest kinds of errors to fix are errors that occur at compile time.

You have made a lot of claims previously that VS was inconsistent. As I recall, 100% of them were due to something you did, not some arbitrary behavior on the part of VS.
 
  • Like
Likes Vanadium 50
  • #25
Mark44 said:
If your program fails to compile, it's because you have an error. VS and other compilers are consistent in notifying you that your code is incorrect. The easiest kinds of errors to fix are errors that occur at compile time.

You have made a lot of claims previously that VS was inconsistent. As I recall, 100% of them were due to something you did, not some arbitrary behavior on the part of VS.
Yes, I know in the pass I was 100% at fault. That's why I did not say anything until now. Like I said, I did not touch the program from last night, I just copied the 3 files to a new program to butcher. But then it compile and work to the point of the last write to file. Then I went back to the original program without touching anything, it run. Like I said, I did rebuild, exit the program and even restart the laptop.

I don't know what to say at this point.
 
  • #26
@yungman, I haven't followed this thread very much, as I was away for part of the weekend, and my internet connection was down yesterday.

In post #1, you showed the declarations and implementations for two separate classes, fileClass and vectorClass. I'm not convinced that this is the best way to go. It seems to me that a better arrangement would be a single class, one that contains a directory together with all the methods needed to add to it, delete from its, store it to disk, whatever.

It seems likely to me that the problems you're having in this thread stem from an overcomplicated collection of classes.
 
  • Like
Likes Vanadium 50, Jarvis323 and yungman
  • #27
yungman said:
Yes, I know in the pass I was 100% at fault. That's why I did not say anything until now. Like I said, I did not touch the program from last night, I just copied the 3 files to a new program to butcher. But then it compile and work to the point of the last write to file. Then I went back to the original program without touching anything, it run. Like I said, I did rebuild, exit the program and even restart the laptop.

I don't know what to say at this point.
If you have a compile error, Cxxxx, then it's something you did. The text that accompanies the error tells you what line it's occurring on, and gives you a hint at what's wrong.
 
  • Like
Likes Vanadium 50
  • #28
yungman said:
Yes, I know in the pass I was 100% at fault. That's why I did not say anything until now. Like I said, I did not touch the program from last night, I just copied the 3 files to a new program to butcher. But then it compile and work to the point of the last write to file. Then I went back to the original program without touching anything, it run. Like I said, I did rebuild, exit the program and even restart the laptop.

I don't know what to say at this point.
Can it be that you didn't save the file after making the changes until you closed VS? Another possibility is that VS is somehow not tracking changes to the header file. Build systems track if a file has changed and only rebuild a cpp file if necessary. I've had issues before in other build systems where it didn't detect the change to a header file and then didn't actually rebuild it until I force it to. I doubt VS would have that problem, but not sure.
 
  • #29
Mark44 said:
@yungman, I haven't followed this thread very much, as I was away for part of the weekend, and my internet connection was down yesterday.

In post #1, you showed the declarations and implementations for two separate classes, fileClass and vectorClass. I'm not convinced that this is the best way to go. It seems to me that a better arrangement would be a single class, one that contains a directory together with all the methods needed to add to it, delete from its, store it to disk, whatever.

It seems likely to me that the problems you're having in this thread stem from an overcomplicated collection of classes.
Yes, I agree. I gave a lot of thought about this. Yes, I did it the first time smoothly with just one header file a while back already, I manage to store in file and read back...That's the reason I decided to use two header files!

I guess I am into S&M! :biggrin: ?:)o_O.....No seriously, I know people use multiple Classes, so I might as well start now. I am pushing myself to very uncomfortable area. I cannot say enough how much I learn writing this program. I don't think I would learn nearly as much if I take the easy way and just work through the programs in the book and cover more chapters. I decided to throw my schedule out the window and just get to it when I am ready. I have been working on this program 8+ hours a day, 7 days a week. I determine to complete this program. I am very close! Hopefully this is the last step, saving to the file. Everything else is working already.

thanks for your concern.
 
  • #30
yungman said:
I know people use multiple Classes, so I might as well start now.
That's not a good reason, and is a large part of the reason that we're already up to 26 posts in this thread. Developers use multiple classes for to solve a problem, not just to do it to stretch themselves. And when they write programs with multiple classes, they do so because, for example, one class defines something that is a subset of something else, or maybe the two classes have little or no connection between the two class types, but one class needs to use a method defined in another class. In the latter case, one option is to make one class a friend of the other class, but I don't think you've come to that topic yet.

Again, the main idea in your program is a directory, so I'm not convinced that multiple classes are needed, or even useful.

Back in post #15 you said this:
yungman said:
It complain Directory is undeclared, thereby Temp1 is undeclared.
You apparently ignores the error just before this one, and didn't include the part of the code that the error message referred to. If you get compile errors, you have to look at the first one listed - it could be that any errors that follow it arose because of the first error.
 
  • #31
Jarvis323 said:
Can it be that you didn't save the file after making the changes until you closed VS? Another possibility is that VS is somehow not tracking changes to the header file. Build systems track if a file has changed and only rebuild a cpp file if necessary. I've had issues before in other build systems where it didn't detect the change to a header file and then didn't actually rebuild it until I force it to. I doubt VS would have that problem, but not sure.
I always have a habit to save the stuffs every time I change something. Particularly it was very late last night about 2am, I just copy and pasted the 3 files to and new program and went to bed. I ran the new program when I got up this morning, it ran to the writeFile, so I opened the original program and it ran also.

I don't even care at this point, just count it as my fault. I am too busy working on the program as I am very close to the finishing line.

Also, I notice VS is very good telling me what's wrong in smaller programs, with this program, I can make very obvious error in the header files and VS won't show the red wiggle line below the code like it normally does. But what do I know...
 
  • #32
yungman said:
I am pushing myself to very uncomfortable area. I cannot say enough how much I learn writing this program. I don't think I would learn nearly as much if I take the easy way and just work through the programs in the book and cover more chapters.
Personally, I wish you would stop pushing yourself so far beyond your current knowledge. The only reason you are able to learn as much as you have, is not because of your persistence in bulling through stuff you don't know about, but is instead because of the patience of the people who respond in your threads. Frankly, some of the people who have helped in the past have gotten fed up, and have decided against helping you further.
 
  • Like
Likes Vanadium 50
  • #33
yungman said:
Also, I notice VS is very good telling me what's wrong in smaller programs, with this program, I can make very obvious error in the header files and VS won't show the red wiggle line below the code like it normally does.
But it shows you a list of errors, such as one you asked about earlier in this thread, C3867.

Here's a link to the page in the VS docs where this compile error is discussed: https://docs.microsoft.com/en-us/cp...r-errors-2/compiler-error-c3867?view=msvc-160

Try as I might, I don't find any Russian on this page (I speak some Russian). It's all in English, together with an example of some code that throws this error and advice on how to fix the problem.
 
  • Like
Likes Vanadium 50
  • #34
yungman said:
Yes, I agree. I gave a lot of thought about this. Yes, I did it the first time smoothly with just one header file a while back already, I manage to store in file and read back...That's the reason I decided to use two header files!

I guess I am into S&M! :biggrin: ?:)o_O.....No seriously, I know people use multiple Classes, so I might as well start now. I am pushing myself to very uncomfortable area. I cannot say enough how much I learn writing this program. I don't think I would learn nearly as much if I take the easy way and just work through the programs in the book and cover more chapters. I decided to throw my schedule out the window and just get to it when I am ready. I have been working on this program 8+ hours a day, 7 days a week. I determine to complete this program. I am very close! Hopefully this is the last step, saving to the file. Everything else is working already.

thanks for your concern.
I think the main issue is that the organization isn't very good.

What I might do if I want to break it up like you are doing into multiple classes, is to create a DirectoryIO class that deals with IO. IO includes user input, reading and writing. Then I would have a Directory (managing the collection of DirectoryEntries) class, and it would also have a DirectoryIO object. Then your main function would have not much in it. Something like this.

C:
DirectoryEntry
     name
     address

//doesn't hold any data only takes the data as arguments
DirectoryIO
    writeDirectoryEntry(
        const string & filePath,
        const Directory & d );
    writeDirectories(
        const string & filePath,
        const vector<DirectoryEntrie> & directories );
    inputDirectory(); // get user input
    read(...

Directory
    vector<DirectoryEntry> entries;
    DirectoryIO IOManager;
    addEntry(...)
    ...

There is a whole lot to learn on organization and design. A popular design pattern is the component/composition design pattern.

https://www.learncpp.com/cpp-tutorial/102-composition/
 
Last edited:
  • #35
Jarvis323 said:
I think the main issue is that the organization isn't very good.

What I might do if I want to break it up like you are doing into multiple classes, is to create a DirectoryIO class that deals with IO. IO includes user input, reading and writing. Then I would have a Directory (managing the collection of DirectoryEntries) class, and it would also have a DirectoryIO object. Then your main function would have not much in it. Something like this.

C:
DirectoryEntry
     name
     address

//doesn't hold any data only takes the data as arguments
DirectoryIO
    writeDirectoryEntry(
        const string & filePath,
        const Directory & d );
    writeDirectories(
        const string & filePath,
        const vector<DirectoryEntrie> & directories );
    inputDirectory(); // get user input
    read(...

Directory
    vector<DirectoryEntry> entries;
    DirectoryIO IOManager;
    addEntry(...)
    ...

There is a whole lot to learn on organization and design. A popular design pattern is the component/composition design pattern.

https://www.learncpp.com/cpp-tutorial/102-composition/
Hi Jarvis323

Thanks for the advice, it's a little late to change direction at this point as I think if I can fix the problem of DirV[] to the fileManage, the program should work. I know if I put file handling into vectorEdit.h, it should work with no problem.

I simplified the program to a few lines, I think the problem is the header files must have a different way of communicate. Obviously main() has no problem communicating with either header file to do things, but not between the two header files. Here is the short program:

main():
C++:
#include <iostream>
#include <cstring>
#include <vector>
#include "fileManage.h"
#include "vectorEdit.h"
using namespace std;
vectorClass vectC;
fileClass file;
int main()
{ cout << " Enter the last name: "; cin >> vectC.Dir.lastName;
  cout << endl;
  vectC.printName();
  file.goPrint();
  vectC.printName();
  return 0;
}//End main()

Here is the vectorEdit.h
C++:
#ifndef vectorEdit_H
#define vectorEdit_H
#include <vector>
#include <fstream>
#include <iomanip>
#include <iostream>

class vectorClass
{
  private:
    const static int nameLen = 25, phoneLen = 12;
  public:
    struct Directory
    {   char lastName[nameLen]; char firstName[nameLen];
        char phone[phoneLen]; int element;
    };
    Directory  Dir;
    void printName()
    { std::cout << " In vectorEdit, name is: " << Dir.lastName << "\n\n"; }

};
#endif

Here is the fileManage.h
C++:
#ifndef fileManage_H
#define fileManage_H
#include <vector>
#include <fstream>
#include <iostream>
#include "vectorEdit.h"
//using namespace std;

class fileClass
{    public:
        vectorClass vectC;
        bool newF, failOpen;
        std::fstream file;

        void goPrint() { std::cout << " In fileManage  " <<
            vectC.Dir.lastName << "\n\n"; vectC.printName(); }
};//End of fileClass
#endif

Here is the screen capture of the cmd:
output.jpg


1) main() calling member function printName() in vectorEdit.h. It works.
2) main() calling member function goPrint() in filemanage.h, it will NOT print "name is: Alan".
3) also in goPrint() it calls call printName() in vectorEdit.h Notice even calling the same printName(), it missed "Alan"
4) to confirm Dir still contain "Alan", main() call printName() one last time and it shows everything is there.Bottom line, fileManage.h cannot do anything on the data.

Am I just missing a little bit or it'll take a lot more to make this work. Obvious if it takes a lot more, I will just put the file handling back in vectorEdit.h, it's proven it will work as long as they are in the same header file. It is very clear this is way over my head.

Thanks for the advice.
 

Similar threads

  • Programming and Computer Science
2
Replies
36
Views
3K
  • Programming and Computer Science
Replies
12
Views
1K
  • Programming and Computer Science
Replies
30
Views
2K
  • Programming and Computer Science
3
Replies
89
Views
4K
  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
Replies
32
Views
2K
  • Programming and Computer Science
2
Replies
66
Views
4K
  • Programming and Computer Science
Replies
5
Views
885
  • Programming and Computer Science
Replies
20
Views
1K
  • Programming and Computer Science
3
Replies
73
Views
4K
Back
Top