www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - char[] to string

reply Jonathan Sternberg <jonathansternberg gmail.com> writes:
Why doesn't this work?

import std.stdio;

string copy_string(char [] input)
{
    return input.dup;
}

int main()
{
    char [] buf = ['h', 'e', 'l', 'l', 'o'];
    writeln( copy_string(buf) );
}

I want to do something more complex. In my code, I want to have a dynamic
array that I can append stuff into and then return it as a string. In C++, a
non-const variable can be implicitly converted into a const. I know string is
an alias for const char. Is there a reason why it won't implicitly convert it?

I hesitate to use cast for this type of thing as it probably indicates I'm
doing something fundamentally wrong as I'm just starting to learn the language.
Jun 10 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-10 19:56, Jonathan Sternberg wrote:
 Why doesn't this work?
 
 import std.stdio;
 
 string copy_string(char [] input)
 {
     return input.dup;
 }
 
 int main()
 {
     char [] buf = ['h', 'e', 'l', 'l', 'o'];
     writeln( copy_string(buf) );
 }
 
 I want to do something more complex. In my code, I want to have a dynamic
 array that I can append stuff into and then return it as a string. In C++,
 a non-const variable can be implicitly converted into a const. I know
 string is an alias for const char. Is there a reason why it won't
 implicitly convert it?
 
 I hesitate to use cast for this type of thing as it probably indicates I'm
 doing something fundamentally wrong as I'm just starting to learn the
 language.

string is an alias for immutable(char)[]. The elements of a string can never be altered. dup returns a mutable copy of a string (not const, not immutable). idup returns an immutable copy. So, in this case you want idup, not dup. Even better though, would be to use std.conv.to - e.g. to!string(input). This will convert input to a string, but it has the advantage that if input is already a string, then it'll just return the string rather than making another copy like idup would. - Jonathan M Davis
Jun 10 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Even better though, would be to use std.conv.to - e.g. to!string(input). This
will 
 convert input to a string, but it has the advantage that if input is already a 
 string, then it'll just return the string rather than making another copy like 
 idup would.

I didn't know this. Isn't it very good to give this bit of intelligence to idup too? Bye, bearophile
Jun 11 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 it's generally best to use dup and idup only when you 
 definitely want to make a copy. By using them, you're explicitly stating that 
 you _want_ a copy to be made. If you just want a conversion, then to!() will 
 do the trick in what is hopefully the most efficient way possible.

Thank you for the answer. I think this comment needs to go in the online docs (if it's not already present). Bye, bearophile
Jun 11 2011
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 2011-06-10 19:56, Jonathan Sternberg wrote:
 Why doesn't this work?

 import std.stdio;

 string copy_string(char [] input)
 {
     return input.dup;
 }

 int main()
 {
     char [] buf = ['h', 'e', 'l', 'l', 'o'];
     writeln( copy_string(buf) );
 }

 I want to do something more complex. In my code, I want to have a dynamic
 array that I can append stuff into and then return it as a string. In C++,
 a non-const variable can be implicitly converted into a const. I know
 string is an alias for const char. Is there a reason why it won't
 implicitly convert it?

 I hesitate to use cast for this type of thing as it probably indicates I'm
 doing something fundamentally wrong as I'm just starting to learn the
 language.

Hi, You can append to a string. You only need char[] if you have to modify individual characters. // idup fixes your specific problem string copy_string(char [] input) { return input.idup; } string build_string(string str1, string str2){ string result; result~=str1; foreach(i;0..3) result~=str2; return result; } unittest{ assert(build_string("hi","lo") == "hilololo"); } If you really need char[] and you know that there is only one mutable reference to your data, then you can use std.exception.assumeUnique. (No idea why it is *there* though) import std.exception; string toUpper(char[] str){ char[] result = str.dup; foreach(ref x;result) if('a'<=x && x<='z') x+='A'-'a'; return result.assumeUnique(); // this is only safe if there really is only one reference to your data } Timon
Jun 11 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-11 05:12, bearophile wrote:
 Jonathan M Davis:
 Even better though, would be to use std.conv.to - e.g. to!string(input).
 This will convert input to a string, but it has the advantage that if
 input is already a string, then it'll just return the string rather than
 making another copy like idup would.

I didn't know this. Isn't it very good to give this bit of intelligence to idup too?

Except that if you actually need it to create a copy for some reason, then it's a lot harder. However, to!() goes far beyond just improving idup anyway, because to!() should always be avoiding doing conversions if they're not actually necessary. So, if you trying to convert to char[] or const(wchar)[] or whatever, if no conversion is actually necessary, then the original argument will be returned. It doesn't matter what the original argument was. dup and idup only cover the case where you're trying to explicitly copy an array, whereas to!() covers any time that you're trying to convert to one to another type. So, it's generally best to use dup and idup only when you definitely want to make a copy. By using them, you're explicitly stating that you _want_ a copy to be made. If you just want a conversion, then to!() will do the trick in what is hopefully the most efficient way possible. - Jonathan M Davis
Jun 11 2011