Thread: Minor Problem

  1. #1
    Registered User
    Join Date
    Mar 2005
    Posts
    27

    Minor Problem

    Hi,

    I have just been rounding off learning the basics of working with C++ at the console level by coding a very simple game. Part of this entails opting to play the game again.

    Basically, i if the user enters "y" then i need to call the start function again otherwise the program can terminate normally.

    Code:
    int main() {
     start();
    
     cout << "Play Again? (y/n)... ";
     
     cin.ignore();
     cin.getline(again,2);
     cout << "|" << again << "|" << endl; //debug: again is empty?
     if (strcmp(again,"y") == 0) start();
    
     system("pause");
    
     return 0;
    }
    I also have (before the above):

    Code:
    char again[2];
    Before strcmp i also tried: if (again == "y") {

    The problem seems to be before that though, with getline as the again variable is empty.

    How should i be doing this?

    Thank you

  2. #2
    Registered User
    Join Date
    May 2003
    Posts
    82
    You can't use cout on a c-string.
    I'm not sure what the best way to output a c-string is (you could write the function to loop through and print each char, but it may have been done better/before elsewhere*).

    The problem goes away if you use the string class though. Also simplifies the comparisons and input.

    * quick c-string output, probably not perfect:
    Code:
    void strOut(char start[], ostream& out = cout) {
         while(*start != '\0')
         {
           out << *start;
           start++;
         }
    };
    Last edited by AH_Tze; 04-04-2005 at 03:18 PM.

  3. #3
    Registered User
    Join Date
    May 2003
    Posts
    82
    Much cleaner. String has been implemented so you can use the stream insertions with it (cout << and cin>>). You can also directly compare them, no messing around with strcmp.

    Code:
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    void start() {
         cout << "Start stub" << endl;     
    };
    
    
    int main() {
        string againChoice; // holds user input choice
        string repeat("y"); // value to flag a repeat
        
     start();
    
     cout << "Play Again? (y/n)... ";
     
     cin >> againChoice;
     cout << "|" << againChoice << "|" << endl; //debug: should look good
     if (againChoice == repeat) 
        start();
    
     system("pause");
    
     return 0;
    }

  4. #4
    Registered User
    Join Date
    Mar 2005
    Posts
    27
    Thank you =)

    I wasn't aware you could set a variable as type string, i had thought you could only use an array with char arr[n] in c++.

  5. #5
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by AH_Tze
    You can't use cout on a c-string.

    ...

    The problem goes away if you use the string class though. Also simplifies the comparisons and input.
    Of course you can. (But just because you can doesn't mean you should. C++ gives us the string class. I agree that it's waaaay better --- usually.)

    Code:
    #include <iostream>
    
    using std::cout;
    using std::endl;
    using std::cin;
    
    int main()
    {
      char again[2];
    
      cout << "Play Again? (y/n)... ";
     
      cin.getline(again,2);
    
      cout << "Here's again |" << again << "|" << endl;
    
      if (strcmp(again,"y") == 0){
        cout << "strcmp() evaluated to zero" <<endl;
      }
      else {
        cout << "strcmp() did not give zero" << endl;
      }
    
      return 0;
    }
    Regards,

    Dave

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Code:
    char again[2];
    Before strcmp i also tried: if (again == "y")
    char literals are denoted with single quotes:

    if(again=='y')

    while string literals are denoted with double quotes:

    "some text"

    A string literal can be used to initialize a char array:

    char again[] = "y";

    However, that is a two step process. If I've got this right, what happens is that when the compiler sees a string literal, it first tacks on a '\0' to the end of the string literal:

    y\0

    and stores it in memory somewhere. Then, the address is assigned to the variable 'again'.
    So, in actuality, a char array name is a pointer to a string in memory(see below as to why that is difficult to prove). Therefore, when you do this:

    if (again == "y")

    you are comparing an address stored in the pointer 'again' to "y". But, an address looks something like this: 006BFDF4, so they will never be equal.

    To compare c-strings, you have to use strcmp() in <cstring>. strcmp() returns 0 if the cstrings are equal:
    Code:
    char again[] = "y";
    
    if(strcmp(again, "y")==0)
    {
    	cout<<"they are the same"<<endl;
    }
    else
    {
    	cout<<"not the same"<<endl;
    }
    Quote Originally Posted by AH_Tze
    You can't use cout on a c-string.
    In fact, cout<< is specifically tailored to handle c-strings. c-string variables are pointers to the strings, and normally when you cout<< a pointer variable, you get an address:
    Code:
    int num = 10;
    int* p = &num;
    cout<<p<<endl; //006BFDF4
    However, with c-strings the <<operator is programmed to automatically convert the address to the value at that address, and display the string:
    Code:
    char text[] = "some text";
    cout<<text<<endl;  //some text
    That is why it is hard to know that a char array name is actually a pointer.

    Where you may have gotten confused is that there is a distinction between an "array-of-chars" and a c-string. The terms char arrays and c-strings are sometimes used interchangeably, but then you have to have a term to identify another entity, which I'm calling an "array-of-chars". An "array-of-chars" is different from a c-string/char array. The defining aspect of a c-string/char array is that the array ends with a '\0' character. That '\0' character enables the <cstring> functions and cout<< to know when the end of the array has been reached, and to stop. With an array-of-chars, there is no '\0' character at the end of the array, so the <cstring> functions and cout<< will run past the end of the array and go out of bounds, spewing out all kinds of junk characters. Here is an example:

    char my_array[] = {'a', 'b', 'c'};
    cout<<my_array<<endl; //abc#@$

    If you try that, it will display abc, but then you will also get a bunch of junk after that, as the <<operator runs past the end of the array. There is no '\0' char to signal the end of the array, so the <<operator keeps going.

    To ouput an array-of-chars, you have to use a for-loop and output each char one at a time. You also need to know the size of the array, so you can tell the for-loop when to stop, and prevent it from going out of bounds:

    Code:
    char my_array[] = {'a', 'b', 'c'};
    
    for(int i=0; i<3; i++)
    {
    	cout<<my_array[i];
    }
    cout<<endl;
    Presumably, the <<operator is programmed to ouput a c-string in much the same way, it just has to check for the '\0' char so it doesn't go out of bounds:
    Code:
    char my_array[] = "abc";
    
    int i = 0;
    while(my_array[i] != '\0')
    {
    	cout<<my_array[i];
    	i++;
    }
    Similarly, the <cstring> functions are all pretty simple functions that just loop through a char array until they come across a '\0', and then they end.
    Last edited by 7stud; 04-04-2005 at 05:24 PM.

Popular pages Recent additions subscribe to a feed