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!

script editing (determine keywords in files)

Status
Not open for further replies.

decripit

Programmer
Jan 16, 2002
3
US
I have aquired a job in which my program has to read in a script file and decipher it. I know how to read in the file and read the lines, but I do not know how to search for certain keywords, values, brackets, etc.
For example:

//this would be the script file
header
[
<author: &quot;decripit&quot;>
]
-object
<name: &quot;object1&quot;>
<description: &quot;object1 does stuff&quot;>
-end object
//end header file

I need to read in this file, check to see if the header is there, which I can do, and then look inside the header's scope (brackets) to find the author's name. How would I do that? I can look for the authors name, but I don't know how to do it inside a certain scope... does anyone else? I have to find out if the script has <> around the keywords and such.

I've read in and parsed file before, but not done functions like this. Any help would save me tons of frusteration and effort.

Thanks much,
 
Well, I would design somewhat of a finite state machine but with a few modificaitons so you dont need to do the whole thing. With an ifstream you can continually do .get()'s and when the sequence

'a' 'u' 't' 'h' 'o' 'r' comes up you can read in the from &quot;<&quot; to &quot;>&quot;

This is just one thought. I believe you could also look into string pattern matching. A search on Boyer Moore and/or KMP will give you some pointers on this.

Matt
 
There are a few different meathods...You could read the entire script file into a buffer (char *buf, or
char buf[MAX_LENGTH]), and then use strcmp() to look for certain tags, ex.

if (strcmp(buf, &quot;<object1>&quot;)) {
do_object1();
}

or you could read the file line by line stoping at certain dilimiter points...ex.

header~ // Stop at the ~, and store the prior test to
// char *header
[ // When this is read, read the next line into
author name~ // char *AuthName, again stop at the ~
]
// Now scan for Optoins

O // If(ReadChar = 'O')....
Object name~ // then read option info, next line stores in
// char *ObjectName[MAX_OBJECTS], again,
// stop at the ~
// Next you need to know the different things
// the script can cause, ex.
<display PIC> // if strcmp(option, &quot;<display PIC>&quot;) then
// display PIC
$ // You can also use a symbol to signify the
// end of a script, so you can store as many
// scripts in a sigle file as you want.

Hope this gives you a good start, good luck,
Rob
&quot;Programming is like art...It makes me feel like chopping my ear off.&quot;

- Currently down
 
another thing you could do if you read the whole file into a buffer is use strstr for the keywords you are looking for.

Matt
 
i figured as much as that, but the problem with doing things that way is it would search through the whole buffer, and I just want to search inside the scope of the []s. If I just took a certain chunk of the file in the buffer, say keep on writing to the buffer until you hit a ']', there are more []s inside the scope, and it would have the possibility to stop at the wrong bracket. This would be a bad thing. I need a surefire way to make sure its reading the right stuff inside the right scope. I can definately use the strstr and the strcmp kinds of functions, but i need to be able to tell which scope im in to determine the validity of the statememts inside.
did that make sense? if so, any suggestions?

Cyprus
 
When I read a file like this, I use getline, C++ strings, and the C++ string find method. I open the file for reading using file streams. Then I use getline to read a line (to the carriage return) from the file into a string. (You could also just read a certain number of bytes, too.) Then I use the find method to look for another string inside the string from the file. If this is what you are looking for I can post some code here.
James P. Cottingham

I am the Unknown lead by the Unknowing.
I have done so much with so little
for so long that I am now qualified
to do anything with nothing.
 
maybe it is. I could check and see. if it is not too much trouble, please do post that code. otherwise I can just figure it out on my own if that is imposing.
I rarely use String functions to parse files, but theres a first time for everything. I could try it and see how it works.

thanks, Cyprus
 
OK, here goes. This is a generalized function and may not exactly work like you need. Also, I chopped this from a function that does work but I may have missed something in the translation.
Code:
string GetData (string LookFor)
{
    string TheRetStr = &quot;Bad data&quot;;

    ifstream CommFile; // stream set up
    CommFile.open(&quot;C:\\SomeDir\\SomeFile.txt&quot;);

    // Check File
    if (!CommFile)
    {
        // Something went wrong
        // Put error code here
        TheRetStr = &quot;Bad data&quot;;
    }
    else
    {
        // File opened OK. Now get data
        string ALine;

        // Proceed as long as there is data;
        while (getline(CommFile, ALine, '\n'))
        {
            // Look for what we want
            if (ALine.find(LookFor.c_str()) == 0)
            {
                // Found what I was looking for.
                // Now do something with it
            }   // Found what we wanted
        }   // While there is data
    }   // Get data

    // Done! Finish up
    CommFile.close();
    return TheRetStr;
}
James P. Cottingham

I am the Unknown lead by the Unknowing.
I have done so much with so little
for so long that I am now qualified
to do anything with nothing.
 
