Computer Science Canada

string manipulation and arrays

Author:  r0ssar00 [ Mon Feb 20, 2006 11:19 am ]
Post subject:  string manipulation and arrays

i have a function (already written)
code:
nameTag(data:string,part:int):int
that returns a piece of data in the form of f_$tag or t_$tag or /f_$tag or /t_$tag where $tag can change and the function that calls this function manipulates that string. my problem is i hit the error "right bound of substring is greater than length of string" the two erroring lines are indicated with comments
code:

    var debug:boolean:=true
    fcn classData (dataVar : string) : string
        var tmp : array 1 .. 3 of string % where 1 is opentag, 2 is data, and 3 is closing tag
        tmp (1) := nameTag (dataVar, 1)
        tmp (2) := nameTag (dataVar, 2)
        tmp (3) := nameTag (dataVar, 3)
        if debug then
            for i : 1 .. 3
                put tmp (i)
            end for
        end if
        var openTagTest, closeTagTest : string
        openTagTest := tmp (1) (1 .. 2) % error #1
        if openTagTest = "f_" then
            result "ofile"
        elsif openTagTest = "t_" then
            result "otree"
        else
            closeTagTest := tmp (3) (1 .. 3) % error #2 (same error as #1)
            if openTagTest = "/f_" then
                result "cfile"
            elsif openTagTest = "/t_" then
                result "ctree"
            else
                result Errors (1)
            end if
        end if
        %put openTagTest
        %put closeTagTest
    end classData

any help would be appreciated

Author:  Cervantes [ Mon Feb 20, 2006 7:20 pm ]
Post subject: 

Something is wrong. You say nameTag returns an integer, and yet the code you show us treats it as returning a string. I'll assume it's a typo, and it returns a string.

nameTag (dataVar, 1) is returning a string of length more than 2.
nameTag (dataVar, 3) is returning a string of length more than 3.

I can't say more without knowing what dataVar is, or the nameTag function.

Author:  r0ssar00 [ Tue Feb 21, 2006 11:31 am ]
Post subject: 

it was a typo
dataVar is the input to a the function which determines from dataVar if it should be labeled fileopen,fileclose,diropen,dirclose
nameTag (dataVar, 1) where dataVar is "<f_test>test string 1</f_test>
would return "f_test"
nameTag (dataVar, 2) where dataVar is "<f_test>test string 1</f_test>
would return "test string 1"
nameTag (dataVar, 3) where dataVar is "<f_test>test string 1</f_test>
would return "/f_test"
this allows me to figure out what the first and last parts are going to be
problem is, which i figured out with some puts, is that nameTag is returning "", not "f_trest"
i guess that means you need the nameTag code so here it is
code:

    fcn nameTag (raw : string, data : int) : string
        var tmpString : string := ""
        var tmpInt : int := 0
        % lets find out how many spaces are before the start of the real data
        loop
            tmpInt += 1
            exit when raw (tmpInt) not= " "
        end loop
        % lets eliminate the whitespace from the string
        for i : tmpInt .. length (raw)
            tmpString := tmpString + raw (i)
        end for
        var tmp2String : string
        % lets remove the tags from the string
        tmp2String := tmpString (2 .. * -1)
        % now we determine what to return: 1 for opentag, 2 for data, 3 for closetag
        if data = 1 then
            if debug then
                put processName.returnFirst (tmp2String, ">")
            end if
            result processName.returnFirst (tmp2String, ">")
        elsif data = 2 then
            if debug then
                put processName.returnMiddle (tmp2String, ">", "<")
            end if
            result processName.returnMiddle (tmp2String, ">", "<")
        elsif data = 3 then
            if debug then
                put processName.returnLast (tmp2String, "<")
            end if
            result processName.returnLast (tmp2String, "<")
        end if
        %put tmp2String
    end nameTag

sorry all the code is indented, thats how it was indented in turing
where raw:string is the input of " <f_test>data 1</f_test>" which may or may not have the whitespace at the beginning
and where data:int tells the function what part of the string to return
processName.returnFirst has two args: string to get first word from, and the character that is the desired seperator
processName.returnMiddle has three args: string to get middle word from, the start seperator, and the end seperator (very useful in my opinion)
processName.returnLast has similiar usage to returnFirst except that it goes from the last seperator to the end of the string
this should be all you need
thanks

Author:  Cervantes [ Sat Feb 25, 2006 9:18 am ]
Post subject:  Re: string manipulation and arrays

r0ssar00 wrote:

code:

...
        tmp (1) := nameTag (dataVar, 1)
...


