Solving Vector Length Test Problem: EOF & Do-While Loops

  • Thread starter yungman
  • Start date
  • Tags
    Vectors
In summary, the conversation is about a program that uses vectors to store information in a directory. The program is intended to take input for multiple names and phone numbers, but there is an issue with the input being skipped after the first iteration. The program also needs to be able to detect the end of the vector to stop the operation, but the method for doing so is unclear. The person is trying to use vectors as a scalable option, but is considering other options such as using pointers or fstream file. The conversation discusses the possibility of an issue with the input buffer after line 29, but the person is not sure what the issue may be.
  • #1
yungman
5,718
240
I have something I cannot fix in this program. Also I don't know how to test EOF in vector to jump out of do-while loop.
Code:
//Vector length test
#include<iostream>
#include <vector>
#include <cstring>
#include <iomanip>
using namespace std;
    const int ln = 21, al = 31, eA = 21, pN = 15;
    struct empName
    { char lastName[ln]; char fstName[ln];};
    struct Directory
    { empName name;    int phone;    };

int main()

{  
    char more;
    Directory Info;//temporary structure
    vector<Directory>IVar;
    do
    {
         cout << setw(21) << left << " Enter Last name:  ";
        cin.getline(Info.name.lastName, ln); cout << endl;
        cout << setw(21) << left << " Enter First name:  ";
        cin.getline(Info.name.fstName, ln); cout << endl;
        cout << setw(21) << left << " Enter phone:  ";
        cin >> Info.phone; cout << "\n\n";
//Save into vector array.
        IVar.push_back(Info);
        cout << " Type 'y' if You want to enter more  "; cin >> more;//Type 'y' to enter another one
    } while (tolower(more) == 'y');
    int index = 0;
    cout << "This is what you entered:\n\n";
    do
    {
        cout << " Name #" << (index + 1) << ":  " <<
            IVar[index].name.fstName << " " << IVar[index].name.lastName << endl;
        cout << " Phone number:  " << IVar[index].phone << "\n\n";
        index++;
    } while (index < 3);

    return 0;
}

I try to enter 3 names. The first time ran ok, but it will skip asking the Last Name on the 2nd and 3rd name and you can see in the image of output captured. Somehow the program skip line22 the second and third time. I cannot figure this out as it's inside the do-while loop, why it work only the first go around?

Result.jpg


Also, if you look at line39, I put a 3 to stop the loop. I really want to have a way to detect the EOF of the vector to stop the do-while loop. I cannot find this in the book. Please advice what can I do as this is only an experiment program. In my real program, I want to put in different number of names and I need to detect EOF to stop the operation. I don't know how to push_back an EOF to the last element of the vector array.

Thanks
 
Last edited:
Technology news on Phys.org
  • #2
The title of this thread is "Question on vectors". What makes you think that this has anything to do with vectors? What is in the input buffer after line 29?
 
  • #3
Vanadium 50 said:
The title of this thread is "Question on vectors". What makes you think that this has anything to do with vectors? What is in the input buffer after line 29?
The whole thread is about vector, most important is how to set up to detect EOF.

After line 29, the program works. It shows I actually stored 3 elements of structure in the vector array and read them out correctly. Problem is it skipped the Last Name in the second go around in the loop.

This is much more difficult than what's in the book, the book just gave some vect<int>, vect<char> type. This is array of vector of structure within structure. For simple char or int, I can put some NULL of something in the last element and detect it, this is a structure, how do I set it up to be detected as EOF?

Thanks
 
  • #4
yungman said:
The whole thread is about vector

Just because you have a vector in your code does not mean the problem is with vectors.

Vanadium 50 said:
What is in the input buffer after line 29?

Why do you think I asked this? And why do you think ignoring it is the best way forward?
 
  • #5
I don't know, like I said, this program is way beyond what the book covered, I am winging it as I need a scalable size array of structure and class object. I am looking into vector(sizable), pointer to allocate memory or fstream file. So I am looking deeper into vector first to see whether it can fulfill what I need. I try not to use fstream file as I plan to not only scale the size, I will perform sorting in the future. I don't want to run the flash or HD doing that. I much rather do all the sizing and sorting with vector array or allocated memory first, then store it one time into file.

That leaves vector as the most apparent choice as it's scalable.

I don't know what you are looking for the buffer after line 29, the only buffer is Directory Info which is the temporary structure object to store the info to be push_back into the vector. It's not being used after line 29. I assume it contains the info of the 3rd element. Like I said, when I read back from the vector array IVar, I read all 3 elements of structure Directory out correctly. I am not ignoring anything.
 
  • #6
This has nothing whatsoever to do with vector. I don't why you keep insisting it does. After all, you don't know what your code is doing wrong, so how can you be sure where the problem is?

yungman said:
the only buffer is Directory Info

I mean the input buffer. When you ask the user to type y if they want to enter more, what is in the input buffer after they type 'y'?

Hint #1: it's not 'y'
Hint #2: How many keystrokes does the user enter?
Hint #3: The answer to #2 is not "1".
 
  • Like
Likes yungman
  • #7
Vanadium 50 said:
This has nothing whatsoever to do with vector. I don't why you keep insisting it does. After all, you don't know what your code is doing wrong, so how can you be sure where the problem is?
I mean the input buffer. When you ask the user to type y if they want to enter more, what is in the input buffer after they type 'y'?

Hint #1: it's not 'y'
Hint #2: How many keystrokes does the user enter?
Hint #3: The answer to #2 is not "1".
Thanks I got it, I need to put cin.ignore() after line 29.

Speaking of cin.ignore(), I did put that right after line20, the program hung. I know that has something to do with the fact there is no cin >> before that. But why the program got hung?

Do you have any suggestion about the EOF?

Thank

I have change the program, I improved a little by keeping track of the number of names input and display the same number out. It's a little better, BUT, still I would like to see whether I can detect EOF as in my ultimate program, I want to add, delete, sort names any time I want to.
Code:
//Vector length test
#include<iostream>
#include <vector>
#include <cstring>
#include <string>
#include <iomanip>
using namespace std;
    const int ln = 21, al = 31, eA = 21, pN = 15;
    struct empName
    { string lastName; string fstName;};
    struct Directory
    { empName name;    int phone;    };

int main()

{    
    char more;
    Directory Info;//temporary structure
    vector<Directory>IVar;
    int count = 0;
    do
    {
         cout << setw(21) << left << " Enter Last name:  "; 
        getline(cin, Info.name.lastName); cout << endl;
        cout << setw(21) << left << " Enter First name:  "; 
        getline(cin, Info.name.fstName); cout << endl;
        cout << setw(21) << left << " Enter phone:  "; 
        cin >> Info.phone; cout << "\n\n";
//Save into vector array.
        IVar.push_back(Info);
        count++;
        cout << " Type 'y' if You want to enter more  "; cin >> more;//Type 'y' to enter another one
        cin.ignore();
    } while (tolower(more) == 'y');

    int index = 0;
    cout << "This is what you entered:\n\n";
    do
    {
        cout << " Name #" << (index + 1) << ":  " <<
            IVar[index].name.fstName << " " << IVar[index].name.lastName << endl;
        cout << " Phone number:  " << IVar[index].phone << "\n\n";
        index++;
    } while (index < count);

    return 0;
}

Thanks
 
Last edited:
  • #10
Vanadium 50 said:
That will work, but the more C++ way to do this is through an iterator.
If an iterator is appropriate in the use case maybe. But I don't consider using iterators directly for loops to be good style anymore in most cases because of the verbosity.

I'll usually just use range based for loops if the loop is simple enough.
https://en.cppreference.com/w/cpp/language/range-for

If the loop is parallel, or has levels of indirection on the loop index, or internal control structure depending on the loop index, or simply want to print out the index etc, then I'll just use plain indexing.
 
Last edited:
  • #11
yungman said:
Do you have any suggestion about the EOF?
yungman said:
I have change the program, I improved a little by keeping track of the number of names input and display the same number out. It's a little better, BUT, still I would like to see whether I can detect EOF as in my ultimate program, I want to add, delete, sort names any time I want to.
The program, as written, has nothing to do with EOF. If your goal is to modify this program so that it takes input from a file, then reading from the file until EOF is reached makes sense. In that case, you need to look at ios_base::iostate to see if the eofbit flag is set after each input operation.
 
  • Like
Likes yungman
  • #12
Mark44 said:
The program, as written, has nothing to do with EOF. If your goal is to modify this program so that it takes input from a file, then reading from the file until EOF is reached makes sense. In that case, you need to look at ios_base::iostate to see if the eofbit flag is set after each input operation.
Hi Mark

Thanks for the reply. This is only an experimental program. I am going wild this time. My "project" to challenge myself this time is to write a personal directory to store info of each person like address, phone and email address. Just like some of the existing programs, you can add name, delete name anytime, sort into order and store in a file. You can search for names, update info and all. I want to call multiple class objects to do fstream file, add/delete, sort etc. I want to design in a way that it's upgradable. Starting with class object to add, object to create and R/W to file to copy into the vector array and return to main. Then call the add/delete files...

This current program is ONLY to find out which temporary array of nested structure that is passed around to do add/delete and sort. That's the reason I need to find a way to detect EOF as the size of the vector array change after add/delete.

In fact, I have not decided in using vector for sure, I still want to consider pointer allocated memory to see whether that can do the job. I even consider doing all the add/delete and sort right with fstream file. It actually have a lot of the features like seekp and seekg. BUT that heavily involve R/W to hard disk or flash memory, it will be very slow. I think it's better to do all those in RAM first and copy one time to file.

Simple question, Can I call multiple class object( multiple .h files)? I want one just to read/write to file, one to add/delete, one to sort. The main() is just to guide the traffic. Only thing that is beyond my knowledge is how to make it a true .exe program that don't have to have VS to run, that people can load into the computer and use it.

Thanks
 
  • #13
Jarvis323 said:
But I don't consider using iterators directly for loops to be good style anymore in most cases because of the verbosity.

I don't like them either (for different reasons) but if one wants to learn C++, one should learn the C++ way to do things. Otherwise it's like trying to learn French without learning French irregular verbs. ("Il n'y a pas d'eau chaude. L'eau froide est marron.")

A fan of iterators would say that their advantage is that if the programmer decides that he doesn't want a vector - maybe a list or a deque would be better - the loop's code would not need to change.
 
  • #14
yungman said:
I need to find a way to detect EOF
Gaddis discusses two different ways of detecting the end of an input file.

