I need to make some simple program ,but I don't know to start with.
For example ,I got symbol row - 1m213p03a - and this row need to convert to ANSI code ,but only these letter "m", "p" ,"a". In result need to got this - 1109213112397
I need to make this with forms ,and this symbol row need to write user ,who use this program.
Can anyone help me?
I can give you head start with conversion algorithm. It should work in all Delphi versions. Algorithm is searching through input string characters, if character is number then it is written in result string as-is, otherwise it is converted to decimal ANSI representation of underlying character.
function Convert(const input: string): string;
var
i: integer;
begin
result := '';
for i := 1 to Length(input) do
if input[i] in ['0' .. '9'] then result := result + input[i]
else result := result + IntToStr(Ord(input[i]));
end;
var
s: string;
s := Convert('1m213p03a');
Related
First of all I am sorry that I cannot better to describe my problem.
What I have is Word number 65025 which is 0xFE01 or
11111110 00000001 in binary. And I want to pass the value to wstr Word => 11111110 00000001.
I found that using typecast does not work.
And one more question here. If I want to add another number like 10000 => 0x03E8 how to do it. So in the result the widestring should refer to values 0xFE01 0x03E8.
And then, how to retrieve the same numbers from widestring to word back?
var wstr: Widestring;
wo: Word;
begin
wo := 65025;
wstr := Widestring(wo);
wo := 10000;
wstr := wstr + Widestring(wo);
end
Edit:
I'm giving another, simpler example of what I want... If I have word value 49, which is equal to ASCII value 1, then I want the wstr be '1' which is b00110001 in binary terms. I want to copy the bits from word number to the string.
It looks like you want to interpret a word as a UTF-16 code unit. In Unicode Delphi you would use the Chr() function. But I suspect you use an ANSI Delphi. In which case cast to WideChar with WideChar(wo).
You are casting a Word to a WideString. In Delphi, casting usually doesn't convert, so you are simply re-interpreting the value 65025 as a pointer (a WideString is a pointer). But 65025 is not a valid pointer value.
You will have to explicitly convert the Word to a WideString, e.g. with a function like this (untested, but should work):
function WordToBinary(W: Word): WideString;
var
I: Integer;
begin
Result := '0000000000000000';
for I := 0 to 15 do // process bits 0..15
begin
if Odd(W) then
Result[16 - I] := '1';
W := W shr 1;
end;
end;
Now you can do something like:
wo := 65025;
wstr := WordToBinary(wo);
wo := 10000;
wstr := wstr + ' ' + WordToBinary(wo);
For the reverse, you will have to write a function that converts from a WideString to a Word. I'll leave that exercise to you.
Again, you can't cast. You will have to explicitly convert. Both ways.
I have this string where I need to make some characters capital so I use that UpCase command... But what if I need to make small character from capital one? What do I use in that case?
UpCase is not locale aware and only handles the 26 letters of the English language. If that is really all you need then you can create equivalent LoCase functions like this:
function LoCase(ch: AnsiChar): AnsiChar; overload;
begin
case ch of
'A'..'Z':
Result := AnsiChar(Ord(ch) + Ord('a')-Ord('A'));
else
Result := ch;
end;
end;
function LoCase(ch: WideChar): WideChar; overload;
begin
case ch of
'A'..'Z':
Result := WideChar(Ord(ch) + Ord('a')-Ord('A'));
else
Result := ch;
end;
end;
You should learn how to find the solution on your own, not how to use Google or stackoverflow :)
You have the source of the UpCase function in System.pas. Take a look at how it works. All this does is subtract 32 from the lower case characters. If you want the opposite, add 32 instead of subtracting it. The Delphi help will tell you what Dec or Inc does.
var
S: string;
I: Integer;
begin
S := 'ABCd';
for I := 1 to Length(S) do
if S[I] in ['A'..'Z'] then // if you know that input is upper case, you could skip this line
Inc(S[I], 32); // this line converts to lower case
end;
I've done some research here regarding the problem given above and come up with the following code:
VarStr = array of WideChar;
function ArrayToString(const a: VarStr): UnicodeString;
begin
if Length(a) > 0 then
begin
ShowMessage ('Länge des übergebenen Strings: ' + IntToStr(Length(a)));
SetString(Result, PWideChar(#a[0]), Length(a) div 2)
end
else
Result := '';
end;
ShowMessage displays the correct number of characters in a given array, but the result of the function is always an empty string.
Your ideas please?
You are passing the wrong length value. You only ask for half of the characters. Fix your code like this:
function ArrayToString(const a: VarStr): string;
begin
SetString(Result, PWideChar(a), Length(a));
end;
However, you also report that your function returns an empty string. The most likely cause for that is that you are passing invalid input to the function. Consider this program:
{$APPTYPE CONSOLE}
type
VarStr = array of WideChar;
function ArrayToStringBroken(const a: VarStr): UnicodeString;
begin
SetString(Result, PWideChar(#a[0]), Length(a) div 2);
end;
function ArrayToStringSetString(const a: VarStr): UnicodeString;
begin
SetString(Result, PWideChar(a), Length(a));
end;
var
a: VarStr;
begin
a := VarStr.Create('a', 'b', 'c', 'd');
Writeln(ArrayToStringBroken(a));
Writeln(ArrayToStringSetString(a));
end.
The output is:
ab
abcd
So as well as the problem with the code in your question, you would seem to have problems with the code that is not in your question.
Perhaps when you said:
The result of the function is always an empty string.
You actually meant that no text is displayed when you pass the returned value to ShowMessage. That's a completely different thing altogether. As #bummi points out in comments, ShowMessage will truncate its input at the first null-terminator that is encountered. Use proper debugging tools to inspect the contents of variables.
Result:= Trim(string(a));
UPDATE: As colleagues graciously pointed in comments, this is a wrong answer! It works only because internal string and dynamic array implementation are pretty similar and there is no guarantee that such code would work in the future compilator versions. The correct way to DynArray->String conversion is described in the David answer. I would not delete my answer to preserve comments, in my opinion their worth is much greater..
I'm generating texture atlases for rendering Unicode texts in my app. Source texts are stored in ANSI codepages (1250, 1251, 1254, 1257, etc). I want to be able to generate all the symbols from each ANSI codepage.
Here is the outline of the code I would expect to have:
for I := 0 to 255 do
begin
anChar := AnsiChar(I); //obtain AnsiChar
//Apply codepage without converting the chars
//<<--- this part does not work, showing:
//"E2033 Types of actual and formal var parameters must be identical"
SetCodePage(anChar, aCodepages[K], False);
//Assign AnsiChar to UnicodeChar (automatic conversion)
uniChar := anChar;
//Here we get Unicode character index
uniCode := Ord(uniChar);
end;
The code above does not works (E2033) and I'm not sure it is a proper solution at all. Perhaps there's much shorter version.
What is the proper way of converting AnsiChar into Unicode with specific codepage in mind?
I would do it like this:
function AnsiCharToWideChar(ac: AnsiChar; CodePage: UINT): WideChar;
begin
if MultiByteToWideChar(CodePage, 0, #ac, 1, #Result, 1) <> 1 then
RaiseLastOSError;
end;
I think you should avoid using strings for what is in essence a character operation. If you know up front which code pages you need to support then you can hard code the conversions into a lookup table expressed as an array constant.
Note that all the characters that are defined in the ANSI code pages map to Unicode characters from the Basic Multilingual Plane and so are represented by a single UTF-16 character. Hence the size assumptions of the code above.
However, the assumption that you are making, and that this answer persists, is that a single byte represents a character in an ANSI character set. That's a valid assumption for many character sets, for example the single byte western character sets like 1252. But there are character sets like 932 (Japanese), 949 (Koren) etc. that are double byte character sets. Your entire approach breaks down for those code pages. My guess is that only wish to support single byte character sets.
If you are writing cross-platform code then you can replace MultiByteToWideChar with UnicodeFromLocaleChars.
You can also do it in one step for all characters. Here is an example for codepage 1250:
var
encoding: TEncoding;
bytes: TBytes;
unicode: TArray<Word>;
I: Integer;
S: string;
begin
SetLength(bytes, 256);
for I := 0 to 255 do
bytes[I] := I;
SetLength(unicode, 256);
encoding := TEncoding.GetEncoding(1250); // change codepage as needed
try
S := encoding.GetString(bytes);
for I := 0 to 255 do
unicode[I] := Word(S[I+1]); // as long as strings are 1-based
finally
encoding.Free;
end;
end;
Here is the code I have found to be working well:
var
I: Byte;
anChar: AnsiString;
Tmp: RawByteString;
uniChar: Char;
uniCode: Word;
begin
for I := 0 to 255 do
begin
anChar := AnsiChar(I);
Tmp := anChar;
SetCodePage(Tmp, aCodepages[K], False);
uniChar := UnicodeString(Tmp)[1];
uniCode := Word(uniChar);
<...snip...>
end;
We wrote a Delphi program that send some informations with CDO.
In my Win7 machine (hungarian) the accents are working fine.
So if I sent a mail with "ÁÉÍÓÖŐÚÜŰ", I got it in this format.
I used iso-8859-2 encoding in the body, and this encode the subject, and the email addresses to (the sender address is contains name).
I thought that I finished with this.
But when I try to send a mail from a Win2k3 english machine (the mailing server is same!), the result is truncate some accents:
Ű = U
Ő = O
Next I tried to use UTF-8 encoding here.
This provided accents - but wrong accents.
The mail contains accents with ^ signs.
ê <> é
This is not valid hungarian letter... :-(
So I want to know, how to I convert or setup the input to I got good result.
I tried to log the body to see is changes...
Log(SBody);
Msg.Body := SBody;
Log(Msg.Body);
... or not.
But these logs are providing good result, the input is good.
So it is possible lost and misconverted on CDO generate the message.
May I can help the CDO if I can encode the ANSI text into real UTF.
But in Delphi converter functions don't have "CodePage" parameters.
In Python I can said:
s.encode('iso-8859-2')
or
s.decode('iso-8859-2')
But in Delphi I don't see this parameter.
Is anybody knows, how to preserve the accents, how to convert the accented hungarian strings to preserve them accented format?
And I want to know, can I check the result without sending the mail?
Thanks for your help:
dd
a quick google search with "delphi string codepage" got me to torry's delphi pages
and maybe the following codesnippets (found here) can shed some light on your problem:
{:Converts Unicode string to Ansi string using specified code page.
#param ws Unicode string.
#param codePage Code page to be used in conversion.
#returns Converted ansi string.
}
function WideStringToString(const ws: WideString; codePage: Word): AnsiString;
var
l: integer;
begin
if ws = ' then
Result := '
else
begin
l := WideCharToMultiByte(codePage,
WC_COMPOSITECHECK or WC_DISCARDNS or WC_SEPCHARS or WC_DEFAULTCHAR,
#ws[1], - 1, nil, 0, nil, nil);
SetLength(Result, l - 1);
if l > 1 then
WideCharToMultiByte(codePage,
WC_COMPOSITECHECK or WC_DISCARDNS or WC_SEPCHARS or WC_DEFAULTCHAR,
#ws[1], - 1, #Result[1], l - 1, nil, nil);
end;
end; { WideStringToString }
{:Converts Ansi string to Unicode string using specified code page.
#param s Ansi string.
#param codePage Code page to be used in conversion.
#returns Converted wide string.
}
function StringToWideString(const s: AnsiString; codePage: Word): WideString;
var
l: integer;
begin
if s = ' then
Result := '
else
begin
l := MultiByteToWideChar(codePage, MB_PRECOMPOSED, PChar(#s[1]), - 1, nil, 0);
SetLength(Result, l - 1);
if l > 1 then
MultiByteToWideChar(CodePage, MB_PRECOMPOSED, PChar(#s[1]),
- 1, PWideChar(#Result[1]), l - 1);
end;
end; { StringToWideString }
--reinhard