Help with "Text Contains"

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
markcrosbie
Posts: 34
Joined: 30 Sep 2010, 09:56
Location: Ireland
Contact:

Re: Help with "Text Contains"

Post by markcrosbie »

Hi John,

I'd certainly welcome a strstr() function, or some equivalent to the PERL split() function. I spent an (enjoyable) afternoon coding a simple text line parser that could parse lines of configuration data from a file (in the format index=x,y). The resulting code looked ugly, but without a strstr() function seemed the best I could come up with.

Code: Select all

// Parse the text line and return the x,y coordinates
// Return ERR if the line fails to parse, else return SUCCESS
// Line format is index=x,y<newline>
// Does not tolerate whitespace around numbers
int parseLine(string line, int &index, int &x, int &y) {
	int pos, len;
	int equals, comma; // index of the equals and comma chars in the string
	
	equals = comma = -1;
	
	len = strlen(line);
	// Locate the = sign
	for(pos=0; pos < len; pos++) {
		if(StrIndex(line, pos) == EQUAL) {
			equals = pos;
			break;
		}
	}
	
	if(equals == -1) {
		// no equals
		return ERR;
	}
	
	index = StrToNum(SubStr(line, 0, equals+1));
	
	// Now locate the comma
	for( ; pos < len; pos++) {
		if(StrIndex(line, pos) == COMMA) {
			comma = pos;
			break;
		}		
	}

	if(comma == -1) {
		// no comma
		return ERR;
	}

	x = StrToNum(SubStr(line, equals+1, (comma - equals) - 1));
	
	// Whatever is after the comma is the y value
	y = StrToNum(SubStr(line, comma+1, (len - comma) - 1));
	
	return SUCCESS;
}
I'm sure you code hand-tune this to be tighter!

Regards,
Mark
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: Help with "Text Contains"

Post by muntoo »

afanofosc wrote: Here's a slightly more efficient version that uses a repeat loop rather than a for loop:

Code: Select all

bool IsIncluded( string s1, string s2 )
{
  int l1 = StrLen(s1);
  int lDelta = StrLen(s2)-l1;
  int i = 0;
  repeat(lDelta+1)
  {
    if (s1 == SubStr( s2, i, l1))
      return true;
    i++;
  }
  return false;
}

I'm curious: You keep saying repeat is a bit faster. Is it defined separately in the firmware? How much faster is it?

Also:

Code: Select all

/*  Program Name: "FindString.nxc"
**  This program was created by "muntoo" on December 1, 2010
**  Created using BricxCC (by John Hansen) and written in NXC (by John Hansen)
**  ( http://bricxcc.sourceforge.net/ )
*/


#define FIND_EQUALS	0x00000000
#define FIND_STRCMP	0x00000001
#define FIND_ERROR	0xFFFFFFFF

/*
Find toFind inside buf.
If options is set to FIND_EQUALS, the character values are compared without any API functions.
If options is set to FIND_STRCMP, the strings are compared using strcmp().
Ignores the number of toFinds in buf specified in the skip variable.
*/
unsigned long Find(string buf, string toFind, unsigned long options = FIND_STRCMP, unsigned int skip = 0)
{
	unsigned int len_buf = StrLen(buf);
	unsigned int len_toFind = StrLen(toFind);

	if(len_buf < len_toFind)
		return(FIND_ERROR);

	bool keepGoing;

	for(unsigned int szIdx = 0; szIdx < len_buf; szIdx++)
	{
		keepGoing = true;

		for(unsigned int szIdx2 = 0; (szIdx2 < len_toFind) && keepGoing; szIdx2++)
		{
			switch(options)
			{
				case FIND_EQUALS:
					if(!(buf[szIdx] == toFind[szIdx2]))
						keepGoing = false;
					break;

				case FIND_STRCMP:
//					if(strcmp(SubStr(buf, szIdx, 1), SubStr(toFind, szIdx2, 1)))
					if(!(strcmp(SubStr(buf, szIdx, 1), SubStr(toFind, szIdx2, 1)) == 0))
						keepGoing = false;
					break;
			}

			szIdx++;
		}

		if(keepGoing == true)
		{
			keepGoing = false;

			if(skip > 0)
				skip--;
			else
				return(szIdx - len_toFind);
		}
	}

	return(FIND_ERROR);
}


task main()
{
	string buf = "ABCDEF1, deDEf2, deF3, I will kill all of you fools.";
	ClearScreen();
	for(int skip = 0; skip < 4; skip++)
	{
		TextOut(0, skip * 8, SubStr(buf, Find(buf, "DEF", FIND_STRCMP, skip), 4), 0);
	}
	Wait(5000);
}

I can't guarantee if it works (I haven't tested it out, and the nearest NXT is about 1.5 km away, trying to figure out what 6 times 9 is*), but test out the speed. It may be faster (if stripped of all those extra features, such as skip) than the functions posted earlier.

*42, but don't tell it that; it's meant as a "simple" exercise for the depressed android, M*****.
Image

Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: Help with "Text Contains"

Post by afanofosc »

muntoo wrote: I'm curious: You keep saying repeat is a bit faster. Is it defined separately in the firmware? How much faster is it?
The repeat loop is faster than a for loop because it results in simpler NBC code. That's mainly because the number of loop iterations is known up front. A for loop, on the other hand, needs to check every time it reaches the end of the loop to see if it needs to start the loop over again.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests