Page 2 of 2 First 12
  • Jump to page:
    #16
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    2
    Okay,

    Cigar and Don't Cry shouldn't be listed as palindromes and I'm trying to figure out why everything is listed as being a palindrome.

    Also, Madam is printed 5 times, Lid Off A Daffodil is printed 7 times, Red Lost solider is printed 2 times, and cigar is printed 14 times.

    So, I tried sitting through the logic thus far:

    I understand that I created an array of strings called phrases, and that I also made a string called letters that will act as accumulator late ron. I also understand the for each loop will look at each individual "phrase" string in the phrases array. Another for each loop will examine each character in the current phrase, and check to see if its a letter, and if so, it will add its lower case form to the letters accumulator.

    Another for loop will go throughout half the entire length in the opposite direction, and also check with an if loop to see if the current position of letters matches the position in the opposite direction with the previous for each loop.

    Finally an output statement is made during the course of this for loop to determine whether or not a palindrome exists.

    Here's my code, indented like you had. Though I see an extra tab for line 39, is that this website's formatting or is this okay? I went with it, and it ran okay, but obviously I'm going wrong somewhere in my logic:

    Code:
    // Chapt4_Exercise6.cpp : main project file.
    
    #include "stdafx.h"
    #include "ctype.h"
    
    using namespace System;
    
    int main(array<System::String ^> ^args)
    {
    
    /* Write a C++/CLI program that creates an array containing the following strings:
    
    “Madam I’m Adam.”
    “Don’t cry for me, Marge and Tina.”
    “Lid off a daffodil.”
    “Red lost soldier.”
    “Cigar? Toss it in a can. It is so tragic.”
    
    The program should examine each string in turn, output the string and indicate 
    whether it is or is not a palindrome (that is, the same sequence of letters reading 
    backward or forward, ignoring spaces and punctuation).
    
    */
    
    	array<String^>^ phrases = {L"Madam I'm Adam.", 
    							   L"Don't cry for me, Marge and Tina.",
    							   L"Lid off a daffodil.", 
    							   L"Red lost soldier.", 
    							   L"Cigar? Toss it in a can. It is so tragic."};
    
    	String^ letters;
    
    	bool isPalindrome;
    
    	for each(String^ phrase in phrases)
    	{
    
    			// Extract the letters and make them lower case:
    			letters = L"";
    
    			for each(wchar_t ch in phrase)
    				if (Char::IsLetter(ch))
    						letters += Char::ToLower(ch);
    
    			// Test for Palindrome:
    			isPalindrome = true;
    			for (int i = 0; i < letters->Length / 2; i++)
    			{
    					if (letters[i] != letters[letters->Length-i-1])
    					{
    							isPalindrome = false;
    							break;
    					}
    
    					Console::WriteLine(L"\"" + phrase + L"\" " 
    					+ (isPalindrome ? "is":  "is not") + L" a palindrome.");
    
    			}
    		
        
    	}
    
    	return 0;
    
    }
  2. #17
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    Read your code for comprehension.

    For each character in letters, you do this:
    1. test for corresponding characters not being equal. If they are not equal, then set isPalindrome to false and break out of the for loop.

    2. WriteLine phrase and report its current isPalindrome status. Of course, once isPalidrome is set to false you will no longer reach this line of the code, so you just repeatedly output the phrase and report that it's a palindrome until you do hit a mismatch. Sometimes it takes two characters to find a mismatch, etc.

    That is what your for loop does. Is that what you want it to do? That is certainly what you describe it as doing.

    If you only want that WriteLine to happen after you have finished testing letters for being a palindrom, then that WriteLine belongs outside the for loop.

    Think about what you want your code to do and think about what your code is actually doing. Your goal is to make those the same.
  4. #18
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    2
    I put the output statement OUTSIDE the for loop that checks for palindromes, and the program works fine.

    The only exception I have to work on is Madam, because obviously its not a complete palindrome because of the I'm (there would have to be two I's and M's in the middle to make some nonsensical word for it to really pass the test)

    The main problem probably lies within the logic behind the for loop's conditions that tells it to go half of the length.

    For some reason, I'm still not getting why Madam is still being considered as a palindrome. All I could think of it to maybe add another condition like a for loop or if statement to prevent that type of case from occurring...

    That's IT! The problem DOES lie in that for loop! To start halfway along the length would work for the other phrases, but for the ****ing Madam phrase, there's an I'm to trip that logic off completely (real clever, author... clever... -_-)

    All I could think of now is to maybe add an if statement or something, I'm trying to think of some universal way to catch a statement like Madam with characters that don't match in the middle. Just as I thought going both ways made sense, now I realized it just shot me in the foot!

    Anyway, here's my code thus far, I'm a bit frustrated at myself on how I don't know what to do:

    Code:
    // Chapt4_Exercise6.cpp : main project file.
    
    #include "stdafx.h"
    #include "ctype.h"
    
    using namespace System;
    
    int main(array<System::String ^> ^args)
    {
    
    /* Write a C++/CLI program that creates an array containing the following strings:
    
    “Madam I’m Adam.”
    “Don’t cry for me, Marge and Tina.”
    “Lid off a daffodil.”
    “Red lost soldier.”
    “Cigar? Toss it in a can. It is so tragic.”
    
    The program should examine each string in turn, output the string and indicate 
    whether it is or is not a palindrome (that is, the same sequence of letters reading 
    backward or forward, ignoring spaces and punctuation).
    
    */
    
    	array<String^>^ phrases = {L"Madam I'm Adam.", 
    							   L"Don't cry for me, Marge and Tina.",
    							   L"Lid off a daffodil.", 
    							   L"Red lost soldier.", 
    							   L"Cigar? Toss it in a can. It is so tragic."};
    
    	String^ letters;
    
    	bool isPalindrome;
    
    	for each(String^ phrase in phrases)
    	{
    		
    			// Print out current phrase:
    			Console::WriteLine();
    			Console::WriteLine(L"Current phrase being examined: {0}", phrase);
    			Console::WriteLine();
    
    
    			// Extract the letters and make them lower case:
    			letters = L"";
    
    			for each(wchar_t ch in phrase)
    				if (Char::IsLetter(ch))
    						letters += Char::ToLower(ch);
    
    			// Test for Palindrome:
    			isPalindrome = true;
    			for (int i = 0; i < letters->Length / 2; i++)
    			{
    					if (letters[i] != letters[letters->Length-i-1])
    					{
    							isPalindrome = false;
    							Console::WriteLine(L"Current status of isPalindrome: {0}", isPalindrome);
    							break;
    					}
    
    					// How can I test against the Madam phrase... What makes it
    					// so special that as i goes along half of the length of 
    					// the string that it causes it to stop being checked and
    					// be considered as a palidrome
    
    					// Shouldn't it be false as soon as the 'I' in 'I'm' and the
    					// corresponding 'm' in "I'm' are reached? 
    
    			}
    
    			// After the program is finished checking the entire length of
    			// the current phrase and determining if its a palindrome, print
    			// the results:
    
    			Console::WriteLine(L"\"" + phrase + L"\" " 
    			+ (isPalindrome ? "is":  "is not") + L" a palindrome.");
    
    	}
    
    	return 0;
    
    }
  6. #19
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    Originally Posted by HauntJemimah
    The only exception I have to work on is Madam, because obviously its not a complete palindrome because of the I'm (there would have to be two I's and M's in the middle to make some nonsensical word for it to really pass the test)
    Huh? How is it not a palindrome?
    Code:
    forwards  /  backwards
          m   /   m
          a   /   a
          d   /   d
          a   /   a
          m   /   m
          i   /   i
          m   /   m
          a   /   a
          d   /   d
          a   /   a
          m   /   m
    Now, your for loop could possibly not be quite correct. It has a boundary condition that you need to verify in the center of the string being tested, in that it is possible that you are not testing the center letters. You should examine its behavior for both even length and odd length strings.

    "Madam I'm Adam." has an odd length. Modifying that string using your for loop, here is what I get (you can see the changes I make in the output):
    "Madam I'm Adam." is a palindrome.
    "Madam I'im Adam." is a palindrome.
    "Madam I'n Adam." is not a palindrome.
    "Madam I'nm Adam." is not a palindrome.
    So it appears that your for-loop is working correctly. You could have also tested it with pencil and paper by stepping through the process with both even- and odd-length strings and verifying that each letter is incorporated in the testing.

    Just to see a slightly different approach, I recently wrote this for-statement for a string reversal:
    Code:
            for (i=0, j=strlen(r)-1; j>i; i++, j--)
            {
                n = r[i];
                r[i] = r[j];
                r[j] = n;
            }
    Note that i and j are initialized to point to the first and last characters of the string, respectively. Then I increment i and decrement j in each iteration so that they point to their corresponding characters. I only do this so long as j is greater than i: in an even-length string I'm done once the indices have passed each other, and in an odd-length string I'm done as soon as they both point to the same character position in the string. In this code example, it is better to place that evaluation based on string length in one place since I need to apply the j index in more than one place; it's just my programming style that I prefer to perform a calculation or function call only once if possible and save the result in a variable for repeated use.
  8. #20
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    2
    Code:
            for (i=0, j=strlen(r)-1; j>i; i++, j--)
            {
                n = r[i];
                r[i] = r[j];
                r[j] = n;
            }
    Woah, awesome. I would have never figured that out lol, pretty intuitive and makes sense.

    Though, I should still put 'int''s in front of i and j inside the conditions in the for loop though right?

    i and j make total sense, but the use of r I guess is throwing me off a little bit, same with another n to match.

    r appears to be the string itself. n is the corresponding element that follows i, from left to right.
  10. #21
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    That was from one iteration I quickly jotted down (and ran for myself) for sparky's recent Need help with converting thread; what I ended up posting used an entirely different approach that didn't require reversing the string. Sorry I can't post the program, but that's on my computer at work and this is one of my Fridays off.

    r is a char array, though it could actually be an array of anything; that fact that I was working with chars makes absolutely no difference in the code. Plus, n is just a temporary variable needed to hold the value of r[i] which is about to get replaced by r[j]. In most swap loops, n would have been named temp; I was just using the variables that sparky had declared but wasn't using (or was using incorrectly). And OBTW, the body of that for loop is the basic code for swapping the values of two variables; you will use it yourself when you write a sort routine.

    Originally Posted by HauntJemimah
    Though, I should still put 'int''s in front of i and j inside the conditions in the for loop though right?
    That all depends. I wrote that in C, so I had declared all the variables up at the top of the function -- in C89 it is illegal to declare a new variable in the midst of code, but it is allowed in C++ and in C99.

    Similarly, you could declare i and j within the for-statement as you ask, but only if you hadn't already declared them before that for-statement. What you describe is common C++ idiom, but that doesn't require you to do it that way.
  12. #22
  13. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    2
    I declared the integer variables at the top of the loop and tried to implement the for loop you suggested instead of my other embedded for loop.

    The main errors I have are with the conditions within the for loop, as well as the three lines you suggested due to me not knowing that they do not have a 'set' method (I have no idea what that means)

    Here is the error on line 58 that I am talking about:

    Code:
    .\Chapt4_Exercise6.cpp(58) : error C3070: 'System::String::default': property does not have a 'set' method

    The other errors are regarding the for loop's conditional statements on Line 55 for missing semicolons and parenthesis (I have no idea why).

    Here's my code thus far:
    Code:
    // Chapt4_Exercise6.cpp : main project file.
    
    #include "stdafx.h"
    #include "ctype.h"
    
    using namespace System;
    
    int main(array<System::String ^> ^args)
    {
    
    /* Write a C++/CLI program that creates an array containing the following strings:
    
    “Madam I’m Adam.”
    “Don’t cry for me, Marge and Tina.”
    “Lid off a daffodil.”
    “Red lost soldier.”
    “Cigar? Toss it in a can. It is so tragic.”
    
    The program should examine each string in turn, output the string and indicate 
    whether it is or is not a palindrome (that is, the same sequence of letters reading 
    backward or forward, ignoring spaces and punctuation).
    
    */
    
    	array<String^>^ phrases = {L"Madam I'm Adam.", 
    							   L"Don't cry for me, Marge and Tina.",
    							   L"Lid off a daffodil.", 
    							   L"Red lost soldier.", 
    							   L"Cigar? Toss it in a can. It is so tragic."};
    
    	String^ letters;
    
    	bool isPalindrome;
    
    	int i, j, r, n;
    
    	for each(String^ phrase in phrases)
    	{
    		
    			// Print out current phrase:
    			Console::WriteLine();
    			Console::WriteLine(L"Current phrase being examined: {0}", phrase);
    			Console::WriteLine();
    
    
    			// Extract the letters and make them lower case:
    			letters = L"";
    
    			for each(wchar_t ch in phrase)
    				if (Char::IsLetter(ch))
    						letters += Char::ToLower(ch);
    
    			// Test for Palindrome:
    			isPalindrome = true;
    			for (i = 0; j = strlen(phrase)-1; j>i; i++; j--)
    			{
    					n = phrase[i]; 
    					phrase[i] = phrase[j]; 
    					phrase[j] = n;
    
    					if (letters[i] != letters[letters->Length-i-1])
    					{
    							isPalindrome = false;
    							Console::WriteLine(L"Current status of isPalindrome: {0}", isPalindrome);
    							break;
    					}
    
    					// How can I test against the Madam phrase... What makes it
    					// so special that as i goes along half of the length of 
    					// the string that it causes it to stop being checked and
    					// be considered as a palidrome
    
    					// Shouldn't it be false as soon as the 'I' in 'I'm' and the
    					// corresponding 'm' in "I'm' are reached? 
    
    			}
    
    			// After the program is finished checking the entire length of
    			// the current phrase and determining if its a palindrome, print
    			// the results:
    
    			Console::WriteLine(L"\"" + phrase + L"\" " 
    			+ (isPalindrome ? "is":  "is not") + L" a palindrome.");
    
    	}
    
    	return 0;
    
    }
  14. #23
  15. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    I keep telling you to think about what you are writing and read what you have written for comprehension (IOW, think about what it says!), but you don't seem to be listening.

    You are writing in C++/CLI. That is not the same as C89. It's not even the same as C++. Yes, a number of C89 statements can also be used in C++/CLI, but the likelihood of that holding true diminishes rapidly when you use data types that are unique to C++/CLI. So when you plop some strictly C89 code into a C++/CLI program, you must be prepared to translate it into C++/CLI.

    You may research solutions to your problems from other sources, but the vast majority of those other sources will be in other languages. That means that when you do research from another language, then you must translate that researched material into your target language. For example, if I'm writing a paper in English and I find some information in a German source, I would have to be a complete idiot to just plop that German information into my paper instead of translating the German information into English. That should be blatantly obvious to anybody, and yet it had escaped you.

    What you did was to plop C89 code into C++/CLI source. The main reason why it couldn't work is that you are calling a strings.h function (without #include'ing that header file, BTW, so the compiler had no idea what that was supposed to be!) that is designed to work on a C-style string, which is a completely different animal from a String reference which is what the argument, phrase, is actually declared to be. All you succeeded in doing was to confuse the compiler greatly, such that it thought you were trying to do something else which was coincidentally not supported (the set method error). If set were supported, then you may not have gotten any indication that, because of the compiler misunderstanding what you wanted it to do, your program would actually do something completely different from what you wanted it to do.

    And on top of all that, you proceeded to completely mess up the for-statement by ignoring the syntax for a for-statement.

    As I have already related to you, in my very first programming class, FORTRAN, I applied my language-learning skills to great benefit. I thought and wrote and read in terms of "What am I telling the computer to do?". When the output came back as not what I wanted, I would go directly to that part of my program and read it to see why I got the output that I did get and from that figure out how to change it to get what I wanted. At the same time, I observed my fellow students going into a panic and try one random change after another in the vain hope of something eventually working. That being 1978 and we being the lowest-ranking computer science students (hence with the least access to resources such as terminals), we wrote our programs on keypunch machines, drop our card decks into a bin for the operator to pick up and load into the mainframe's job queue, and then wait for our deck and printout to be placed in the out boxes. Total turn-around time averaged to about an hour. That meant that the random-change approach wasted a lot of time, a waste of time that I avoided by reading for comprehension. And, yes, we practically lived down in that basement which housed the computer center. Good times!

    Now to address the errors:
    Originally Posted by HauntJemimah
    I declared the integer variables at the top of the loop and tried to implement the for loop you suggested instead of my other embedded for loop.

    The main errors I have are with the conditions within the for loop, as well as the three lines you suggested due to me not knowing that they do not have a 'set' method (I have no idea what that means)
    Code:
    			for (i = 0; j = strlen(phrase)-1; j>i; i++; j--)
    			{
    					n = phrase[i]; 
    					phrase[i] = phrase[j]; 
    					phrase[j] = n;
    As I already said, I immediately decided to learn C# instead of C++/CLI, since I already knew C++ quite well and if I were to be required to learn an entirely new language, then C#, the language intimately tied to .NET, would be the better choice. Of course, being four years from retirement (and able to retire tomorrow if I chose or needed to) in a job where we have no plans to dive into the .NET world, I can safely afford to ignore C++/CLI. OTOH, you have many decades ahead of you during which you may well need to know C++/CLI or whatever that will evolve into, plus you will have to constantly learn new languages and development environments, so C++/CLI is a valid step for you to learn. So one of the important things for you to learn is how to learn a programming language; over the years you're going to be spending a lot of your time doing just that.

    I have no idea what you can and cannot do with a String^. But String is a .NET-provided datatype which also appears in C#, as do many of the functions and namespaces that you will be using. In C++, when you declare a class you are supposed to hide the class' properties by declaring them to be private. Then in order to be able to access those private properties you declare public access methods through which you can get and set the values of those private properties, usually incorporating some kind of validation and/or unit translation. In C#, you can create actual get and set methods to do that and which you call by simply using the object's name. I assume that that is what that error message is about. Though it could be that String does have a set method, but it has no idea how to set a String method to an integer value, which is what n is declared to be.

    But my real question is: What the hell were you thinking? I specifically told you that that code was for swapping the values of two variables as part of the operation of reversing a C-style string. Your program has no purpose for trying to reverse a string and most decidedly not a C-style string. What were you thinking?

    And why did you screw up the for statement like that?
    Code:
    			for (i = 0; j = strlen(phrase)-1; j>i; i++; j--)
    You know the syntax for a for-statement! Abridged from C Syntax in BNF:
    Code:
    iteration_stat        : 'for' '(' exp ';' exp ';' exp ')' stat
    So how could you have written what you did? You already know that a for-statement has two and only two semicolons separating three and only three expressions. And that each of those three and only three expressions has a very well-defined purpose. So why did you add two extra expressions?

    Now at that same website, look at the syntax for an expression, exp:
    Code:
    exp                 : assignment_exp
                        | exp ',' assignment_exp
                        ;
    assignment_exp      : conditional_exp
                        | unary_exp assignment_operator assignment_exp
                        ;
    Of course, it expands rapidly from there. The main point is the comma operator, which is used to combine multiple expressions together. Look at the for-statement that I had given you and compare it with what you had distorted it into. What I had written:
    Code:
            for (i=0, j=strlen(r)-1; j>i; i++, j--)
    There the first expression is: i=0, j=strlen(r)-1
    As you can see, the two parts of this expression initializes the two variables, i and j.

    The second expression, j>i, does not use the comma operator nor should it normally. All expressions evaluate to a value and an expression consisting of expressions chained together by the comma operator evaluates to the value of the last expression. So if you were to use the comma operator in the test expression, the first expressions would have no effect (unless they produce side-effects).

    The third expression is: i++, j--
    As you can clearly see, it changes the values of the two variables, i and j.

    When you replaced those commas with semicolons, you completely messed that for-statement up beyond all recognition, AKA FUBAR. It just plain violated the syntax for a for-statement, so the compiler didn't even bother to try to figure it out.


    You need to learn to think about what you are writing!
  16. #24
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    187
    Rep Power
    82
    The source of your problem is a closing brace that is located in the wrong position. Below is corrected code from post #16. Please note the closing brace position.

    Code:
    //#include "stdafx.h"
    //#include "ctype.h"
    
    using namespace System;
    
    int main(array<System::String ^> ^args)
    {
    
        /* Write a C++/CLI program that creates an array containing the following strings:
    
        “Madam I’m Adam.”
        “Don’t cry for me, Marge and Tina.”
        “Lid off a daffodil.”
        “Red lost soldier.”
        “Cigar? Toss it in a can. It is so tragic.”
    
        The program should examine each string in turn, output the string and indicate
        whether it is or is not a palindrome (that is, the same sequence of letters reading
        backward or forward, ignoring spaces and punctuation).
    
        */
    
        array<String^>^ phrases = {L"Madam I'm Adam.",
                                   L"Don't cry for me, Marge and Tina.",
                                   L"Lid off a daffodil.",
                                   L"Red lost soldier.",
                                   L"Cigar? Toss it in a can. It is so tragic."
                                  };
    
        String^ letters;
    
        bool isPalindrome;
    
        for each(String^ phrase in phrases)
        {
    
            // Extract the letters and make them lower case:
            letters = L"";
    
            for each(wchar_t ch in phrase)
                if (Char::IsLetter(ch))
                    letters += Char::ToLower(ch);
    
            // Test for Palindrome:
            isPalindrome = true;
            for (int i = 0; i < letters->Length / 2; i++)
            {
                if (letters[i] != letters[letters->Length-i-1])
                {
                    isPalindrome = false;
                    break;
                }
            }
            Console::WriteLine(L"\"" + phrase + L"\" "
                               + (isPalindrome ? "is":  "is not") + L" a palindrome.");
    
    //			}
    
    
        }
    
        return 0;
    
    }
    Last edited by BobS0327; October 26th, 2013 at 11:45 PM.
  18. #25
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    2
    Originally Posted by BobS0327
    The source of your problem is a closing brace that is located in the wrong position. Below is corrected code from post #16. Please note the closing brace position.

    Code:
    //#include "stdafx.h"
    //#include "ctype.h"
    
    using namespace System;
    
    int main(array<System::String ^> ^args)
    {
    
        /* Write a C++/CLI program that creates an array containing the following strings:
    
        “Madam I’m Adam.”
        “Don’t cry for me, Marge and Tina.”
        “Lid off a daffodil.”
        “Red lost soldier.”
        “Cigar? Toss it in a can. It is so tragic.”
    
        The program should examine each string in turn, output the string and indicate
        whether it is or is not a palindrome (that is, the same sequence of letters reading
        backward or forward, ignoring spaces and punctuation).
    
        */
    
        array<String^>^ phrases = {L"Madam I'm Adam.",
                                   L"Don't cry for me, Marge and Tina.",
                                   L"Lid off a daffodil.",
                                   L"Red lost soldier.",
                                   L"Cigar? Toss it in a can. It is so tragic."
                                  };
    
        String^ letters;
    
        bool isPalindrome;
    
        for each(String^ phrase in phrases)
        {
    
            // Extract the letters and make them lower case:
            letters = L"";
    
            for each(wchar_t ch in phrase)
                if (Char::IsLetter(ch))
                    letters += Char::ToLower(ch);
    
            // Test for Palindrome:
            isPalindrome = true;
            for (int i = 0; i < letters->Length / 2; i++)
            {
                if (letters[i] != letters[letters->Length-i-1])
                {
                    isPalindrome = false;
                    break;
                }
            }
            Console::WriteLine(L"\"" + phrase + L"\" "
                               + (isPalindrome ? "is":  "is not") + L" a palindrome.");
    
    //			}
    
    
        }
    
        return 0;
    
    }
    I tried this revision, and received ten more related errors... Are you sure about the bracket usage being the problem? (I'm actually not sure myself honestly).

    The way I see your solution Dwise is great, but honestly, if you think I'm too beginner for this forum, I'll post elsewhere.

    I don't mind criticism but I feel like I'm pissing you off or something, so if you don't want to reply to my posts, you don't have to.

    Either way, I did the revisions like you said to stop the semi colon usage between the i and j increments, which makes sense in that case to use commas since they are related. I think I've been so used to semi-colon usage in for loops that I forgot you could use commas in that case.

    And what you're doing with r, n, i, and j, makes sense to me, like some sort of three way equals sign.

    The problem is how to go from your C89 code to C++/CLI apparently.

    It appears to be okay though. I thought you could assign an individual element from an array to be any value you want. Maybe its because I have no idea what its meaning by 'set' method.

    The only thing I could think of is from that Coursera C# course in terms of the Get/Set methods for classes or constructors (I forget which one we used that idea for).
  20. #26
  21. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    187
    Rep Power
    82
    Are you sure about the bracket usage being the problem? (I'm actually not sure myself honestly).
    Listed below is the output that I get when make the brace change..
    "Madam I'm Adam." is a palindrome.
    "Don't cry for me, Marge and Tina." is not a palindrome.
    "Lid off a daffodil." is a palindrome.
    "Red lost soldier." is not a palindrome.
    "Cigar? Toss it in a can. It is so tragic." is a palindrome.
  22. #27
  23. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    Originally Posted by HauntJemimah
    The way I see your solution Dwise is great, but honestly, if you think I'm too beginner for this forum, I'll post elsewhere.

    I don't mind criticism but I feel like I'm pissing you off or something, so if you don't want to reply to my posts, you don't have to.
    I don't think there's such a thing as "too beginner for this forum." It's just that you don't seem to be listening, but instead are trying to do random things. Of course you'll make mistakes along the way, but you really do need to think about what you are saying in your code.

    Originally Posted by HauntJemimah
    Either way, I did the revisions like you said to stop the semi colon usage between the i and j increments, which makes sense in that case to use commas since they are related. I think I've been so used to semi-colon usage in for loops that I forgot you could use commas in that case.
    Understand the syntax. Understand what the semicolons are used for. Understand what the commas are used for. And understand that commas and semicolons are not interchangeable.

    Originally Posted by HauntJemimah
    The problem is how to go from your C89 code to C++/CLI apparently.
    The only line of real interest is the for-statement itself. I only included the string reversal swaps as an example of how i and j were being used. The string reversal code can serve no purpose in your program and should not be included.

    The only thing that needs to change in the for-statement would be how you get the length of the string. In my C89 code, that string is a C-style string and hence its length needed to obtain with a function that works on a C-style string. In your program, the string is a String^, so you need to substitute however you obtain the length of a String^.

    Hence, among other things you need to pay attention to the datatypes you are translating from and to and the differences in how they are manipulated. Just as it is in all translation from one language to another, even with human languages, you need to come up with code that will mean the same thing as in the original.

    In the future, you will find yourself doing a lot of translation from one language to another, so there's no time like the present to start learning how to do it.

    Originally Posted by HauntJemimah
    It appears to be okay though. I thought you could assign an individual element from an array to be any value you want. Maybe its because I have no idea what its meaning by 'set' method.

    The only thing I could think of is from that Coursera C# course in terms of the Get/Set methods for classes or constructors (I forget which one we used that idea for).
    I thought I already described that. Since Horton has you using .NET data objects, such as String, he should cover it in the book. If not, then in your program single-click on String and then press the F1 function key. After several seconds (Visual Studio does seem to have a rather large overhead), the help page for String should appear. That page may or may not explicitly mention set/get, but you should notice methods which have the same name as the object, String. It is by using the name of the object as if it were a mere variable that the get and set methods are called.

    Normally, we aren't taught about get and set methods until we are being taught to write our own for our own classes. As I said, in C++ you would write access methods which have their own names. I do not know whether C++/CLI, being a different language than C++, supports the writing of get and set methods.

    At any rate, the only reason for you to know anything about set methods at this point is to understand that error message you got. Other than that you're not expected to even know that they exist. And when it comes time for you to create your own object classes, then you will be taught about access methods.
  24. #28
  25. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2013
    Posts
    232
    Rep Power
    2
    I tried using the .length() method from the "String" header file, based on this site:

    http://www.cplusplus.com/reference/string/string/length/

    BUT, this would only work in Native C++. Again, I'm just as confounded and still in disarray why Ivor Horton even mentions .NET, but as you mentioned, it won't hurt to know it too and I guess I won't skip those sections.

    Though, the difference being is that the use #include <string> and not #include "string"... so I'm not sure if I'm even doing this correctly.

    Alright looking at that section in my book, they really do use ->Length in an example, and now its blowing my mind on what to do.

    Maybe I added an additional space between the arrow and the Length property... I'm not sure.

    ALRIGHT!

    :rockon:

    I went back and added ->Length's to wherever I needed it instead of using .length(), and intellisense pretty much gave me the option. I built it and it obviously succeeded (there's probably going to still be errors, as expected but that moment was pure excitement regardless ;D)

    The only warnings are about how I don't reference r or n later on in the program, so obviously I should remove them from the top initialization statement.

    It runs and works beautifully now, and I'm actually pretty happy.

    At least I went from using crazy pointers to making some sense of it honestly. But, I do have a video on YouTube in my favorites queue that is just a tutorial on Pointers anyway, so maybe that'll clarify things EVEN MORE than that awesome article you posted on the topic.

    Either way, here's my code for those that are interested in the final product:

    Code:
    // Chapt4_Exercise6.cpp : main project file.
    
    #include "stdafx.h"
    #include "ctype.h"
    #include "string.h"
    
    using namespace System;
    
    int main(array<System::String ^> ^args)
    {
    
    /* Write a C++/CLI program that creates an array containing the following strings:
    
    “Madam I’m Adam.”
    “Don’t cry for me, Marge and Tina.”
    “Lid off a daffodil.”
    “Red lost soldier.”
    “Cigar? Toss it in a can. It is so tragic.”
    
    The program should examine each string in turn, output the string and indicate 
    whether it is or is not a palindrome (that is, the same sequence of letters reading 
    backward or forward, ignoring spaces and punctuation).
    
    */
    
    	array<String^>^ phrases = {L"Madam I'm Adam.", 
    							   L"Don't cry for me, Marge and Tina.",
    							   L"Lid off a daffodil.", 
    							   L"Red lost soldier.", 
    							   L"Cigar? Toss it in a can. It is so tragic."};
    
    	String^ letters;
    
    	bool isPalindrome;
    
    	int i, j;
    
    	for each(String^ phrase in phrases)
    	{
    		
    			// Print out current phrase:
    			Console::WriteLine();
    			Console::WriteLine(L"Current phrase being examined: {0}", phrase);
    			Console::WriteLine();
    
    
    			// Extract the letters and make them lower case:
    			letters = L"";
    
    			for each(wchar_t ch in phrase)
    				if (Char::IsLetter(ch))
    						letters += Char::ToLower(ch);
    
    			// Test for Palindrome:
    			isPalindrome = true;
    
    			// Declare a variable for length of the phrase itself:
    			const size_t phrase_length = phrase->Length;
    
    			// Make a for loop that will go throughout the length of the
    			// current phrase:
    			for (i = 0, j = phrase_length-1; j>i; i++, j--)
    			{
    					// Confused on this if statement:
    					// What it says: Basically, if the current element of
    					// the letters string is NOT equal to the element
    					// in the reverse direction that matches the forward
    					// direction (pretty clever imo), then declare the
    					// current palindrome as false
    
    					// Fix the -> Length since we are dealing with ^String:
    					if (letters[i] != letters[letters->Length-i-1])
    					{
    							isPalindrome = false;
    							Console::WriteLine(L"Current status of isPalindrome: {0}", isPalindrome);
    							Console::WriteLine();
    							break;
    					}
    
    			}
    
    			Console::WriteLine(L"\"" + phrase + L"\" " 
    			+ (isPalindrome ? "is":  "is not") + L" a palindrome.");
    
    			Console::WriteLine();
    
    	}
    	return 0;
    }
    Last edited by HauntJemimah; October 29th, 2013 at 03:20 PM.
  26. #29
  27. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    Originally Posted by HauntJemimah
    I tried using the .length() method from the "String" header file, ...

    Though, the difference being is that the use #include <string> and not #include "string"... ...
    I think that your confusion is that you don't quite realize that a string is entirely different from a String.

    First back to basics. Many programming languages, are case-insensitive, meaning that capitalization doesn't make any difference. That was what I worked with for my first 14 years of programming. For example, in Pascal, these would all be treated as the same thing: string, String, STRING, sTrInG. For that matter, MS-DOS was also case-insensitive, so the command-line commands could be capitalized or not and you could use any combination of upper- and lower-case letters in file and directory names. Windows is also case-insensitive; if in Windows Explorer you sort the files by name, then a.exe will go before A2.bat, because whether it's capitalized or not doesn't matter.

    UNIX is case-sensitive and, since C was basically co-designed with UNIX, so is C and so are most, if not all, C-ish languages (eg, C++, C#, Java). In a UNIX shell, LS would be a different command than ls. And if you list files sorted by name, A2.bat would go before a.exe; for that matter, even Zzz.txt would go before a.exe, since that is ASCII order. And since C and C++ and C++/CLI are case-sensitive, that means that string and String are two entirely different identifiers.

    Now for some very basic history. We started with C (which in turn came from B, which came from BCPL, but that's a different history) in 1971, which became K&R C in 1978, ANSI C in 1989, and C99 in 1999. C gave rise to C with Classes in 1980 which became C++ in 1983, which became C++ ANSI/ISO in 1998. In 2000, C# drew from both Java and C++. Under .NET, C++ begat Managed C++, which was later reformed into C++/CLI. In our discussions, we are only dealing with three of those languages and how they handle strings: C, C++, and C++/CLI.

    C did not have any built-in support for strings, so programmers developed the convention of the C-style string, which was merely an array of char terminated by a special character, the null-terminator ('\0'), and they developed a set of functions to perform common operations on those null-terminated char arrays, which became incorporated in the Standard C Library and are prototyped in string.h.

    At first, C++ just used C-style strings and the functions in string.h. But working with C-style strings is a lot of work and requires a lot of constant attention to detail, so one of the first personal projects for every C++ programmer was to create a string class to get away from having to work with C-style strings. Then in 1998, ANSI/ISO C++ introduced a standard basic string class, string. It also introduced new header files that did not have the .h file extension, so the header file for the basic string class was string and for C-style strings was cstring (actually, several C++ headers for the C headers were created, each one being the old C name prefixed with a 'c'; eg, cmath, cstdio). A vestigial of C++'s pre-1998 use of C-style strings is the fact that many iostream functions requiring a string argument, such as for opening a file, take a char pointer (indicative of a C-style string) instead of a basic string class. Also, iostream still has the strstream class which is for C-style strings, along with a new stringstream class for the new string class.

    Part of the development of the .NET framework was the create of a standard set of datatypes that would be available for all languages (eg, C#, C++, Visual Basic). For C# and Visual Basic, those .NET datatypes were the standard datatypes for those languages, whereas for C++ they were an extra set of datatypes in addition to the standard C++ datatypes. That means that in C++/CLI, the capitalization of the datatypes is extremely important, since that is what distinguishes between the .NET and the C++ datatypes.

    So then, we have these basic facts:

    1. A string is not a String, is not a C-style string. Each type of string is separate and unique and must be treated that way.

    2. In C, you have to use a C-style string.

    3. In C++, you may use the basic string class, or a C-style string. You need to know the differences in how to use the two.

    4. In C++/CLI, you may use the .NET String class, the basic string class, or a C-style string. You need to know the differences in how to use the three.

    5. To use a C-style string in either C++ or in C++/CLI, you include cstring.

    6. To use the basic string class in either C++ or in C++/CLI, you include string.

    7. In .NET, the String class is in the System namespace, so to use String in C++/CLI you need to use System. There is no header file for String.

    8. For each type of string, you can only use the functions and methods for that particular type. That means that if you use a String then you cannot try to use any of the basic string class' methods on it -- eg, a String uses Length while a basic string object uses length(), so you cannot use length() with a String nor Length with a basic string object.

    I hope that makes things clear for you.

    Originally Posted by HauntJemimah
    Again, I'm just as confounded and still in disarray why Ivor Horton even mentions .NET, but as you mentioned, it won't hurt to know it too and I guess I won't skip those sections.
    No, that is not the case. I believe and am quite certain that the reason why Ivor Horton even mentions .NET is because by writing in C++/CLI you are using .NET! Where do you think that the System namespace came from? From .NET! Where do you think that the String type came from? From .NET! By having chosen to learn C++/CLI, you have chosen to use .NET.

    You can start to familiarize yourself with .NET on Wikipedia (.NET):
    Originally Posted by Wikipedia
    The .NET Framework (pronounced dot net) is a software framework developed by Microsoft that runs primarily on Microsoft Windows. It includes a large library and provides language interoperability (each language can use code written in other languages) across several programming languages. Programs written for the .NET Framework execute in a software environment (as contrasted to hardware environment), known as the Common Language Runtime (CLR), an application virtual machine that provides services such as security, memory management, and exception handling. The class library and the CLR together constitute the .NET Framework.

    . . .

    The purpose of the Common Language Infrastructure (CLI) is to provide a language-neutral platform for application development and execution, including functions for exception handling, garbage collection, security, and interoperability. By implementing the core aspects of the .NET Framework within the scope of the CLI, this functionality will not be tied to a single language but will be available across the many languages supported by the framework. Microsoft's implementation of the CLI is called the Common Language Runtime, or CLR.
    I don't expect you to understand everything in that article, but rather suggest it for orientation so that you can start to realize how things work.

    There are actually many software engineering problems that .NET addresses and tries to solve. .NET or something like it will be around for a long time, so you will need to know it for the future -- even if .NET gets replaced with something else, what you learn with .NET will be transferable to the new system. While the details of the systems will be forever changing, the fundamental principles will remain the same for the most part. Learn the principles and you will be able to deal with the future changes.
  28. #30
  29. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    Originally Posted by HauntJemimah
    At least I went from using crazy pointers to making some sense of it honestly. But, I do have a video on YouTube in my favorites queue that is just a tutorial on Pointers anyway, so maybe that'll clarify things EVEN MORE than that awesome article you posted on the topic.
    Yes, you do need to schedule what to concentrate on learning first, but you really must return to pointers eventually. It is virtually impossible to meaningful programming in C without pointers, C++ uses pointers extensively, and the principles that are based on pointers are what make references work. You will need to learn pointers.

    Back to a little basic history. C was designed by super-programmers to do everything that they needed and wanted to do. The most powerful programming language there is is assembly, but that is very difficult and time-consuming and you have to completely rewrite and redesign your program when you move it to a different platform. So they designed C to provide them with the low-level access to the system (both software and hardware) that they needed while at the same time be portable to other platforms -- designing UNIX in C is what made it spread so quickly to other systems, compared to other operating systems being written in assembly which made porting them to a new platform very time-consuming and labor-intensive.

    As a result, C was lean and mean and very powerful, but it depended on the programmer really knowing what he was doing. In order to keep it simple, programmers would use indirect addressing which they knew so well from assembly in order to implement features that the language did not directly provide, much in the same way that they also implemented C-style strings. With indirect addressing you work with values that are memory addresses in order to access data indirectly through their memory address, IOW pointers. The most common place where you must use pointers in C is in order to implement call by name (AKA "call by reference"); follow that link for an explanation and also read the "call by value" section above it:
    Originally Posted by Wikipedia
    Even among languages that don't exactly support call-by-reference, many, including C and ML, support explicit references (objects that refer to other objects), such as pointers (objects representing the memory addresses of other objects), and these can be used to effect or simulate call-by-reference (but with the complication that a function's caller must explicitly generate the reference to supply as an argument).
    There are three principal problems with pointers in C and C++:

    1. You must understand and use the notation. That problem can be solved by learning and practicing.

    2. You must always be away of what you are doing and of what the code is doing. That requires learning, experience, and dilligence.

    3. The fullfilment of the old adage: "To err is human, but really mess things up you need a computer." -- also "A computer lets you make more mistakes faster than any other invention in human history, with the possible exception of handguns and tequila." Using pointers is perhaps the most dangerous part of C/C++ programming and the source of a great many bugs, including that is perhaps the most insidious bug of all, the memory leak (follow that link for a description of the problem).

    Added in the design of C++ was references, which are basically pointers without the pointer notation. Their main usefulness is to hide from the programmer the details of simulating "call by reference", thus making coding easier (this is called syntactic sugar, another example of which is array indexing which hides the details of pointer arithmetic from you). However, in order to create objects you still need to use and manage pointers. It is in C++ that the problems created by memory leaks become the most apparent.

    Out of years of experience with software and faced with the ever increasing problems with and demand for reliable software, especially in constantly running systems that lives depend on, there has grown a philosophy that might be called "protecting the programmer from himself." Instead of giving the programmer great freedom because "he knows what he is doing" (the implicit philosophy of C and of C++), newer languages and development environments are much more restrictive and seem to assume that the programmer is highly prone to error (see the discussion of syntactic salt about features designed to make it harder to write bad code). My understanding of "managed code" is that, besides increasing security, it blocks the use of language features that are deemed to be unsafe, such as pointers.

    Since pointers are a common source of unreliability in programs, the newer languages either discourage or completely eliminate the use of pointers. C# and Java do not allow pointers, but rather have extended the idea of references to completely take over their function. This also requires programs to manage the objects being referenced, which includes deleting them when they're no longer being used -- that's called garbage collection, which can introduce problems of its own, including a tendency to slow a real-time application down to a slow crawl (a friend who's a tech writer for one such project described that to me and I was able to correctly identify what it was developed in).

    So then, learn how to use references in C++/CLI since that's the primary model that .NET uses. But also learn pointers for when you work in "native" C++ and in C, as well as to understand the principles behind references.
Page 2 of 2 First 12
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo