Получить простой символ * из строки в D? - PullRequest
11 голосов
/ 18 июня 2011

У меня абсолютный ад времени, когда я пытаюсь выяснить, как получить простую, изменчивую строку C (char *) из строки D (неизменяемого (char) []), которую я могу передать символьные данные в унаследованном коде C. toStringz не работает, так как я получаю сообщение об ошибке, в котором говорится, что «я не могу неявно преобразовать выражение (toStringz (this.fileName ())) типа immutable (char) * в char *». Нужно ли заново создавать новый, изменяемый массив символов и копировать символы?

Ответы [ 5 ]

13 голосов
/ 18 июня 2011

Если вы можете изменить заголовок интерфейса D этого унаследованного кода C, и , вы уверены, что унаследованный код C не изменит строку, вы можете заставить ее принять const(char)*, например

char* strncpy(char* dest, const(char)* src, size_t count);
//                        ^^^^^^^^^^^^
9 голосов
/ 18 июня 2011

Да, это не красиво, потому что результат неизменен.

Вот почему я всегда возвращаю изменчивую копию новых массивов в моем коде. Нет смысла делать их неизменными.

Решения:

Вы могли бы просто сделать

char[] buffer = (myString ~ '\0').dup; //Concatenate a null terminator, then dup

затем используйте buffer.ptr в качестве указателя.

Однако:

тратит строку. Лучшим подходом может быть:

char[] buffer = myString.dup;
buffer ~= '\0'; //Hopefully this doesn't reallocate

и последующее использование buffer.ptr.


Другое решение заключается в использовании метода, подобного этому:

char* toStringz(in char[] s)
{
    string result;
    if (s.length > 0 && s[$ - 1] == '\0') //Is it null-terminated?
    { result = s.dup; }
    else { result = new char[s.length + 1]; result[0 .. s.length][] = s[]; }
    return result.ptr;
}

Это самый эффективный, но и самый длинный.

( Редактировать : Упс, у меня была опечатка в if; исправил.)

3 голосов
/ 20 июня 2011

Если вы хотите передать изменяемый char* в функцию C, вам нужно выделить изменяемый char[].string не сработает, потому что он неизменен (char) [].Вы не можете изменять неизменяемые переменные, поэтому нет способа передать string в функцию (C или иначе), которая должна изменить свои элементы.

Итак, если выиметь string, и вам нужно передать его функции, которая принимает char[], затем вы можете использовать to!(char[]) или dup и получить изменяемую копию этого.Кроме того, если вы хотите передать его в функцию C, вам нужно добавить к нему '\0', чтобы он заканчивался нулем.Самый простой способ сделать это - просто сделать ~= '\0' на char[], но более эффективным способом, вероятно, было бы сделать что-то вроде этого:

auto cstring = new char[](str.length + 1);
cstring[0 .. str.length] = str[];
cstring[$ - 1] = '\0';

В любом случае вы затем передаете cstring.ptr к функции C, которую вы вызываете.

Если вы знаете , что функция C, которую вы вызываете, не собирается изменять строку, то вы можете сделатькак KennyTM предлагает и изменить сигнатуру функции C в D, чтобы получить const(char)*, или вы можете привести строку.например,

auto cstring = toStringz(str);
cfunc(cast(char*)cstring.ptr);

Изменение подписи функции C было бы более правильным и менее подверженным ошибкам.

Звучит так, как будто мы изменяем std.conv.to, чтобы быть достаточно умными, чтобы превратить строки вСтроки с нулевым символом в конце при преобразовании в char*, const(char)* и т. д. Итак, как только это будет сделано, получить изменяемую строку с нулевым символом в конце должно быть проще, но на данный момент вам просто нужно скопировать строку и добавить'\0' к нему, чтобы он заканчивался нулем.Но, тем не менее, вы никогда не сможете передать string в функцию C, которая должна его изменить, потому что string не может быть мутирован.

1 голос
/ 19 июня 2011

Без какого-либо контекста, какую функцию вы вызываете, трудно сказать, какое решение является правильным.

Как правило, если функция C хочет изменить или записать строку, она, вероятно, ожидает, что вы предоставите буфер и длину. Обычно я делаю:

Выделите буфер:

auto buffer = new char[](256);  // your own length instead of 256 here

И вызвать функцию C:

CWriteString(buffer.ptr, buffer.length);
0 голосов
/ 18 июня 2011

Вы можете попробовать следующее:

char a [] = "abc";

char * p = a;

Теперь вы можете передать указатель 'p' в массив в любой функции.

Надеюсь, это сработает.

...