Chapter 8 User Defined Simple Data Types

Download Report

Transcript Chapter 8 User Defined Simple Data Types

CHAPTER 8
USER-DEFINED SIMPLE DATA
TYPES, NAMESPACES,
AND THE string TYPE
In this chapter, you will:
 Learn how to create and manipulate your own simple data
type—called the enumeration type
 Become aware of the typedef statement
 Learn about the namespace mechanism
 Explore the string data type, and learn how to use the various
string functions to manipulate strings
ENUMERATION TYPE
 A data type is a set of values together with a set of operations on those
values.
 In order to define a new simple data type, called enumeration type,
we need three things:
 A name for the data type.
 A set of values for the data type.
 A set of operations on the values.
 C++ allows the user to define a new simple data type by specifying its
name and the values, but not the operations.
 The values that we specify for the data type must be identifiers.
 The syntax for enumeration type is:
enum typeName{value1, value2, ...};
where value1, value2, … are identifiers.
 value1, value2, … are called enumerators.
 value1 < value2 < value3 <...
 In C++, enum is a reserved word.
 Enumeration type is an ordered set of values.
Example 8-1
enum colors{brown, blue, red, green, yellow};
defines a new data type, called colors
 The values belonging to this data type are brown, blue, red,
green, and yellow.
Example 8-2
enum standing{freshman, sophomore, junior, senior};
defines standing to be an enumeration type.
 The values belonging to standing are freshman, sophomore,
junior, and senior.
Example 8-3
• The following are illegal enumeration types because none of the
values is an identifier.
//Illegal enumeration types
enum grades{'A', 'B', 'C', 'D', 'F'};
enum places{1st, 2nd, 3rd, 4th};
• The following are legal enumeration types:
enum grades{A, B, C, D, F};
enum places{first, second, third, fourth};
 If a value has already been used in one enumeration type, it cannot be
used by any other enumeration type in the same block.
 The same rules apply to enumeration types declared outside of any
blocks.
Example 8-4
enum mathStudent{John, Bill, Cindy, Lisa, Ron};
enum compStudent{Susan, Cathy, John, William}; //Illegal
 Suppose that these statements are in the same program in the same
block.
 The second enumeration type, compStudent, is not allowed
because the value John was used in the previous enumeration type
mathStudent.
Declaring Variables
The syntax for declaring variables is the same as before, that is,
dataType identifier, identifier,...;
 The following statement defines an enumeration type sports
enum sports{basketball, football, hockey,
baseball, soccer,volleyball};
 The following statement declares variables of the type sports.
sports popularSport, mySport;
Assignment
 The statement
popularSport = football;
stores football in popularSport
 The statement
mySport = popularSport;
copies the content of popularSport in mySport.
Operations on Enumeration Types
 No arithmetic operation is allowed on enumeration type.
 The following statements are illegal;
mySport = popularSport + 2; //illegal
popularSport = football + soccer; //illegal
popularSport = popularSport * 2; // illegal
 Also, the increment and decrement operations are not allowed on
enumeration types.
 The following statements are illegal;
popularSport++;
popularSport--;
//illegal
//illegal
 To increment the value of popularSport by 1, we can use the
cast operator as follows:
popularSport = static_cast<sports>(popularSport + 1);
 Consider the following statements:
popularSport = football;
popularSport = static_cast<sports>(popularSport + 1);
 After the second statement, the value of popularSport will be
hockey.
 The following statements results in storing basketball in
popularSport.
popularSport = football;
popularSport = static_cast<sports>(popularSport - 1);
Relational Operators
Suppose we have the enumeration type sports and the variables
popularSport and mySport as defined above. Then
football <= soccer
hockey > basketball
baseball < football
is
is
is
true
true
false
If
popularSport = soccer;
mySport = volleyball;
then
popularSport < mySport
is true
Enumeration Types and Loops
Suppose mySport is a variable as declared above.
for(mySport = basketball; mySport <= soccer;
mySport = static_cast<sports>(mySport+1))
...
• This for loop executes 5 times.
Input/Output of Enumeration Types
 Input and output are defined only for built-in data types such as int,
