第四章
4.2字符串
在这里我们需要了解和掌握字符串常量和字符常量的区别。
==字符常量(使用双引号)不能与字符常量(使用单引号)互换。==在ASCII系统上,‘S’只是83的另一种写法,因此,下面的语句将83赋给shirt size:
char shirt_size='S'
== 但‘S’不是字符常量,它表示的是两个字符(字符S和\0)组成的字符串。更糟糕的是,’‘S’'实际上表示的是字符串所在的内存地址。==因此下面的语句试图将一个内存地址赋给shirt_size:
char shirt_size = 'S';
4.2.2在数组中使用字符串
#include<iostream>
#include<cstring>//为了利用strlen()这个函数
using namespace std;
int main() {
const int size = 15;
char name1[size]; //empty array
char name2[size] = "C++owboy";//innitialized array
cout << "My name is " << name2 << " ! what is your name? \n";
cin >> name1;
cout << "My name is " << name1 << ". Nice to meet you." << " My name has " << strlen(name1) << " letters and " << sizeof(name1) << " byte.\n";
name2[3] = '\0';//设置空字符,这使得字符串在第3个字符后结束读取
cout << "Here are the first 3 characters of my name: " << name2;
getchar();//保持程序一直运行不关闭
4.2.4 每次读取一行字符串输入
1.面向行的输入:getline()
getline()函数读取整行,它使用通过回车键输入的换行符来确定输入的结尾。要调用这种方法可以使用cin.getline()。该函数有两个参数,cin.getline(数据名称,读取长度);geiline()成员函数在读取指定数目的字符或遇到换行符时停止读取。getline()抛弃换行符,最终在字符串最后自动添加空字符。
#include<iostream>
int main() {
using namespace std;
const int size = 20;
char name[size];
char food[size];
cout << "Enter your name: ";
cin.getline(name, size); //获取输入
cout << "Enter your favorite dessert: \n";
cin.getline(food,size);
cout<<" I have some delicious "<<food<< " for you, " << name;
getchar();
}
2.面向行的输入:get()
get与getline()相似,但是get函数不抛弃换行符。
如果两次调用get():
cin.get(name,20);
cin.get(food,20);
由于第一次调用调用后,换行符将留在输入队列中,因此第二次调用时看到的第一个字符便是换行符。因此get()认为已到达行尾,如果不借助帮助,get()将不能跨过该换行符。
使用任何不带参数的cin.get()调用可读取下一个字符,即使是换行符。
因此上面的代码修正为:
cin.get(name,20);
cin.get();//read newline
cin.get(food,20);
所以利用get函数编写getline函数等价程序如下:
#include<iostream>
int main() {
using namespace std;
const int size = 20;
char name[size];
char food[size];
cout << "Enter your name: ";
cin.get(name, size).get(); //获取输入,read newline
cout << "Enter your favorite dessert: \n";
cin.get(food,size).get();
cout<<" I have some delicious "<<food<< " for you, " << name;
getchar();
}
4.2.5混合输入字符串和数字
int year;
char address[50];
cin>>year;
cin.getline(address,50);
cout<<year;
cout<<address;
上面的程序无法输出address的内容,原因是当cin读取年份,将回车键生产的换行符留在了输入队列中。后面的cin.getline()看到换行符后,将认为是一个空行,并将一个空行字符串赋给address数组。解决的方法是,在读取地址之前先读取并丢弃换行符,可以使用没有参数的get函数,也可以使用接受一个char参数的get函数。
#include<iostream>
int main() {
using namespace std;
int year;
char address[80];
cout << "What year was your house built?\n";
cin >> year;
cin.get();
cout << "What is its street address?\n";
cin.getline(address, 80);
cout<< "Address: " << address << endl;
cout << "Year built: " << year;
getchar();
}
4.3 string类简介
要使用string类,必须在程序中包含头文件string。string类位于名称空间std中。必须使用using namespace string.
string类的设计能够自动处理string 对象的大小。
4.3.1字符串的赋值、拼接和附加
string str1;
string str2="panther";
str1=str2;
string str3;
str3=str1+str2;
知识点代码化:
#include<string>
#include<iostream>
#include<cstring> //提供函数strcpy strcat
int main()
{
using namespace std;
char charr[20];
string str;
cout << "Length of string in charr before input: " << strlen(charr) << endl;//函数 strlen()用于char
cout << " Length of string in str before input: " << str.size() << endl;
cout << "Enter a line of text:\n";
cin.getline(charr,20);//getline函数 参数: name,length //用于将输入读取到数组中
cout << "You entered: " << charr << endl;
cout << "Enter another line of text:\n";
getline(cin, str);//将输入读取到string对象中,getline()不是类方法。它将cin作为参数,指出到哪里去查找输入,另外,也没有指出字符串长度的参数。
cout << "You entered: " << str << endl;
cout << "Length of string in charr after input: " << strlen(charr) << endl;
cout << "Length of string in str after input: " << str.size() << endl;
return 0;
}
结构介绍
struct inflatable {
char name[20];
float volume;
double price;
};//inflatable 是新的类型名称
//定义结构后,可以创建改类型的变量
inflatable hat={"Daphne",0.12,9.98};
//由于 hat 类型为inflatable,因此可以用成员运算符(.)来访问各个成员。
//例如hat.price hat.volume...
结构数组
inflatable gifts[100];
cin>>gifts[0].volume
//gitfs本身是一个数组,而不是结构,因此像gitfs.price这样的表述是无效的
//初始化方式如下:
inflatable guest[2]=
{
{"Bambi",0.5,21.99},
{"Godzilla",2000,565.99}
}
4.7 指针和自由存储空间
指针是一个变量,存储的是值的地址,而不是值的本身。
指针的代码知识如下:
#include<iostream>
int main() {
using namespace std;
int update = 6;
int *p_updates;
p_updates = &update;//&update是update的存储地址,将地址赋给指针的值
//express value two ways
cout << "Value:updates = " << update;
cout << ",*p_updates=" << *p_updates << endl;//update=*p_updates,&update=p_updates
//express address two ways
cout << "Adress of update: = " << &update << ",p_updates = " << p_updates << endl;
//使用指针改变变量的值
*p_updates += 1;
cout << "Now update = " << update << endl;
return 0;
4.7.1 指针声明和初始化
int higgens = 5;
int* pt = &higgens;
4.7.2 使用 new 来分配内存,使用delete来释放内存
第一种情况非动态数组类型的new 数据:
int* ps=new int;//allocate memory with new
delete ps; //free memory with delete when done
第二种情况 动态数组:
int* ps=new int [10];
delete [] ps;
new 运算符返回第一个元素的地址,该地址赋给指针ps
请注意delete和指针之间的方括号。如果使用new时,不带方括号,则使用delete时也不应该使用方括号。如果使用new时带方括号则使用delete也要使用方括号
为数组分配内存的通用格式如下:
type_name* pointer_name=new type_name [num_element];
使
4.7.3 结构与指针
#include<iostream>
#include<string>
#include <stdlib.h>
struct inflatable {
char name[20];
float volume;
double price;
};
int main()
{
using namespace std;
inflatable* ps = new inflatable;//creat an object of type inflatable;
cout << "Enter name of inflatable item: " << endl;
cin.getline(ps->name,20);
cout << "Enter volume in cubic feet: " << endl;
cin >> (*ps).volume;
/*这里需要指出的是inflatable* ps 指出(*ps)相当于结构对象名,可以使用运算符“.”;
ps是指针名当他访问结构时需要使用运算符“->”;*/
cout << "Enter the price:$ ";
cin >> ps->price;
cout << "Name is " << ps->name<< " and Volume is " << ps->volume << " and Price is " << (*ps).price;
system("pause");
return 0;
}
4.9 类型组合
本章介绍了数组、结构和指针。可以各种方式组合它们。
struct a_years_end{
int year;
};
可以创建这种类型的变量:
a_years_end s01,s02,s03;
然后使用成员运算符访问其成员:
s01.year=1998;
可以创建指向这个结构的指针:
a_years_end* pa =&s02;
pa->year=1999;
可以创建结构数组:
a_years_end trio[3];
//然后可以使用成员运算符访问元素的成员
trio[0].year=2003;
//其中trio是一个数组,trio[0]是一个结构,而trio[0].year是该结构的一个成员。//
由于数组名是一个指针,因此也可以使用成员运算符
(trio+1)->year=2004;//same as trio[1].year=2004