Форум: "Основная";
Текущий архив: 2002.09.02;
Скачать: [xml.tar.bz2];
ВнизКак привести строку или число к типу Char? Найти похожие ветки
← →
nikolo (2002-08-16 16:40) [0]Всем привет! У меня есть строка или число > 0 и < 10. Как я могу привести эту строку и число к типу Char?
Помогите, срочно надо!
← →
Skier (2002-08-16 16:43) [1]>nikolo
StringVar[Index] - это и есть Char;
А ащё есть функции StrToInt и IntToStr.
← →
Esu (2002-08-16 16:44) [2]Не очень понял суть вопроса но похоже тебе помогут функции:
IntToStr, StrToInt, Chr, Ord
← →
MBo (2002-08-16 16:45) [3]AChar:=Chr(Ord("0")+anumber)
Achar:=AString[1]
← →
nikolo (2002-08-16 16:47) [4]Поясню:
var
i: Integer;
c: Char;
s: String;
begin
i := 6;
s := IntToStr(i); - это понятно
c := ? - как сделать, чтобы в c было "6"?
end;
← →
Skier (2002-08-16 16:48) [5]>nikolo
c := s[1];
← →
nikolo (2002-08-16 16:51) [6]s я привел для примера, код в общем такой:
var
i: Integer;
C: Char;
begin
i := 6;
C := ? - как сделать, чтобы в C было "6"?
end;
← →
MBo (2002-08-16 16:53) [7]nikolo
cм. первую строку
MBo © (16.08.02 16:45)
← →
Skier (2002-08-16 16:54) [8]>nikolo
C := IntToStr(i)[1];
А вообще если это будет скажем число 12, не задумывался ?
← →
Skier (2002-08-16 16:59) [9]>nikolo
Забыл про > 0 и < 10. Мои извинения...
← →
nikolo (2002-08-16 17:19) [10]В продолжение темы. Первый раз столкнулся с PChar, ну и геморойная же вещь... Не могу понять, почему не работает функция:
Function TfmMain.FFF(StrP: PChar): PChar;
Var
Source, Dest: PChar;
cc: Char;
Begin
Source := StrP;
Dest := StrP;
while Source^ <> #0 do begin
cc := IntToStr(StrToInt(Source^)+1)[1];
Dest^ := cc; - не работает
Dest^ := Source^; - работает
Inc(Dest);
Inc(Source);
end;
Dest^ := #0;
Result := StrP;
End;
Как вообще надо работать с PChar? Мне эту функцию потом нужно положить в dll, так что без PChar не обойтись. Вообще, интересно, в функциях dll можно объяслять локальные переменные типа String или надо извращаться только с PChar?
← →
nikolo (2002-08-16 17:36) [11]Help!!!
Ответьте, почему я не могу написать следующий код:
Var
Dest: PChar;
cc: Char;
Begin
cc := "7";
Dest[3] := cc;
End;
ведь PChar - это массив символов, заканчивающийся #0...
← →
Skier (2002-08-16 17:39) [12]>nikolo
Память не пытался выделять !?
Var
Dest: PChar;
cc: Char;
Begin
Dest := AllocMem(4);
try
cc := "7";
Dest[3] := cc;
finally
FreeMem(Dest, 4);
end; //try
End;
← →
nikolo (2002-08-16 18:05) [13]Ребята, а что без выделения памяти не обойтись?
Мне нужно передать в функцию строку, состоящую только из цифр, например "928476234234", которая увеличит все символы на 1 (если 9, то в 0). Обязательно работать только с PChar? Можно ли в функции локально объявить переменную типа String и работать с ней (в dll)?
Я пробовал делать так:
function FFF(PSt: PChar): PChar;
var St: String;
begin
St := StrPas(PSt);
...
Result := PChar(St);
end;
но работает как-то странно - то нормально, а то на выходе ерунда какая-то.
В чем проблема?
← →
Skier (2002-08-16 18:08) [14]>nikolo
А зачем тебе вообще этот PChar, только
String нельзя что ли обойтись ?
← →
nikolo (2002-08-16 18:11) [15]Я же писал, что функция должна быть в dll, а там со стрингами проблемы.
← →
Skier (2002-08-16 18:13) [16]>nikolo
Это с передачей String в качестве параметра - проблемы,
а использовать String внутри функции в DLL можно на УРА.
← →
Dmitriy Polskoy (2002-08-16 18:15) [17]Попробуй так:
function FFF(PSt: PChar): PChar;
var St: String;
begin
St := StrPas(PSt);
...
St[Ord(Length(St)) + 1] := #0;
Result := @St[1];
end;
← →
Bars (2002-08-16 23:12) [18]Procedure .....
var
Str:string;
Int:integer;
Pch:Pchar;
begin
Pch:=pchar(Str); // или Pch:=pchar(Int)
// или
Procedure .....
var
Str:string;
Int:integer;
Pch:char;
begin
Pch:=char(Str); // или ch:=pchar(Int)
← →
Юрий Зотов (2002-08-16 23:40) [19]> Как я могу привести эту строку и число к типу Char?
Строку - никак. Char - это один символ, а в строке их может быть несколько, как же ее приведешь? А число от 0 до 9 - запросто, по таблице ASCII. Как уже говорил MBo:
Ch := Char(Ord("0") + число);
> в функциях dll можно объявлять локальные переменные типа String
И локальные, и глобальные - можно, без малейших проблем. Проблемы возникают только тогда, когда такие переменные используются в ПАРАМЕТРАХ процедур и функций из DLL. В этом случае самое простое - в uses и DLL, и работающего с ней EXE прописать ShareMem (строго в самих DPR и строго самым первым). Тогда не нужно будет никаких PChar, но с такой DLL сможет работать только Delphi-программа. Если же нужно, чтобы эту DLL могла использовать вообще любая программа, то параметры должны быть только PChar.
> ведь PChar - это массив символов, заканчивающийся #0...
Нет. Это УКАЗАТЕЛЬ на массив символов, заканчивающийся #0. Сам этот указатель статический и всегда занимает 4 байта. А вот массив, на который он указывает может быть до 4 Гб, но память под него должна выделить Ваша программа. А после использования, конечно, освободить.
← →
nikolo (2002-08-19 14:44) [20]Грубо говоря, я могу в функцию dll написать следующим образом?
Function FFF(pParam: PChar): PChar;
Var
S: String;
Begin
S := StrPas(pParam);
.....
действия с S
.....
Result := PChar(S);
End;
Или нужно как-то иначе работать с PChar внутри функции?
← →
Skier (2002-08-19 14:48) [21]>nikolo
Нет. Так нельзя !
Вот выдержка из Help-a :
A common error when working with PChars is to store in a data structure, or return as a value, a local variable. When your routine ends, the PChar will disappear because it is simply a pointer to memory, and is not a reference counted copy of the string. For example:
function title(n: Integer): PChar;
var
s: string;
begin
s := Format("title - %d", [n]);
Result := PChar(s); // DON"T DO THISend;
This example returns a pointer to string data that is freed when the title function returns.
В твоём случае нужно выделить память под PChar и
скопировать в неё String;
← →
Толик (2002-08-19 15:00) [22]Прошу прощения, что вмешиваюсь в обсуждение, но возник вопрос к Юрий Зотов © (16.08.02 23:40).
А почему pchar может указывать только на массив не более 4Гб??? А на 4Гб + 1 байт ему силёнок не хватает??? Там же ни где не хранится размер массива, ограниченный размерностью longword.
Или я что-то упустил?
← →
nikolo (2002-08-19 15:09) [23]> Skier ©, ты писал уже:
Var
Dest: PChar;
cc: Char;
Begin
Dest := AllocMem(4);
try
cc := "7";
Dest[3] := cc;
finally
FreeMem(Dest, 4);
end;
End;
но не понятно, как реализовать мне работу именно со String внутри функции, а не с PChar? Что значит "выделить память под PChar и скопировать в неё String"?
Не мог бы на примере показать как реализовать такую функцию:
Function FFF(pParam: PChar): PChar;
Var
S: String;
Begin
S := StrPas(pParam);
.....
действия с S
.....
Result := PChar(S);
End;
← →
Skier (2002-08-19 15:15) [24]>nikolo
Скажи мне такую вещь : как ты планируешь (и где) использовать
результат функции FFF ?
← →
nikolo (2002-08-19 15:21) [25]Есть основная программа, к ней подключается dll, в которой нужно реализовать несколько функций для работы со строками. А вызываться эти функции будут из основной программы. Т.е. в основной программе, например, будет что-то типа:
Label1.Caption := FFF(ed.Text);
← →
Skier (2002-08-19 15:38) [26]>nikolo
Function FFF(pParam: PChar): PChar;
Var
S: String;
Begin
S := StrPas(pParam);
//.....
StrLCopy(Result, PChar(S), Length(S) + 1);
if Result = nil then;
End;
← →
Skier (2002-08-19 15:39) [27]>nikolo
if Result = nil then; - это выбрось :)
← →
nikolo (2002-08-19 16:00) [28]Ты знаешь, Access violation вылазит... В чем может быть дело?
Делаю так:
Function TfmMain.FFF(pParam: PChar): PChar;
Var
S: String;
Begin
S := StrPas(pParam);
S := S+" 222";
StrLCopy(Result, PChar(S), Length(S) + 1);
End;
procedure TfmMain.Button1Click(Sender: TObject);
Var SS: String;
Begin
SS := "111";
Label1.Caption := FFF(PChar(SS));
end;
← →
Юрий Зотов (2002-08-19 22:39) [29]> Толик © (19.08.02 15:00)
Как и любой другой указатель, PChar в Win32 занимает 4 байта - то есть, 32 бита. Следовательно, минимальный адрес, который он может содержать - это 32 нуля (то есть, ноль), а максимальный - 32 единички (то есть, 4 Гб).
В Win32 ЛЮБОЙ указатель может адресовать в пределах 4 Гб. Вот когда перейдем на 64-битные системы - тогда картина будет другая.
← →
Юрий Зотов (2002-08-19 22:54) [30]> Юрий Зотов © (19.08.02 22:39)
Дорогой Юрий, прими поздравления от самого себя! И больше не путай адрес массива с его длиной!
:о)
> Толик © (19.08.02 15:00)
Но все равно предел длины - 4 Гб (теоретический, а практический намного меньше). Просто 4 Гб - это все адресное пространство процесса (почему - написано выше) и за его пределами находиться вообще ничего не может. А нашей программе доступны даже не все 4 Гб (не помню наизусть, надо посмотреть в книжке, но что-то типа 2 Гб - причем эта цифра для 9х и NT разная).
← →
nikolo (2002-08-20 11:44) [31]Ребята, ответьте, пожалуйста, на мой последний вопрос...
← →
nikolo (2002-08-20 12:02) [32]АУ!!!!
← →
Digitman (2002-08-20 12:19) [33]>nikolo
Function TfmMain.FFF(pParam: PChar): PChar;
Var
S: String;
Begin
S := StrPas(pParam);
S := S+" 222";
// результат функции есть просто указатель на блок памяти
// который при возврате из ф-ции должен содержать строку символов
// ограниченную справа символом-терминатором
// вопрос : откуда он возьмется, этот самый блок памяти ?
// не сам же по себе будет выделен !
// нужно об этом позаботиться
GetMem(Result, Length(S) + 1); // вот здесь и выделим его
// а теперь - смело копируем содержимое некоей строки S в этот блок
StrLCopy(Result, // адрес результирующего блока
PChar(S), // адрес блока, распределенного автоматически для исходной копируемой строки
Length(S) + 1); // размер копируемого блока (включая байт с символом-терминатором)
End;
← →
Юрий Зотов (2002-08-20 14:34) [34]Вот же Фома неверующий. Ведь давным-давно было сказано:
1. PChar - это УКАЗАТЕЛЬ, а не массив.
2. Под ТЕЛО массива надо выделить ПАМЯТЬ.
3. А потом ее ОСВОБОДИТЬ.
Почему Вы СРАЗУ не прислушались к этим словам - не знаю. Конечно, вольному воля, но в итоге Вы потеряли кучу времени, измучили и себя, и форум.
У Вас PChar"ный Result получает адрес памяти, которая выделена не специально для него, а была автоматически выделена компилятором под тело ЛОКАЛЬНОЙ строки. Поскольку строка ЛОКАЛЬНАЯ, то при завершении функции эта память тем же компилятором так же автоматически освобождается. И на что после этого указывает Result? На то, чего уже нет. Отсюда и Access Violation.
И еще надо подумать о том, ГДЕ выделять и ГДЕ освобождать память. Обычная практика - где выделяется, там и освобождается, тогда не будет проблем с менеджером памяти. Поскольку результат должен быть передан в EXE, то в DLL память освобождать нельзя, это надо делать в EXE. Значит, и выделять память нужно тоже в EXE.
Короче говоря, вот работающий пример.
// Процедура в DLL.
procedure Proc(Src, Dest: PChar); // Если надо, поставьте stdcall
var
S: string;
begin
// Что-то делаем с исходной строкой. О выделении памяти под тело
// строки S не заботимся, этим управляет компилятор.
S := "Ура! Мы изменили " + String(Src);
// Записываем результат по адресу Dest. Это самое важное, потому что
// при завершении Proc память, выделенная под тело S будет освобождена.
// Внимание! Это всего лишь пример! Поэтому здесь не проверяется
// размер участка памяти, которую адресует Dest. Если он окажется
// недостаточным, возможны любые ошибки.
StrCopy(Dest, PChar(S))
end;
// Вызов из основной программы.
procedure TForm1.Button1Click(Sender: TObject);
var
P: PChar;
begin
// Выделяем память под результат работы Proc. Внимание!!! Если
// этих 512 байт окажется мало, возможно что угодно.
GetMem(P, 512);
try
// Преобразуем Edit1.Text с помошью Proc
Proc(PChar(Edit1.Text), P);
// Переносим результат в Edit2.Text
Edit2.Text := String(P)
finally
// Освобождаем выделенную память
FreeMem(P, 512)
end
end;
← →
nikolo (2002-08-20 15:02) [35]Все понятно, всем спасибо. Тему закрываем.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.09.02;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.008 c