1. You can use the input operation itself in a while statement. If the operation fails, the while statement evaluates it as false, and the loop ends. See for example program 5-15 on page 278.

You can input multiple items using this method:
Code:
    while (inputFile >> firstName >> lastName >> phone)
Beware that the first and last names each have to be single words. If the first name is "Mary Jane" and the last name is "Smith", then firstName becomes "Mary", lastName becomes "Jane", and phone becomes "Smith" if it's a string. If phone is an int, this causes an error which ends the loop.

To deal with problems like this, you can use getline() to read an entire line into a string, but then you need to use string-manipulation functions to extract the various pieces of information as necessary.

Code:
    while (getline (inputFile, line))
    {
        // do something with the line
    }

2. You can use the fstream eof() member function to detect the end of file. See for example program 12-6 on page 668.

The details of either method depend on how you arrange the data in the input file. So you should first decide how you want to do this.
 
  • Like
Likes yungman
  • #15
yungman said:
I want to call multiple class objects to do fstream file, add/delete, sort etc. I want to design in a way that it's upgradable. Starting with class object to add, object to create and R/W to file to copy into the vector array and return to main.
You don't call class objects - you call member functions (AKA "methods" in OO parlance) of the objects. In this regard, an object -- an instance of a class -- is just like a struct.
yungman said:
This current program is ONLY to find out which temporary array of nested structure that is passed around to do add/delete and sort. That's the reason I need to find a way to detect EOF as the size of the vector array change after add/delete.
Take a look at the documentation for the vector template class. The member function size() keeps track of how many elements are in the vector.
As a vector in memory, EOF is not at all relevant. If you're talking about serializing the data in a vector (storing the data to hard drive or reading the data from a hard drive), that's a whole different topic.
yungman said:
It actually have a lot of the features like seekp and seekg. BUT that heavily involve R/W to hard disk or flash memory, it will be very slow. I think it's better to do all those in RAM first and copy one time to file.
It will be slow only if you have a huge amount of data, on the order of 100's or 1000's of MB. If I were working on this, I would make sure I have everything else understood and working before worrying about file I/O.
yungman said:
Simple question, Can I call multiple class object( multiple .h files)? I want one just to read/write to file, one to add/delete, one to sort.
For each class that you define, my advice is to put the template for the class in one .h file, and the implementation of the class methods in their own .cpp file.
If read, write, add, and delete are member functions for a particular class, it makes no sense to scatter the implementation across multiple .cpp files.
Again, you don't call class objects -- you call member functions of the class.
yungman said:
The main() is just to guide the traffic. Only thing that is beyond my knowledge is how to make it a true .exe program that don't have to have VS to run, that people can load into the computer and use it.
If you compile the program in Debug mode, there will be a directory named Debug with an executable in it. If you compile in Release mode, there will be a directory named Release that has the executable in it. If you open a command prompt window, and CD to one or the other of these directories, you can type the name of the executable and it will run.
 
  • Like
Likes yungman
  • #16
Mark44 said:
You don't call class objects - you call member functions (AKA "methods" in OO parlance) of the objects. In this regard, an object -- an instance of a class -- is just like a struct.
I thought the .h file contain the class object, within the class object, there are member function in the PUBLIC to interface with the private data. That the member functions are subset of the class object.

Mark44 said:
Take a look at the documentation for the vector template class. The member function size() keeps track of how many elements are in the vector.
As a vector in memory, EOF is not at all relevant. If you're talking about serializing the data in a vector (storing the data to hard drive or reading the data from a hard drive), that's a whole different topic.
It will be slow only if you have a huge amount of data, on the order of 100's or 1000's of MB. If I were working on this, I would make sure I have everything else understood and working before worrying about file I/O.
I don't know I am right or not, my thinking is ultimately the whole vector array is going to be STORED in the binary file onto the HD or Flash in the computer so I can retrieve it and work on it to update the file. You think I should bypass the the middle stage of using vector and just do the whole thing in fstream file?

I have been reviewing vectors, pointer allocate memory and fstream file. I am trying to have better understanding all these, that's the main reason I want to write this program. All the stuffs in the book are really really easy, that's not going to help me advancing my programming. Yes, I might be running into issues, but that's the best way to learn.

Mark44 said:
For each class that you define, my advice is to put the template for the class in one .h file, and the implementation of the class methods in their own .cpp file.
If read, write, add, and delete are member functions for a particular class, it makes no sense to scatter the implementation across multiple .cpp files.
Again, you don't call class objects -- you call member functions of the class.
If you compile the program in Debug mode, there will be a directory named Debug with an executable in it. If you compile in Release mode, there will be a directory named Release that has the executable in it. If you open a command prompt window, and CD to one or the other of these directories, you can type the name of the executable and it will run.
What is CD?

Thanks so much for your long response, I am still kind of feeling my way on this one. So I should put as much of the add/delete and sort in one .h file and go to .cpp to detail the member function?

I have a question, is vector same as array in the sense eg. char cAr[]; cAr is the starting address of the array. For vector<char>vec; Is vec the starting address of the vector vec? That I can pass around to functions?

I am having problem using pointer to vector to access to element of the vector. I am still reading online.

Thanks for your help.
 
  • #17
@yungman, don't operate on the data on the hard disk.

Load it into memory first. A vector is a good choice. Rather than using EOF when reading the file, just write the size/number of elements to disk as well, then read it all in one read call into the vector. You need to resize the vector first based in the size of the file. The member function data() gives you the pointer inside the vector.

Here is an example (I'm not going through the trouble to ensure it is correct or use your variables, cause I'm typing on a phone).

C:
void writeInv(
    const std::string & path,
    const std::vector<Inv> & items)
{
    std::ofstream outFile(path,  ios::out | ios::binary);
    uint64_t SZ = items.size();
    .. check file opened ...
    outFile.write( (char*) &SZ, sizeof(uint64_t));
    outFile.write((char*) items.data(), items.size()*sizeof(Inv));
    outFile.close();
}

void readInv(
    const std::string & path,
    std::vector<Inv> & items )
{
    std::ifstream inFile( path,ios::in | ios::binary);
    ... check file opened
    uint64_t SZ;
    inFile.read( (char*) & SZ, sizeof(uint64_t));
    items.resize( SZ );
    inFile.read( (char*) items.data(), SZ * sizeof( Inv ));
    inFile.close();
}

EDIT

I just notice that your classes have strings in them. You can't use the functions above then because the strings have their own internal data and size that isn't accounted for in sizeof, and write.

Instead you need to do something more, like go into the struct and write the strings separately while also writing their size, or something like that.

This is the reason I suggested fixed size char arrays might be good, because then every instance is the same size and the memory is all contiguous, which simplifies IO.
 
Last edited:
  • #18
yungman said:
is vector same as array in the sense eg. char cAr[]; cAr is the starting address of the array. For vector<char>vec; Is vec the starting address of the vector vec? That I can pass around to functions?
No. If you want to pass the address of the first element, to a function that expects to receive a pointer to a single char, you can use &vec[0]. If you want to pass the address of the vector, to a function that expects to receive a pointer to a vector, use &vec.
 
  • Like
Likes yungman
  • #19
jtbell said:
No. If you want to pass the address of the first element, to a function that expects to receive a pointer to a single char, you can use &vec[0]. If you want to pass the address of the vector, to a function that expects to receive a pointer to a vector, use &vec.
Thanks Jtbell

I have been searching around, I just got to your first post. Let me print it out to read it first. I'll be back.

That's what I found on line, they use &vec instead of actually *vecptr. Unless using Iterator...which is in chapter 16 which I am not even close to that. Maybe I should hold off a little on this aggressive program as there must be a better way when I get to STL stuffs.

Ha ha, seems like I am digging the hole for myself deeper and deeper, My first goal is just finish to Chapter 15 Inheritance and Polymorphism, now I have to look at Chapter 16 STL Template!

Thanks
 
Last edited:
  • #20
I prefer to use references instead of pointers for passing data to functions, e.g. like this:
C++:
#include <iostream>
#include <vector>

using namespace std;

int VectorSum (const vector<int>& vec)
{
    int sum = 0;
    for (int k = 0; k < vec.size(); ++k)
    {
        sum += vec[k];
    }
    return sum;
}

int main ()
{
    vector<int> myVec = {1, 2, 3, 4, 5};
    cout << "Sum is " << VectorSum (myVec) << endl;
    return 0;
}
If you use a pointer to pass the vector to the function, things get a little bit messy inside the function. I just realized this while working out the example below:
C++:
#include <iostream>
#include <vector>

using namespace std;

int VectorSum (const vector<int>* vec)
{
    int sum = 0;
    for (int k = 0; k < (*vec).size(); ++k)
    {
        sum += (*vec)[k];
    }
    return sum;
}

int main ()
{
    vector<int> myVec = {1, 2, 3, 4, 5};
    cout << "Sum is " << VectorSum (&myVec) << endl;
    return 0;
}
If I remove the parentheses in (*vec) in the function, I get compiler error messages.
 
  • Like
Likes Jarvis323
  • #21
yungman said:
I thought the .h file contain the class object, within the class object, there are member function in the PUBLIC to interface with the private data. That the member functions are subset of the class object.
Your use of the term "class object" indicates that you don't understand the difference between a class declaration (the blueprint) and an object (an instance of a class). I've said this before -- the difference between a class declaration and an instance of a class (an object) is the same as the difference between a struct declaration and a variable of that struct type.

The .h file typically contains the blueprint for the class -- declarations for the data members and declarations (only) for the function members. You can include the full definitions of the function members in the same .h file, but one or two of your other programs put the definitions for the function members in an implementation file, a .cpp file.

Objects, or instances of a class, typically are in the code that uses the class. In your case, the .cpp file that contains main().

yungman said:
I have been reviewing vectors, pointer allocate memory and fstream file. I am trying to have better understanding all these, that's the main reason I want to write this program. All the stuffs in the book are really really easy, that's not going to help me advancing my programming. Yes, I might be running into issues, but that's the best way to learn.
I disagree that this is the best way to learn. Crawl. Walk. Run. You're trying to run when you are barely able to crawl.
yungman said:
What is CD?
Change directory. Have you not ever used a command prompt before?
yungman said:
Thanks so much for your long response, I am still kind of feeling my way on this one. So I should put as much of the add/delete and sort in one .h file and go to .cpp to detail the member function?
You've missed my point. Put the class definition with declarations of the data members and declarations (only) of the function members in the .h file, like this:
C++:
//MyClass.h
class MyClass
{
      int data1;
      int data2;
    public:
      void addPerson(<parameter list>);
      void deletePerson(<parameter list>);
      ...
};

