Hi guys. I have a question - searched for it for at least an hour (i think more, but nevermind).

I have this piece of code:

cout << word.getLastWord() << "<---" << '\n';

It is supposed to call getLastWord method of class called Extract.
Method returns a pointer to the next word extracted form the text. No problem with that. I use this command to "parse" the whole text, but when I'm done with parsing text, if I continue calling the function it goes in depths of my computer's memory.

So, I decided to make a small correction. Include a part of code to make sure that function returns NULL pointer after reaching NULL pointer once (ie after reaching the end of the text).

Problem is that when I call the mentioned piece of code (after calling it many times and reaching the end of text) , nothing is outputted to the screen. So, I am guessing that outputting NULL pointing pointer makes that mess.

I'm new to C++. I have used C so far, so I cannot localize the problem.

Thank you all in advance.

Recommended Answers

All 10 Replies

couldn't you just use the standard substr() method to get that last word?...or do you have to have that method set up to return a pointer?...

ok i guess my question was bad...sorry

i have a task to implement a class that can extract words form a given text, one after another. it also counts how many words have been extracted and offers a method to check the last extracted word.

i am quite new to Object Oriented Programming so i am exercising (this is one of the tasks in the book i am learning OOP from). i dont know any standard methods to extract words, nor did i search for them - there is no fun using built-in methods (dont forget that my main goal at this time is to learn, not to make things work! :) ). also, task was to make a class to do the extraction, not to use built-in one. (i didnt say that before - sorry for bad explanation of my problem)

here is my code:
any criticism is very welcome, but i will ask you to first answer my question regarding output (and flushing output stream..i dont know where is the problem - i guess that using std::cout << ptr; where ptr is a NULL pointer, makes things bad)

#include <iostream>
#include <cstring>

#define MAX_WORD_LEN 50 + 1

using namespace std;

class Extract
{
  private:
    int readable;
    char *cursor;
    char word[MAX_WORD_LEN];
    int wordCount;

  public:
    Extract (char *start) : readable(1), cursor(start), wordCount(0) { word[0] = NULL; }

    char *extractWord ();
    char *getLastWord () { return word; }
    int getWordCount () { return wordCount; }
};

int main (void)
{
    char *text = (char *)"This is a sample text.";   // Note that this text has only 5 words and that calling a function
    Extract word(text);                              // 6 times will make it access memory out of bounds or (because i
                                                     // have handled that problem) will return a NULL
                                                     // pointer to the output stream
    cout << word.getLastWord() << "<---" << '\n';

    for (int i = 0; i < 6; i++)
    {
        cout << word.extractWord() << "<---" << '\n';
        cout << word.getLastWord() << "<---" << '\n';
    }
    cout << word.getWordCount() << "<---" << '\n';

    return 0;
}

char *Extract::extractWord ()
{
    if (!readable)
        return NULL;

    int len = 0;
    for (strncpy(word, cursor, 50); *(cursor++) != ' '; len++) ;
    word[len] = NULL;

    if (!*cursor)
        readable = 0;
    if (word[0])
        wordCount++;

    return word;
}

i also included "<--" in output to see where is the newline, and to see what happens when outputting NULL pointer or whatever.

thank you all in advance

okk...I didn't feel like reading your code. here is a little program that will give you the number of words you entered(i hope it gives you a rough idea about how to do this program). it gets the user input and puts it in an array. there are still a couple of things you will need to figure out. one is how many letters have been input. because you will have to set the for loops counters accordingly. otherwise its going to output rubbish data if you set it too high and will miss some characters from the string if you set it too low. second, how do you want to get that last characters of word. that also should be quite east. The last word comes after the second last space character which has been calculated in this program already. I am sure people can come up with better methods to do this. But this is what i thought of :).good luck. hope this helps.

#include <iostream>


using namespace std;

class WordExtractor 
		  {
			public:
			WordExtractor(){}
			void StringWordExtractor(char[]);
		  };

void WordExtractor::StringWordExtractor(char MyString[])
		  {
			
			int counter=0;
			
			for(int x=0;x<30;x++)
			   {
				if(MyString[x] != 0)
				  {
					counter++;	     
				  }
			   }
			
			
			int SecondCounter=0;
			int ThirdCounter=0;
			int CountingSpacesArray[200]={0};
			 
			for(int j=0;j<counter;j++)
			   {
				if(MyString[j] != ' ')
				  {
					
					SecondCounter++;
				  }
	
				if(MyString[j] == ' ')
				  {
					
					CountingSpacesArray[ThirdCounter] = j;
					ThirdCounter++;

				  }
	
			
				  
				
			   }
			
			cout<<"You Entered A Total of "<<ThirdCounter+1<<" Words"<<endl;
			int constCounter=0;
			for(int h=0;h<counter;h++)
			   {
				if(h == CountingSpacesArray[constCounter])
				  {
					MyString[h] = '\n';
					constCounter++;
				  }

			   }
			for(int a=0;a<counter+counter;a++)
			   {
				  
					cout<<MyString[a]; 				  

			   }
			cout<<endl;
			  
			
			

		  }

int main()
	  {

		WordExtractor FunctionCaller;	
		char MyStringCharacters[40]={0};
		cout<<"Enter a string: ";
		cin.getline(MyStringCharacters,40);
		char checker;
		int counter =0;
		FunctionCaller.StringWordExtractor(MyStringCharacters);
		

		return 0;
	  }

thank you for taking time to respond to my question. :D

i think that your code seems to insert newlines in places where it finds whitespaces. am i right? if so...i think that you didn't understand my problem. my program works quite well. it extracts a new word from the text on each call.

when method is done extracting all words from the text, its return value on each next call after that is NULL. point is, that when i try to print NULL pointer to the screen, using cout, all the cout statements after that point seem not to work. i do not know what is the problem.

please, if i am still not precise enough in defining my problem, please state it so i can try with different approach in stating question.

cheers

Well I did understand your question. But its just that I dont like working with pointers when there are other ways around. What I am doing is i am inserting a newline in the white space as you said, just for being able to print words on separate lines. if you don't want that,it can be avoided as well. But its not any different than you inserting the "<---" symbol when you print out your code. The original string is still intact. I tried to understand your code but wasn't able to. seems like you want to do this with pointers. I can tell you a few things. Your getlastword() method is not doing anything. it just returns all the words. seems like you are aware that if you run the loop more than the strings length, its gonna output malicious data. it is always helpful to give variables meaningful names :). Ok. I understand this is not the way you want the program to be, but if its worth anything, I think this does what you want.

#include <iostream>


using namespace std;

class WordExtractor 
		  {
			public:
			WordExtractor(){}
			void StringWordExtractor(char[]);
		  };

void WordExtractor::StringWordExtractor(char MyString[])
		  {
			
			int counter=0;
			
			for(int x=0;x<30;x++)
			   {
				if(MyString[x] != 0)
				  {
					counter++;	     
				  }
			   }
			
			
			int SecondCounter=0;
			int ThirdCounter=0;
			int CountingSpacesArray[200]={0};
			 
			for(int j=0;j<counter;j++)
			   {
				if(MyString[j] != ' ')
				  {
					
					SecondCounter++;
				  }
	
				if(MyString[j] == ' ')
				  {
					
					CountingSpacesArray[ThirdCounter] = j;
					ThirdCounter++;

				  }
	
			
				  
				
			   }
			
			cout<<"You Entered A Total of "<<ThirdCounter+1<<" Words"<<endl;
			int constCounter=0;
			int space[10]={0};
			for(int h=0;h<counter;h++)
			   {
				if(h == CountingSpacesArray[constCounter])
				  {
					MyString[h] = '\n';
					space[constCounter] = h;
					constCounter++;
				  }

			   }
			for(int a=0;a<counter+counter;a++)
			   {
					cout<<MyString[a]; 				  

			   }	
			int spaceCounter =0;
			
			for(int g=0;g<10;g++)
			   {
				if(space[g] != 0)
				  spaceCounter++;	
				   	
			   }
			cout<<endl;
			cout<<endl;
			cout<<"The Last Word Was: ";
			
			int lastWordCounter=0;
							
				lastWordCounter = space[spaceCounter-1];
				
				while(lastWordCounter < counter)
				     {
				
					cout<<MyString[lastWordCounter];
					lastWordCounter++;
					
				     }		   	
			   
			
			cout<<endl;
			  
			
			

		  }

int main()
	  {

		WordExtractor FunctionCaller;	
		char MyStringCharacters[40]={0};
		string SampleString = "This Is a Sample String";
		char SampleStringArray[40]={0};
		for(int i=0;i<SampleString.length();i++)
		   {
			SampleStringArray[i] = SampleString[i];
		   }
		cout<<"Original String: ";
		cout<<SampleStringArray<<endl;
		FunctionCaller.StringWordExtractor(SampleStringArray);
		cout<<"Enter a string: ";
		cin.getline(MyStringCharacters,40);
		cout<<"Original String: ";
		cout<<MyStringCharacters<<endl;
		FunctionCaller.StringWordExtractor(MyStringCharacters);
		
		

		return 0;
	  }

good luck.

ok...i like your code :D
thank you very much
i felt free to play with your code and make it somewhat shorter :)
well, it doesnt seem to be shorter since there are A LOT of comments

#include <iostream>

// String can be 100 characters long, + 1 is used to reserve place
// for terminating NULL character
#define MAX_STRING_LEN 100 + 1

using namespace std;

class WordExtractor
{
  public:
    WordExtractor(){}
    void StringWordExtractor(string);
};

// Changed char MyString[], to string MyString, so it would be
// easier to handle with MyString
void WordExtractor::StringWordExtractor(string MyString)
{
//  for(int x = 0; x < 30; x++)  //
//      if(MyString[x] != 0)     //
//          counter++;           //

// This loop was used to count the lenght of the text. It was able to
// process texts that were shorter than 30 characters (that could be
// changed, but even if we typed 10000, it would still be limited).
// We could have used while loop and it would be able to count the
// lenght of any text. But, since MyString is a string now, we can
// use lenght() operator
    int length = MyString.length();

// I have decided to change the approach a bit. Instead of counting
// where the spaces are located, we could just walk along the string
// and change every space into a newline

// The SecondCounter wasn't used at all so we tossed it
// The ThirdCounter and CountingSpacesArray were used together
// to record where is each space located, we don't need them in
// this new approach, but I will keep ThirdCounter, because it
// also counted the number of words in the text

    int ThirdCounter = 0;
    for(int i = 0; i < length; i++)
        if(MyString[i] == ' ')
        {
            MyString[i] = '\n';
            ThirdCounter++;
        }

    cout << "You Entered A Total of " << ThirdCounter + 1 << " Words" << endl;

// We don't need to print each letter separately, we can
// print the whole string to the screen like this:
    cout << MyString << endl;

// I have decided to remove the last part of code that was
// used to get the last word from the text since I realized
// that getting the last word wasn't quite useful :D
}

int main()
{
    WordExtractor FunctionCaller;

    string SampleString = "This Is a Sample String.";
    char SampleStringArray[MAX_STRING_LEN];
    for(int i = 0; i < SampleString.length(); i++)
        SampleStringArray[i] = SampleString[i];
    cout << "Original String: " << SampleStringArray << endl;
    FunctionCaller.StringWordExtractor(SampleStringArray);

    char MyStringCharacters[MAX_STRING_LEN] = {0};
    cout << "Enter a string: ";
    cin.getline(MyStringCharacters, MAX_STRING_LEN);
    cout << "Original String: " << MyStringCharacters << endl;
    FunctionCaller.StringWordExtractor(MyStringCharacters);

    return 0;
}

now, i'll make even better improvement, because this code isn't quite correct

input, let's say: "This<space>is<space>my<space><space>new<space>text. "
Substitute <space> with real space :D

The result is 6 instead of 5, because program relies on space counting.

To handle this problem we'll need to record last read letter and if we have 2 consecutive spaces, we do not increase wordCount (ie ThirdCounter)

Hey pretty good. Like I said before, I left you the part to figure out how to count the string length. setting the loop too high would output rubbish and too low would miss chars. But if it works...it works :). So why were you using pointers in the first place?. I avoid using pointers at all costs, unless I absolutely have to. But anyway. Good luck modifying it.

hmmm
well, I have made a function that returns a pointer to extracted word. how does it work? it simply makes a new array of chars. copies letters from text to it until space is reached, and then simply returns the pointer to that word.

pointers are quite powerful. it is true that you can make mistakes with them, but you can also make mistakes with other things. so i tend to use pointers where they can provide much more functionality than usual techniques. :D i dont have time at the moment, but i'll try to modify last code to make it bug free. and i'll try not to use pointers. :D

i think i have no time for these tweaks....but i;d prefer using pointers on this one because it is easier to extract word by word with pointers...

cheers

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.