char, double.
 The enumeration type can be neither input nor output (directly).
 You can input and output enumeration indirectly
Example 8-5
enum courses{algebra, basic, pascal, cpp,
philosophy, analysis, chemistry, history};
courses registered;
char ch1,ch2;
cin>>ch1>>ch2;
//read two characters
switch(ch1)
{
case 'a': if(ch2 == 'l')
registered = algebra;
else
registered = analysis;
break;
case 'b': registered = basic;
break;
case 'c': if(ch2 == 'h')
registered = chemistry;
else
registered = cpp;
break;
case 'h': registered = history;
break;
case 'p': if(ch2 == 'a')
registered = pascal;
else
registered = philosophy;
break;
default: cout<<"Illegal input."<<endl;
}
 Enumeration type can be output indirectly as follows:
switch(registered)
{
case algebra: cout<<"algebra";
break;
case analysis: cout<<"analysis";
break;
case basic: cout<<"basic";
break;
case chemistry: cout<<"chemistry";
break;
case cpp: cout<<"cpp";
break;
case history: cout<<"history";
break;
case pascal: cout<<"pascal";
break;
case philosophy: cout<<"philosophy";
}
enum courses{algebra, basic, pascal, cpp,
philosophy, analysis, chemistry, history};
courses registered;
 If you try to output the value of an enumerator directly, the computer
will output the value assigned to the enumerator.
 Suppose that registered = algebra;
 The following statement outputs the value 0 because the (default)
value assigned to algebra is 0:
cout<<registered<<endl;
 The following statement outputs 4:
cout<<philosophy<<endl;
Functions and Enumeration Types
 Enumeration type can be passed as parameters to functions either by
value or by reference.
 A function can return a value of the enumeration type.
courses readCourses()
{
courses registered;
char ch1,ch2;
cout<<"Enter the first two letters of the course: "<<endl;
cin>>ch1>>ch2;
switch(ch1)
{
case 'a': if(ch2 == 'l')
registered = algebra;
else
registered = analysis;
break;
case 'b': registered = basic;
break;
case 'c': if(ch2 == 'h')
registered = chemistry;
else
registered = cpp;
break;
case 'h': registered = history;
break;
case 'p': if(ch2 == 'a')
registered = pascal;
else
registered = philosophy;
break;
default: cout<<"Illegal input."<<endl;
} //end switch
return registered;
} //end readCourses
void printEnum(courses registered)
{
switch(registered)
{
case algebra: cout<<"algebra";
break;
case analysis: cout<<"analysis";
break;
case basic: cout<<"basic";
break;
case chemistry: cout<<"chemistry";
break;
case cpp: cout<<"cpp";
break;
case history: cout<<history";
break;
case pascal: cout<<"pascal";
break;
case philosophy: cout<<"philosophy";
} //end switch
} //end printEnum
Declaring Variables When Defining the Enumeration Type
enum grades{A,B,C,D,F} courseGrade;
enum coins{penny, nickel, dime, halfDollar,
dollar} change, usCoins;
Anonymous Data Types
 A data type in which values are directly specified in the variable
declaration with no type name is called an anonymous type.
enum {basketball, football, baseball, hockey} mysport;
 Creating an anonymous type has drawbacks.
 We cannot pass an anonymous type as a parameter to a function.
 A function cannot return a value of an anonymous type.
 Values used in one anonymous type can be used in another
anonymous type, but variables of those types are treated
differently.
enum {English, French, Spanish, German, Russian}
languages;
enum {English, French, Spanish, German, Russian}
foreignLanguages;
languages = foreignLanguages; //illegal
The typedef Statement
 In C++, you can create synonyms or aliases to a previously defined
data type by using the typedef statement.
 The general syntax of the typedef statement is
typedef existingTypeName newTypeName;
 In C++, typedef is a reserved word.
 The typedef statement does not create any new data type; it creates
