Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Argh! Strings, chars and integers! 2

Status
Not open for further replies.

gwar2k1

Programmer
Apr 17, 2003
387
GB
I need to read a string say : FFCCBBAA
Then I need to make a number for each letter : 66332211

How I do this (doesnt work) is like this:

c := copy(input,1,1); {copies 1st character}

Obviously c is a string... so I cant run a CASE statement with it: CASE c OF <-- wrong type =(

So I tried val in vain:

val(c,i,e); {converts string to a numerical value}

But of course it returns all letters as 0...

Is there any way for me to copy from a string to a character? Is there any way for me to use a string in a case statement or is there any way for me to get a number from the val statement?

WAIT! ord(c) right? Nope =(

OK is there any way for me to use a string in the ord() statement?

All this is in TP7. Thanks

~*Gwar3k1*~
&quot;To the pressure, everything's just like: an illusion. I'll be losing you before long...&quot;
 
What I would do is define an array of byte absolute at the address where the string is:

var
c : string[47];
cbyte : array[47] of byte absolute c;

This &quot;overlays&quot; a byte array on top of your pascal string c. The content of cbyte[0] is now a byte holding the string length (that is how pascal strings work). From cbyte[1] to cbyte[cbyte[0]] is your string, accessible in byte format.
You can then read each &quot;character&quot; as its ascii value, and convert that (in whatever way you choose) to a number. If you want A=1, B=2 etc., then a suitable conversion would actually by cbyte[x] - ord('A') + 1

There are other ways, but this &quot;cheat&quot; of using a variable declared on top of another is a very easy approach. You could probably also type-cast to achieve the same effect.

If you actually want at the end a string of numerical digits corresponding to the letters A, B, C..J then you can just manipulate the array cbyte[0] by subtracting ord('A') from each byte and adding ord('0'). Then, at the end, the string c will miraculously hold what you want!
 
you can also use:

case c[index] of
'A': ...
'B': ...

Regards,
Bert Vingerhoets
vingerhoetsbert@hotmail.com
Don't worry what people think about you. They're too busy wondering what you think about them.
 
Hey thanx both of you. lol didnt think of arrays =P

~*Gwar3k1*~
&quot;To the pressure, everything's just like: an illusion. I'll be losing you before long...&quot;
 
lionelhill, dont suppose you could give me a bit more psuedo code, im still unsure with what you provided

~*Gwar3k1*~
&quot;To the pressure, everything's just like: an illusion. I'll be losing you before long...&quot;
 
sorry, i wish they had an edit feature...

My code is:

PROCEDURE name(s:string; VAR l:integer);

VAR
c : ARRAY [1..1] OF byte ABSOLUTE s;

BEGIN
CASE c[1] OF
'a' : l := 1;
...

But that produces Error 74: Constant and case do not match at the semi-colon.
I honestly don't know how to fix it and help will be greeted with great thanks.

TIA

~*Gwar3k1*~
&quot;To the pressure, everything's just like: an illusion. I'll be losing you before long...&quot;
 
You define the array c as an array of bytes and you use a char in your case. Unlike C, Pascal is much stricter in type matching.

Lionelhill's example makes you able to address each character in a string as a byte, but he uses a complicated way of doing so. Since Pascal strings can be accessed as an array, it is possible to address each character in a string as you would address a character in an array of char.

Example:
VAR s : string;
...
for counter:=1 to length(s) do
write(s[counter]); { print each character of the string s on screen }

similarly, you can use a case statement:

case s[counter] of
'a' : write('small a');
'A' : write('capital A');
'b','B' : write('any B');
'C'..'Z' : write('some other capital');
else write('something else');
end;

If you really want to use numbers in stead of characters, you don't need to declare an array at an absolute address, but use a more ordinary type cast:

case byte(s[counter]) of
65 : write('capital A');
else write('something else');
end;


Absolute castings are generally used to access a special memory location like the screen memory for example:
TYPE screen_char = record
character : char;
attribute : byte;
end;
VAR screen : array[1..25,1..80] of screen_char absolute $B800:$0000;

Regards,
Bert Vingerhoets
vingerhoetsbert@hotmail.com
Don't worry what people think about you. They're too busy wondering what you think about them.
 
hehe, i was having a bit of trouble with the output. I had a test value that should have shown 1 1 1 1 1 1 1 1 but they all had 37 infront of them.
I increased the expected result to 11 and again it showed 3711 so I checked my code... I'd put a writeln where I should have put writexy (a customised function). My bad!

~*Gwar3k1*~
&quot;To the pressure, everything's just like: an illusion. I'll be losing you before long...&quot;
 
Hi.

To assign numbers to each letter in a string i would try:

Code:
function texttonumbers(inp: string):string;
var i,a,b: integer;
    temp,out: string;
    error: boolean;
begin
  out:= '';
  error:= false;
  for i:=1 to length(inp) do
  begin
    a:=ord(inp[i]);{ASCII value of letter}
    if a>90 then a:=a-32 {lower to uppercase}
    if a<65 then error:= true;{less than letters in table}
    if a>90 then error:= true;{greater than letters in table}
    a:=a-64;{offset ASCII values so 'A' becomes 1}
    str(a,temp);{convert number to text}
    out:= out+ temp+',,';{add number and a comma separator}
  end;
  if error:= false then texttonumbers:= temp else texttonumbers:='';
end;
 
Sorry, replace this row:

if error= false then texttonumbers:= out else texttonumbers:='';

I have not tested this example...
 
I really don't understand what you try to achieve by this complicated function, Hebbe; you convert a string with meaning into a string without any use.
If you want to do something with the numerical value of each character with no distinction between upper- or lowercase , you should write something like this:
Code:
for counter:=1 to length(s) do
 case byte(upcase(s[counter])) of
   0..31 : write('Control character');
   65..90 : write('Letter');
   32..64,91..96,123..127 : write('Special character');
   else write('Extended ASCII');
 end;

Regards,
Bert Vingerhoets
vingerhoetsbert@hotmail.com
Don't worry what people think about you. They're too busy wondering what you think about them.
 
Also you don't want to use integer variable in this situation, as that allows for negative numbers, doesn't it? And in this case you want numbers from 0..255.

Yes, Bert is right to point out that my define absolute is a bit of a long-winded way to go round it. The reason is quite simply that I learnt pascal from a variety of books and sources, none of which actually told me you can treat a string like an array, so I got into the habit of using my absolute arrays, and habits are hard to break!

I personally like Pascal's strict attitude to variable types. But you can always get round it by typecasting if necessary (i.e. it's OK to say something like
my_word := word(my_byte_array[2]);
 
Yeah I like its strikt, good for programs just its annoying when I wanna convert =P

~*Gwar3k1*~
&quot;To the pressure, everything's just like: an illusion. I'll be losing you before long...&quot;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top