【C++ Primer】字符串和数组

一、命名空间的using声明

1、using声明:using namespace::name,例如:using std::cin。一旦声明了上述语句,就可以直接访问命名空间的变量。每个变量都需要using声明,位于头文件中的代码不应该使用using声明。

2、using编译:using namespace std;直接使用整个命名空间。

    一般来说,使用using声明比使用using编译指令更安全,这是由于它只导入指定的名称。如果该名称与局部名称发生冲突,编译器将付出指示。using编译指令导入所有名称,包括可能并不需要的名称。如果与局部名称发生冲突,则局部名称将覆盖名称空间版本,而编译器并不会发出警告,另外,名称空间的开放性意味着名称空间的名称可能分散在多个地方,这使得难以准确的知道添加了哪些名称。

 

二、标准库类型string

    标准库string表示可变长的字符序列,string对象中所存储的内容,是不以空字符结尾的(区别于C风格字符串)

 

#include <string>
using std::string;

 

1、定义和初始化string对象:

 

 

string s1;//初始化为空串。
string s2(s1);//s2是s1的副本。
string s2 = s1;//拷贝初始化。
string s3("value");//直接初始化。
string s3 = "value";//拷贝初始化。
string s4(10,'a');//初始化为多个相同字符组成的串。

 

2、string对象上的操作:

 

string s1,s2,s3;
int a;
cin >> s2;//从第一个真正的字符开始读,直到遇到空白为止。
while(cin >> s2)//读取未知数量的string对象(连续输入时,想结束输入可以换行后输入ctrl+Z)
	cout << s2 << endl;
cin.clear();//清空缓冲区。
cin >> a;
cin.get();//输入数字后使用cin.get()去掉换行符。
getline(cin,s3);//读取一整行(换行符被丢弃),保留输入时的空白符。

/*string的empty和size操作*/
if(!s3.empty() && s3.size()>3)//如果s3非空并且s3的长度大于3。
	cout << s3 << endl;

/*string::size_type类型*/
using st = string::size_type;
for (st i=0 ; i<s3.size() ; ++i)//无符号类型的值,用于处理string对象,好处在于避免混用带符号和无符号类型。
	cout << s3[i] << endl;

/*string对象相加、与字面值相加*/
string s4 = s2 + s3;//字符串连接。
string s5 = s3 + "abc";//必须确保每个加法运算(+)两侧的运算对象至少有一个是string,字符串字面值不等于string。

 

3、处理string对象的字符:

 

(1)范围for【c++11】:遍历给定序列中的每个元素并对序列中的每个值执行某种操作。

 

for (const auto s : s5)//对于s5中的每个字符,输出当前字符。
	cout << s << endl;
for (auto & s : s5)//s是引用,因此会改变s5中的字符值。
	s = toupper(s);

(2)下标运算符:下标从0计算起,string对象的下标必须大于0小于size(),使用下标必须确保其在合理范围内

 

//用decltype定义变量的类型,isspace判断s[index]是否遇到空白符,toupper把小写字母转换为大写字母。
for (decltype(s.size()) index = 0 ; index != s.size() && !isspace(s[index]) ; ++index)
	s[index] = toupper(s[index]);


三、数组

 

    数组是存放类型相同的对象的数据结构,这些对象本身没有名字,通过下标访问。数组的大小是确定的,不能随意增加元素(这一点与vector不同)。在某些情况下运行时性能较好,但是也损失了灵活性。

    【Note】:如果不清楚元素的数量,请使用vector。

 

1、定义和初始化数组:

(1)简单的初始化:

 

int a[cnt];//数组的维度必须是常量表达式。
int cnt2 = 4,b[cnt2];
string s1 = {"abc","edf"};//列表初始化。

    【Note】:不能将数组的内容拷贝给其他数组作为其初始值,也不能使用数组为其他数组赋值,所以函数也不能返回数组。

 

(2)复杂的数组声明:

 

int *ptrs[10];//ptrs是含有10个整型指针的数组。
int &refs[10];//错误:不存在引用的数组。
int (*p)[10] = &arr;//p指向一个含有10个整数的数组。
int (&a)[10] = arr;//a引用一个含有10个整数的数组。

    默认情况下,类型修饰符从右向左依次绑定。就数组而言,要想理解数组声明的含义,最好的办法是从数组的名字开始由内向外(先右后左)的顺序阅读

 

 

2、访问数组元素:

 

unsigned scores[11] = {};
unsigned grade;
while(cin >> grade)
{
    if(grade <= 100)
	++scores[grade/10];//通过下标访问。
}
for (auto i : scores)//i是size_t类型。
    cout << i << endl;

    大多数常见的问题都源于缓冲区的溢出错误,当下标越界或者试图访问非法内存区域时,就会产生此类错误。

 

 

3、指针和数组:   

(1)在很多用到数组名字的地方,编译器都会自动的将其替换为一个指向数组首元素的指针(尤其是作为函数形参的时候)。在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针

 

int *p = scores;//等价于p = &scores[0]。
auto p2(scores);

(2)标准库函数begin和end【c++11】

 

 

 

    为了让指针的使用更简单、安全,引入了begin和end的函数。

 

int *beg = begin(scores);//指向首元素。
int *lst = end(scores);//指向尾元素的下一个位置。

    【Note】:尾后指针不能执行解引用和递增操作。

 

(3)指针运算:

    给指针加上一个整数,得到的新指针任然指向同一数组的其他元素,两个指针相减的结果是它们之间的距离。

 

4、C风格字符串

 

char a[4] = {'a','b','\0'};
char b[2] = {};
size_t l = strlen(a);//计算字符串大小,不包括空字符。
strcpy(b,a);//将a拷贝给b。
strcat(a,b);//将b连接到a后面。
for (const auto s : a)
{
    cout << s << endl;
}

    【Note】:现代的C++程序应当尽量使用vector和迭代器,避免使用内置数组和指针;应该尽量使用string,避免使用C风格的字符串
 

 

四、多维数组

    多维数组其实就是数组的数组。

 

//列表初始化,第一个维度可以省略。
int ia[][2] = 
{
    {1,2},
    {3,4}
};
for (auto p=begin(ia) ; p!=end(ia) ; ++p)
{
    for (auto q=begin(*p) ; q!=end(*p) ; ++q)
	cout << *q << endl;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~青萍之末~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值