What is the value of tmp(1)? What is the exact string (dataVar) you're passing to nameTag?

Author:  r0ssar00 [ Mon Feb 27, 2006 2:42 pm ]
Post subject: 

im sorry, i have to say it, and no insult intended, but cervantes:are you thick? if you bothered to read _everything_ in both of my posts with code, you would find all the answers you are looking for. read from top to bottom, and then ask an intelligent question *please*, it will save us both time
i already gave an example for dataVar, tmp is an array, look at the nameTag funtion for what it _should_ equal
cervantes, read _all_ of the code i have posted, everything you need is right there

Author:  Delos [ Mon Feb 27, 2006 5:09 pm ]
Post subject: 

Ok now. Let's not get all aggravated over something as simply fixed as this...perhaps Cervantes misread your post (which, btw, I personally had a little bit of trouble following myself). Perhaps he was so stressed about which one of his 8K+ scholarships he should accept that he skipped a few words...
The point being, he's a busy guy and does a lot around here. Be a little nicer, eh?

Anyhow, I tried this...not sure if it's what you wanted, or if it works, but yeah, 'tis what I figured based upon what you posted.

code:

var debug : boolean := false

fcn nameTag (raw : string, data : int) : string
    var tmpString : string := ""
    var tmpInt : int := 0
    % lets find out how many spaces are before the start of the real data
    loop
        tmpInt += 1
        exit when raw (tmpInt) not= " "
    end loop
    % lets eliminate the whitespace from the string
    for i : tmpInt .. length (raw)
        tmpString := tmpString + raw (i)
    end for
    var tmp2String : string
    % lets remove the tags from the string
    tmp2String := tmpString (2 .. * -1)
    % now we determine what to return: 1 for opentag, 2 for data, 3 for closetag
    if data = 1 then
        if debug then
            put "dg1" % processName.returnFirst (tmp2String, ">")
        end if
        result tmpString (index (tmpString, "<") + 1 .. index (tmpString, ">") - 1) % processName.returnFirst (tmp2String, ">")processName.returnFirst (tmp2String, ">")
    elsif data = 2 then
        if debug then
            put "dg2" % processName.returnFirst (tmp2String, ">")processName.returnMiddle (tmp2String, ">", "<")
        end if
        result tmp2String (index (tmp2String, ">") + 1 .. index (tmp2String, "<") - 1) % processName.returnFirst (tmp2String, ">")processName.returnMiddle (tmp2String, ">", "<")
    elsif data = 3 then
        if debug then
            put "dg3" % processName.returnFirst (tmp2String, ">")processName.returnLast (tmp2String, "<")
        end if
        result tmp2String (index (tmp2String, "<") + 1 .. *) % processName.returnFirst (tmp2String, ">")processName.returnLast (tmp2String, "<")
    end if
    %put tmp2String
end nameTag

fcn classData (dataVar : string) : string
    var tmp : array 1 .. 3 of string     % where 1 is opentag, 2 is data, and 3 is closing tag
    tmp (1) := nameTag (dataVar, 1)
    tmp (2) := nameTag (dataVar, 2)
    tmp (3) := nameTag (dataVar, 3)
    if debug then
        for i : 1 .. 3
            put "tmp: ", tmp (i)
        end for
    end if
    var openTagTest, closeTagTest : string
    openTagTest := tmp (1) (1 .. 2)     % error #1
    % put "ott: ", openTagTest

    if openTagTest = "f_" then
        result "ofile"
    elsif openTagTest = "t_" then
        result "otree"
    else
        closeTagTest := tmp (3) (1 .. 3)     % error #2 (same error as #1)
        if openTagTest = "/f_" then
            result "cfile"
        elsif openTagTest = "/t_" then
            result "ctree"
        else
            result "Errors (1)"
        end if
    end if
    %put openTagTest
    %put closeTagTest
    %*** Neither of these will ever execute, since they exist after the final result.
end classData

var a : string := "<f_test>test string 1</f_test>"

put classData (a)


I had to redo some of the, uh, missing bits of code. Probably similar to what you currently have.

Author:  r0ssar00 [ Tue Mar 21, 2006 11:58 am ]
Post subject: 

it didnt work when put into the main program
ill attach the code for the whole program. its supposed to turn an xml file into a filesystem accessible by turing programs. a really easy way to have configuration done in xml. it will later have links to real files on a drive. for now, im just reading it into memory. later there will be write support too. sorry for the lack of comments in my code. i have a whole lot at the beginning describing the program, but after that, theres close to nothing.

p.s. another problem with the program is with the chars function, tmpData is null, there is no data in it, could you check that out too? thanks

