Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
3-3319
SerVS
2002-08-08 00:52
2002.09.02
Ошибка при подключении к IB


1-3497
denimas
2002-08-21 09:55
2002.09.02
Реестр


8-3527
Valex
2002-03-16 16:56
2002.09.02
Существует ли компонент для проигрывания трекерной музыки (s3m,mod etc.)?


1-3466
MMarat
2002-08-20 15:53
2002.09.02
mailto:


6-3535
Slava V.
2002-06-21 13:05
2002.09.02
проверка наличия интернет IP адреса





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский