C/C++ Efficient C++ String Manipulation: Tips and Tricks from Experts

  • Thread starter Thread starter yungman
  • Start date Start date
  • Tags Tags
    C++ Strings
Click For Summary
The discussion revolves around the challenges of copying a C++ string to a C-string and the associated memory management. The original poster seeks to allocate memory for a C-string based on the length of the input string but encounters issues with Visual Studio (VS) not compiling correctly. Experts clarify that the code provided does not actually create a C-string but rather an array of STL string objects, and they recommend using the `c_str()` method to convert an STL string to a C-string. Additionally, there are discussions about configuration settings in VS, with suggestions to run the program in different modes and ensure proper project settings to avoid compilation errors. The conversation highlights the importance of understanding the differences between C-strings and character arrays in C++.
  • #61
I am not in a position to look at code, but I believe an STL string can be is small as one or three bytes longer than a c_string. A c_string is the size of the string + 1 byte for the terminating zero. A STL string can be resized to the length of the string plus the value of the length of the string, 2 bytes for a short and 4 bytes for an int.

Worrying about an extra byte is silly.
 
Technology news on Phys.org
  • #62
A Google search for "c++ std::string implementation" led me to this as the first hit:

libc++'s implementation of std::string

Long, long ago, before the 1998 C++ standard introduced std::string, it was a common exercise for C++ textbooks and students to create their own string class. Usually it consisted of a struct with two members: a pointer to a dynamically allocated char array, and an int which contained the size of the array.

That's actually pretty close to what's described in the linked article! Its struct has two ints: one for the size (capacity) of the dynamic char array, and one for the actual number of chars stored in it. In general, the array is larger than necessary, so that chars can be added to it without always having to reallocate the array and copy all the chars to the new array.

The clever thing is that for very short strings ("short string mode"), the chars are stored directly in the struct, apparently using a union. :cool:

This is just one implementation of std::string. As I understand it, in general the C++ standard doesn't require specific implementations for strings, vectors, etc. Instead, it specifies the interfaces to their member functions, and their performance characteristics. Compiler writers are free to use any implementation which meets those requirements.
 
  • #63
Always look at the first line of the errors list. It says 'variable invItem::length is uninitialized. Always intitialize a member variable'. Take a look at where you define invItem::length and you will find your problem.

You got into this habit of not initializing variables very early on and ingnored advice that this was a bad thing; worse you started to write code like
C:
int one;
one = 2;
Do you now understand why this is nonsense?

Also, on lines 5-7 of invItem.h you have defined global variables description, cost and units. Can you explain your thought process behind this?
 
  • #64
jtbell said:
So there's a tradeoff. If you need to work close to hardware level, with "small" processors and limited amounts of memory, then C-style ways of doing things may be better, at the cost of you having to spend more programming time to get things to work right in all circumstances. If you're working with a typical desktop computer, tablet, or even phone, you have oodles of memory and lots of computing power, and can easily afford to let it do more of your work for you.
This cannot be stressed enough.

It is insane to 'unlearn' everything you have learned with std::string. 99% of the time, this is the class to use when writing C++ code. String handling is not something we do much on microcontrollers: the most I have ever done is write a WiFi connection status and IP address to a 128 pixel wide OLED and this can easily be done with a C-string. But if I am writing a program to process a text file on a PC then I will do it in Python of course I would use std::string.
 
  • #65
pbuk said:
Always look at the first line of the errors list. It says 'variable invItem::length is uninitialized. Always intitialize a member variable'. Take a look at where you define invItem::length and you will find your problem.

You got into this habit of not initializing variables very early on and ingnored advice that this was a bad thing; worse you started to write code like
C:
int one;
one = 2;
Do you now understand why this is nonsense?

Also, on lines 5-7 of invItem.h you have defined global variables description, cost and units. Can you explain your thought process behind this?
I deleted the post, I want to check more first.
 
  • #66
yungman said:
I deleted the post, I want to check more first.
The time to 'check more first' is before you first post it, not after someone has helped you with it. Goodbye, and good luck.
 
  • Like
Likes Vanadium 50 and phinds
  • #67