Author:  Delos [ Tue Mar 21, 2006 5:47 pm ]
Post subject: 

Are you sure you've posted the right files? Both are just filled with xml script.

Author:  r0ssar00 [ Thu Mar 23, 2006 8:05 am ]
Post subject: 

whoa, what the hell? i posted the right files, compsci's upload script screwed up, its the compsci homepage thats there instead. hmm.
heres xmllibfs.t
code:

% xmllib v0.1
% this is SOURCE CODE for xmllib
% change it if u want, say theres a bug, but mail me the change at r0ssar00 at gmail dot com
% ill then change the prog

% i will refer to tags as files and trees as directories

% later, this will include url support
% this library offers access to a xml file like a filesystem, and you can also do various things
% such as: mkdir which creates a new directory
%          touch which creates a new file with empty data
%          rmdir which removes a directory
%          rm which removes a file
%          ls which lists a directory
%          fromfs which will take a text file from the system and put it into the file as a tag
%          cat which gets the data from a tag
%          cd which changes the directory
%          pwd which gets the current directory
%          ln which provides a way to make one tag act like it has the data of another, a link
%                   it is similiar to a soft link in *nix, if the value of the parent changes, so will the link's value
%          mount which will extract the contents of an xml file to a directory tree for disk operations on it (optional)
%          umount which will save the directory tree to a xml file


% anyone who uses linux should be comfortable with the commands
% this library treats an xml file as a filesystem, with a tag being a file,
% and its value being data, its the only way it could ever be pratical in turing
% a tree is represented as a folder
% to access a "directory", you would do var:=xml.cd (stream:int, treename:string)
% to list everything under that, you would do var:=xml.ls (stream:int, directory:string) directory is optional
% the ls outputs everything to a file in the working dir
% to access a value's data, you would do var:=xml.cat (stream:int,directory:string,tag:string)
% a return value of 0 indicates success, a return value of 1 means tag not found, 2 means directory not found
% anything else should be interpreted as a string of data to use

%typical xml file
% <xml>
%     <tree1>
%           <tag1>data1</tag1>
%           <tag2>data2</tag2>
%     </tree1
%     <tree2>
%           <tag3>data 3</tag3>
%           <tag4>data 4</tag4>
%                <tree3>
%                     <tag5>tag data 5</tag5>
%                </tree3
%     </tree2>
%  </xml>

% examples of usage
% to access tree1,data2
% data(2):=xml.cat (xmlfilestream,"/xml/tree1/","tag2")