Put the definitions of the member functions in a .cpp file.

Crawl. Walk. Run.
 
  • Like
Likes Jarvis323 and Vanadium 50
  • #22
jtbell said:
Gaddis discusses two different ways of detecting the end of an input file.

1. You can use the input operation itself in a while statement. If the operation fails, the while statement evaluates it as false, and the loop ends. See for example program 5-15 on page 278.

You can input multiple items using this method:
Code:
    while (inputFile >> firstName >> lastName >> phone)
Beware that the first and last names each have to be single words. If the first name is "Mary Jane" and the last name is "Smith", then firstName becomes "Mary", lastName becomes "Jane", and phone becomes "Smith" if it's a string. If phone is an int, this causes an error which ends the loop.

To deal with problems like this, you can use getline() to read an entire line into a string, but then you need to use string-manipulation functions to extract the various pieces of information as necessary.

Code:
    while (getline (inputFile, line))
    {
        // do something with the line
    }

2. You can use the fstream eof() member function to detect the end of file. See for example program 12-6 on page 668.

The details of either method depend on how you arrange the data in the input file. So you should first decide how you want to do this.
Thanks for the reply, actually my question is on vector, not fstream file.

Thanks
 
  • #23
yungman said:
actually my question is on vector, not fstream file.
Yeah, I finally realized that. Your terminology confused me, because one doesn't normally use EOF to refer to the end of a vector or array.
 
  • #24
Mark44 said:
Your use of the term "class object" indicates that you don't understand the difference between a class declaration (the blueprint) and an object (an instance of a class). I've said this before -- the difference between a class declaration and an instance of a class (an object) is the same as the difference between a struct declaration and a variable of that struct type.
I might use the wrong name, but I think I mean the same thing as you described. Like class AddDel with all the private and public and member function declaration. Then in main(), declare AddDel IVar that IVar is the object of the class( maybe incident of the class). Just like struct Inventory, in main() declare Inventory Info
where Info is the object of the struct Inventory. It's like AddDel is the blueprint and IVar is created from the blueprint.

Mark44 said:
The .h file typically contains the blueprint for the class -- declarations for the data members and declarations (only) for the function members. You can include the full definitions of the function members in the same .h file, but one or two of your other programs put the definitions for the function members in an implementation file, a .cpp file.

Objects, or instances of a class, typically are in the code that uses the class. In your case, the .cpp file that contains main().

I disagree that this is the best way to learn. Crawl. Walk. Run. You're trying to run when you are barely able to crawl.
In real life work environment, you get threw into the lion dent in very short time when you are assigned to a new job/project. Hell, in 1982 after I successfully designed the 8085 controller unit and design the firmware, I was sent to NY to work with the owner of LeCroy ( Walter LeCroy) and worked directly under him to design a data acquisition frontend! First time in analog and high speed at that. I was pretty much sink or swim! Doing this program is a tiny stretch relatively. I am quite sure I will complete it one way or the other. The question for me is whether I should wait to learn about STD Template on vector iteration first or just plunge ahead. Look at it this way, imagine a bear is chasing you, whether you are ready or not, you run! 😊 :)):nb)

That's how it is working in silicon valley. You make it, you get promotion, raise and all the good stuffs. You can't make it, you stay down at the bottom. How about in 1984 after I mastered designing the data acquisition frontend, I quit and got a job in analog IC design?! Talk about jump. People get used to this. We survive on less. Particularly I NEVER even took an analog electronic design class in my life, all from selfstudy by myself. I am slowing down as I get old now... I am very unhappy this is only so much to show for after 3 1/2 months of hard study. If it is 30 years ago, I would kick myself if I don't get to this point in a month!
Mark44 said:
Change directory. Have you not ever used a command prompt before?
You've missed my point. Put the class definition with declarations of the data members and declarations (only) of the function members in the .h file, like this:
C++:
//MyClass.h
class MyClass
{
      int data1;
      int data2;
    public:
      void addPerson(<parameter list>);
      void deletePerson(<parameter list>);
      ...
};

Put the definitions of the member functions in a .cpp file.

Crawl. Walk. Run.

Thanks for the suggestion to start the .h file. This still miss the part of writing to the file. Should I put into the same .h file?

Thanks for the reply.
 
Last edited by a moderator:
  • #25
My feeling is that you've got to build on solid foundations. It's like if you go on to calculous, you should make sure you have commutativity and associativity down. Otherwise everything you do from then on might be wrong and you won't go far at all.
 
  • #26
Jarvis323 said:
My feeling is that you've got to build on solid foundations. It's like if you go on to calculous, you should make sure you have commutativity and associativity down. Otherwise everything you do from then on might be wrong and you won't go far at all.
You mean calculus? I don't even know what is commutativity and associativity! I am not good with names, a lot of times when my grandkids ask me questions on math, I don't know the name, then I look online, then I realize what it is. I studied multi-variable, ODE and PDE, I actually took the class in ODE 13 years ago and I was the first in the class. I studied multi-var and PDE on my own. I needed those for RF and microwave as they are all electromagnetics. My degree was Chemistry, never work a day in Chemistry. I never took a class of analog electronics in my life and I had a full career as chief EE and manager of EE.

