在D语言中将临时字符数组转换为字符串

9

我正在学习D语言(我对C++很熟悉)... 我想做一些Windows特定的东西,所以我写了这个程序来尝试API:

import core.sys.windows.windows;
import std.stdio;

string name()
{
    char buffer[100];
    uint size = 100;

    GetComputerNameA(&buffer[0], &size);

    return buffer;
}

void main()
{
    writeln(name());
}

我在返回语句中获得的内容:

test.d(11): Error: cannot implicitly convert expression (buffer) of type char[100] to string

好的,在C++中,它将调用构造函数来创建一个字符串。因为它是隐式的,所以让我们使用C语言风格的转换方式:return (string)buffer;

test.d(11): Error: C style cast illegal, use cast(string)buffer

啊,好的,我记得了,语法不同。
return cast(string)buffer;

现在代码编译通过,但输出的结果却是一些垃圾字符。我猜测这是因为代码将一个指针存储到了字符串中的临时缓冲区。我不想这样做,我想将字符复制到一个字符串中,但令人烦恼的是我似乎找不到如何实现这一点的方法?
所以我的问题是:
  1. 如何从字符数组构建一个真正意义上的字符串,能够正确分配存储空间并复制字符?
  2. 像这样随意分配缓冲区大小并转换为字符串似乎很丑陋,D语言中是否有更好的方法呢?(我说的是一般性的问题,不仅限于这个API,只是为了防止还有其他获取计算机名称的API)
  3. 如果这些问题的答案已经在手册中提供了,请问我应该在哪里查找相关细节?
感谢您的帮助和建议。

你能否尝试在转换之前检查buffer的实际值,因为转换不应该失败。 - Bauss
转换是有效的……如果我在函数中打印它……如果我返回字符串,它会失败,可能是因为它仍然指向临时缓冲区。 - jcoder
1
@Bauss,不应该。实际上2.068会中止编译并显示错误信息:Error: escaping reference to local variable buffer - sigod
@sigod 原始代码在我的Windows系统上使用2.068编译器没有任何错误或警告。 - jcoder
此外,D语言中数组的语法为:type[...] name - sigod
显示剩余2条评论
2个回答

8
我认为您需要:

我认为您需要:

string name()
{
   char buffer[100];
   uint size = 100;

   GetComputerNameA(buffer.ptr, &size);

   return buffer[0 .. size].idup;
}

1
但它仍然忽略了ERROR_BUFFER_OVERFLOW和GetLastError。正确的代码应该检查size是否小于缓冲区长度,并在需要时分配新的更大缓冲区。 - sibnick
当然可以,我的原始示例只是我能写出来以演示问题的最短示例。它并不意味着完整。 - jcoder

6
buffer.idup是获取不可变副本的标准方法。对于这种情况,由于您想要一个动态大小的string(请记住,string实际上只是immutable(char)[]的简写),您需要使用D语言的数组切片,即buffer[0..size].idup
有关更多信息,请参见http://dlang.org/arrays.html
(这有点吹毛求疵,但是出于可读性考虑,您可能希望使用buffer.ptr而不是&buffer[0]。)

非常好,谢谢。可以了。好的,现在信息很清楚了。当你刚接触一门语言时,很难知道文档中要查找什么。感谢您的指正!当我刚开始学习D语言时,这正是我需要的建议类型 :) - jcoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接