string类对象还具备C方式字符串的灵活性吗?还能直接访问单个字符吗?
string类最大限度的考虑了C字符串的兼容性
可以按照使用C字符串的方式使用string对象
#include <iostream> #include <string> using namespace std; int main() { string s = "a1b2c3d4"; int n = 0; for(int i = 0; i<s.length(); i++) { if(isdigit(s[i])) { n++; } } cout << n << endl; }
从上面的例子可以看出,string类对象是支持数组的下标访问的?
问题:难道类的对象也支持数组的下标访问?
举个简单的例子:
#include <iostream> using namespace std; class Test { }; int main() { Test t; cout << t[0] << endl; }
说明C++编译器并不认可将数组访问操作符和任意的类对象共同使用。
被忽略的事实:
-数组访问操作符是C/C++中的内置操作符(和+ - * /地位是一样的)
-数组访问符的原生意义是数组访问和指针运算
a[n]<----->*(a+n) <----->*(n+a) <---->n[a]
指针与数组的复习
#include <iostream> using namespace std; int main() { int a[5] = {0}; for(int i=0; i<5; i++) { a[i] = i; } for(int i=0; i<5; i++) { cout << *(a + i) << endl; } for(int i=0; i<5; i++) { i[a] = i+10; } for(int i=0; i<5; i++) { cout << *(i + a) << endl; } return 0; }
数组访问操作符([])
-只能通过类的成员函数重载
-重载函数能且仅能使用一个参数
-可以定义不同参数的多个重载函数
根据上面的规则,编写数组操作符的重载函数
#include <iostream> using namespace std; class Test { public: int operator [](int n) { return 0; } int operator [](const char *s) { return 0; } }; int main() { Test t; cout << t[1] << endl; return 0; }
上面的程序编译正确,在语法上面是ok的。
#include <iostream> using namespace std; class Test { private: int a[5]; public: int operator [](int i) { return a[i]; } int operator [](const char *s) { return 0; } int getLength() { return 5; } }; int main() { Test t; for(int i=0; i<t.getLength(); i++) { t[i] = i; } for(int i=0; i<t.getLength(); i++) { cout << t[i] <<endl; } return 0; }
编译时,提示有一个不合法的左值。即t[i] = i不合法。
将该条语句改为它的等价形式:t.operator[](i)=i; 此时想要将i赋给函数的返回值,这样肯定不合法,函数调用的返回值怎么能够作为左值使用呢?
要考虑一下,有没有什么技术可以使函数的返回值出现在赋值符号的左边---------引用就登场了。
int operator [](int i) { return a[i]; //在这里我们想要返回的是数组元素的返回值,此时可以返回引用。 }
#include <iostream> using namespace std; class Test { private: int a[5]; public: int& operator [](int i) { return a[i]; } int& operator [](const char *s) { return a[0]; } int getLength() { return 5; } }; int main() { Test t; for(int i=0; i<t.getLength(); i++) { //t.operator [](i) = i; t[i] = i; } for(int i=0; i<t.getLength(); i++) { cout << t[i] <<endl; } return 0; }
int& operator [](const char *s) { return a[0]; }这个数组操作符重载函数挺怪异的,它的参数是一个字符指针,究竟它想做什么呢?其实它想要实现通过字符串来访问一个数组:
#include <iostream> using namespace std; class Test { private: int a[5]; public: int& operator [](int i) { return a[i]; } int& operator [](const string& s) { if( s== "1st") { return a[0]; } else if(s == "2nd") { return a[1]; } else if(s == "3rd") { return a[2]; } else if(s == "4th") { return a[3]; } else if(s == "5th") { return a[4]; } return a[0]; //默认返回a[0] } int getLength() { return 5; } }; int main() { Test t; for(int i=0; i<t.getLength(); i++) { //t.operator [](i) = i; t[i] = i; } for(int i=0; i<t.getLength(); i++) { cout << t[i] <<endl; } //以字符串的形式访问一个数组,以前在C语言中见都没见过。 cout << t["1st"] << endl; cout << t["2nd"] << endl; cout << t["3rd"] << endl; cout << t["4th"] << endl; cout << t["5th"] << endl; return 0; }
编译通过,说明以字符串为下标访问一个数组是合法的。
做这个演示的目的:
如果要学习C++的后续语言,比如C#,D语言等,确实可以将一个字符串作为一个下标来访问一个数组。以后再碰见这种用法,千万不要觉得奇怪。
#include<iostream>
usingnamespacestd;
intmain()
{
inta[5]={0};
for(inti=0;i<5;i++)
{
a[i]=i;
}
for(inti=0;i<5;i++)
{
cout<<*(a+i)<<endl;
}
for(inti=0;i<5;i++)
{
i[a]=i+10;
}
for(inti=0;i<5;i++)
{
cout<<*(i+a)<<endl;
}
return0;
}