I reposting the same issue. My original post was VALID. I checked very carefully. I did NOT miss declaring variables as BEING ACCUSED. The ONLY reason I deleted the post was I left out one std::string and I had to change it back to c-string. NOT that I retract what I said.

Now that I fixed everything, I have to EXACT same problem with VS. My original project FAILS, I copy the error list below. I copied the .h and .cpp to a brand new created project. I compiled and ran like a champ.

This is the source.cpp file.
C++:
#include <iostream>
#include <iomanip>
#include <string>
#include "invItem.h"
using namespace std;
int main()
{
    const int size = 21;
    //call default constructor #1
    char cAr[size] = "Hammer";
    invItem item1;
    item1.setDesc(cAr);
    item1.setCost(6.95);
    item1.setUnits(12);

//call constructor #1 with all parammeters.
    cout << left << setw(30) << " Item description: " << item1.getDesc() << "\n";
    cout << left << setw(30) << " Cost: " << "$" << item1.getCost() << "\n";
    cout << left << setw(30) << " Units on hand: " << item1.getUnits() << "\n\n";
    return 0;
}

This is the invItem.h file:
C++:
#ifndef invItem_H
#define invItem_H
#include <cstring>
#include <string>class invItem
{
private:
    char* description;
    int L = 21;//default length.
    double cost;
    int units;
public:
    //Constructor #1 with no parameter
    invItem()
    {
        description = new char[L];
        *description = '\0';//First char = NULL
        cost = 0.0; units = 0;
    }

    //Mutator function
    void setDesc(char* d) { description = d; }
    void setCost(double c) { cost = c; }
    void setUnits(int u) { units = u; }
    //Accessor functions
    const char* getDesc() const { return description; }
    double getCost() const { return cost; }
    int getUnits() const { return units; }
};
#endif

This is the error list:
Error 10_15.jpg


I have no idea what all the complains of already defined in invItem.obj. I stress again, the exact same two files that give error, when copied into a new project, it ran. I compared most of the Project-->Properties, both projects looks the same. There must be some setting in VS that is different.Please help.

Thanks
 
Last edited:
  • #68
pbuk said:
The time to 'check more first' is before you first post it, not after someone has helped you with it. Goodbye, and good luck.
You did NOT read the content of my post before you made the accusation. You accusation was WRONG. I checked everything carefully. Did you read that I copied the EXACT .h and .cpp into another project and it compiled and ran like a champ? I bet you did not read that.
 
  • #69
I'm not sure where to start because there are some major fundamental problems with it. I think it might be time to go back to the books. Then maybe just delete this program entirely and start over following the book more closely.

But just to let you know, the errors are due to the global variables in the header file. The contents of the header file are inserted into the files that include it. In your case, you're inserting those global variables into multiple different cpp files, and that means you have multiple definitions of them.
 
Last edited:
  • #70
I don't use VS, so I won't comment on the error messages specifically (at least now). However one thing jumps out at me immediately when looking at your code.

In invItem.h, I suspect that description, cost and units (lines 5,6,7) are intended to be the private member data of an object of class invItem. In their current location, they are outside of the class definition which begins at line 8. They should be inside the class definition, below the current line 10 which marks the beginning of the private section.
 
  • #71
jtbell said:
I don't use VS, so I won't comment on the error messages specifically (at least now). However one thing jumps out at me immediately when looking at your code.

In invItem.h, I suspect that description, cost and units (lines 5,6,7) are intended to be the private member data of an object of class invItem. In their current location, they are outside of the class definition which begins at line 8. They should be inside the class definition, below the current line 10 which marks the beginning of the private section.
You are right, In the book, they should be private. But that shouldn't make a difference as the source.cpp doesn't call any of that. I agree that's a bad practice though.

I'll try to put those inside Private and see what happen.

ThanksEDIT:
I put all those in Private. I updated post#67. You can take a look to verify. I copy into the new project, it works. but in the original project, the error window is exactly the same as in post #67.
 
Last edited:
  • #72
Jarvis323 said:
I'm not sure where to start because there are some major fundamental problems with it. I think it might be time to go back to the books. Then maybe just delete this program entirely and start over following the book more closely.