Another meathod is to store the script in a binary file, and store the information that would usually be in the brackets in a specific location. There are meathods of going to a specific location in a file and only reading from # - #. This however, will only work if you know the specific location to look to. If you're going to take premade script files, that you have no control over, I would suggest 2ffat's meathod.

Let me know, Rob
&quot;Programming is like art...It makes me feel like chopping my ear off.&quot;

- Currently down
 
This is my code for parsing and replacing in my program &quot;Tiny&quot; parse is sent the line number in memo.

void LineInfo::parse(int n)
{
int i;
nw = 0;
const int nc=16;
char command[nc][16]={&quot;ADD &quot;, &quot;PRINT &quot;, &quot;IF &quot;, &quot;ELSE &quot;, &quot;ENDIF &quot;,
&quot;NEXT &quot;, &quot;COLOR &quot;, &quot;CLEAR &quot;, &quot;SHAPE &quot;, &quot;DRAW &quot;,
&quot;SCALE &quot;, &quot;DEFINE &quot;, &quot;RETURN &quot;, &quot;CALL &quot;, &quot;END &quot;, &quot;FOR &quot;};
String string=Form1->Memo->Lines->Strings[n]+&quot; ~&quot;;

//if line is blank
if(string==&quot; ~&quot;)
{
token=20;
return;
}

//numbers first statement if its first char in sring
if(string[1]!=' ')
wp[nw++]=1;

//numbers everthing with space infront incrementally
for(i=2; string!='~'; i++)
if(string!=' ' && string[i-1]==' ')
wp[nw++]=i;

//assigns the token number for the line
token=-1;
for(i=0; i<nc; i++)
if(strncmp(command, &string[wp[0]], strlen(command))==0)
token=i;

}
//---------------------------------------------------------------------------
//execute_this_line contains all the code that performs the 'tiny' actions
int LineInfo::execute_this_line(int* num)
{
int t1, t2, t3, t4, i, dx, dy;
String string2;
lineError = 0;



String string=Form1->Memo->Lines->Strings[*num]+&quot; ~&quot;;

enum{ADD, PRINT, IF, ELSE, ENDIF, NEXT, COLOR, CLEAR, SHAPE,
DRAW, SCALE, DEFINE, RETURN, CALL, END, FOR};


switch(token)
{
//if the line is blank
case 20: (*num)++; break;

//ADD #/var # var
case ADD:
{ //yadda yadda yadda

i hope i havent wasted your time by just throwing something up here but this method works.

A few key things you are looking at here: &quot;char command[nc][16]&quot; and &quot;enum&quot; items must be in the same order. The switch-case just picks out with code to perform.
Also, &quot;for(i=0; i<nc; i++)
if(strncmp(command, &string[wp[0]], strlen(command))==0)
token=i;&quot;
does the actual work in finding the key word. If ive screwed you up.... shoot me ;p
 
Hey XNOR,
[tab]i hope i havent wasted your time by just throwing something up here but this method works. It's never a waste of time to show us some working code. ;-) James P. Cottingham

I am the Unknown lead by the Unknowing.
I have done so much with so little
for so long that I am now qualified
to do anything with nothing.
 
thats right. thanks for the code everyone. I kinda pieced together a few different DOS functions and String functions, took a bit from just about every one of your posts and It works great... with one exception:

I'm reading in a line, for example:

author = &quot;cyprus106&quot;

I want to get just 'cyprus106' out of that when it finds the 'author' and the '='. I tried to delete everything but cyprus, but failed miserably. could anybody propose a method to get this? I tried a vew variations of strtok and such, but it didnt quite work right. Thanks for all the help, it was greatly appreciated everyone...
Cyprus
 
I THINK I know what you want. As a general algorithm:
1) Find the length of the string.
2) Find the position of the equal (=) sign.
3) Subtract the postion of the equal sign from the length of the string.
4) Add to the above number to skip the postion of the equal sign.
5) Take the substring of the original string starting at the number you just calculated.
6) Optional, trim off any spaces from the new string.
For example, using C++ standard string:
Code:
string ALine

ALine = &quot;author = \&quot;cyprus106\&quot;&quot;;

int PathLen = ALine.length(); // length of string
int EqlPlace = ALine.find(&quot; = &quot;)+3; // I THINK this is correct
int PlaceLen = PathLen - EqlPlace; // Position of cyprus106&quot;

// Check to see if = sign was found and not end of line
if ((EqlPlace > 0) && (PlaceLen > 0))
{
    string PlaceHolder = ALine.substr(EqlPlace, PlaceLen);
    // PlaceHolder should be cyprus106&quot;
    // You'll have to eliminate the ending = sign
}

I'm not certain about how many to add to EqlPlace to skip equal sign. You may not even want to so play with this number.

You can do something similar with C character arrays, too.
James P. Cottingham

I am the Unknown lead by the Unknowing.
I have done so much with so little
for so long that I am now qualified
to do anything with nothing.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top