Hello ladies and gents,

I'm trying to copy two words, for instance test and word into an array of characters and have this:

#include <iostream>

int main()
{
	char word[10]= "";
	char *wordArr[10];

	for(size_t i = 0; i < 2; i++)
	{
		std::cin >> word;
		*(wordArr + i)  = word;
	}

	for(size_t i = 0; i < 2; i++)
		std::cout << wordArr[i] << '\n';

	std::cin.ignore(2);
	
	return 0;
}

Thing is, it prints the last word twice as if it doesn't store the first word, what am I doing wrong, can anyone point me in the right direction?

I know I could use strings or even a vector, but, my idea is to work out a version using characters first, then strings and then a vector.

Well, found a solution like this:

#include <iostream>

int main()
{
	char word[10]= "";
	char wordArr[10][10];

	for(size_t i = 0; i < 2; i++)
	{
		size_t j;
		std::cin >> word;
		for(j = 0; j < strlen(word); j++)
			wordArr[i][j] = word[j];
		wordArr[i][j] = '\0';
	}

	for(size_t i = 0; i < 2; i++)
	{
		for(size_t j = 0; j < strlen(wordArr[i]); j++)
			std::cout << wordArr[i][j];
		std::cout << '\n';
	}

	std::cin.ignore(2);
	
	return 0;
}

But, there has to be a way of using char *wordArr[10]; right?

It would make it easier since the use of a pointer to an array of char's wouldn't need to be terminated by yourself, the compiler would do this like Ancient Dragon said in another thread right.

Does any of you guys know how I could use that type of definition in my program?

Hope something in here meets your needs and helps you understand the syntax.

char * wordArr[10];

means wordArr is an array of 10 char pointers, not that wordArray is a pointer to 10 char arrays.

char * word = new char[10];

means word is a pointer to a char array that can contain up to 10 char.

Now, an example of putting words into array directly. without need for user termination

#include <iostream>
using namespace std;

int main()
{
   char word[10]= "";
   char wordArr[10][10];
   int i;

   for(i = 0; i < 10; ++i)
       cin >> wordArr[i];
  
   for(i = 0; i < 10; ++i)
       cout << wordArr[i] << endl;
   
   cin.get();
}

Inputting words into an array indirectly

#include <iostream>
using namespace std;

int main()
{
    char word[10] = "";
    char wordArr[10][10];
    int i;

    for(i = 0; i < 10; ++i)
    {
        cin >> word;
        strcpy(wordArr[i], word);
    }

    for(i = 0; i < 10; ++i)
        cout << wordArr[i] << endl;

    cin.get();
}

Using pointer to pointer to char instead of array of char arrays

#include <iostream>
using namespace std;

int main()
{
   char  **wordArr;
   int i, j, k;
   cin >> i;
   cin >> j;
   wordArr = new char*[i];
   for( j = 0; j < i; ++i)
     wordArr[i] = new char[j];
   
   for(j = 0; j < i; ++j)
      cin >> wordArr[j];

   for(j = 0; j < i; ++j)
      cout >> wordArr[j] << endl;
   
   for(j = 0; j < i; ++j)
      delete[] wordArr[i];
  
   delete wordArr;
    cin.get();
}

Using array of char pointers instead of pointer to pointer to char

#include<iostream>
using namespace std;

int main()
{
   char *wordArr[10];
   int i, j;
   cin >> j;

   for(i = 0; i < 10; ++i)
      wordArr[i] = new char[j];
   
   for(i = 0; i < 10; ++i)
      cin >> wordArr[i];

   for (i = 0; i < 10; ++i)
      cout << wordArr[i] << endl;

   for(i = 0; i < 10; ++i)
       delete[] wordArr[i];
   
   cin.get()
}

Another version using array of char pointers:

#include <iostream>
using namespace std;

int main()
{
   char * wordArr[2] = { {"Hello"}, {"World"} };
   cout << wordArr[0] << ' ' << wordArr[1] << endl;

   cin.get()
}
Comments
Great examples given !!!

Thanks for those examples Lerner. The reason I came up with my first example code was because the exercise tells you not to store two identical words, therefore I used two variables char word[10]= ""; and char wordArr[10][10]; . That way, I can compare when entering a new word with the already added words to check whether it's not in the list.

I should've written the exercise out, but, I wanted to take this one in small parts as you guys always tell forumers to do, so they don't get overwhelmed with the code. Sorry for that. Anyway, the exercise goes as follows:

- Read a sequence of words from input. Use Quit as a word that therminates input. Print the words in the order they were entered. Don't print a word twice. Modify the program to sort the words before printing them.

I'll be back next week-end, don't have the time to do the exercise now, anyway, thanks again for the thourough explanatioin and examples :!:

Hey Lerner,

Finally got time to work on this exercise again, but, before I do, I'd like to ask whether this way of adding a word into another array is good or not. If not, what are the reasons this is not ideal?

for(size_t i = 0; i < 2; i++)
	{
		size_t j;
		std::cin >> word;
		for(j = 0; j < strlen(word); j++)
			wordArr[i][j] = word[j];
		wordArr[i][j] = '\0';
	}

The intention here was just two add two words into the array to try out. Was I correct that I had to add the '\0' to the end of the word so that it would be correctly terminated?

Hi guys,

Was wondering if any of you could help me out, I'm trying to print the words only once, but, it seems I'm doing something wrong, could someone point me in the right direction?

#include <iostream>
#include <cstring>

int main()
{
	char wordArr[5][10];
	short contr;

	for(size_t i = 0; i < 5; i++)
		std::cin >> wordArr[i];

	for(size_t i = 0; i < 5; i++)
	{
			contr = strcmp(wordArr[i], wordArr[i+1]);
			
			if (contr != 0)
				std::cout << wordArr[i] << '\n';
	}

	std::cin.ignore(2);
	
	return 0;
}

Just wanted to tell you that sometimes your description is rather vague. Always post a question in such way that the person reading it doesn't have to use a compiler to test it out what is going wrong.

If your program displays something and takes some kind of user input, just paste a sample output which is erroneous or not as expected along with what did you expect. This kind of description will help us understanding the problem better.

Now as per your question is concerned, your program only checks to see whether the preceding string is equal to the current string and if it is so then it just skips printing the current string. But your program will fail in conditions where you alternate the words inputted to the program like:

hello
hell
hello
hell
hello

I hope you understand the twist .

>>Was I correct that I had to add the '\0'to the end of the word so that it would be correctly terminated?

No, cin >> automatically null terminates input from either the keyboard or antother stream. The same goes for getline(), which is another way to read in a string.

for(size_t i = 0; i < 5; i++) //for each word in the array
{
   //compare this word with the next word in the array
   contr = strcmp(wordArr[i], wordArr[i+1]);

     //if the two words are not the same
     if (contr != 0)
        //print out current word
        std::cout << wordArr[i] << '\n';
}

You don't want that for two reasons. Number one, when i == 4 you will try to compare wordArr[4] with wordArr[5] but wordArr[5] doesn't exist. If you are lucky your program will crash. If you are unlucky you will get undefined behavior and who knows what will happen, it may even appear to work correctly. Number two, the logic isn't what you want. You want:

bool found = false
for each word in the array //this word
   for each word prior to this word //current word
      if this word is the same as current word
         set found to true
   if not found 
      print out this word

Why ain't you using std::strings?

>> First post "I know I could use strings or even a vector, but, my idea is to work out a version using characters first, then strings and then a vector." ;)

Just wanted to tell you that sometimes your description is rather vague. Always post a question in such way that the person reading it doesn't have to use a compiler to test it out what is going wrong.

I'll try my best to explain it more thoroughly next time :!:

@ Lerner, thanks for the explanation.

I GIVE UP !!!!!

Ive been trying to program for over two years now, have been reading several books, did all exercises, but for some unknown reason, I'm not getting it.

So, after some thought about it, Ive decided to stop, I want to thank all of you who have helped me the past two years here on Daniweb and wish you all the best.

Kind regards,
Johan aka JoBe

Thanks for the kind words s.o.s, but, I can't stop untill I know the answer, so if someone would please help me out with this, Ive been trying and I can't find the solution.

The code Ive got is this:

#include <iostream>
#include <cstring>

int main()
{
	char wordArr[5][10];
	bool contr = false;
	size_t i, j;

	for(i = 0; i < 5; i++)
		std::cin >> wordArr[i];

	for(i = 0; i < 5; i++)
	{
		for(j = 0; j < i; j++)
		{
			contr = strcmp(wordArr[i], wordArr[j]);
			
			if (contr == true)
				contr = true;
		}
			if (contr == false)
				std::cout << wordArr[i] << '\n';
	}

	std::cin.ignore(2);
	
	return 0;
}

But, if I use the input:
one
two
one
four
five

The output is:
one

What am I doing wrong :confused:

Getting so frustrated by not finding this solution :mad: And it is probably something simple that I can't see !!!!!!

#include <iostream>
#include <cstring>

int main()
{
	char wordArr[5][10];
	bool contr = false;
	size_t i, j;

	for(i = 0; i < 5; i++)
		std::cin >> wordArr[i];

	for(i = 0; i < 5; i++)
	{
		for(j = 0; j < i; j++)
		{
			contr = strcmp(wordArr[i], wordArr[j]);
			// If the above line sets contr to true or false...
			if (contr == true)    // what are these two lines for?
				contr = true;
		}
			if (contr == false)
				std::cout << wordArr[i] << '\n';
	}

	std::cin.ignore(2);
	
	return 0;
}

What is it you are trying to do?

Hi Walt,


Well, Lerner posted this helpfull piece of pseudo code:

bool found = false
for each word in the array //this word
   for each word prior to this word //current word
      if this word is the same as current word
         set found to true
   if not found 
      print out this word

And I thought, oh, now I get it:

-First I have a loop for the whole array.
-Then, I have a loop for the word that is being checked whether it exists allready.
-Then, if that word is the same one of the allready added words in the first loop, put the bool variable to true, if not, at the end of looping threw the second loop. Output the word, since it hasn't been added yet.

The idea of the exercise now is to print every word only once, meaning:
one
two
one
four
five

would have to print:
one
two
four
five

Somehow, I'm just not seeing what it is that is wrong with the code Ive written with the help of the pseudo code from Lerner.

Hi Walt,


Well, Lerner posted this helpfull piece of pseudo code:

bool found = false
for each word in the array //this word
   for each word prior to this word //current word
      if this word is the same as current word
         set found to true
   if not found 
      print out this word

And I thought, oh, now I get it:

-First I have a loop for the whole array.
-Then, I have a loop for the word that is being checked whether it exists allready.
-Then, if that word is the same one of the allready added words in the first loop, put the bool variable to true, if not, at the end of looping threw the second loop. Output the word, since it hasn't been added yet.

The idea of the exercise now is to print every word only once, meaning:
one
two
one
four
five

would have to print:
one
two
four
five

Somehow, I'm just not seeing what it is that is wrong with the code Ive written with the help of the pseudo code from Lerner.

Hint: wouldn't it be a lot easier if you sorted the current words into alphabetical order first.

Hint: wouldn't it be a lot easier if you sorted the current words into alphabetical order first.

Probably, but the exercise goes as follows:

- Read a sequence of words from input. Use Quit as a word that therminates input. Print the words in the order they were entered. Don't print a word twice. Modify the program to sort the words before printing them.

So,
1) Read a sequence of words from input.
2) Use Quit as a word that terminates input.
3) Print the words in the order they were entered.
4) Don't print a word twice.
And
5) Modify the program to sort the words before printing them.

I could try what you suggest, but, then I won't be doing it in the order the exercise says, probably for the reason that N°4 would become easier:?:

Anyway, thanks for the tip iamthwee

>I could try what you suggest, but, then I won't be doing it in the order the exercise says, probably for the reason that N°4 would become easier

It certainly would be a lot easier. Which is how most hash tables operate I would imagine. I.e sorting the list first before removing duplicates.

Of course after sorting you lose the order you begin with.

Somehow, I'm just not seeing what it is that is wrong with the code Ive written with the help of the pseudo code from Lerner.

Okay. Here this goes.

What Mr. Lerner tried to explain is that if you start from the start of the array, you would have a hard time keeping track of duplicates.

Eg. one, two, one, two, three

If you begin at the start of the array you have no way of knowing that the current word under consideration would be repeated or not i.e. if we consider the first word "one" we have no way of knowing that "one" would occur again or not.

The only logical thing to beat this problem would be to start from the end of the array, eg. "three", look up for it in the whole array, and see if it occurs anywhere in the whole array. If it does, don't print "three" because we know for sure that we will encounter "three" again definately.

A sample run for input "one, two, one, two, three"

Current Word: three
Searching upwards for "three"...not found
Print "three"

Current word: two
Searching upwards for "two"...found
Dont print "two"

Current word: one
Searching upwards for "one"...found
Dont print "one"

Current word: two
Searching upwards for "two"...not found
Print "two"

Current word: one
Searching upwards for "one"...not found
Print "one"

I won't let you give up so easily ;)

Hope it helped, repost if necessary.

Okay. Here this goes.

What Mr. Lerner tried to explain is that if you start from the start of the array, you would have a hard time keeping track of duplicates.

Ah, ok, let me see whether I can find a solution that way.

I won't let you give up so easily ;)

Thanks for sticking in s.o.s :) Programming is sometimes so frustrating, but, I can't seem to let it go, seems like Ive been bitten by the microbe, problem is, my brains don't seem to be willing to help out here. Glad that this is merely a hobby of mine and I don't have to earn a living with it, wouldn't be earning alot with it :cheesy:

Hope it helped, repost if necessary.

I most certainly will s.o.s, but, it'll probably will be next week since during the week, I don't have time, full time job and other responcebilities.

In boolean logic false is assigned the integer value of zero and true is any other nonzero integer value.

strcmp() returns zero if the two strings are equal, less than zero if the first string is less than the second, and more than zero if the first string is larger than the second.

To merge boolean logic with the logic of strcmp(), if strcmp() returns zero it will assign false value to a boolean variable and any other return value will be interpreted as true.

Therefore, I think it's best not to try to merge boolean logic with strcmp() at this point. Instead I would do something like this:

bool contr = false;  //declare and set a boolean variable to act as a flag

//first word hasn't been printed before so it will always be printed
cout << wordArr[i] << endl;

//for each word in wordArr after first word and call it current word
for(i = 1; i < 5; i++)
{
   //look at all prior words in wordArr
   for(j = 0; j < i; j++)
  {
      //if any prior word in wordArr is the same as current word
      if(strcmp(wordArr[i], wordArr[j]) == 0)  //use straightforward strccmp() logic
        //assign the value of true to the flag    
        contr = true;   //convert strcmp logic to boolean logic
   }
   //now that all prior words have been looked at, evaluate the value of contr
   if (contr == false)
      //if the current word wasn't found in list of prior words
      //print it out
      std::cout << wordArr[i] << '\n';
   else
       //if current word was found in list of prior words
       //reset value of contr to false, but don't print it out
       contr = false;
   
  //go to next word in wordArr, if there is one
}

I would go about it differently

Loop thru words first to last-1, index is IDX1
{
    set FLAG to True
    Loop thru words IDX1 to last, index is IDX2
    {
        if word(IDX1) = word(IDX2) then
        {
            set FLAG to False
            break out of inner loop
        }
    }
    if FLAG is True, display the word, there is no duplicate
}

This way you will not print the duplicates if there is one further down the list -- you print the last occurence of each word. This will give you
two
one
three
four
five

Then you can work on your last step about sorting.

Hi Walt,

When trying out your pseudo code like this:

#include <iostream>

