Thread: to lower or to upper that is the question!

  1. #1
    Registered User verbity's Avatar
    Join Date
    Nov 2006
    Posts
    101

    to lower or to upper that is the question!

    I'm getting strange output when I print a conversion to upper and lower....here it is:

    22. Testing: CaseString class.

    s22 "BaLLooN" String Length: 7
    Lower Case:
    büllÅÅn
    Upper Case:

    t22 "BaLLooN" String Length: 7
    Lower Case:
    büllÅÅn
    Upper Case:

    u22 "BaLLooN" String Length: 7
    Lower Case:
    büllÅÅn
    Upper Case:


    Press any key to continue.



    I have no idea why, I'm staring at the msdn and it looks like I'm doing everything right m_buf is coming from a String class of which this Case class is derived. Just an ordinary string buffer.....

    Code:
    #include "stdafx.h"
    #include "string.h"
    #include "case.h"
    
    Case::Case() : String()
    {
    }
    
    Case::Case(const Case& cs) : String(cs)
    {
    }
    
    Case::Case(char* str) : String(str)
    {
    }
    
    Case::~Case()
    {
    	if(NULL != m_name)
    	{
    		delete[]m_name;
    		m_name=NULL;
    	}
    	if(NULL != m_buf)
    	{
    		delete[]m_buf;
    		m_buf=NULL;
    	}
    }
    
    
    
    Case& Case::operator=(const Case& cs)
    {
    	if(this == &cs)
       {
    	   return *this;
       }
    	String::operator=(cs);
    	m_length = cs.m_length;
    	if(NULL != m_buf)
    	{
    		delete[]m_buf;
    		m_buf = NULL;
    	}
        m_buf = new char[m_length + 1];
    	strcpy_s(m_buf, m_length + 1, cs.m_buf);
      	   
    	return *this;
    }
    
    void Case::print()
    {
    	m_lower = m_buf;
    	m_upper = m_buf;
    
    	cout << m_name << " \""<< m_buf << "\"  String Length: " << getLength() << endl;
    	
    	cout << "Lower Case: " << endl;
    	if(isupper (*m_lower))
    	{
    		for( m_lower; m_lower < m_buf + strlen(m_buf); m_lower++ )
    		{
    			putchar( _tolower( *m_lower ) );
    		}
    	}
    
    	cout << endl;
    
    	cout << "Upper Case: "<< m_lower<< endl;
    
    	if(islower (*m_upper))
    	{
    		for( m_upper; m_upper < m_buf + strlen(m_buf); m_upper++ )
    		{
    			putchar( _toupper( *m_upper ) );
    		}
    	}
    
    	cout << endl;
    	
    
    }
    
     Am I just messing the obvious???

  2. #2
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    A few things, yeah.
    First, String is probably not intended to be derived from.
    Second, "string.h" is not a good idea in C++. Use <string> for the C++ std::string class or <cstring> for the C-style string manipulation functions.
    "stdafx.h" is not a good idea out of principle in exercises. (But you'll get errors if you remove it. You must also disable precompiled headers in your project settings.)
    Furthermore, it looks, to me, like Case is messing with the members of String in the copy constructor, destructor and/or copy assignment operator. The three also behave inconsistently, as do the other two constructors. What is m_name? Where is it initialized? What about m_buf?
    What about m_lower and m_upper - why are they members? They look like local variables to me.
    Why do you mix C-style and C++-style I/O? (putchar and cout) That's generally not a good idea.
    What is _tolower()? What's wrong with the standard tolower() from <cctype> or the one from <locale>?
    Also, you should compute the length of the string once and store it in a local variable. Calling strlen() over and over is a waste of cycles.

    If I were to guess at the observed problem, it's that the _tolower() is poorly implemented and doesn't check whether the character passed actually is an upper-case letter before adding the ASCII offset to it. And since you only call isupper() for the very first character instead of each one, as you probably meant to ...
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  3. #3
    Registered User verbity's Avatar
    Join Date
    Nov 2006
    Posts
    101
    String is set up to be derived from...m_name, m_length and m_buf are protected member variables of String....as for String.h I can't help that it's part of the project parameters. I understand what you're saying about repeated calls to strlen and I'm going to fix that.

    Can I use the pointer *m_lower to use the tolower() function?? for example cout << (tolower(*m_lower))? I copied that little bit of code trying to change to upper or lower from the MSDN almost exactly just substituting my variables. Normally I would just run a little loop taking the index of the buffer and running a tolower() on it, but I'm forced to use the pointer as part of the project parameters....

  4. #4
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Yes, you can.

    The real question is, what is the implementation of _tolower? Did you write it?
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  5. #5
    Registered User verbity's Avatar
    Join Date
    Nov 2006
    Posts
    101
    As I said I just looked up convert to lowercase in the MSDN and the _tolower function came up and I took a look at the example and tried to use that....

  6. #6
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    > m_lower = m_buf;
    > m_upper = m_buf;
    You never set up m_buf in any of your constructors. The only place you allocate it is in your assignment operator.

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    m_buf is a member of the String base class, so it should be initialized in the base class constructor. Instead of this line:
    Code:
    putchar( _tolower( *m_lower ) );
    Try
    Code:
    cout << "Letter: " << *m_lower << " lowercase: " << _tolower(*m_lower) << '\n';
    Then show us the output.

  8. #8
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >m_buf is a member of the String base class, so it should be initialized in the base class constructor.
    Yeah, I think you're right, but do you have any idea why it's being deleted in the destructor of Case?

  9. #9
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Do you have any idea why it's protected in the first place? No data should ever be anything but private, except in trivial structs.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  10. #10
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >Do you have any idea why it's protected in the first place?
    Well it's being used in the assignment (=) operator. Is that a good reason?

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    No - it shouldn't be used in the assignment operator. In fact, it shouldn't be used anywhere except in String's direct, own members. To but it bluntly, the design of String is just broken.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  12. #12
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >No - it shouldn't be used in the assignment operator.
    Ok, I had a sneaking suspicion that might be the case.

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You are right that it should not be deleted in the destructor. Also, making it protected is bad design, but I wouldn't be surprised if that was part of the assignment (this appears to be the same/similar to warfang's assignment).

    However, I think the problem is with _tolower. On MSVC++, _tolower('a') returns &#252;, while tolower('a') returns a. To solve the problem just switch to tolower.

  14. #14
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I think that MSVC's _tolower() is used when you know that its argument is uppercase, whereas the standard function tolower() can be used with any argument. That is, here are minimalistic (and unportable) implementations:
    Code:
    int _tolower(int c) {
        return c-'A'+'a';
    }
    
    int tolower(int c) {
        if(c >= 'A' && c <= 'Z') c = c-'A'+'a';
    
        return c;
    }
    I just checked, and it is the case: http://www.opengroup.org/onlinepubs/.../_tolower.html
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  15. #15
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    >I think that MSVC's _tolower() is used when you know that its argument is uppercase
    Now that you mention it, if you look at the output posted, that is exactly what's happening. And I bet the reason Upper Case is blank is due to the delete in the destructor.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Glad this board is back! Vector question
    By hpy_gilmore8 in forum C++ Programming
    Replies: 9
    Last Post: 02-23-2004, 12:13 PM
  2. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 09:47 PM
  3. upper case to lower case problem
    By Jasonymk in forum C++ Programming
    Replies: 3
    Last Post: 04-27-2003, 05:35 AM
  4. Lower to Upper
    By Krush in forum C Programming
    Replies: 13
    Last Post: 11-19-2002, 10:14 PM
  5. lower to upper
    By Unregistered in forum C Programming
    Replies: 12
    Last Post: 07-29-2002, 07:50 PM