Actually after Mark mentioned about crawling and running, I actually stop and think about it. Nothing in what I want to do in the directory program is really new. I did the fixed length directory program already and I did similar inventory program with choice to select to read any structure element in the file. This one is just able to add and delete and sort. The file is of variable length rather than fix length. The sorting part to me is the easiest part, those are common sense like those bubble sort etc.

I am just shopping for the best tool( like fstream, vector or dynamic memory) to do the job and design so the program is expandable. I can just write the whole thing in one program, I just want to fit the class using .h file to fit to the chapter I am working on.

I am sure I will run into problems, but that's just the way of learning. Problem is my memory is degrading, I have to keep repeat doing things over and over. I have to keep using stuffs I learn before to remember them. If not because of my memory, I could have learn this so much faster. When I was young, I don't forget things I learn after I learn it the first time, now it's very frustrating that I keep forgetting things. there's nothing good about getting old. That's the reason I decided to learn C++, get out of the comfort zone. It would be so easy for me to do a hobby in electronics and have things to show for. I just spent over 3 years designing very high end hifi power amps and I have amps I designed and built lining up that compare very good with any two channels power amps at least in $5K+ range. It's easy, that's why I decided to learn something I never really learn deeply, the little I learn was from 40 years ago...to get out of the comfort zone. Brain is like body, you don't use it, you loose it.
 
Last edited:
  • #27
yungman said:
I might use the wrong name, but I think I mean the same thing as you described. Like class AddDel with all the private and public and member function declaration.
This is what you said, that I replied to:
I want to call multiple class objects
This isn't a matter of using the wrong names for things, which is bad in its own right, because someone reading what you wrote won't understand what you're trying to get across. What's bad about what you wrote is that class, object, and function all mean different things. You can call a function, or you can call a function on an object, but it's meaningless to say you want to call class objects, let alone multiple class objects.
yungman said:
Then in main(), declare AddDel IVar that IVar is the object of the class( maybe incident of the class).
IVar would be an object AKA an instance of the AddDel class.
By the way, AddDel is a terrible name for a class -- add and del are actions (verbs) and a class is a thing, so its name should be a noun. And IVar is a useless name for an instance of that class. What does 'I' signify -- instance? And Var? The name should suggest to another reader what it's being used for.
Since your program is intended to represent a directory of people's names, a much better name for the class would be Directory or ContactList or some other name that makes it crystal clear what the class contains. Some of the methods (member functions) might be AddContact(), DelContact(), SaveContacts() and whatever other actions the class is intended to provide.

In main(), you would create a Directory instance, and then call AddContact() or other function members of the Directory object, but you wouldn't "call a Directory object."
yungman said:
First time in analog and high speed at that. I was pretty much sink or swim! Doing this program is a tiny stretch relatively.
That was hardware, and it was 38 years ago, when Bjarne Stroustrup was only just starting to work on developing C++ . In the meantime C++ has gone through very many changes, and has greatly increased in complexity. As mentioned several times before, the fact that you designed hardware 30+ years ago means just about zilch in terms of your ability to learn a very complex programming language now.

The only reason that learning C++ is a relatively "tiny stretch" now is that you have the experience of people on this site to get you out of the very many holes that you regularly dig yourself into. How long would it have taken for you to figure out, on your own, why the problem you were having at the start of this thread had nothing to do with the vector template class, but everything to do with character input?
yungman said:
Thanks for the suggestion to start the .h file. This still miss the part of writing to the file. Should I put into the same .h file?
What I wrote was just a skeleton for what a class definition might look like. Of course a function to write the contact list info to a file should be in the header file.
 
Last edited:
  • Like
Likes yungman and Vanadium 50
  • #28
Mark44 said:
That was hardware, and it was 38 years ago, when Bjarne Stroustrup was only just starting to work on developing C++ . In the meantime C++ has gone through very many changes, and has greatly increased in complexity. As mentioned several times before, the fact that you designed hardware 30+ years ago means just about zilch in terms of your ability to learn a very complex programming language now.

The only reason that learning C++ is a relatively "tiny stretch" now is that you have the experience of people on this site to get you out of the very many holes that you regularly dig yourself into. How long would it have taken for you to figure out, on your own, why the problem you were having at the start of this thread had nothing to do with the vector template class, but everything to do with character input?
What I wrote was just a skeleton for what a class definition might look like. Of course a function to write the contact list info to a file should be in the header file.
I am not talking about what you consider hardware like MPU and digital logic. I am talking about analog, RF and microwave. I threw the MPU digital hardware out in 1984 since because it's too easy and not challenging at all. It's child's play compare to analog RF microwave where you actually need math, physics to touch. The good thing is after the very steep learning curve, analog don't change like programming. I still have to design different MPU controller on and off until 2005 because I was the only one that know how to do it. So I am NOT exactly that out of the loop. The basics are just the SAME all these years, just more ADCs and DACs, Flash and RAM built in. So I am not exactly out of touch. Just reluctantly had to design them every few years throughout my career which, I never even put it in my resume so people don't get the wrong idea.

I cannot thank you and few others enough for helping. Yes, it will take me longer to even get to this point. Old age really doesn't help, it's one thing to keep up in my own expertise, it's another thing to start learning from almost scratch at 67. Yes, C++ is a different world from the days I learn programming 40 years ago. But I still find it's hard to read books in C++ compare to physics, calculus, RF books. Those concepts are much harder to learn, but they are more logical and consistent. In a way, it's much much easier to read. We gone through this a few times already.
 
Last edited:
  • #29
yungman said:
I am not talking about what you consider hardware like MPU and digital logic. I am talking about analog, RF and microwave.
I am including both analog and digital components as hardware. My point was that expertise with various types of hardware doesn't translate to much of a leg up when you're learning programming, which is not that far from starting from scratch in your case. The first four or five chapters in Gaddis weren't too hard for you, because you could draw from your experience with Pascal 30 or 40 years back, once you got to pointers and arrays and classes, it was all new. I would categorize this part as anything but a "tiny stretch," as you put it. To say this does a great disservice to the people who have worked with you in literally hundreds of posts over the past few months.
Back when many of us were learning C or C++, resources on the internet were minimal at best, if not nonexistent. Most of us learned on our own through our own digging, without much in the way of the hand-holding that you have greatly benefitted from.
 
  • #30
Mark44 said:
I am including both analog and digital components as hardware. My point was that expertise with various types of hardware doesn't translate to much of a leg up when you're learning programming, which is not that far from starting from scratch in your case. The first four or five chapters in Gaddis weren't too hard for you, because you could draw from your experience with Pascal 30 or 40 years back, once you got to pointers and arrays and classes, it was all new. I would categorize this part as anything but a "tiny stretch," as you put it. To say this does a great disservice to the people who have worked with you in literally hundreds of posts over the past few months.
Back when many of us were learning C or C++, resources on the internet were minimal at best, if not nonexistent. Most of us learned on our own through our own digging, without much in the way of the hand-holding that you have greatly benefitted from.
Of cause I am not implying learning all the hardware translate to any leg up in learning programming. That's the very reason I choose C++ as it's not challenging to take up another hobby in electronics.

As I said, I cannot thank you and others enough for the help.


Anyway, I don't want to offend you, you have been very helpful to spend time helping me.
 
  • #31
yungman said:
BUT that heavily involve R/W to hard disk or flash memory, it will be very slow. I think it's better to do all those in RAM first and copy one time to file.

Whoa! Slow down!

First, you want to get your code working first before deciding it's too slow. Getting a wrong answer faster is no real virtue.

Second, you have no idea whether your code is too slow until you run it. Your records are 88 bytes long, so a modern disk can read in two million of these records per second.

Finally, you have no idea where your code is too slow until you run it. Spending time optimizing one part can be a total waste if it's some other part slowing you down.

PS If you are planning on using a bubble sort, it is unlikely that disk read time will be your biggest concern.
 
Last edited:
  • #32
yungman said:
imagine a bear is chasing you, whether you are ready or not, you run!
Those that can tell their story are those that know:
[*] Bears run faster than people
[*] Bears have very poor eyesight for stationary objects, rather better for things that move
 
  • #33
Just speaking as a programmer, when things don't behave as expected, have you tried debugging? Reviewing the values of all variables at each program step? When things are acting strangely, debugging can quickly lead you to the actual problem, it may not be what you think is causing the problem.
 
  • #34
I have been working on the program, yes, I am still crawling in C++, but after I worked on the program, the program is not exactly running material. I say it's at best slow walk. I manage to using the Constructor in the .h file to check for file existence, if not, create an empty file. In main, I have option to create the new file or read back the existing names.

This is a much simplified version that each name structure has only name and phone number. I can create as many name as I want in the directory. So far, the option is to read them all back. Displaying particular name, add new name or delete name will come later. But the structure of the program is done already. Doing the sorting, adding, deleting should be quite easy. In the whole C++, the sorting so far is the easiest part for me. So I am not worry about it.

Of cause, this is the first time I wrote such a complicate program, I am sure it can be improved quite a bit. Any suggestion is very welcome. I want to push what I learn so far, this program sure did pushed me. I spent a lot of time searching on line to look at how people do things also. Here is what I have. It's is NOT a big program so far.

I still believe in doing as few interfacing with the file as possible. Not only it's slower, hard disk and flash memory have finite working cycles. I don't want to do all the searching, sorting stuff directly on the file. What I do is download the entire file to the vector DirV in the Constructor, the rest of the program is just working on the DirV until closing the program. The Destructor then write the entire content of the vector DirV back into the file. So one read and one write to the file every time I open the program.Here is the .h file, I use inline function instead of creating a separate implementation file:
C++:
#ifndef VectorCall_H
#define VectorCall_H
#include <vector>
#include <fstream>
class VectorCall
{
  private:
    const static int nameL = 25, phoneL = 12;
  public:
    struct Directory { char name[nameL];    char phone[phoneL]; };
    std::vector<Directory>DirV;
    Directory Dir; bool newF;
    std::fstream file;

