1

I'm working on a project for school, and we just found out that outtextxy() (a function from graphics.h, which we must use) requires as the text parameter a char array. Here is its declaration: void outtextxy (int x, int y, char *textstring)

The issue is that we need to print out a number of type double, including the decimal point. I have previously tried making it work using knowledge from other similar questions, but none has worked.

Here are is my latest attempt, which resulted in a Segmentation Fault:

char *DoubleToString(long double x)
{
    char s[256]="\000";

    std::ostringstream strs;
    strs << x;
    string ss = strs.str();

    for(int i=0; i < ss.length(); i++)
        s[i] = ss[i];
    return s;
}

NOTE: I am still somewhat new to programming and I don't exactly know what ostringstream and the bitshift-looking operation are doing, but I tried to copy-paste that part in hopes of it working.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • `return s;` You are returning the address of a local variable. Undefined behavior. Why not simply return `std::string`? – PaulMcKenzie Dec 23 '20 at 20:29
  • To add onto what @Paul's saying, you'd then take that string you get back (call it `str`), and call `outtextxy(x, y, str.c_str())` – scohe001 Dec 23 '20 at 20:31
  • *I don't exactly know what ostringstream and the bitshift-looking operation are doing,* -- That is not doing a bitshift. That operator does the same thing as `std::cout << "Hello World"`. It "writes" the data to a stream, it is just that the stream is a string buffer instead of the console. – PaulMcKenzie Dec 23 '20 at 20:33
  • 1
    You want to convert a double to its c-string representation, is that correct? The value `double(10.125)` should end up as the character array `{'1', '0', '.', '1', '2', '5', '\0'}`, correct? – JohnFilleau Dec 23 '20 at 20:37
  • @PaulMcKenzie @scohe001 I tried this right now and it resulted in ```error: invalid conversion from 'const char*' to 'char*' [-fpermissive]|``` – Andrei Loghin Dec 23 '20 at 20:41
  • @JohnFilleau yes, that's exactly what I want to do – Andrei Loghin Dec 23 '20 at 20:42
  • @Andrei `const` in C++ is a promise that a variable won't be modified. Since the function you need to use has a `char *`, not a `const char*`, that means the function is totally allowed to change the underlying data. Your compiler is rightfully not allowing you to use `c_str()` because that returns a pointer to the underlying string data that may not be changed - a `const char*`. Using `str.data()` points to the same exact data, but it removes the `const` qualifier. Note that this all happens in "compile" time. `const` doesn't exist in runtime. – JohnFilleau Dec 23 '20 at 20:44
  • 1
    `outtextxy(x,y,(char*)to_string(your_double).c_str());` I think you can use like that – qqq Dec 23 '20 at 20:57
  • @JohnFilleau I am using C++98 (which I am using and I am required to use). I also tried what you asked, but it still doesn't want to convert from ```const char*``` to ```char*``` and the program will **not** build – Andrei Loghin Dec 23 '20 at 21:09
  • @AndreiLoghin did the professor specifically say you have to use the compiler in c++98 mode , instead of using c++11 or c++14 mode (which it does support) ? If so then you should add that information into the question – M.M Dec 23 '20 at 21:10
  • @M.M No, he didn't mention anything about that. I was not even aware I could use the compiler in c++11 or c++14. Could you tell me how to do that? – Andrei Loghin Dec 23 '20 at 21:13
  • @AndreiLoghin If you are using code::blocks, in the compiler config it has some checkboxes where you can choose c++11 and other options – M.M Dec 23 '20 at 21:15
  • @M.M Okay, it only allowed me to select C++98 or C++11. So I selected C++11 but I still get the same error. – Andrei Loghin Dec 23 '20 at 21:24
  • @AndreiLoghin none of the discussion here is changed by c++11 vs c++98 anyway – M.M Dec 23 '20 at 21:29
  • 1
    @AndreiLoghin, *Do not under any circumstance return a pointer to a local variable!!* Nasal demons will happen, your cows will only give spoiled milk etc!! After you return from the function, the variable doesn't exist any more, and the memory may be used for other purposes. If it seems to work it is only by bad luck. It would have been better if the program crashed immediately so you didn't have a ticking bomb. You should return a `std::string` and call `outtextxy` with casting as @qqq showed in the comment above. – HAL9000 Dec 24 '20 at 03:17
  • My mistake. `string::data` doesn't return a non-const pointer until C++17. `&str[0]` is a non-const `char *`, as is `&str.front()`. – JohnFilleau Dec 24 '20 at 14:25

2 Answers2

2

... requires as the text parameter a char array.

Ok, then use a std::string:

std::string DoubleToString(long double x)
{
    std::ostringstream strs;
    strs << x;
    return strs.str();
}

If you need the underlying character array use the strings data() method. It does return a pointer to the first element of the strings character array. For example:

std::string s = DoubleToString(3.141);
function_that_needs_pointer_to_char( s.data() );

Note that before C++17 data returned a const char* (and since C++11 the character array is null-terminated, as one would expect ;).

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • I don't need to use the characters, I only need to display them with ```outtextxy()```. The issue with your approach is that it gives me this error: ```invalid conversion from 'const char*' to 'char*' [-fpermissive]|``` It is because outtextxy is declared like this inside the graphics.h library: ```void outtextxy (int x, int y, char *textstring)``` – Andrei Loghin Dec 23 '20 at 20:49
  • @AndreiLoghin which version of C++ are you using? As I mentioned, it changed with C++17 (which is the current one) – 463035818_is_not_an_ai Dec 23 '20 at 20:50
  • @largest_prime_is_463035818 C++20 is the current one – M.M Dec 23 '20 at 20:51
  • another improvement would be to get rid of `DoubleToString` and call `std::to_string` instead – M.M Dec 23 '20 at 20:51
  • @M.M thats new to me. Which compiler fully supports C++20? – 463035818_is_not_an_ai Dec 23 '20 at 20:52
  • @largest_prime_is_463035818 probably none of them (as with every standard version in the past). Compilers publish standard conformance tables these days so you can check. – M.M Dec 23 '20 at 20:53
  • @largest_prime_is_463035818 I am using version MinGW version 4.9.2 . It's also the version our professor advised us to use when working in graphics.h – Andrei Loghin Dec 23 '20 at 20:55
  • @AndreiLoghin Why do schools insist on using `graphics.h`, which uses a 30-year old graphics library that hasn't been updated in 20 years? Second, the C++ version mentioned is the C++ language version, not the version of the compiler. There is C++ 98, C++03, C++11, C++ 17, C++20. – PaulMcKenzie Dec 23 '20 at 21:00
  • @PaulMcKenzie maybe it indicates a need for development of a simple-to-use console graphics library in C++ – M.M Dec 23 '20 at 21:06
  • @PaulMcKenzie C++98 :) . CodeBlocks and MinGW came as a bundle from the professor, who asked us to use this. – Andrei Loghin Dec 23 '20 at 21:06
  • g++ 4.9.2 supports C++14 , however if you are using mingw.org (as opposed to the modern fork , mingw-w64) then library support is sorely lacking – M.M Dec 23 '20 at 21:08
  • @AndreiLoghin use the `C++98` tag when you cannot use a newer standard, quite a lot has changed since then. And definitiely you should have a talk to your professor. Getting an uptodate compiler does not cost a thing – 463035818_is_not_an_ai Dec 23 '20 at 21:15
  • @AndreiLoghin, are you using `outtextxy` from turbo-c? Turbo-c was important in the history of C, but its time has passed. Please let it die with dignity. The problem with `outtextxy` is that it takes a `char *` as parameter rather than `const char *`. Because the passed string doesn't get modified, is this one of the few cases where we *do* know better than the compiler what is going on, and we are allowed to cast the pointer. Add a `(char *)` before passing the string to `outtextxy`. The function was implemented at a time (1987) when people didn't know better. – HAL9000 Dec 23 '20 at 22:12
  • @HAL9000 hahaha, I'm using ```outtextxy``` from graphics.h and winbgim.h . I must use them as a requirement for my project. I have, however, managed to make it work. You can check the edit – Andrei Loghin Dec 23 '20 at 23:05
  • 1
    @AdreiLoghin the code in your edit has undefined behavior. You cannot return a pointer to a local variable. If this appears to work, then only by luck. Anyhow, please do not edit the question to add the solution. Thats what answers are for. You can post an answer for your own question – 463035818_is_not_an_ai Dec 24 '20 at 14:18
-1

I know it is undefined behaviour, but it works. And I only need to pass the returned char* to outtextxy(), and not manipulate it later on, since I have the double variable stored in an object.

char *DoubleToString(long double x)
{
    char s[256]="\000";

    std::ostringstream strs;
    strs << x;

    string sd = strs.str();
    strcpy(s, sd.data());

    return s;
}
  • *I know it is undefined behaviour, but it works.* -- Your code does not "work". If you compile with different options, or even change compilers, that code could fail right away. The answer is basically incorrect C++. – PaulMcKenzie Dec 24 '20 at 17:22