C++ Prime Plus
Compound Types
- Introducing Arrays
short months[12]; // creates array of 12 short
;
int yamcosts[3] = {20, 30, 5}; // create, initialize array
;
You can use the initialization form only when defining the array.You cannot use it later, and you cannot assign one array wholesale to another:
int cards[4] = {3, 6, 8, 10}; // okay;
int hand[4]; // okay;
hand[4] = {5, 6, 7, 9}; // not allowed;
hand = cards; // not allowed;
When initializing an array,you can provide fewer values than array elements. For example,the following statement initializes only the first two elements of hotelTips :
float hotelTips[5] = {5.0, 2.5}
;
If you partially initialize an array,the compiler sets the remaining elements to zero. Thus,it’s easy to initialize all the elements of an array to zero—just explicitly initialize the first element to zero and then let the compiler initialize the remaining elements to zero:
long totals[500] = {0}
;
If your main concern is that the program, not you, knows how large an array is, you can do something like this:
short things[] = {1, 5, 3, 8}
;
int num_elements = sizeof things / sizeof (short)
;
-
C++11 Array Initialization
double earnings[4] {1.2e4, 1.6e4, 1.1e4, 1.7e4}; // okay with C++11
unsigned int counts[10] = {}; // all elements set to 0
float balances[100] {}; // all elements set to 0
long plifs[] = {25, 92, 3.0}; // not allowed
char slifs[4] {'h', 'i', 1122011, '\0'}; // not allowed
char tlifs[4] {'h', 'i', 112, '\0'}; // allowed
The first initialization fails because converting from a floating-point type to an integer type is narrowing,even if the floating-point value has only zeros after the decimal point. The second initialization fails because 1122011 is outside the range of a char ,assuming we have an 8-bit char .The third succeeds because,even though 112 is an int value,it still is in the range of a char. -
Line-Oriented Input with getline()
// instr2.cpp -- reading more than one word with getline
#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.getline(name, ArSize); // reads through newline
cout << "Enter your favorite dessert:\n";
cin.getline(dessert, ArSize);
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
return 0;
}
// instr3.cpp -- reading more than one word with get() & get()
#include <iostream>
int main()
{
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];
cout << "Enter your name:\n";
cin.get(name, ArSize).get(); // read string, newline
cout << "Enter your favorite dessert:\n";
cin.get(dessert, ArSize).get();
cout << "I have some delicious " << dessert;
cout << " for you, " << name << ".\n";
return 0;
}
- Line-Oriented Input with get()
The call cin.get() (with no arguments) reads the single next character,even if it is a newline,so you can use it to
dispose of the newline character and prepare for the next line of input.That is,this sequence works:
cin.get(name, ArSize); // read first line
cin.get(); // read newline
cin.get(dessert, Arsize); // read second line
Another way to use get() is to concatenate,or join,the two class member functions,as
follows:
cin.get(name, ArSize).get(); // concatenate member functions
- Mixing String and Numeric Input
cin >> year;
cin.get(); // or cin.get(ch);
Or you can concatenate the calls,making use of the fact that the expression cin >> year returns the cin object:
(cin >> year).get(); // or (cin >> year).get(ch);
- More string Class Operations
// strtype3.cpp -- more string class features
#include <iostream>
#include <string> // make string class available
#include <cstring> // C-style string library
int main()
{
using namespace std;
char charr1[20];
char charr2[20] = "jaguar";
string str1;
string str2 = "panther";
// assignment for string objects and character arrays
str1 = str2; // copy str2 to str1
strcpy(charr1, charr2); // copy charr2 to charr1
// appending for string objects and character arrays
str1 += " paste"; // add paste to end of str1
strcat(charr1, " juice"); // add juice to end of charr1
// finding the length of a string object and a C-style string
int len1 = str1.size(); // obtain length of str1
int len2 = strlen(charr1); // obtain length of charr1
cout << "The string " << str1 << " contains " << len1 << " characters.\n";
cout << "The string " << charr1 << " contains " << len2 << " characters.\n";
return 0;
}
- Structures
struct inflatable // structure declaration
{
char name[20];
float volume;
double price;
};
inflatable guest =
{
"Glorious Gloria", // name value
1.88, // volume value
29.99 // price value
};
or
inflatable duck = {"Daphne", 0.12, 9.98};
inflatable duck {"Daphne", 0.12, 9.98}; // can omit the = in C++11
struct perks
{
int key_number;
char car[12];
} mr_smith, ms_jones; // two perks variables
You even can initialize a variable you create in this fashion:
struct perks
{
int key_number;
char car[12];
} mr_glitz =
{
7, // value for mr_glitz.key_number member
"Packard" // value for mr_glitz.car member
};
inflatable guests[2] = // initializing an array of structs
{
{"Bambi", 0.5, 21.99}, // first structure in array
{"Godzilla", 2000, 565.99} // next structure in array
};
- Unions
One use for a union is to save space when a data item can use two or more formats but never simultaneously.For example, suppose you manage a mixed inventory of widgets, some of which have an integer ID, and some of which have a string ID.In that case, you could use the following:
struct widget
{
char brand[20];
int type;
union id // format depends on widget type
{
long id_num; // type 1 widgets
char id_char[20]; // other widgets
} id_val;
};
...
widget prize;
...
if (prize.type == 1) // if-else statement (Chapter 6)
cin >> prize.id_val.id_num; // use member name to indicate mode
else
cin >> prize.id_val.id_char;
An anonymous union has no name;in essence,its members become variables that share the same address. Naturally,only one member can be current at a time:
struct widget
{
char brand[20];
int type;
union // anonymous union
{
long id_num; // type 1 widgets
char id_char[20]; // other widgets
};
};
...
widget prize;
...
if (prize.type == 1)
cin >> prize.id_num;
else
cin >> prize.id_char;
Unions often (but not exclusively) are used to save memory space. That may not seem that necessary in these days of gigabytes of RAM and terabytes of storage,but not all C++ programs are written for such systems. C++ also is used for embedded systems, such as the processors used to control a toaster oven, an MP3 player, or a Mars rover. In these applications space may be at a premium.Also unions often are used when working with operating systems or hardware data structures.
- Enumerations
enum spectrum {red, orange, yellow, green, blue, violet, indigo, ultraviolet};
You can set enumerator values explicitly by using the assignment operator:
enum bits{one = 1, two = 2, four = 4, eight = 8};
- Pointer
// pointer.cpp -- our first pointer variable
#include <iostream>
int main()
{
using namespace std;
int updates = 6; // declare a variable
int * p_updates; // declare pointer to an int
p_updates = &updates; // assign address of int to pointer
// express values two ways
cout << "Values: updates = " << updates;
cout << ", *p_updates = " << *p_updates << endl;
// express address two ways
cout << "Addresses: &updates = " << &updates;
cout << ", p_updates = " << p_updates << endl;
// use pointer to change value
*p_updates = *p_updates + 1;
cout << "Now updates = " << updates << endl;
return 0;
}
Caution:
Pointer Golden Rule: Always initialize a pointer to a definite and appropriate address before you apply the dereferencing operator ( * ) to it.
- Allocating Memory with new
int * pn = new int;
int * psome = new int [10]; // get a block of 10 ints
`typeName * pointer_name = new typeName ;
- Freeing Memory with delete
int * ps = new int; // allocate memory with new
int * psome = new int [10]; // get a block of 10 ints
. . . // use the memory
delete ps; // free memory with delete when done
delete [] psome;
Caution
You should use delete only to free memory allocated with new. However, it is safe to apply delete to a null pointer.
In short,you should observe these rules when you use new and delete :
- Don’t use delete to free memory that new didn’t allocate.
- Don’t use delete to free the same block of memory twice in succession.
- Use delete [] if you used new [] to allocate an array.
- Use delete (no brackets) if you used new to allocate a single entity.
- It’s safe to apply delete to the null pointer (nothing happens).
- Vector
#include <vector>
...
using namespace std;
vector<int> vi; // create a zero-size array of int
int n;
cin >> n;
vector<double> vd(n); // create an array of n doubles
- Array (C++11)
array< typeName , n_elem > arr;
网友评论