only an alias to an existing data type.
Example 8-6
 The following statement creates an alias, integer, for the data type
int.
typedef int integer;
 The following statement creates an alias, real, for the data type
double.
typedef double real;
 The following statement creates an alias, decimal, for the data type
double.
typedef double decimal;
Example 8-7
typedef int Boolean;
const Boolean True = 1;
const Boolean False = 0;
//Line 1
//Line 2
//Line 3
Boolean flag;
//Line 4
 The statement at Line 1 creates an alias, Boolean, for the data type
int.
 The statements at Lines 2 and 3 declare the named constants True
and False and initialize them to 1 and 0, respectively.
 The statement at Line 4 declares flag to be a variable of the type
Boolean.
 Because flag is a variable of the type Boolean, the following
statement is legal:
flag = True;
 In July 1998, ANSI/ISO standard C++ was officially approved.
 Most of the recent compilers are also compatible with ANSI/ISO
standard C++.
 In previous chapters, we mainly dealt with standard C++ and briefly
introduced the features of ANSI/ISO standard C++.
 For most part the two standards are the same. In this chapter, we
discuss some of the features of ANSI/ISO standard C++ language
that are not available in standard C++.
Namespaces
 When a header file, such as iostream, is included in a program,
the global identifiers in the header file also become the global
identifiers in the program.
 If a global identifier in a program has the same name as one of the
global identifiers in the header file, the compiler will generate syntax
error (such as identifier redefined).
 The same problem can occur if a program uses third party libraries.
 To overcome this problem, third party vendors begin their global
identifiers with a special symbol.
 Since compiler vendors begin their global identifier with _ (under
score), to avoid linking errors do not begin identifiers in your
program with _ (under score).
 ANSI/ISO standard C++ attempts to solve this problem of
overlapping global identifier names with the namespace mechanism.
Syntax: namespace
The syntax of the statement namespace is:
namespace namespace_name
{
members
}
where a member is usually a variable declaration, a named constant,
a function, or another namespace.
• In C++, namespace is a reserved word.
Example 8-8
The statement
namespace globalType
{
const int n = 10;
const double rate = 7.50;
int count = 0;
void printResult();
}
defines globalType to be a namespace with four members.
 The scope of a namespace member is local to the namespace.
 There are usually two ways a namespace member can be accessed
outside the namespace.
Syntax: Accessing a namespace Member
namespace_name::identifier
 To access the member rate of the namespace globalType, the
following statement is required:
globalType::rate
 To access the member printResult (which is a function), the
following statement is required:
globalType::printResult();
 To simplify the accessing of a namespace member, C++ provides
the use of the statement using.
Syntax: using
(a) To simplify the accessing of all namespace members:
using namespace namespace_name;
(b) To simplify the accessing of a specific namespace member:
using namespace_name::identifier;
 The using statement
using namespace globalType;
simplifies the accessing of all members of the namespace
globalType
 The statement
using globalType::rate;
simplifies the accessing of the member rate of the namespace
globalType.
 In C++, using is a reserved word.
 The using statement is usually put after the namespace
declaration.
namespace globalType
{
const int n = 10;
const double rate = 7.50;
int count = 0;
void printResult();
}
using namespace globalType;
• After the using statement, to access a namespace member it is
not necessary to precede the namespace_name and the scope
resolution operator before the namespace member.
• If a namespace member and a global identifier in a program have
the same name, to access this namespace member in the program,
the namespace_name and the scope resolution operator must
precede the namespace member.
• If a namespace member and an identifier in a block have the same
name, to access this namespace member in the block, the
namespace_name and the scope resolution operator precedes the
namespace member.
Example 8-9
#include <iostream>
using namespace std;
.
.
.
int main()
{
.
.
.
}
.
.
.
• In this example, we can refer to global identifiers of the header file
iostream, such as cin, cout, and endl, without using the prefix
std:: before the identifier name.
• The obvious restriction is that the block (or the function) where the
global identifier (of the header file iostream) is referred must not
contain any identifier with the same name as this global identifier.
Example 8-10
#include <cmath>
int main()
{
double x = 15.3;
double y;
y = std::pow(x,2);
.
.
.
}
• In this example the function pow of the header file cmath is
accessed
Example 8-11
#include <iostream>
.
.
.
int main()
{
using namespace std;
.
.
.
}
.
.
.
• In this example, the function main can refer to the global identifiers
of the header file iostream without using the prefix std:: before
the identifier name.
• Since the using statement appears inside the function main, other
functions (if any) should use the prefix std:: before the name of
the global identifier of the header file iostream unless the function
also has a similar using statement.
Example 8-12
#include <iostream>
using namespace std;
//Line 1
int t;
double u;
//Line 2
//Line 3
namespace exp
{
int x;
char t;
double u;
void printResult();
}
//Line
//Line
//Line
//Line
4
5
6
7
using namespace exp;
int main()
{
int one;
double t;
double three;
.
.
.
}
//Line 8
//Line 9
//Line 10
void exp::printResult()
{
.
.
.
}
1. To refer to the variable t at Line 2 in main, use the scope resolution
operator (that is, refer to t as ::t) since the function main has a
variable named t (declared at Line 5).
2. To refer to the member t (declared at Line 5) of the namespace
exp in main, use the prefix exp:: with t (that is, refer to t as
exp::t) since there is a global variable named t (declared at Line
2) and there is also a variable named t in main.
3. To refer to the member u (declared at Line 6) of the namespace
exp in main, use the prefix exp:: with u (that is, refer to u as
exp::u) since there is a global variable named u (declared at Line
3).
4. The member x (declared at Line 4) of the namespace exp can be
referenced in main either as x or exp::x since there is no global
identifier named x and the function main does not contain any
identifier named x.
5. The definition of the function that is a member of a namespace,
such as printResult, is usually written outside the
namespace as in the above program. To write the definition of the
function printResult, in the function heading the name of the
function can be either printresult or exp::printResult
(because there is no other global identifier named printResult).
The string Type
• To use the data type string, the program must include the header
file string
#include <string>
• The statement
string name = "William Jacob";
declares name to be string variable and also initializes name to
"William Jacob".
• The position of the first character, 'W', in name is 0, the position of
the second character, 'i', is 1, and so on.
• The variable name is capable of storing (just about) any size string.
• Binary operator + (to allow the string concatenation operation), and
the array index (subscript) operator [], have been defined for the
data type string.
Suppose we have the following declarations.
string str1, str2, str3;
The statement
str1 = "Hello There";
stores the string "Hello There" in str1.
The statement
str2 = str1;
copies the value of str1 into str2.
• If str1 = "Sunny", the statement
str2 =
str1 + " Day";
stores the string "Sunny Day" into str2.
• If
str1 = "Hello"
and
str2 = "There".
then
str3 = str1 + " " + str2;
stores "Hello There" into str3.
• This statement is equivalent to the statement
str3 = str1 + ' ' + str2;
• The statement
str1 = str1 + "Mickey";
updates the value of str1 by appending the string "Mickey" to its
old value.
• If str1 = "Hello there", the statement
str1[6] = 'T';
replaces the character t with the character T.
• The data type string has a data type, string::size_type,
and a named constant, string::npos, associated with it.
string::size_type
An unsigned integer (data) type
string::npos
The maximum value of the (data) type
string::size_type, a number such
as 4294967295 on many machines
The length Function
 The length function returns the number of characters currently in
the string.
 The value returned is an unsigned integer.
 The syntax to call the length function is:
strVar.length()
where strVar is variable of the type string.
 The function length has no arguments.
Consider the following statements:
string firstName;
string name;
string str;
firstName = "Elizabeth";
name = firstName + " Jones";
str = "It is sunny.";
Statement
cout<<firstName.length()<<endl;
cout<<name.length()<<endl;
cout<<str.length()<<endl;
Effect
Outputs 9
Outputs 15
outputs 12
• The function length returns an unsigned integer.
• The value returned can be stored in an integer variable.
• Since the data type string has the data type
string::size_type associated with it, the variable to hold the
value returned by the length function is usually of this type.
string::size_type len;
Statement
len = firstName.length();
Effect
The value of len is 9
len = name.length();
The value of len is 15
len = str.length();
The value of len is 12
The size Function
 The function size is same as the function length.
 Both these functions return the same value.
 The syntax to call the function size is:
strVar.size()
where strVar is variable of the type string.
 As in the case of the function length, the function size has no
arguments.
The find Function
• The find function searches a string to find the first occurrence of a
particular substring and returns an unsigned integer value (of type
string::size_type) giving the result of the search.
The syntax to call the function find is:
strVar.find(strExp)
where strVar is a string variable and strExp is a string
expression evaluating to a string. The string expression, strExp,
can also be a character.
• If the search is successful, the function find returns the position in
strVar where the match begins.
• For the search to be successful, the match must be exact.
• If the search is unsuccessful, the function returns the special value
string::npos (“not a position within the string”).
The following are valid calls to the function find.
str1.find(str2)
str1.find("the")
str1.find('a')
str1.find(str2+"xyz")
str1.find(str2+'b')
string
sentence;
string
str;
string::size_type position;
sentence = "It is cloudy and warm.";
str = "cloudy";
Statement
cout<<sentence.find("is")<<endl;
cout<<sentence.find("and")<<endl;
cout<<sentence.find('s')<<endl;
cout<<sentence.find(str)<<endl;
cout<<sentence.find("the")<<endl;
position = sentence.find("warm");
Effect
Outputs 3
Outputs 13
Outputs 4
Outputs 6
Outputs the value
of string::nops
Assigns 17 to
position
The substr Function
• The substr function returns a particular substring of a string.
The syntax to call the function substr is:
strVar.substr(expr1,expr2)
where expr1 and expr2 are expressions evaluating to unsigned
integers.
• The expression expr1 specifies a position within the string (starting
position of the substring). The expression expr2 specifies the length
of the substring to be returned.
string
string
sentence;
str;
sentence = "It is cloudy and warm.";
Statement
cout<<sentence.substr(0,5)
<<endl;
cout<<sentence.substr(6,6)
<<endl;
cout<<sentence.substr(6,16)
<<endl;
cout<<sentence.substr(3,6)
<<endl;
str = sentence.substr(0,8);
str = sentence.substr(2,10);
Effect
Outputs: It is
Outputs: cloudy
Outputs: cloudy and warm.
Outputs: is clo
str = "It is cl"
str = " is cloudy"
The Function swap
 The function swap is used to swap—that is, interchange—the
contents of two string variables.
 The syntax to use the function swap is
strVar1.swap(strVar2);
where strVar1 and strVar2 are string variables.
 Suppose you have the following statements:
string str1 = "Warm";
string str2 = "Cold";
 After the following statement executes, the value of str1 is
"Cold" and the value of str2 is "Warm".
str1.swap(str2);
PROGRAMMING EXAMPLE: PIG LATIN STRINGS
In this programming example, we write a program that prompts the
user to input a string and then outputs the string in the pig Latin form.
The rules for converting a string into pig Latin form are as follows:
1. If the string begins with a vowel, add the string "-way" at the end
of the string. For example, the pig Latin form of the string "eye"
is "eye-way".
2. If the string does not begin with a vowel, first add "-" at the end
of the string. Then rotate the string one character at a time; that is,
move the first character of the string to the end of the string until
the first character of the string becomes a vowel. Then add the
string "ay" at the end. For example, the pig Latin form of the
string "There" is "ere-Thay".
3. Strings such as "by" contain no vowels. In cases like this, the
letter y can be considered a vowel. So, for this program the vowels
are a, e, i, o, u, y, A, E, I, O, U, and Y. Therefore, the pig Latin
form of "by" is "y-bay".
4. Strings such as "1234" contain no vowels. The pig Latin form of
the string "1234" is "1234-way". That is, the pig Latin form of
a string that has no vowels in it is the string followed by the string
"-way".
Input: Input to the program is a string.
Output: Output of the program is the string in the pig Latin form.
Problem Analysis and Algorithm Design
• Suppose that str denotes a string.
• To convert str into pig Latin, check the first character, str[0], of
str.
• If str[0] is a vowel, add "-way" at the end of str—that is, str
= str + "-way".
• Suppose that the first character of str, str[0], is not a vowel.
• First add "-" at the end of the string.
• Remove the first character of str from str and put it at end of
str. Now the second character of str becomes the first character of
str.
• This process of checking the first character of str and moving it to
the end of str if the first character of str is not a vowel is repeated
until either the first character of str is a vowel or all characters of
str are processed, in which case str does not contain any vowels.
 The program contains the following functions:
 A function isVowel, to determine whether a character is a