But just to let you know, the errors are due to the global variables in the header file. The contents of the header file are inserted into the files that include it. In your case, you're inserting those global variables into multiple different cpp files, and that means you have multiple definitions of them.
I am working on that also. I am still checking my c-string stuffs, I have to go back to my notes, have not work on c-string for a while. Got into habit of using std::string whenever called for...Just when I feel comfortable!I want to emphasize, the name of the project that has problem is called 13.2. It has been giving me problem as of yesterday when I still using std::strings. I have worked on it, copy over to the temp project and another one. Those ALWAYS worked. project 13.2 consistently failed. I just did one more time putting those variables pointed out by jtbell, ran again in both 13.2 and temp, 13.2 failed and temp works just fine. This is really strange.

Thanks
 
Last edited:
  • #73
You are right, In the book, they should be private. But that shouldn't make a difference as the source.cpp doesn't call any of that. I agree that's a bad practice though.

It's more than that. It's completely outside the class. You can't have a variable like that in a header file as the compiler error explains. But even if you could, you should realize that every inventory item would be sharing the same description, cost and units variable. Each time you added a new inventory item, it would just overwrite the value of those variables.

Besides that, you're calling new, but not delete. So you also have a memory leak.

yungman said:
I am working on that also. I am still checking my c-string stuffs, I have to go back to my notes, have not work on c-string for a while. Got into habit of using std::string whenever called for...Just when I feel comfortable!

Thanks
I think for Inventory item, it might make sense to have a fixed size C-string so that you can use your binary IO in a straightforward way, and have guarantees on the storage requirements. I don't think performance or memory is a concern here. You can still use string while storing just a char array in InvItem if you want to. You could write something like this.

C:
#ifndef InvItem_H
#define InvItem_H

#include <cstring>
#include <string>

class invItem
{

private:

    static const int DESC_SIZE = 21;
    char m_description[ DESC_SIZE ]; // m_ prefix reminds you this is a member variable
    double m_cost;
    int m_units;

public:

    invItem()
    {
        m_description[ 0 ] = '\0';
        m_cost = 0.0;
        m_units = 0;
    }

    invItem(
        const std::string & d,
        double c,
        int u )
    {
        setDesc( d );
        setCost( c );
        setUnits( u );
    }

    //Mutator function
    void setDesc(const std::string & d)
    {
        std::snprintf(
            m_description,
            DESC_SIZE,
            "%s",
            d.c_str() );
    }

    void setCost(double c) { m_cost = c; }
    void setUnits(int u) { m_units = u; }

    //Accessor functions
    std::string getDesc() const { return std::string( m_description ); }
    double getCost() const { return m_cost; }
    int getUnits() const { return m_units; }
};
#endif

C:
#include "invItem.h"

#include <iostream>
#include <iomanip>

int main()
{
    invItem item1( "Hammer", 6.95, 12 );

    cout << left << setw(30) << " Item description: " << item1.getDesc() << "\n";
    cout << left << setw(30) << " Cost: " << "$" << item1.getCost() << "\n";
    cout << left << setw(30) << " Units on hand: " << item1.getUnits() << "\n\n";

    return 0;
}

Or if you just want to use a string and try to still save memory.

C:
#ifndef InvItem_H
#define InvItem_H

#include <cstring>
#include <string>

class invItem
{

private:

    string m_description;
    double m_cost;
    int m_units;

public:

    invItem()
    {
        m_description.reserve( 20 );
        m_cost = 0.0;
        m_units = 0;
    }

    invItem(
        const std::string & d,
        double c,
        int u )
    {
        setDesc( d );
        setCost( c );
        setUnits( u );
    }

    //Mutator function
    void setDesc(const std::string & d)
    {
        m_description = d;
        m_description.shrink_to_fit();
    }

    void setCost(double c) { m_cost = c; }
    void setUnits(int u) { m_units = u; }

    //Accessor functions
    const std::string & getDesc() const {  m_description; }
    double getCost() const { return m_cost; }
    int getUnits() const { return m_units; }
};
#endif

Or if you want dynamic C-strings, something like this