    VectorCall()//Constructor read file to DirV
    {
        file.open("Directory.dat", std::ios::in | std::ios::binary);
        if (file.fail())
        {//If file doesn't exist, create the file
          std::cout << " File does not exist";
          file.open("Directory.dat", std::ios::out|std::ios::binary|std::ios::app);
          file.close();
          newF = true;
        }
        else
        {//If the file exist, read entire file into vector DirV.
          file.read(reinterpret_cast<char*>(&Dir), sizeof(Dir));
          do
          {
            DirV.push_back(Dir);
            file.read(reinterpret_cast<char*>(&Dir), sizeof(Dir));
          } while (!file.eof());
          file.close();
        }
    }
    ~VectorCall()//Distructor
    { 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*>(&DirV[ct2]), sizeof(DirV[ct2]));
        ct2++;
      }while(ct2 < DirV.size());
      file.close();
    }
    void push_backV() { DirV.push_back(Dir); }
    void writeFile(){}
    void print() { std::cout << "Name:  " << Dir.name <<
            "   Phone:  " << Dir.phone << "\n\n"; }
};
#endif

This is the main .cpp file:
C++:
#include <iostream>
#include <string>
#include <vector>
#include "VectorCall.h"
using namespace std;

int main()
{
  char more;  int index = 0; const int nameL = 25, phoneL = 12;
  VectorCall Info;
  char yes;
  if (Info.newF == true)
  {//First time set up the directory by entering all the names and info
     cout << " Welcome to the Directory program. You need to enter informations:\n\n";

    do
    {
        cout << " Enter name:  "; cin.getline(Info.Dir.name, nameL);
        cout << " Enter phone:  "; cin.getline(Info.Dir.phone, phoneL);
        //Info.print();
        Info.push_backV();//writing into vector DirV.
        cout << " Do you want to enter another name?  "; cin.get(more);
        cin.ignore();
    } while (tolower(more) == 'y');
    Info.writeFile();
  }
  else
  {//If the file exist, ask whether to display all the information in the file.
      cout << "  Press 'y' to see the whole list.  "; cin >> yes;
      cin.ignore(); cout << endl;
      if (yes == tolower('y'))
      {   do
          {  cout << "Name stored in DirV is:  " << Info.DirV[index].name <<
                  " phone:  " << Info.DirV[index].phone << "\n\n";
             index++;
          } while (index < Info.DirV.size());
      }
      else { cout << " Bye\n\n"; }
  }
    return 0;
}

I still have not decided whether to complete the program as I think I built the backbone of the program already, the rest are just adding member functions. Still thinking about putting putting the display of names into function and make the main() simpler. This is a very educational experiment, did I had to review the former chapters, read through my notes, improving my notes so I can save a lot of times in the future. The book really doesn't go deep enough into each topic, a lot of things I want to do is not there. My memory ( or the lack of) really slowing me down, there's no other way than to just keep dreaming up programs to make me go back and read through the material over and over.

One think I am still not quite get, why the int variable has to have "static" in front when declaring in the class inside the .h file. that tripped me for a little while.
 
Last edited:
  • #35
Well done, you have reached a big milestone: we can now start talking about how to write object oriented code that is easy to debug, maintain and extend. You see although you have written your code as a class, it doesn't leverage the power of OOP.

One way to start writing a class is to write down what you want it to do.
  • I want a class for a contact directory: a good name will be Contacts.
  • The class will define a struct Contact with the following elements:
    • name
    • phone
  • This class should have public methods that:
    • Read the contacts in from a disk file
    • Write the contacts out to a disk file
    • Create a contact
    • Retrieve a contact
    • Update a contact
    • Delete a contact
    • (these last four operations are commonly known as CRUD)
    • Sort the contacts into alphabetical order
    • List the contacts
You should then be able to create the header file - this will not contain any code, we will leave this to the implementation file. Notice how similar this is to the plain language list above: with practice you will be able to write the first draft of the header file without doing it in plain language first. Note however that I have included some mistakes that you will have to fix :smile:. [Edit- added] Finally, I have kept to your use of C-strings for the name and telephone number (and filename) - you should use std::string for these, it is a lot easier and safer and there is no valid reason not to.

C:
#ifndef Contacts_H
#define Contacts_H
#include <vector>
#include <fstream>

class Contacts {
  private:
    const static int nameL = 25, phoneL = 12;
    // Cache the entries in a vector.
    std::vector <Contact> _entries;

  public:
    struct Contact {
        // Full name.
        char name[nameL];
        // Telephone number.
        char phone[phoneL];
    };

    // Constructor - takes a filename to use for permanent storage.
    void Contacts(char& filename);

    // Read the contacts in from a disk file.
    void read(char& filename);

    // Write the contacts back out to the original file.
    void flush();

    // Create a contact.
    void createContact(Contact& newContact);

    // Retrieve a contact.
    Contact getContact(char& name);

    // Update a contact.
    void updateContact(Contact& updatedContact);

    // Delete a contact.
    void deleteContact(char& name);

    // Sort the contacts into alphabetical order.
    void sort();

    // Get all the contacts so they can be printed out.
    std::vector* getContacts();
};
#endif
 
Last edited:

Similar threads

Replies
10
Views
951
  • Programming and Computer Science
Replies
30
Views
2K
  • Programming and Computer Science
2
Replies
52
Views
3K
  • Programming and Computer Science
3
Replies
75
Views
4K
  • Programming and Computer Science
Replies
5
Views
872
  • Programming and Computer Science
2
Replies
36
Views
3K
  • Programming and Computer Science
Replies
2
Views
862
  • Programming and Computer Science
Replies
5
Views
2K
  • Programming and Computer Science
3
Replies
89
Views
4K
  • Programming and Computer Science
Replies
2
Views
1K
Back
Top