Using a custom constructor in a C++ class

  • Context: Comp Sci 
  • Thread starter Thread starter diredragon
  • Start date Start date
  • Tags Tags
    c++ class programming
Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
7 replies · 3K views
diredragon
Messages
321
Reaction score
15

Homework Statement


I am quite new to C++. I have completed my C course and am now taking a C++ course at my college. The first problem i encountered is with classes and custom made constructors. In the first part of the problem I am supposed to create a class with a field which is a dynamic char array for storing numbers like decimal ones. I am also forbidden to use anything but <iostream>. Here is the problem:
Create a class called Number which stores numbers in a dynamic array (number can be a decimal number) in a way that one digit is one array place. Number of digits is not limited. Implement the constructors Numbers::Numbers(char* nms); and Number::Number(int* part1, int* part2);, where part1 is left of the . and part2 right of the .

Homework Equations


3. The Attempt at a Solution [/B]
Code:
#include <iostream>

using namespace std;

class Number {
    char* numarr;

public:
    Number(char* nms) {
        numarr = nms; //Can i do this or do i need to know the length of nms and then allocate numarr?
    }
    Number(int* part1, int* part2) {
        //This is the hard part for me. How do i insert integers into an array digit by digit? Do i convert them to strings?
    }
};
Also and most important, what is with this dynamic memory? I can't realloc like in C? How do i deal with unknown sizes of dynamic arrays then?
 
on Phys.org
diredragon said:
do i need to know the length of nms and then allocate numarr?
Yes, you should do that.
diredragon said:
Also and most important, what is with this dynamic memory? I can't realloc like in C? How do i deal with unknown sizes of dynamic arrays then?
The first constructor is given a char* "string" as its argument, so it should be able to find the length of that "string" (the number of digits) using a suitable standard library function.

The second constructor is given two ints, so it should be able to find the number of digits in each, and therefore the length of the combined decimal number, by doing some calculations.

In general, if you want to change the length of a dynamic array allocated with 'new', you have to use 'new' to allocate a new array of the desired length, copy data as necessary from the old array to the new one, use 'delete' to dispose of the old array, and then adjust your class's member data (pointer) to point to the new array.

Using the standard C++ 'string' data type would make such gymnastics much easier (no pointers or explicit memory allocation/deallocation). Are you allowed to use that?
 
jtbell said:
Yes, you should do that.

The first constructor is given a char* "string" as its argument, so it should be able to find the length of that "string" (the number of digits) using a suitable standard library function.

The second constructor is given two ints, so it should be able to find the number of digits in each, and therefore the length of the combined decimal number, by doing some calculations.

In general, if you want to change the length of a dynamic array allocated with 'new', you have to use 'new' to allocate a new array of the desired length, copy data as necessary from the old array to the new one, use 'delete' to dispose of the old array, and then adjust your class's member data (pointer) to point to the new array.

Using the standard C++ 'string' data type would make such gymnastics much easier (no pointers or explicit memory allocation/deallocation). Are you allowed to use that?
No, sadly we cannot use anything other than <iostream>. Here is what i found:
Code:
#include <iostream>

using namespace std;

class Number {
    char* numarr;

public:
    Number(char* nms) {
        int i = nms.size();
        numarr = new char[i];
       
        numarr = nms; //Is this ok now?
    }
   
    Number(int* part1, int* part2) {
        int length = 1;
    while ( part1 /= 10 )
    length++;
    while ( part2 /= 10 )
    length++
    numarr = new char[length+1] //allocating one more space for a dot
    //But now i need to extract the digits and add them right?
    }

};
 
diredragon said:
nms.size();
size() is for std::vector and std::string, not for arrays or pointers to arrays. There's a different library function for the length of null-terminated C-strings (char arrays). IIRC the appropriate header file is <cstring>, or string.h if your instructor prefers that. It's been a long time since I've used it, because I've always preferred std::string from <string>.

I suggest that for debugging purposes you put a count statement in each constructor that displays a message to tell you the contents of numarr (or rather, what it points to). Something like "Constructed 12345!". Or write a Number::Display() member function that displays the contents of a Number. I bet you have to do something like that anyway as part of the exercise. But there's less to go wrong if you simply stick a count in the constructor for debugging.

diredragon said:
But now i need to extract the digits and add them right?

Right. :cool:
 
Last edited:
jtbell said:
size() is for std::vector and std::string, not for arrays or pointers to arrays. There's a different library function for the length of null-terminated C-strings (char arrays). IIRC the appropriate header file is <cstring>, or string.h if your instructor prefers that. It's been a long time since I've used it, because I've always preferred std::string from <string>.
Code:
#include <iostream> //Only library I can use.

using namespace std;

class Number {
    char* numarr;

public:
    Number(char* nms) {
        int i = 0;
        while (nms[i] != '\0') i++;
      
        numarr = new char[i];
    
        numarr = nms;
    }

    Number(int* part1, int* part2) {
        int length = 1;
    while ( part1 /= 10 )
    length++;
    while ( part2 /= 10 )
    length++
    numarr = new char[length+1] //allocating one more space for a dot
    //But now i need to extract the digits and add them right?
    }

};
How about now? I couldn't find a library function so i calculated myself. Is it ok? Also is the thinking for the second part good?
 
I think you've got the right idea, except maybe for "off-by-one" counting errors. Remember, you can always put in count statements for debugging, to show you exactly what's really happening. Ah wait, I see something:

diredragon said:
numarr = nms;

This copies the pointer, not the data that it points to. You want a new Number object to have a separate copy of the digits (chars) from the one in the calling function (that was passed in as the argument to the constructor).
 
jtbell said:
I think you've got the right idea, except maybe for "off-by-one" counting errors. Remember, you can always put in count statements for debugging, to show you exactly what's really happening. Ah wait, I see something:
This copies the pointer, not the data that it points to. You want a new Number object to have a separate copy of the digits (chars) from the one in the calling function (that was passed in as the argument to the constructor).
Aha, so something like this?
Code:
Number(char* nms) {
        int i = 0, k =0;
        while (nms[i++] != '\0');
      
        numarr = new char[i];
      
        while (k != i+1) numarr[k] = nms[k++];
    }
 
Something like that, yeah, but test it to make sure that k stays in sync for both numarr and nms. Make sure k gets incremented when you think it does. I personally prefer to keep the incrementing step separate. I've never been one of those people who try to cram as many operations as possible into a single statement. :oldwink:
 
  • Like
Likes   Reactions: diredragon