C:
#ifndef InvItem_H
#define InvItem_H

#include <cstring>
#include <string>

class invItem
{
private:

    char * m_description;
    double m_cost;
    int m_units;

public:

    // make sure memory allocated for m_description is freed when the object is destroyed
    ~invItem()
    {
        delete m_description;
    }

    invItem()
    {
        m_description = nullptr;
        m_cost = 0.0;
        m_units = 0;
    }

    invItem(
        const std::string & d,
        double c,
        int u )
    {
        m_description = nullptr;
        setDesc( d );
        setCost( c );
        setUnits( u );
    }

    //Mutator function
    void setDesc(const std::string & d)
    {
        if( m_description != nullptr )
        {
            delete m_description;
        }

        const size_t NEW_SIZE = d.length() + 1;
        m_description = new char[ NEW_SIZE ];

        std::snprintf(
            m_description,
            NEW_SIZE,
            "%s",
            d.c_str() );
    }

    void setCost(double c) { m_cost = c; }
    void setUnits(int u) { m_units = u; }

    //Accessor functions
    char * getDesc() const { return m_description; }
    double getCost() const { return m_cost; }
    int getUnits() const { return m_units; }
};
#endif
 
Last edited:
  • Like
Likes yungman
  • #74
Jarvis323 said:
It's more than that. It's completely outside the class. You can't have a variable like that in a header file as the compiler error explains. But even if you could, you should realize that every inventory item would be sharing the same description, cost and units variable. Each time you added a new inventory item, it would just overwrite the value of those variables.

Besides that, you're calling new, but not delete. So you also have a memory leak.

......
Hi Jarvis

Thanks for helping. I only reply on the first section. I have to copy your codes to look at it in VS on the second part.

I follow the book, I am still learning about Constructor.

This is copy of the book on the same problem, I just put in the first part on InventoryItem.h( I am lazy, I called invItem.h), same as I use L instead of the long DEFAULT_SIZE:
Book invItem.h.jpg
This is the source.cpp in the book:
Book source.cpp.jpg


Notice the line I drew red line. It doesn't work. I have to use char cAr[]="Hammer". The book is not very good in this chapter.

This is the pdf of the book. This is from p755 to p757 in case.
https://cplusplushelp.weebly.com/uploads/2/5/6/5/25655197/0136022537.pdf

I'll look at the second part of your code before I reply.

Thanks
 
Last edited:
  • #75
If I were the one writing this program, I would use std::string throughout, including the 'description' data member. Nevertheless, I think yungman should write it both ways as an educational exercise: one version using C-strings, and a second version using std::string.
 
  • Like
Likes yungman
  • #76
yungman said:
Hi Jarvis

Thanks for helping. I only reply on the first section. I have to copy your codes to look at it in VS on the second part.

I follow the book, I am still learning about Constructor.

This is copy of the book on the same problem, I just put in the first part on InventoryItem.h( I am lazy, I called invItem.h), same as I use L instead of the long DEFAULT_SIZE:
View attachment 270998This is the source.cpp in the book:
View attachment 270999

Notice the line I drew red line. It doesn't work. I have to use char cAr[]="Hammer". The book is not very good in this chapter.

This is the pdf of the book. This is from p755 to p757 in case.
https://cplusplushelp.weebly.com/uploads/2/5/6/5/25655197/0136022537.pdf

I'll look at the second part of your code before I reply.

Thanks
C++ allows a const to be in a header file without causing duplicate symbols but not a variable. Also, every InvItem can share the same DEFAULT_SIZE but not the same description. It's still not great to put the const outside the class in this case though because DEFAULT_SIZE isn't needed outside of the class.
https://stackoverflow.com/questions/12042549/define-constant-variables-in-c-header

I can't tell why the books code wouldn't work because you didn't show the implementation of setDescription. Nothing in the part you posted has any errors that I can see.
 
  • Like
Likes Vanadium 50
  • #77
Jarvis323 said:
I can't tell why the books code wouldn't work because you didn't show the implementation of setDescription.

Here's what yungman didn't tell us (from the book):

We have also added mutator functions that set values for description, cost, and units.
Program 13-12 demonstrates the class. (This file is also stored in the Student Source Code
Folder Chapter 13\InventoryItem Version 2
.)

(emphasis mine)

So of course this doesn't work. The book is using a subset of the code to illustrate something else: in this case constructors, not strings.
 
  • Like
Likes Jarvis323
  • #78
jtbell said:
If I were the one writing this program, I would use std::string throughout, including the 'description' data member. Nevertheless, I think yungman should write it both ways as an educational exercise: one version using C-strings, and a second version using std::string.
Yes, I am not in position to say which way is better. But, it's time for me to sweat it out a little. Believe me, I am sweating it out right now because the pointer for c-string and std::string is very different as the name of c-string is actually the starting address, and passing c-string in parameter is the address already. Also strlen() and all are different. Particular strncpy_s()....

Also, I am not as familiar with calling function to have {return ptr}, I always use void function and use pass by reference in the (). It's time for me to practice return. I don't like function return type, I use passing reference parameter from day one. This is giving me problem right now. These two are making my head spin right now!:nb)?:)

Thanks
 
  • #79
Vanadium 50 said:
Here's what yungman didn't tell us (from the book):
(emphasis mine)

So of course this doesn't work. The book is using a subset of the code to illustrate something else: in this case constructors, not strings.
Did you read my question? Why the same code won't work in one project consistently, but the EXACT code COPIED over to a new temp project AND another existing project compile and ran? Exact same two files copied into 3 projects, two works, one doesn't.

This is NOT just about my code having problem.
 
Last edited:
  • #80
yungman said:
Did you read my question?

I was answering jarvis.

As far as not having the CD, maybe you should get it.
 
  • #81
Jarvis323 said:
C++ allows a const to be in a header file without causing duplicate symbols but not a variable. Also, every InvItem can share the same DEFAULT_SIZE but not the same description. It's still not great to put the const outside the class in this case though because DEFAULT_SIZE isn't needed outside of the class.
https://stackoverflow.com/questions/12042549/define-constant-variables-in-c-header

I can't tell why the books code wouldn't work because you didn't show the implementation of setDescription. Nothing in the part you posted has any errors that I can see.
This is the code I got from the CD with the book and I want to show what doesn't work. It's in the source.cpp file

This is the source.cpp. I have to make correction to line 13, 21 and 26 to make it work using char cAr1,cAr2 and cAr3.
C++:
// This program demonstrates a class with overloaded constructors.
#include <iostream>
#include <iomanip>
#include "InventoryItem.h"
using namespace std;

int main()
{
   // Create an InventoryItem object and call
   // the default constructor.
   InventoryItem item1;
   char cAr1[] = "Hammer";//New line to fix problem
  // item1.getDescription("Hammer");// Set the description
   item1.setDescription(cAr1); //This line works
   item1.setCost(6.95);            // Set the cost
   item1.setUnits(12);             // Set the units

   // Create an InventoryItem object and call
   // constructor #2.
   char cAr2[] = "Pliers";//added
   //InventoryItem item2("Pliers");
   InventoryItem item2(cAr2); //This line works
   // Create an InventoryItem object and call
   // constructor #3.
   char cAr3[] = "Wrench";
   //InventoryItem item3("Wrench", 8.75, 20);
   InventoryItem item3(cAr3, 8.75, 20);
   cout << "The following items are in inventory:\n";
   cout << setprecision(2) << fixed << showpoint;
  
   // Display the data for item 1.
   cout << "Description: " << item1.getDescription() << endl;
   cout << "Cost: $" << item1.getCost() << endl;
   cout << "Units on Hand: " << item1.getUnits() << endl << endl;

   // Display the data for item 2.
   cout << "Description: " << item2.getDescription() << endl;
   cout << "Cost: $" << item2.getCost() << endl;
   cout << "Units on Hand: " << item2.getUnits() << endl << endl;

   // Display the data for item 3.
   cout << "Description: " << item3.getDescription() << endl;
   cout << "Cost: $" << item3.getCost() << endl;
   cout << "Units on Hand: " << item3.getUnits() << endl;
   return 0;
}

Also, I have to change all the strcpy() to strncpy_s() in InventoryItem.h as VS won't compile.
C++:
// This class has overloaded constructors.
#ifndef INVENTORYITEM_H
#define INVENTORYITEM_H
#include <cstring>   // Needed for strlen and strcpy

// Constant for the description's default size
const int DEFAULT_SIZE = 51;

class InventoryItem
{
private:
   char *description;  // The item description
   double cost;        // The item cost
   int units;          // Number of units on hand
public:
   // Constructor #1
   InventoryItem()
      { // Allocate the default amount of memory for description.
        description = new char [DEFAULT_SIZE];
       
        // Store a null terminator in the first character.
        *description = '\0';
       
        // Initialize cost and units.
        cost = 0.0;
        units = 0; }

   // Constructor #2
   InventoryItem(char *desc)
      { // Allocate just enough memory for the description.
        description = new char [strlen(desc) + 1];
       
        // Copy the description to the allocated memory.
        strncpy_s(description, strlen(desc) + 1,desc, strlen(desc) + 1);
       
        // Initialize cost and units.
        cost = 0.0;
        units = 0; }
       
   // Constructor #3
   InventoryItem(char *desc, double c, int u)
      { // Allocate just enough memory for the description.
        description = new char [strlen(desc) + 1];
       
        // Copy the description to the allocated memory.
        strncpy_s(description, strlen(desc) + 1, desc, strlen(desc) + 1);
       
        // Assign values to cost and units.
        cost = c;
        units = u; }
       
   // Destructor
   ~InventoryItem()
      { delete [] description; }

   // Mutator functions
   void setDescription(char *d)
      { strncpy_s(description, 10, d, 10);}
   void setCost(double c)
      { cost = c; }
     
   void setUnits(int u)
      { units = u; }

   // Accessor functions
   const char *getDescription() const
      { return description; }
        
   double getCost() const
      { return cost; }

   int getUnits() const
      { return units; }
};
#endif

EDIT:
I put these two files in the problem project, to my surprise, it works.


Thanks for your time to help me.

Alan
 
Last edited:
  • #82
Vanadium 50 said:
I was answering jarvis.

As far as not having the CD, maybe you should get it.
But you were calling me out in a sarcastic way. I use the CD from the complete edition of the same book and it has the codes like I just posted to Jarvis. I did have to fix the code to make it work. Now I am going to copy this code into the problem project to see.
 
  • #83
yungman said:
But you were calling me out in a sarcastic way. I use the CD from the complete edition of the same book and it has the codes like I just posted to Jarvis. I did have to fix the code to make it work. Now I am going to copy this code into the problem project to see.
You made one mistakes copying the code from the book. On line 13, item1.getDescription("Hammer"); should be item1.setDescription("Hammer");

