C++
  Home arrow C++ arrow Page 2 - More on Handling Basic Data Types
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
C++

More on Handling Basic Data Types
By: Apress Publishing
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 5
    2005-03-02

    Table of Contents:
  • More on Handling Basic Data Types
  • Try It Out: Explicit Casting
  • Finding Out About Types
  • Try It Out: Finding the Sizes of Data Types
  • Using the Bitwise AND
  • Using the Bitwise Exclusive OR
  • Try It Out: Using the Bitwise Operators
  • More on Output Manipulators
  • Enumerated Data Types
  • Try It Out: Enumerated Data Types
  • The Lifetime of a Variable
  • Try It Out: The Scope Resolution Operator
  • Declaring External Variables

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    More on Handling Basic Data Types - Try It Out: Explicit Casting


    (Page 2 of 13 )

    Suppose you need to be able to convert a length in yards (as a decimal value) to yards, feet, and inches (as integer values). You can put together a program to do this:

    // Program 3.1 Using Explicit Casts
    #include <iostream>
    using std::cin;
    using std::cout;
    using std::endl;
    int main() {
      const long feet_per_yard = 3;
      const long inches_per_foot = 12;
      double yards = 0.0;           // Length as decimal yards
      long yds = 0;                 // Whole yards
      long ft = 0;                  // Whole feet
      long ins = 0;                 // Whole inches
      cout << "Enter a length in yards as a decimal: ";
      cin >> yards;
      // Get the length as yards, feet, and inches
      yds = static_cast<long>(yards);
      ft = static_cast<long>((yards - yds)
      *feet_per_yard);
      ins = static_cast<long>
               (yards * feet_per_yard *
            inches_per_foot)% inches_per_foot;
     cout << endl
          << yards << " yards converts to "
          << yds   << " yards "
          << ft    << " feet "
          << ins   << " inches.";
     cout << endl;
     return 0;
    }

    Typical output from this program will be:

    ==========================================================
     
    Enter a length in yards as a decimal: 2.75

    2.75 yards converts to 2 yards 2 feet 3inches.

    ==========================================================

    HOW IT WORKS

    The first two statements in main() declare a couple of conversion constants that you’ll use:

      const long feet_per_yard = 3;
      const long inches_per_foot = 12;

    You declare these variables as const to prevent them from being modified accidentally in the program, and you use the type long to be consistent with the other values. Although the type short would have been adequate to store these values, using it may actually increase (rather than decrease) the size of your program in the long run. This is because of additional, implicit conversions that may be necessary when using them in expressions with other integer types.

    The next four declarations define the variables you’ll use in the calculation:

    double yards = 0.0;                 // Length as decimal yards
    long yds = 0;                         // Whole yards
    long ft = 0;                           // Whole feet
    long ins = 0;                         // Whole inches

    You prompt for the required input and then read a value from the keyboard with these statements:

      cout << "Enter a length in yards as a decimal: ";
      cin >> yards;

    The next statement computes the whole number of yards from the input value with an explicit cast:

      yds = static_cast (yards);

    The cast to type long discards the fractional part of the value in yards and stores the integral result in yds. If you omit the explicit cast here, some compilers will compile the program without warning you that they’ve inserted the required conversion, even though there’s clearly a potential loss of data in this conversion operation. You should always write an explicit cast in such cases to indicate that you intend this to happen. If you leave it out, it’s not clear that you realized the need for the conversion and the potential loss of data.

    You obtain the number of whole feet in the length with the following statement:

     ft = static_cast ((yards – yds) * feet_per_yard);

    You want the number of whole feet that aren’t contained in the whole yards, so you subtract the value in yds from yards. The compiler will arrange for the value in yds to be converted automatically to type double for the subtraction, and the result will be of type double as well. The value of feet_per_yard will then be converted automatically to double to allow the multiplication to take place, and finally your explicit cast will be applied to the result to convert it from type double to type long.

    The final part of the calculation is to obtain the residual number of whole inches:

      ins = static_cast<long>
      (yards * feet_per_yard * inches_per_foot) %
        inches_per_foot;

    This is done by calculating the total number of inches in the original length, converting this to type long with an explicit cast, and then getting the remainder after dividing by the number of inches in a foot.

    Lastly, you output the results with the following statement:

     cout << std::endl
          << yards << " yards converts to "
          << yds   << " yards"
          << ft    << "  feet "
          << ins   << "  inches.";



    Old-Style Casts

    Prior to the introduction of static_cast<>() (and the other casts, const_cast<>(), dynamic_cast<>(), and reinterpret_cast<>(), which I discuss later in the book) into C++, an explicit cast of the result of an expression to another type was written like this:

    (the_type_to_convert_to)expression

    The result of expression is cast to the type between the parentheses. For example, the statement to calculate ins in the previous example could be written like this:

    ins = (long)(yards * feet_per_yard * inches_per_foot) %
      inches_per_foot;

    Essentially, there are four different kinds of casts, and the old-style casting syntax covers them all. Because of this, code using the old-style casts is more prone to error— it isn’t always clear what you intended, and you may not get the result you expected. Although you’ll still see old-style casting used extensively (it’s still part of the language), I strongly recommend that you stick to using only the new casts in your code.

    More on Pseudo-Random Number Generation

    Now that you know about casting, you can make sure that you don’t run into difficulties with using a value returned by the rand()in an arithmetic expression. I noted in the last chapter that rand()returns values from 0 to RAND_MAX, and RAND_MAX could be defined as any positive int value up to the maximum in the range. Assuming type long has a greater range than type int, you can avoid any possible problems when you want to perform arithmetic with a random integer by casting the value that is returned by the function to type long, for example:

    long even = 2*static_cast<long>(std::rand());

    With the value from rand() as type long, the multiply operation will be carried out after converting the value 2 to the same type. Thus the result of the multiplication will always be within range. You can produce the same effect by defining the literal as type long:

    long even = 2L* std::rand();

    Because 2L is of type long, the compiler will arrange to cast the value that is returned by rand() to type long before executing the multiply operation.

    You could use rand() to obtain random integers in a more limited range than 0 to RAND_MAX. For instance, suppose you wanted random integers from to 0 to 10 inclusive. You could generate that from the value returned by the rand() function:

    const int limit = 11;
    int random_value = static_cast<int>(
                              (limit*static_cast<long>
                        (std::rand()))/(RAND_MAX+1L));

    What you’re effectively doing here is dividing the range 0 to RAND_MAX into limit segments, in which all the values returned by rand() within a given segment will result in one of the values in the range 0 to limit-1 inclusive. You do this by multiplying limit by the ratio rand()/(RAND_MAX+1L). You divide by RAND_MAX+1L rather than RAND_MAX to deal with the case in which rand() returns a value that is exactly RAND_MAX. If you were to divide by RAND_MAX, the result would be limit in this singular case, instead of limit-1. The constant 1L that you add to RAND_MAX is of type long, so RAND_MAX will be converted to type long too before the addition is carried out. As I’ve already said, RAND_MAX is defined to be the largest possible integer of type int with some implementations of rand(). In this case, you can’t add 1 and get a correct result without converting to type long first.

    If you want your random values to be between 1 and some upper limit, rather than having a lower limit of 0, this is also very easy to arrange:

    const int limit = 100;
    int random_value = static_cast<int>(
                         1L+(limit*static_cast<long>(std::rand
                        ()))/(RAND_MAX+1L));

    Here you use the same expression as you did previously to produce values from 0 to limit-1 inclusive, and you add 1 to produce values from 1 to limit.

    As I said at the beginning, all this assumes that type long has a greater range than type int. If this isn’t the case and you need to generate random values outside the range of type int, your only recourse is to cast the value returned by rand() to a floating-point type and store the result of your calculations as floating-point. For example, to produce values in a range from 0 to limit, you could use the following statements:

    const double limit = 11.0;
    double random_value = limit*std::rand()/(RAND_MAX+1.0);

    Because you’ve declared limit to be of type double, the compiler will promote the integer that’s returned by rand() to that type so you don’t need to insert an explicit cast.

    This article is excerpted from Beginning ANSI C++ The Complete Language by Ivor Horton (Apress, 2004; ISBN  1590592271). Check it out at your favorite bookstore today. Buy this book now.

    More C++ Articles
    More By Apress Publishing


     

    C++ ARTICLES

    - More Tricks to Gain Speed in Programming Con...
    - Easy and Efficient Programming for Contests
    - Preparing For Programming Contests
    - Programming Contests: Why Bother?
    - Polymorphism in C++
    - Overview of Virtual Functions
    - Inheritance in C++
    - Extending the Basic Streams in C++
    - Using Stringstreams in C++
    - Custom Stream Manipulation in C++
    - General Stream Manipulation in C++
    - Serialize Your Class into Streams in C++
    - Advanced File Handling with Streams in C++
    - File Handling and Streams in C++
    - The STL String Class







    © 2003-2009 by Developer Shed. All rights reserved. DS Cluster 5 Hosted by Hostway
    Stay green...Green IT