0

I am new to C++ and am trying to make a function that takes an array of numbers and converts those numbers into the ASCII character, i.e. int to string. When I try to output the string however I get random characters. I have searched tutorials and a suggestion was that I should add a string terminator, which I did, but it doesn't seem to fix it and I can't find an answer that would solve this.

i.e. I want the below code to print "Hello".

#include <iostream>
#include <string>

char* intToString(int* array, int size)
{
    char string[size + 1];
    string[size] = '\0';
    for (int i = 0; i <= size; i++)
        string[i] = array[i];

    return string;
}


int main()
{
    int my_array[5] = {72, 101, 108, 108, 111};
    int size = 5;
    std::cout << intToString(my_array, size);

    return 0;
}
Andrew Cina
  • 134
  • 10

5 Answers5

1

char * is not a string. It's a pointer to char. In your case you get random characters because you return pointer to local string which is destroyed after the call. Use std::string or, if you want arrays that much, you can get proper copy semantics from std::array.

Dan M.
  • 3,818
  • 1
  • 23
  • 41
1

Your code shouldn't even compile because size+1 isn't a compile time constant value, changing the line

char string[size+1];

to

char string*=new char[size+1]

should make your code compile and give correct output because you create your array on the heap (so the array is not destroyed when the function returns). However that means that you have to destroy delete it yourself.

So it's a good idea to change

std::cout << intToString(my_array, size);

To

char *string=intToString(my_array, size);
std::cout << string;
delete[] string;

Though note that others answers are right that you should use std::string and std::vector instead of char arrays and arrays in general, what you're doing right now is mixing c with c++.

kingW3
  • 439
  • 10
  • 20
  • Thanks, is there more information somewhere on not mixing c with c++? I don't fully understand the taboo I've broken with mixing them. – Andrew Cina Apr 26 '18 at 15:25
  • One of the primary design goals of C++ is its compatibility with C. This means that as a developer you have to decide when to use C types like plain arrays or C++ (better: STL) types like `std::vector`. For example if you are developing in C++ for certain microcontroller architectures it can even be forbidden to use any of the STL types like `std::vector` or `std::string` as there is no dynamic heap memory and/or the performance of these types does not meet the very strict requirements in these areas. Hence the choice of types and therefore style does very much depend on your environment. – Angle.Bracket Apr 26 '18 at 15:37
  • I recommend this [question](https://stackoverflow.com/questions/4025869/using-mixing-c-in-c-code) in general there's not much wrong with it but for beginners it's better to either grasp C or C++. because std::string is not the same as char[] so if you use one function with char array and second with std string you're going to have a bad time. Later on you might mix C with C++ when you get familiar enough with C++. – kingW3 Apr 26 '18 at 15:51
  • Thanks both - I looked at that question and it’s definitly useful, but, not to go off topic too much, when am I actually using c in c++? When I’m trying to write code that can be handled easier by the STL? For example, as far as any tutorial on c++ that I’ve done shows, arrays appear to be fair game. Hope that makes sense and isn’t a bad question. – Andrew Cina Apr 26 '18 at 16:52
  • @AndrewCina Arrays certainly have their uses in c++, if you want a chess board for example it's better to use an array int a[8][8] then to use a vector. I don't think you should focus that much on it really. – kingW3 Apr 26 '18 at 17:40
  • @AndrewCina When you write code in C++ without making use of the STL or polymorphism or templates then your program will most probably resemble a C program. As has been stated above there can be good reasons to do so, so you won't break any taboo. – Angle.Bracket Apr 27 '18 at 09:50
0

There is still a problem in the updated solution that you have written.

  • You should still declare the string array with size+1 and need to make the last element as \0.
  • Or you can use the std::string.

Here is C++ way of doing it, it can be further shortened, but this is as close as it can get to your code.

#include <iostream>
#include <string>
#include <vector>

std::string intToString(const std::vector<int>& vec)
{
    std::string ans;
    for (auto& each : vec)
        ans += char(each);
    return ans;
}


int main()
{
    std::vector<int> vec{72, 101, 108, 108, 111};
    std::cout << intToString(vec);
    return 0;
}
harmands
  • 1,082
  • 9
  • 24
  • Some new language for me to explore there - thank you. So I understand correctly that my code (not shortened) would be corrected by just declaring the string with std::string instead of char? Is there a reason for this? – Andrew Cina Apr 26 '18 at 13:37
  • Its not enough to just declare `string` of type `std::string`. See my answer. – Angle.Bracket Apr 26 '18 at 14:07
  • As I have mentioned, you can use `char[size+1]`, but it's working by chance in your case. – harmands Apr 26 '18 at 14:08
0

As close as possible to your initial attempt:

#include <iostream>
#include <string>
std::string intToString(int my_array[], int size)
{
    // just declare a variable of type std::string instead of char string[size+1]
    // there's no need to define a size as this std::string will grow dynamically
    // there's also no need to add a delimiter as std::string takes 
    // care of this itself
    std::string string;
    for (int i = 0; i < size; i++) {
        // this appends an integer representing an (ASCII) codepoint 
        // to an initially empty std::string
        string += my_array[i];
        // this won't work as string is initially empty
        // so you can't access the element at index 0 
        // string[i] = my_array[i];
    }
    return string;
}
int main()
{
    const int size = 5;
    int my_array[] = { 72, 101, 108, 108, 111 };
    std::cout << intToString(my_array, size) << std::endl;
    return 0;
}

Notice the differences to your solution pointed out in the comments.

Angle.Bracket
  • 1,438
  • 13
  • 29
  • 3
    While it's technically true that the buffer managed by a `std::string` is going to be terminated by a `'\0'` (because this is the only decent way to implement it given the requirements of `op[]`), instead of saying "[string] takes care of [the delimiter] itself" it's more logically correct to say "string doesn't have a delimiter because it tracks content length separately". – Lightness Races in Orbit Apr 26 '18 at 14:26
0

In C++11 std::to_string is preferable. If you need your converter function for more than one type and/or datacontainer you can use a template function like this

#include <iostream>
#include <string>
#include <vector>
#include <array>

template <typename T>
std::string toString(const T & items) {
    std::string str;
    for (const auto & item : items) {
        str += std::to_string(item);
    }

    return str;
}


int main() {
    const std::vector<int> my_vector {102, 101, 108, 108, 111};
    std::cout << toString(my_vector);


    std::cout << std::endl;

    const std::array<double,5> my_array {102, 101, 108, 108.5, 111.0};
    std::cout << toString(my_array);
    return 0;
}
schorsch312
  • 5,553
  • 5
  • 28
  • 57
  • The question's author specified that he want to convert ints to corresponding ascii chars not their string representation. – Dan M. Apr 26 '18 at 16:29