The book is probably a little outdated, because passing a string literal as a char * is now depreciated (it was legal, but now it's not). You have to use const char *, as the parameter type now for it to work.
 
  • Like
Likes yungman
  • #84
Jarvis323 said:
You made one mistakes copying the code from the book. On line 13, item1.getDescription("Hammer"); should be item1.setDescription("Hammer");

The book is probably a little outdated, because passing a string literal as a char * is now depreciated (it was legal, but now it's not). You have to use const char *, as the parameter type now for it to work.
Ha! The book is wrong, I did not type this from reading the book, I actually copied the code from the CD and ran. I did not even see they were get instead of set!

But still in line21 and line 26 is the same way. You cannot using set("Hammer"...), it has to be from a c-string.

That's something, the code from CD is wrong.

You have SHARP eyes!

Thanks
 
  • #85
yungman said:
Ha! The book is wrong, I did not type this from reading the book, I actually copied the code from the CD and ran. I did not even see they were get instead of set!

But still in line21 and line 26 is the same way. You cannot using set("Hammer"...), it has to be from a c-string.

That's something, the code from CD is wrong.

You have SHARP eyes!

Thanks
It probably wasn't wrong when it was made. It's outdated.
 
  • Like
Likes yungman
  • #86
Anyway, for whatever reason, The problem project now doesn't fail anymore. I even went back to post 67 and copy the two files and put them into the problem project, it works now.

I guess this just chuck it into the X-File. I definitely did NOT change any setting. At this point, I know better after working a few days on VS. It was failing for over a day until I copied the original two files from the book's CD in. Somehow it's not failing anymore.

I am sure there are a lot of thing you can criticize in my codes, but that's really not the point. Something did happen.

Thanks for all your time.
 
  • #87
I just step through the program in post #81 one step at a time. I put breakpoint on each and every single line of code. I use F5 to step through one line at a time and LABEL what steps of the line from 0 to 44.

I want to see how the overload Constructor works. How does the main() step through the functions in the Class .h file. It really gives me an insight to how the whole program works. It is a lot clearer how the Constructors work particularly with over load.

I did not know that even though the pointer description is the same name for all 3 Constructors to allocate dynamic memory, EACH has it's separate address so I actually have 3 segments of memory each for one Constructor! This really answer a lot of my questions.

Just want to thank you guys for all the help. I really feel I am learning.

Alan
 
  • #88
yungman said:
I just step through the program in post #81 one step at a time. I put breakpoint on each and every single line of code. I use F5 to step through one line at a time and LABEL what steps of the line from 0 to 44.
F5 is used to Continue executing the program. If you didn't have breakpoints, pressing F5 would cause all program lines to execute, either to the end or to some line asking for input.
What I do is to put one breakpoint somewhere near the beginning of the code in main(), hit F5, and then use F10 to single step a line of code at a time.
I use F10 (Step Over) and F11 (Step Into) a lot.
Step Into (F11) takes you into the body of a function so you can see exactly what constructors and other functions are doing.
Step Over (F10) just executes that line of code without taking you into the function body.
yungman said:
I want to see how the overload Constructor works. How does the main() step through the functions in the Class .h file. It really gives me an insight to how the whole program works. It is a lot clearer how the Constructors work particularly with over load.
Here's a better way to use VS.
Put a breakpoint in main() at this line:
InventoryItem item1;
Press F5 - the line above will be ready to execute.
Press F11 to take you into the body of your default constructor.
Press F10 to skip over the function call, and take you to the next line in main().

yungman said:
I did not know that even though the pointer description is the same name for all 3 Constructors to allocate dynamic memory, EACH has it's separate address so I actually have 3 segments of memory each for one Constructor!
It's not clear what you're saying here about three segments of memory. Memory segments are usually divided into stack, heap, and static memory. Each InventoryItem object that you create has its own chunk of memory on the heap, that will contain the item description. You have three overloaded constructors: a default constructor with no parameters, a constructor with just a description parameter, and a constructor with all three parameters.

Every InventoryItem object that you create will have three data members -- description, cost, and units. The difference is which constructor you use and whether the data members are filled in by a constructor or not.
 
  • Like
Likes yungman
  • #89
Hi Mark

Really miss you yesterday on the strange thing with VS I encounted, it's too late now, I cannot make it fail anymore. I really looked into it, looking at Solution Explorer, Project Properties, all the options. Using all the knowledge I learned in the pass few days from you and others to look and still cannot find what was the difference in the setting.

Thanks for the suggestion on F11, I have to copy your response and print it out to read it slowly. I read F11, it said "step into" and show the dot. To me it's like step to the next break point. I did NOT know F11 is stepping one line at a time. So I did it the dumb way...dotted every single line! So I hit F5, I step through every line.

I am really having a ball with the debugger. Yes, 3 constructor creating 3 separate chunk of memories using the same overload pointer description.I want to ask you and the other experts. Do people use overload Constructors like in my example from the book in real world? It is interesting to learn...BUT in real life where programs are a lot bigger and much more complicate. Is it even a good practice to use overload Constructors where you pretty much have to be forced to use overload variables like description, units, cost in the program in post #67? That all have the same name and you have to keep tract of them at all times.

I know you have no choice in using overload Constructors in some cases, BUT I know you can use Overload inside the program also. Do you really want to do that in the program? Seems like it's easier to just use different names. Like if I can help it, I would use description1, description2, description3, cost1, cost2, cost3 etc. As much as possible instead going into overload just because I can do it. One thing I learn from experience, it's nice to have clever circuit/code, more elegant and fancier. But in real life working environment, just make it simple, straight forward whenever possible. It doesn't pay to be fancy. People don't care how you do it, they just care you get the job done consistently and reliably. the fancier it is, the more likely to make mistake. To me, that's the golden rule.

Thanks
 
Last edited:
  • #90
yungman said:
I did NOT know F11 is stepping one line at a time. So I did it the dumb way...dotted every single line! So I hit F5, I step through every line.
F11 will step into the function one step. F10 will step over the function call and go to the line right after the call to the function. If you know that a function is working correctly it makes more sense to step over (F10) the function call, but if you're debugging the function you want to step into it (F11).
yungman said:
BUT in real life where programs are a lot bigger and much more complicate. Is it even a good practice to use overload Constructors where you pretty much have to be forced to use overload variables like description, units, cost in the program in post #67? That all have the same name and you have to keep tract of them at all times.
Yes, it's good practice to have multiple constructors, and you haven't even come to a couple more -- copy constructor and move constructor.
Regarding overload variables, there's no such thing. One thing that would help you with your question is to use a certain style for the class members, and a different style for the constructor parameters. A common style for class member names is m_name. The 'm' at the beginning is a clue that this is a class member name.
Here are your revised class definition and two of your constructors, modified to use this style.
C++:
class InventoryItem
{
private:
    char *m_description;  // The item description
    double m_cost;        // The item cost
    int m_units;          // Number of units on hand
public:
.
.
.
C++:
// Constructor #2
    InventoryItem(char *description)
    { // Allocate just enough memory for the description.
        m_description = new char[strlen(description) + 1];

        // Copy the description to the allocated memory.
        strncpy_s(m_description, strlen(description) + 1, description, strlen(description) + 1);

        // Initialize cost and units.
        m_cost = 0.0;
        m_units = 0;
    }
C++:
// Constructor #3
    InventoryItem(char *description, double cost, int units)
    { // Allocate just enough memory for the description.
        m_description = new char[strlen(description) + 1];

        // Copy the description to the allocated memory.
        strncpy_s(m_description, strlen(description) + 1, description, strlen(description) + 1);

        // Assign values to cost and units.
        m_cost = cost;
        m_units = units;
    }
Now the parameters to these two constructors have the same names, so you don't have to come up with a bunch of different parameter names for each constructor, and the class data member names are distinct from the constructor parameter names.
yungman said:
I know you have no choice in using overload Constructors in some cases, BUT I know you can use Overload inside the program also. Do you really want to do that in the program? Seems like it's easier to just use different names. Like if I can help it, I would use description1, description2, description3, cost1, cost2, cost3 etc. As much as possible instead going into overload just because I can do it. One thing I learn from experience, it's nice to have clever circuit/code, more elegant and fancier. But in real life working environment, just make it simple, straight forward whenever possible.
This is a bad idea to use all those variants with numbers at the end. In the examples I show above, if two constructors do something with the same class data member, the parameter names can be, and should be, the same.

One thing that you should realize is that there is a hierarchy of programmers, especially in large programs, in which a team of programmers is involved. One level of programmer in the hierarchy designs and implements classes, and another level writes applications that use those classes. A class designer creates overloaded constructors and member functions as a convenience to application programmers. That way, an application programmer can create a class instance, initializing it with zero, one, or more parameters, depending on what his or her needs. In what you're doing, you're implementing the class, and writing code that uses the class, which is not at all the way things work in the software industry.
 
  • Like
Likes yungman

Similar threads

  • · Replies 22 ·
Replies
22
Views
3K
  • · Replies 13 ·
Replies
13
Views
3K
  • · Replies 8 ·
Replies
8
Views
4K
  • · Replies 8 ·
Replies
8
Views
2K
Replies
89
Views
6K
  • · Replies 15 ·
Replies
15
Views
4K
  • · Replies 1 ·
Replies
1
Views
1K
Replies
5
Views
2K
  • · Replies 4 ·
Replies
4
Views
6K
Replies
12
Views
3K