% to change to a different tree and gets its contents
% tree:=xml.cd (xmlfilestream,"/xml/tree2/")
% tree:=xml.ls (xmlfilestream, ".")
% a "." for the directory string for xml.ls will get the contents of the current directory
% a ".." for the directory string for xml.ls will get the contents of the parent directory
import processName in "./determine.tu"
module xml
    import Sys, processName
    export readXMLFile, nameTag
    var xmlstream : int
    var xmlfile : string
    var currentdir : string
    var temp_tmpdir : string := Sys.GetEnv ("SYSTEMROOT")
    var tmpdir : string
    var tmp_backslashes : array 1 .. 3 of string
    var file : int
    var debug : boolean := false
    var xmlFileDesc : flexible array 1 .. 1 of string % is "ofile"/"cfile" for open/close tags of file, "otree"/"ctree" for open/close of tree
    var xmlFileData : flexible array 1 .. 1 of string % data variable
    var Errors : array 1 .. 2 of string /* for error strings*/ := init ("Bad Data, no xml code", "String Problem, Not Long Enough")
    % convert the backslashes in the string to a forward slash
    tmp_backslashes (1) := processName.returnFirst (temp_tmpdir, "\\")
    tmp_backslashes (2) := processName.returnLast (temp_tmpdir, "\\")
    % assign the resultant to a variable
    tmpdir := tmp_backslashes (1) + "/" + tmp_backslashes (2) + "/Temp"
    % we now have a temporary directory to use for the xml file
    % lets create a function to extract the name of a tag, and erase all spaces
    fcn nameTag (raw : string, data : int) : string
        var tmpString : string := ""
        var tmpInt : int := 0
        % lets find out how many spaces are before the start of the real data
        loop
            tmpInt += 1
            exit when raw (tmpInt) not= " "
        end loop
        % lets eliminate the spaces from the string
        for i : tmpInt .. length (raw)
            tmpString := tmpString + raw (i)
        end for
        var tmp2String : string
        % lets remove the tags from the string
        tmp2String := tmpString (2 .. * -1)
        % now we determine what to return: 1 for opentag, 2 for data, 3 for closetag
        if data = 1 then
            if debug then
                put processName.returnFirst (tmp2String, ">")
            end if
            result processName.returnFirst (tmp2String, ">")
        elsif data = 2 then
            if debug then
                put processName.returnMiddle (tmp2String, ">", "<")
            end if
            result processName.returnMiddle (tmp2String, ">", "<")
        elsif data = 3 then
            if debug then
                put processName.returnLast (tmp2String, "<")
            end if
            result processName.returnLast (tmp2String, "<")
        end if
        %put tmp2String
    end nameTag
    fcn chars (CData : string, num : int) : string
        var tmpStore : string := ""
        var tmpData : string := CData
        if debug then
            put CData
        end if
        if length (tmpData) > num then
            for i : 1 .. num
                tmpStore := tmpStore + tmpData (i)
            end for
        else
            put Errors (2)
        end if
        if debug then
            put tmpStore
        end if
        result tmpStore
    end chars
    % lets now create a function to determine if a tag is directory or file
    fcn classData (dataVar : string) : string
        var tmp : array 1 .. 3 of string     % where 1 is opentag, 2 is data, and 3 is closing tag
        tmp (1) := nameTag (dataVar, 1)
        tmp (2) := nameTag (dataVar, 2)
        tmp (3) := nameTag (dataVar, 3)
        if debug then
            for i : 1 .. 3
                put tmp (i)
            end for
        end if
        var openTagTest, closeTagTest : string
        openTagTest := chars (tmp (1), 2)
        if openTagTest = "f_" then
            result "ofile"
        elsif openTagTest = "t_" then
            result "otree"
        else
            closeTagTest := chars (tmp (3), 3)
            if openTagTest = "/f_" then
                result "cfile"
            elsif openTagTest = "/t_" then
                result "ctree"
            else
                result Errors (1)
            end if
        end if
        %put openTagTest
        %put closeTagTest
    end classData
    % lets create a procedure to read a file into memory
    proc readXMLFile (fileString : string)
        setscreen ("graphics:max;max")
        open : file, fileString, get
        var i := 1
        loop
            exit when eof (file)
            get : file, xmlFileData (i) : *
            new xmlFileData, upper (xmlFileData) + 1
            i += 1
        end loop
        for l : 1 .. i
            new xmlFileDesc, i
        end for
        for m : 1 .. i - 1
            xmlFileDesc (m) := classData (xmlFileData (m))
            if debug then
                %put xmlFileDesc (m)
            end if
        end for
    end readXMLFile
    % lets "extract" the contents to a directory, creating a procedure called: mount
    proc mount (xmlfile : string)
        open : file, xmlfile, get

    end mount
end xml
xml.readXMLFile ("testxml.xml")

yeah, i know, enough comments at the bigeinning, but i needed to have a plan, and i put it in this file
neways, heres determine.tu
code:

unit
module processName
    export returnBiggest, returnSmallest, returnFirst, returnMiddle, returnLast, help
    var biggest, smallest : string
    fcn returnBiggest (name : string, chara : char) : string
        var firstName := name
        for i : 1 .. length (name)
            if name (i) = chara then
                firstName := name (1 .. i - 1)
                exit
            end if
        end for


        var middleName := ""
        var firstSpace := 0
        if firstName not= name then
            for i : 1 .. length (name)
                if name (i) = chara and firstSpace ~= 0 then
                    middleName := name (firstSpace + 1 .. i - 1)
                end if
                if name (i) = chara then
                    firstSpace := i
                end if
            end for
        end if

        var lastName := ""
        if firstName + " " + middleName not= name then
            for i : 1 .. length (name)
                if name (i) = chara then
                    lastName := name (i + 1 .. *)
                end if
            end for
        end if
        var lengths : array 1 .. 3 of int
        lengths (1) := length (firstName)
        lengths (2) := length (middleName)
        lengths (3) := length (lastName)
        if lengths (1) > lengths (2) and lengths (1) > lengths (3) then
            biggest := firstName
        elsif lengths (2) > lengths (1) and lengths (2) > lengths (3) then
            biggest := middleName
        elsif lengths (3) > lengths (1) and lengths (3) > lengths (2) then
            biggest := lastName
        end if
        result biggest
    end returnBiggest
    fcn returnSmallest (name : string, chara : char) : string
        var firstName := name
        for i : 1 .. length (name)
            if name (i) = chara then
                firstName := name (1 .. i - 1)
                exit
            end if
        end for


        var middleName := ""
        var firstSpace := 0
        if firstName not= name then
            for i : 1 .. length (name)
                if name (i) = chara and firstSpace ~= 0 then
                    middleName := name (firstSpace + 1 .. i - 1)
                end if
                if name (i) = " " then
                    firstSpace := i
                end if
            end for
        end if

        var lastName := ""
        if firstName + " " + middleName not= name then
            for i : 1 .. length (name)
                if name (i) = chara then
                    lastName := name (i + 1 .. *)
                end if
            end for
        end if
        var lengths : array 1 .. 3 of int
        lengths (1) := length (firstName)
        if length (middleName) > 0 then
            lengths (2) := length (middleName)
            lengths (3) := length (lastName)
        else
            lengths (2) := 25 ** 2
            lengths (3) := 25 ** 2
        end if
        if lengths (1) < lengths (2) and lengths (1) < lengths (3) then
            smallest := firstName
        elsif lengths (2) < lengths (1) and lengths (2) < lengths (3) then
            smallest := middleName
        elsif lengths (3) < lengths (1) and lengths (3) < lengths (2) then
            smallest := lastName
        end if
        result smallest
    end returnSmallest
    fcn returnFirst (name : string, chara : char) : string
        var firstName : string := ""
        for i : 1 .. length (name)
            if name (i) = chara then
                firstName := name (1 .. i - 1)
                exit
            end if
        end for
        result firstName
    end returnFirst
    fcn returnMiddle (name : string, chara, charb : char) : string
        var middleName := ""
        var firstSpace := 0
        for i : 1 .. length (name)
            if name (i) = charb and firstSpace ~= 0 then
                middleName := name (firstSpace + 1 .. i - 1)
            end if
            if name (i) = chara then
                firstSpace := i
            end if
        end for
        result middleName
    end returnMiddle
    fcn returnLast (name : string, chara : char) : string
        var lastName := ""
        for i : 1 .. length (name)
            if name (i) = chara then
                lastName := name (i + 1 .. *)
            end if
        end for
        result lastName
    end returnLast
    proc help
        var currentwin : int := Window.GetActive
        var currentwin2 : int := Window.GetSelect
        var win : int := Window.Open ("graphics:500;400,nobuttonbar")
        Window.SetActive (win)
        put "returnBiggest: returns the biggest word from three given"
        put "it is a function.  returnBiggest (words:string)"
        put "returnSmallest: returns smallest word, same limitations +         usage."
        put "returnFirst: returns the first word, same limitations +           usage.  Must have # of words >=2"
        put "returnMiddle: returns the middle word, same limitations +         usage.  Must have # of words =2"
        put "returnLast: returns the last word, same limiations + usage.               Must have # of words >=2"
        put "press any key to continue"
        var test : string (1)
        getch (test)
        Window.SetActive (currentwin)
        Window.Select (currentwin2)
        Window.Close (win)
    end help
end processName

ha, beat that upload script! you cant fubar this!
neways, thanks

Author:  Andy [ Thu Mar 23, 2006 9:55 am ]
Post subject: 

done, done and done Smile

Author:  r0ssar00 [ Tue Apr 04, 2006 10:38 am ]
Post subject: 

thanks
i still need some help with this though, if anybody would wish to join me in my quest to make a xml access library, feel free to pm me

Author:  Cervantes [ Tue Apr 04, 2006 9:27 pm ]
Post subject: 

r0ssar00 wrote:
im sorry, i have to say it, and no insult intended, but cervantes:are you thick? if you bothered to read _everything_ in both of my posts with code, you would find all the answers you are looking for. read from top to bottom, and then ask an intelligent question *please*, it will save us both time
i already gave an example for dataVar, tmp is an array, look at the nameTag funtion for what it _should_ equal
cervantes, read _all_ of the code i have posted, everything you need is right there

Hmm, I didn't notice this when it was first posted. It's long since passed, so I'll speak (sort of) generally.

If you're asking others for help, it's a good idea to present all the information you think they'll need, and then some more. Those who help shouldn't have to read it scrupulously just to offer help. You're making it hard for people to help you. You talk as though I'm looking for answers in your code and that I should be asking the questions. Gah?

Anyways, if I remember correctly, I was looking for the exact string you were passing that it failed on, not any odd string. (These could be the same.) I was also looking for whether your function actually correctly did what you said it did.

Delos wrote:

Perhaps he was so stressed about which one of his 8K+ scholarships he should accept that he skipped a few words...

10K scholarship from Queen's, today! And 3K bursary money for Eng / 1K bursary for Science! Smile


: