1

Had this program in C and was trying to convert some to C++ as I learn the language. Basically char arrays to strings and some of the input/output. Only issue is I get a segfault when attempting to put the input string into the string array (test2 prints. test3 does not).

Any ideas? Any bad coding habits I should be aware of as I learn c++?

int main() {
int nstr=0, nchar=0, nint=0, nfloat=0;
string input;
int i, z=0;
float inputFloat;

string *strList = (string*)malloc(sizeof(string) * nstr);
char *charList = (char*)malloc(sizeof(char) * nchar);
int *intList = (int*)malloc(sizeof(int) * nint);
float *floatList = (float*)malloc(sizeof(float) * nfloat);

while (z != -42) {
    cout << "Input:  ";
    cin >> input;
    cin.ignore();

    inputFloat = strtof(input.c_str(), NULL);

    if (inputFloat) {
        if (fmod(inputFloat, 1.0)) {
            nfloat++;
            floatList = (float*)realloc(floatList, sizeof(float) * nfloat);
            floatList[nfloat-1] = inputFloat;
        }
        else {
            nint++;
            intList = (int*)realloc(intList, sizeof(int) * nint);
            intList[nint-1] = (int)inputFloat;
        }
    }
    else {
        if (input.length() == 1) {
            nchar++;
            charList = (char*)realloc(charList, sizeof(char) * nchar);
            if (input.at(0) == 10)
                input = " ";
            charList[nchar-1] = input.at(0);
        }
        else {
            nstr++;
            cout << "test1" << endl;
            strList = (string*)realloc(strList, sizeof(string) * nstr);
            cout << "test2" << endl;
            strList[nstr-1] = input;
            cout << "test3" << endl;
        }
    }

    cout << "Integers: ";
    for (i=0; i<nint; i++)
        cout << intList[i] << " ";

    cout << endl << "  Floats: ";
    for (i=0; i<nfloat; i++)
        cout << floatList[i] << " ";

    cout << endl << "   Chars: ";
    for (i=0; i<nchar; i++)
        cout << charList[i] << " ";

    cout << endl << " Strings: ";
    for (i=0; i<nstr; i++)
        cout << strList[i] << " ";
    cout << endl << endl;
}
}
1
  • Don't use malloc in c++, it won't call the constructor for string. if you have to use new for dynamic allocation, but even better to use vector<string> strList instead of string* strList array. Commented Feb 15, 2015 at 3:03

2 Answers 2

3

As a rule you don't use malloc,calloc,realloc etc. in c++ at all, even though you can. It less meaningful for simple items like: int, char etc. but when using on objects (like std::string) it cause this kind of problems:

When this line runs:

string *strList = (string*)malloc(sizeof(string) * nstr);

You allocate storage to array of strings, but you didn't called any constructor, therefor all the storage you've allocated is still useless.

In c++ you must use new like this:

string *strList = new string[nstr];

it is shorter, easier and call the constructor of each allocated object.

In the end you dealocate it with delete [] like this:

delete [] strList;

Even better is to use:

vector<string> strList;

and add elements by using:

strList.push_back("something"); or strList.push_back(some_string);

vectors are take care for the memory allocation and free, and are freed automatically as regular object at end of life, so it won't needed to be deleted at all.

Sign up to request clarification or add additional context in comments.

5 Comments

string *strList = new string[nstr]; it is shorter , maybe, but you can't increase the size of such an array easily. This code was based on dynamic arrays, done by someone willing to learn about arrays.
Of course, vectors and other classes from STL would do it. This is clearly a learning exercise ".... some to C++ as I learn the language. Basically char arrays to strings " . how to learn arrays without arrays ? I find the approach of an increased array of character, integer, float interesting, together with the clear understanding on the size that would be used into memory, unfortunately, it failed on strings objects. ... with 4 lines of code, just show that the approach was close, very close to correctness ... Not rewrite everything using vectors. That would be a bad learning lesson.
Worked using vectors. I did vector<string> strList and then just used strList.push_back(input), and replaced the for loops for displaying with strList.size().
You should also use vector<int>, vector<char> and vector<float>
Yea I did that shortly after.
-2

realloc reassigns a larger array than the previous one. The new element at the end of the array, you fill it as a integer, float, char , which are basic C types. For C++ objects like strings, the last element in your array is not a new string, one of the possibilities is to create arrays of string pointers.

at the start of your code

string **strList = (string**)malloc(sizeof(string *) * nstr);

and by the end of your code, allocate a new string object at the end of the array.

nstr++;
strList = (string**)realloc(strList, sizeof(string *) * nstr);
strList[nstr-1] = new string(input);

at the end of the program you must delete everything you created through new operator and thru malloc/realloc.

while (nstr--)
{
   delete strList[nstr];
}
free(strList);

4 Comments

"string myString" is a single string. "string *stringList" is an array of strings. "string ** stringList" is an array of pointers to string. You need it because you are dynamically changing the size of the array using realloc, which does not, create and initialize a new string at the end of the array. malloc(), realloc() and free() are C functions who do not manipulate C++ objects like strings.
This is why other answers discourage you to continue that way, even if it works. You would not need "**" apparent complexity if you allocated a c++ array using new[] operator stringList = new string[MAX_COUNT]. You would not need it if you were using a vector class as suggested in the other posts.
You could construct the malloced item by using: new(&listStr[nstr]) string; and destruct by calling the destructor directly like this: listStr[n].~string(); therefore you really don't need to use string** for single dimension array.
@SHR There are hundreds different ways. As you suggest, call the ctor abd dtor explicitly, We can construct malloc with sbrk().. we can also use this ** pattern and use *** and then ****, as an exercise for self-inflicted torture. I suggested a 4 lines changes in the way the existing code was done. to show that a solution was close. And you get it with a churn of 3 lines ,,,,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.