Thread: Next Question...

  1. #1
    Registered User Azmeos's Avatar
    Join Date
    Jun 2003
    Posts
    65

    Next Question...

    I'm writing a (nextToken()) method in which I want the next token (after being tokenized is delimited by '\0') and I can't seem to get it to work... I keep getting an error of "The instruction at "0x00402cea" referenced memory at "0x00000000". The memory could not be "read"." or something like that. I think it has something to do with my length() function ... it seems to be getting passed a character array containing "" at the address 0x00000000 ... so that it gives an "Access Violation" ... I'll put all of my String Tokenizer code here, can someone please help? Everything else in the program works... to the best of my knowledge - I haven't added all of my error checking yet though. (And by the way, if this seems like a newbish question ... I've been programming in C++ for 2 days so go easy on me, heh)

    The problem code seems to be RVString::length() and/or StringTokenizerC::nextToken() Or it could be something I'm missing completely ...

    Code:
    //RVString.h - defines a custom String class
    #ifndef RVSTRING_H
    #define RVSTRING_H
    
    class RVString 
    {
    public:
    	RVString(char* pString);
    	~RVString();
    	int find_first_of(char* pString, char* pArray);
    	int find_first_of(char* pString, char* pArray, int start);
    	int find_first_not_of(char* pString, char* pArray);
    	int find_first_not_of(char* pString, char* pArray, int start);
    	int length(char* pString);
    	char* m_string;
    	int m_length;
    };
    #endif
    ----------------------------------------------------------------------------------
    // StringTokenizerC.h - defines the StringTokenizerC class
    #ifndef STRINGTOKENIZERC_H
    #define STRINGTOKENIZERC_H
    
    using namespace std;
    
    class StringTokenizerC
    {
    public:
    	int m_token_count;
    	int m_position;
    	int m_length;
    	char* m_string;
    	char* m_tstring;
    	char* m_delim;
    
    	StringTokenizerC(char str[]);
    	StringTokenizerC(char str[], char delim[]);
    	~StringTokenizerC();
    	int countTokens();
    	bool hasMoreTokens();
    	char* nextToken();
    	char* nextToken(char delim[]);
    private:
    	bool strCopy(char *pSrc, char *pDst, int maxDstSize);
    };
    
    #endif
    -----------------------------------------------------------------------------------
    #include <iostream>
    #include "RVString.h"
    
    using namespace std;
    
    RVString::RVString(char* pString)							//RVString constructor
    {
    	m_string = pString;										//Allocates the member string incase the user changes the string.
    }
    
    int RVString::find_first_of(char* pString, char* pArray)	//Finds the first character from pArray in pString and returns the location.
    {
    	try {
    	int firstOf = -1;										//-1 Because 0 is a possibility.
    	int n = 0;
    	RVString finding(pArray);
    	RVString subject(pString);
    
    	do{														//Keeps looping until firstOf changes or it reaches the end of the string.
    		for(int i = 0; i < finding.length(pArray); i++) {	//Goes through each character in the pArray and sees if one character in pString is equivalent.
    			if(pString[n] == pArray[i])
    				firstOf = n;
    		}
    		if(pString[n] == '\0') {							//If it reaches the end of the string, it stops.
    			throw "Error: End of string reached with no match found.";
    		}
    		n++;
    	}while(firstOf == -1);
    
    	return firstOf;
    	}catch(const char* message) {}
    }
    
    int RVString::find_first_of(char* pString, char* pArray, int start)
    {															//Same as above except n = start.
    	try {
    	int firstOf = -1;
    	int n = start;								
    	RVString finding(pArray);
    	RVString subject(pString);
    	if(start >= subject.length(pString)) throw "Error: Starting point out of bounds.";
    
    	do{
    		for(int i = 0; i < finding.length(pArray); i++) {
    			if(pString[n] == pArray[i])
    				firstOf = n;
    		}
    		if(pString[n] == '\0')
    			throw "Error: End of string reached with no match found.";
    		n++;
    	}while(firstOf == -1);
    
    	return firstOf;
    	}catch(const char* message) {}
    }
    
    int RVString::find_first_not_of(char* pString, char* pArray)
    {															//Finds the first character in pString that is not in pArray.
    	try {
    	int firstOf = -1;
    	int i = 0;
    	int n = 0;
    	int num = 0;
    	RVString finding(pArray);
    	RVString subject(pString);
    
    	do{														//Loops until firstOf changes or it reaches the end of the string.
    		for(i = 0, num = 0; i < finding.length(pArray); i++) {
    			if(pString[n] != pArray[i]) {
    				num++;										//num will increase every time the character in pArray does not equal pString so that there is something to compare i to in order to get the && effect.
    			}
    		}
    		if(num == i) firstOf = n;							//If num == i, all of the characters in pArray do NOT equal the character in pString, thus it is the first NOT of.
    		if(pString[n] == '\0')
    			throw "Error: End of string reached with no match found.";						//If it reaches the end of the string, it stops.
    		n++;
    	}while(firstOf == -1);
    
    	return firstOf;
    	}catch(const char* message) {}
    }
    
    int RVString::find_first_not_of(char* pString, char* pArray, int start)
    {															//Same as above except n = start.
    	try {
    	int firstOf = -1;
    	int i = 0;
    	int n = start;
    	int num = 0;
    	RVString finding(pArray);
    	RVString subject(pString);
    	if(start >= subject.length(pString)) throw "Error: Starting point out of bounds.";
    
    	do{
    		for(i = 0, num = 0; i < finding.length(pArray); i++) {
    			if(pString[n] != pArray[i]) {
    				num++;
    			}
    		}
    		if(num == i) firstOf = n;
    		if(pString[n] == '\0') 			
    			throw "Error: End of string reached with no match found.";
    		n++;
    	}while(firstOf == -1);
    
    	return firstOf;
    	}catch(const char* message) {}
    }
    
    int RVString::length(char* pString)
    {
    	int i = 0;
    	while(pString[i] != '\0'){										//Get the string length
    		++i;
    	}
    	return i;
    }
    
    RVString::~RVString() {}
    -----------------------------------------------------------------------------------
    #include <iostream>
    #include "StringTokenizerC.h"
    #include "RVString.h"
    
    using namespace std;
    
    #define MAXLINE 1000
    
    char defaultDelim[] = " \n\r\t";
    
    StringTokenizerC::StringTokenizerC(char str[])
    {
    	int j = 0;
    	int p = 0;
    	m_position = 0;
    	m_delim = new char[MAXLINE];
    	m_string = new char[MAXLINE];
    	strCopy(defaultDelim, m_delim, MAXLINE);					//copies defaultDelim to m_delim in case the user changes things.
    	m_token_count = 0;
    	m_length = 0;
    	int start = 0;
    	int end = 0;
    	while(str[m_length] != '\0'){								//Get the string length
    		++m_length;
    	}
    	RVString rvs(str);
    	start = rvs.find_first_not_of(str, m_delim);				//finds the first character that is not a delimeter in the string.
    
    	while(end != m_length)
    	{
    		if(end >= m_length) break;
    		end = rvs.find_first_of(str, m_delim, start + 1);		//finds the (new) end of the token.
    		if(end >= m_length)
    			end = m_length;
    		m_token_count++;
    		for(j = start, p = 0; p < (end - start); j++, p++) {
    			m_string[j] = str[j];								//Adds the characters to the string from the start and end points
    		}
    		m_string[j] = '\0';
    		start = rvs.find_first_not_of(str, m_delim, end + 1);	//finds the (new) start of the token.
    	}
    }
    
    StringTokenizerC::StringTokenizerC(char str[], char delim[])
    {
    	int j = 0;
    	int p = 0;
    	m_delim = new char[MAXLINE];
    	m_string = new char[MAXLINE];
    	strCopy(delim, m_delim, MAXLINE);							//copies user-supplied delimeters to m_delim in case the user changes things.
    	m_token_count = 0;
    	m_length = 0;
    	int start = 0;
    	int end = 0;
    	while(str[m_length] != '\0'){								//Get the string length
    		++m_length;
    	}
    	RVString rvs(str);
    	start = rvs.find_first_not_of(str, m_delim);				//finds the first character that is not a delimeter in the string.
    
    	while(end != m_length)
    	{
    		if(end >= m_length) break;
    		end = rvs.find_first_of(str, m_delim, start + 1);		//finds the (new) end of the token.
    		if(end >= m_length)
    			end = m_length;
    		m_token_count++;
    		for(j = start, p = 0; p < (end - start); j++, p++) {
    			m_string[j] = str[j];								//Adds the characters to the string from the start and end points
    		}
    		m_string[j] = '\0';
    		start = rvs.find_first_not_of(str, m_delim, end + 1);	//finds the (new) start of the token.
    	}
    }
    
    bool StringTokenizerC::strCopy(char *pSrc, char *pDst, int maxDstSize) {
    	int i = 0;
    	char c;
    	while ((c = pSrc[i]) != '\0')								//loops until the end of the string
    	{
    		if(i <= maxDstSize)										//does not allow the string to be larger than the designated size
    			pDst[i] = c;
    		i++;
    	}		
    	pDst[i] = '\0';												//adds a terminate character to the end of the copied string.
    	return true;
    }
    
    int StringTokenizerC::countTokens()
    {
    	return m_token_count;
    }
    
    char* StringTokenizerC::nextToken()
    {
    	m_position++;
    	int j = 0;
    	int p = 0;
    	int start = 0;
    	char* token = new char[MAXLINE];
    	RVString rvs(m_string);
    	int begin = 0;
    	for(int i = 0; i < m_position; i++) {
    	start = rvs.find_first_of(rvs.m_string, '\0', begin);
    	begin = start + 1;
    	}
    	int end = rvs.find_first_of(rvs.m_string, "\0", begin + 1);
    	for(j = start, p = 0; p < (end - start); j++, p++) {
    		token[p] = rvs.m_string[j];									//Adds the characters to the string from the start and end points
    	}
    	return token;
    }
    
    char* StringTokenizerC::nextToken(char* delim)
    {
    	StringTokenizerC stc(m_string, delim);
    	m_position++;
    	int j = 0;
    	int p = 0;
    	int start = 0;
    	char* token = new char[MAXLINE];
    	RVString rvs(m_string);
    	int begin = 0;
    	for(int i = 0; i < m_position; i++) {
    	start = rvs.find_first_of(m_string, "\0", begin);
    	begin = start + 1;
    	}
    	int end = rvs.find_first_of(m_string, "\0", begin + 1);
    	for(j = start, p = 0; p < (end - start); j++, p++) {
    		token[p] = m_string[j];									//Adds the characters to the string from the start and end points
    	}
    	delete [] token;
    	return token;
    }
    
    bool StringTokenizerC::hasMoreTokens()
    {
    	if(m_token_count > m_position)
    		return true;
    	return false;
    }
    
    StringTokenizerC::~StringTokenizerC()							//cleans up afterwards.
    {
    	delete [] m_delim;
    	delete [] m_string;
    }
    
    -----------------------------------------------------------------------------------
    #include <iostream>
    #include "StringTokenizerC.h"
    #include "RVString.h"
    
    using namespace std;
    
    void main() {
    	StringTokenizerC stc("This is a test\nand I hope it works.");
    	cout << stc.nextToken() << endl;
    }
    -----------------------------------------------------------------------------------
    \0

  2. #2
    Registered User Azmeos's Avatar
    Join Date
    Jun 2003
    Posts
    65
    I've narrowed it down to the program not being able to pass a '\0' as an argument ... it passes it with the address of 0x00000000 instead of the string with no value... any suggestions on how I could get it to look for a '\0' ?

    could searching for "" do the same thing?
    \0

  3. #3
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    not being able to pass a '\0' as an argument ... it passes it with the address of 0x00000000 instead of the string with no value...
    Of course; '\0' is the same as the value 0, a.k.a. NULL. An empty string would be "" or "\0", I'm not sure which (or even if this is what you're looking for, lol ).

    Also, please don't post your whole program. I appreciate your use of code tags, but once you've narrowed your problem down, please post only that section of code, as it makes reading it much easier (i.e. I didn't bother to read your code because there's so much to look through).
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  4. #4
    Registered User Azmeos's Avatar
    Join Date
    Jun 2003
    Posts
    65
    Thanks, I figured it out ... but I posted it incase there were some questions about the other parts of my code and how they work.
    \0

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Alice....
    By Lurker in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 06-20-2005, 02:51 PM
  2. Debugging question
    By o_0 in forum C Programming
    Replies: 9
    Last Post: 10-10-2004, 05:51 PM
  3. Question about pointers #2
    By maxhavoc in forum C++ Programming
    Replies: 28
    Last Post: 06-21-2004, 12:52 PM
  4. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 09:47 PM
  5. Question, question!
    By oskilian in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 12-24-2001, 01:47 AM