最近在读《C++ Prime》,不禁想感叹一句:C++真是一种美丽的语言!!!!!!!
C++提供了相比于 C语言更加丰富的库函数,功也更加强大。举个例子吧。
题目:编写一段程序,读入一段包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。
源代码:
-
//编写一个程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分
-
-
#include <iostream>
-
#include <string>
-
-
using
namespace
std;
-
-
int main()
-
{
-
/*src为源字符串即要操作的字符串,dest为目标字符串,存放操作结果*/
-
string src, dest;
-
getline(
cin, src);
/*从输入中读取一行赋值给str1*/
-
for (
auto c : src)
/*对str中的每个字符*/
-
{
-
if (!
ispunct(c))
/*如果该字符不是标点符号*/
-
{
-
dest.push_back(c);
/*把该字符尾插到dest中*/
-
}
-
}
-
cout << dest <<
endl;
/*输出dest中的内容*/
-
system(
"pause");
-
return
0;
-
}
运行示例:
这段代码的功能是,从键盘输入一个字符串,去除字符串中的标点符号后输出。看到这个题目,如果使用C语言,我们可能首先会想到写一个简单的算法实现这一功能。或者有时会再多想一点点,既然是字符串,可能有时会很自然的想到数据结构中的串 的相关知识,将字符存在字符数组中,然后使用下标确定标点符号的位置和个数,然后移动后面的元素,覆盖掉字符串中的标点符号,但这样有时需要移动大量元素,相对比较繁琐,如果使用链式串,则可以从前往后遍历,当遇到字符为标点符号时,使用指针指向的改变删除标点符号,然后释放其空间。使用C语言算法还好,但如果使用数据结构,就有点太复杂了。如果使用C++语言,我们使用编译器提供的库函数,可以很方便的完成上面的题目要求。
在上面的代码中用到的函数ispunct() 在C语言中也有这个库函数,通过MSDN可以查看这个函数,函数需要包含的头文件为<ctype.h>,C语言中的头文件形式:nane.h,C++则将这些文件命名为cname。也就是去掉了.h后缀,而在文件名name之前添加了c,这里的c表示这是一个属于C语言标准库的头文件。所以C++中包含<ctype.h>的格式为<cctype>。上面的代码中还用到了一种C语言中没有见到过的语句形式for (auto c : src) 这是C++11新标准提供的一种语句范围for语句,在下面会详细解释。
当然C++的美丽之处远远不止这些,更多的是面对对象的编程思想,使其更加适合与大型项目,以及模板和泛型编程等等,同时C++也是在不断发展的。这些美丽之处,需要我们在不断的深入学习中慢慢去体会。
好啦,不知不觉写了这么多。下面切入正题,C语言auto关键字和C++ 中的auto关键字的介绍。 最近在读《C++ Prime》的过程中发现auto关键字在C++中的使用和C语言中有很大的不同,自己以前也总结过C语言中的auto关键字。觉得很有必要将C语言和C++相比较来理解auto关键字。
Ⅰ )C语言中的auto关键字
C语言和C++中auto关键字的使用有很大区别。在C语言中使用auto关键字声明一个变量为自动变量,是C语言中应用最广泛的一种类型,在函数内定义变量时,如果没有被声明为其他类型的变量都是自动变量,也就是说,省去类型说明符auto的都是自动变量。这里的其他类型指的是变量的存储类型即:静态类型变量(static )、寄存器类型变量(register)和外部类型变量(extern)。例如:
-
void Test()
-
{
-
auto
int x =
10;
//定义自动变量x,auto可以省略
-
int y;
//y和z都为自动变量,如果省略了auto 关键字则隐含表示为auto类型
-
double z;
-
...
-
}
在C语言中使用auto定义的变量可以不予初始化,但在C++中必须初始化。自动变量,在函数调用时分配存储空间,当完成调用是释放存储空间。当然也存在下面这种形式:
auto val; //当省略数据类型,只使用auto修饰变量,在C语言中默认变量为int型
为了说明当省略数据类型,只使用auto修饰变量,在C语言中默认变量为int型,可以看下面的代码:
-
#include <stdio.h>
-
#include <Windows.h>
-
int main()
-
{
-
double value1 =
3.2, value2 =
3.5;
-
/*使用auto 定义一个变量,在C语言中可以不初始化,编译器会使用一个随机值
-
值初始化变量val,但建议在写代码时进行初始化,为了说明与C++中的不同,这里
-
不予初始化*/
-
auto val;
-
val = value1 + value2;
-
printf(
"%d\n", val);
-
system(
"pause");
-
return
0;
-
}
通过调试监视窗口,观察变量的值的变化,来进行验证。
可以看到,进入程序,当执行过double value1 = 3.2, value2 = 3.5;语句后value1和value2被初始化为3.2和3.5,在调试过过程中编译器把auto value;当声明处理,跳过了该语句,可以通过类型观察到val的数据类型一直为int 执行完求和语句val = value + value2;后,其结果为整形数据6。所以,C语言中,当省略了数据类型,则使用auto关键字修饰的变量默认为int 型数据。
Ⅱ)C++中的auto关键字
C++中的auto关键字是一个类型说明符,通过变量的初始值或者表达式中参与运算的数据类型来推断变量的类型。编程时通常需要把表达式值式赋给变量,这就要求在声明变量时清楚的知道表达式的类型,C++11新标准引入了auto 类型说明符,让编译器去分析表达式的类型。由于,需要编译器推断变量或表达式的类型,所以,auto定义的变量必须初始化。例如:
-
auto val =
5.2f;
//编译器会根据初始化的值来推断val的数据类型为flaot,但要注意如果去掉f则编译器会认为val为double型变量
-
auto x = y + z;
//x初始化为y和z相加的结果,由y和z的数据类型推断x的数据类型
-
auto num;
//但如果在C++中出现这样的语句,会编译报错,提示“类型包含“auto符号”必须具有初始值设定项”
使用auto也能在一条语句中声明多个变量。因为一条语句声明时只能有一种基本数据类型,所以该语句中的所有变量初始基本数据类型必须一样,例如:
-
auto i =
0, *p = &i;
//正确:i是整数、p是整形指针
-
auto sz =
0, pi =
3,
14;
//错误:sz和pi的类型不一致
auto和decltype 的作用有点相似,都可以推断某个表达式的具体类型,当我们希望从表达式的值推断出要定义的变量的类型,但不想用该表达式的值初始化变量时,可以使用decltype,作用是选择并返回操作数的数据类型,但并不计算表达式的值。如果decltype 使用的表达式不是一个变量,则decltype返回表达式结果对用的类型,”如果我们仅仅是想根据初始值确定一个变量合适的数据类型,那么auto是最佳人选。而只有当我们需要推断某个表达式的数据类型,并将其作为一种新的数据类型重复使用(比如,定义多个相同类型变量)或者单独使用(比如,作为函数的返回值类型)时,我们才真正需要用到decltype“。
在范围for语句中,经常会使用到auto关键字,正如文章开篇举得那个例子,范围for语句遍历给定序列中的每个元素并对序列中的每个值执行某种操作。其语法形式为:
-
/*
-
*declaration 部分定义一个变量,该变量用于访问序列中的基础元素,expression部分是一个对象,用于表示
-
*一个序列。每次迭代,declaration部分的变量会初始化为expression部分的下一个元素值,statment是对字
-
*符的操作语句
-
*/
-
-
for (declaration : expression)
-
{
-
statement
-
}
下面看一个例子,将上面介绍到的关键字和范围for语句梳理一下:
-
//编写一段程序,使用范围for语句将字符串内的所有字符用‘X’代替
-
-
-
#include <iostream>
-
#include <string>
-
-
using
namespace
std;
-
-
int main()
-
{
-
string str;
-
getline(
cin, str);
//从输入中读取一行赋值给str1
-
-
//auto 是一个类型说明符,通过变量的初始值来判断变量的类型
-
-
for (
auto &c : str)
//对于字符串str中的每一个c
-
{
-
//decltype 类型指示符,选择并返回操作数的数据类型,如果decltype使用
-
//的表达式不是一个变量,则decltype返回表达式结果对应的类型
-
for (
decltype(str.size()) index =
0; index < str.size(); ++index)
-
{
-
str[index] =
'X';
-
}
-
}
-
cout << str <<
endl;
//打印替换后的字符串
-
system(
"pause");
-
return
0;
-
}
简单分析:上面的代码完成的功能是,把字符串中的所有字符‘X’用代替。先 从键盘读取一行字符串,然后使用范围for语句对其进行处理,在范围for语句中使用auto关键字推断变量c的数据类型,因为要改变字符串中的字符,所以将循环变量C定义为引用类型,然后使用for循环依次处理字符串str中的字符,将其修改为字符‘X’,在使用下标处理字符串中的字符是,我们需要知道字符串的长度,c++中的size()函数用于返回字符串的长度,即:字符串中字符的个数,类似于C语言中的strlen,字符串的下标从0开始,所以下标的取值大于等于0并且小于字符串的size()值,循环控制条件为:index < str.size(); 所以index为decltype(str.size())型的变量,这里使用decltype返回函数size()返回值类型,并且将其作为数据类型定义index作为字符串中字符的下标,(实际上size()返回的是一个size_t类型的值,个人认为,可以把 size_t 理解为unsigned int型),然后,在循环体内实现字符的替换,上面的代码中用到了本文中讲到的auto类型说明符,decltype类型指示符以及范围for语句,可以帮助我们简单的理解其简单应用。
【参考目录】
《C++ Prime》第五版