vowel.
 A function rotate, to move the first character of str to the end
of str
 A function pigLatinString, to find the pig Latin form of
str.
1. Get str.
2. Find the pig Latin form of str by using the function
pigLatinString.
3. Output the pig Latin form of str.
Function isVowel
bool isVowel(char ch)
{
switch(ch)
{
case 'A': case 'E':
case 'I': case 'O':
case 'U': case 'Y':
case 'a': case 'e':
case 'i': case 'o':
case 'u': case 'y': return true;
default: return false;
}
}
Function rotate
 This function takes a string as a parameter, removes the first
character of the string, and places it at the end of the string.
 This is done by extracting the substring starting at position 1 until the
end of the string, and then adding the first character of the string.
string rotate(string pStr)
{
int len = pStr.length();
string rStr;
rStr = pStr.substr(1,len - 1) + pStr[0];
return rStr;
}
Function pigLatinString
1. If pStr[0] is a vowel, add "-way" at the end of pStr.
2. Suppose pStr[0] is not a vowel.
3. Move the first character of pStr to the end of pStr. The second
character of pStr becomes the first character of pStr. Now pStr
may or may not contain a vowel. We use a Boolean variable,
foundVowel, which is set to true if pStr contains a vowel and
false otherwise.
a. Suppose that len denotes the length of pStr.
b. Initialize foundVowel to false.
c. If pStr[0] is not a vowel, move str[0] to the end of pStr
by calling the function rotate.
d. Repeat Step b until either the first character of pStr becomes a
vowel or all characters of pStr have been checked.
4. Convert pStr into the pig Latin form.
5. Return pStr.
string pigLatinString(string pStr)
{
int len;
bool foundVowel;
int counter;
if(isVowel(pStr[0]))
pStr = pStr + "-way";
else
{
pStr = pStr + '-';
pStr = rotate(pStr);
len = pStr.length();
foundVowel = false;
//Step 1
//Step 2
//Step 3
//Step 3.a
//Step 3.b
for(counter = 1; counter < len - 1; counter++)
//Step 3.d
if(isVowel(pStr[0]))
{
foundVowel = true;
break;
}
else
//Step 3.c
pStr = rotate(pStr);
if(!foundVowel)
//Step 4
pStr = pStr.substr(1,len) + "-way";
else
pStr = pStr + "ay";
}
return pStr;
}
//Step 5
#include <iostream>
#include <string>
using namespace std;
bool isVowel(char ch);
string rotate(string pStr);
string pigLatinString(string pStr);
int main()
{
string str;
cout<<"Enter a string: ";
cin>>str;
cout<<endl;
cout<<"The pig Latin form of "<<str<<" is: "
<<pigLatinString(str)<<endl;
return 0;
}
//Place the definitions of the functions isVowel,
//rotate, and pigLatinString as discussed above here
Sample Runs In these sample runs, the user input is in red.
Sample Run 1:
Enter a string: eye
The pig Latin form of eye is: eye-way
Sample Run 2:
Enter a string: There
The pig Latin form of There is: ere-Thay
Sample Run 3:
Enter a string: why
The pig Latin form of why is: y-whay
Sample Run 4:
Enter a string: 123456
The pig Latin form of 123456 is: 123456-way