int main()
{
	char words[5][10];

	for (size_t i = 0; i < 5; ++i)
		std::cin >> words[i];
	std::cout << std::endl;


	for (size_t i = 0; i < 4; i++)
	{
		bool contr = true;
		for (size_t j = 0; j < 5; j++)
		{
			if(words[i] == words[j])
			{
				contr = false;
				break;
			}
		}
		if(contr == true)
			std::cout << words[i] << '\n';
	}

	std::cin.ignore(2);

	return 0;
}

And enter:
one
two
one
four
five

I get no output at all, while the idea is to have:
one
two
four
five

Instead I would do something like this:...

Yep, that did the trick Lerner, it works, only thing I had to change is the initialization of the first word like this:

//first word hasn't been printed before so it will always be printed
	short i = 0;
	std::cout << wordArr[i] << std::endl;

If I didn't do that, the first word wouldn't be printed, instead, junk that was in the array would be printed.

Thanks for that example.

Yes I should have writtten:

cout << wordArr[0];

instead of

cout << wordArr;

In looking at your attempt to work through WaltP's approach I notice you try to compare two C style strings with the == operator. That can't be done. You must use strcmp(), or one of it's cousins. You can compare STL strings with the == operator, but you aren't using them in this program. Other than that, the code looks like it should work, and the logic behind the code seems applicable as well.

You will find that there is seldom one way to write a project. Try to work out the logic in your head and write down the pseudocode before writing code. To start out at least I'd encourage you to use the psuedocode as comments for the actual code to reinforce how you change one into the other. This tends to cause excessive comments, so down the road you won't want to do this, but earlier on in your learning curve it can really help reach your goal.

Hi all,

Lerner, thanks for those tips, I'll try to remember and use them in my future projects, however small they are !

I'll give the pseudo code from WaltP another try and see whether I can get it to work using that, thanks for the help WaltP !!!

Ive finished the exercise which went as follows:
- Read a sequence of words from input. Use Quit as a word that terminates the input. Print the words in the order they were entered. Don't print a word twice(had major difficulty with this(thanks to Lerner and s.o.s for the help). Modify the program to sort the words before printing them.

#include <iostream>

short input(char arr[][10], const short);
void compare(char arr[][10], const short);
void sort(char arr[][10], const short);

int main()
{
	const short SIZE = 10;
	short amount = 0;
	char wordArr[SIZE][10];

	amount = input(wordArr, SIZE);

	compare(wordArr, amount);
	
	std::cin.ignore(2);

	return 0;
}

short input(char arr[][10], const short SIZE)
{
	char tempStr[10][10];
	short amount = 0;

	for(short i = 0; i < SIZE; i++)
	{
		std::cin >> tempStr[i];

		if(strcmp(tempStr[i], "Quit") == 0)
		{
			strcpy_s(arr[i], tempStr[i]);
			return amount;
		}
		else
		{
			strcpy_s(arr[i], tempStr[i]);
			amount++;
		}
	}
	return amount;
}

void compare(char arr[][10], const short SIZE)
{
	bool contr = false;  //declare and set a boolean variable to act as a flag

	sort(arr, SIZE);	//call the sorting function before output

	//for each word in wordArr after first word and call it current word
	for(short i = 0; i < SIZE; i++)
	{
		//look at all prior words in wordArr
		for(short j = 0; j < i; j++)
		{
			//if any prior word in wordArr is the same as current word
			if(strcmp(arr[i], arr[j]) == 0)  //use straightforward strccmp() logic
			//assign the value of true to the flag    
			contr = true;   //convert strcmp logic to boolean logic
		}
		//now that all prior words have been looked at, evaluate the value of contr
		if ((contr == false) && (!strcmp(arr[i],"Quit") == 0))
			//if the current word wasn't found in list of prior words
			//print it out
			std::cout << arr[i] << '\n';
		else
			//if current word was found in list of prior words
			//reset value of contr to false, but don't print it out
			contr = false;

	//go to next word in wordArr, if there is one
	}
}

void sort(char arr[][10], const short SIZE)
{
	for (short i = 0; i < SIZE; i++)
		for (short j = 0; j < i; j++)
		{
			// if the next word is alphabetically smaller then the current word
			if(strcmp(arr[i], arr[j]) == -1)
			{
				// change it's position by using a temporary stacking place
				char temp[10];
				strcpy_s(temp, arr[i]);
				strcpy_s(arr[i], arr[j]);
				strcpy_s(arr[j], temp);
			}
		}
}

The reason for posting this is the following:

- Can I improve this code without using strings? I'm going to make an alternative exercise with using strings.

- As you can see in the code, I used strcpy_s() for the reason that when using strcpy() I would get a warning mentioning the following.

warning C4996: 'strcpy' was declared deprecated
d:\microsoft visual studio\vc\include\string.h(73) : see declaration of 'strcpy'
Message: 'This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'

Ive tried adding #include <cstring> or #include <string> without any result, thought that to be the problem but apparantly it's not.

Does any of you guys know what that means and why I can't use strcpy ?

Hmm...actually too many logical problems:

1. strcpy_s is a non standard function which works only in the case of MS compilers and would not compile on any other standard compilers. Stay away from it and just do as the warning says i.e. use _CRT_SECURE_NO_DEPRECATE.

I guess its just MS's way of saying that they know the standards better than the standard setters so you better use their new functions. IMHO stay away from it and use normal functions.

2.

short input(char arr[][10], const short SIZE)
{
    char tempStr[10][10];
    short amount = 0;

    for(short i = 0; i < SIZE; i++)
    {
        std::cin >> tempStr[i];
       <snip>
    }
}

Come on Jobe, why you need to declare a temporary two dimensional character array for holding the temporary string when you can do the same using a single character array.
Something like:

short input(char arr[][10], const short SIZE)
{
    // if possible always initialize variables to avoid subtle bugs
    char tempStr[BUFSIZ] = { '\0' } ;
    short amount = 0;

    for(short i = 0; i < SIZE; i++)
    {
        std::cin >> tempStr ;
       <snip>
    }
}

3. The given piece of code is well..bad. Declaring variables or placing snippets which always perform a constant function inside a loop is bad programming practice. It wastes your precious memory and processor cycles..
You wrote:

if(strcmp(arr[i], arr[j]) == -1)
{
     // what is a variable declaration doing inside a loop !!!
    // move it outside and place it at the start of function
     char temp[10];

     strcpy_s(temp, arr[i]);
     strcpy_s(arr[i], arr[j]);
     strcpy_s(arr[j], temp);
}

MOve the variable declaration outside the loop.

4. And oh yeah...dont bother using short, int is better since normally int occupies 32 bytes which is normally the word size of your processor, so the data which is of the word size gets processes faster since its taken up in one sweep, rather than bothering the processor pick up 16 bits..

Many people won't agree to this, but this is my humble opinion and from what I have studied in "Microprocessors".

Hope it helped, bye.

Note, strcmp returns 0, less than 0 or greater than 0. It doesn't necessarily return -1 if the first parameter is less than the second. It may return -3 or -111, who knows. It will be less than 0, but the exact value isn't mandatory. Therefore, I would recommend you use something like this:

if(strcmp(arr, arr[j]) < 0)

rather than this:

if(strcmp(arr, arr[j]) == -1)

Comments
Ah good one, it escaped my eyes ;)

Therefore, I would recommend you use something like this:

if(strcmp(arr, arr[j]) < 0)

rather than this:

if(strcmp(arr, arr[j]) == -1)

Yes I would ask you to compulsorily make the change.

Normally the strcmp( ) returns -1 , 0 or 1.

Try out this program:

#include <stdio.h>
#include <string.h>

int main( )
{
    // all return -1 on my compiler
    printf( "The ans is %d", strcmp( "ABCD", "abcd" ) ) ;
    printf( "The ans is %d", strcmp( "abcc", "abcd" ) ) ;
    printf( "The ans is %d", strcmp( "abcb", "abcd" ) ) ;

    getchar( ) ;
    return 0;
}

But the documentation states that it returns a value lesser than 0 when the first string is less than the second string so you are better off using the < operator rather than comparing for -1.

This question has already been answered. Start a new discussion instead.