C++ 循环和关系表达式

for循环的步骤:

  • 设置初始值
  • 执行测试,看看循环是否应当继续进行
  • 执行循环操作
  • 更新用于测试的值

在C++中,常在for和while等控制语句中,如for,在for和括号之间增写一个空格,以强化控制语句与函数调用之间的区别.。

前缀自增减会将值加1减1,然后返回结果,而后缀自增减首先要创建一个副本,将值加1减1,然后将复制的副本返回,因此,对于类来说,前缀版本的效率要比后缀版本的效率高。

对于内置类型,采用前后缀不会有差别,但对于用户定义的类型,前缀格式的效率更高。

自增减的优先级与相同,但如果同时出现会从右到左执行*(注意指针上的应用)。

string不使用空字符来标记字符串的末尾。

在头文件ctime中,提供了clock()函数来调用系统时间,和循环配合使用可以有效的控制和实现相关程序停顿等问题。

ctime中还定义了CLOCKS_PER_SEC来标记系统的时间与秒的转换参数。

cin >> secs;
clock_t delay = secs * CLOCKS_PER_SEC;
clock_t start = clock();
while(clock() - start

C++11新增了一种基于范围的for循环,简化了一种常见的任务:对数组(或容器类)的每个元素执行相同的操作。

double num[5] = {1.0,5.2,5.4,5.1,0.2};

for(double x : num)
cout

很C++11总是给人高大上的感觉。

但是要注意的是,如果需要修改x的值,则需要添加上引用。

如果和各种容器配合,这种用法将更加方便,类似:

for(int x : {1,2,3,4,5,6})
cout

用cin输入的时候,文件结尾依然是EOF,但是cin是如何判断EOF的呢?

之前用C做题,写的是while(scanf(...) != EOF)

而C++写的是while(cin >> x)

看起来没有任何和EOF有关的判断,但是cin当检测到EOF时是有标记的的

在第四章写过失效位(failbit),其实这里和这个类似,用的是eofbit,如果cin检测到EOF,则,cin.eof()将返回bool值true,否则返回false。

其实无论是failbit和eofbit,只要有一个被标记为1,则cin.fail()则为true,然后cin便失效,不再工作,需要cin.clear()清除标记。

C++也有怀旧情结,因此广泛支持C语言,甚至一些写法故意的怀旧,比如为了模仿getchar和putchar

cin和cout可以:

ch = cin.get();
cout.put(ch);

当然,很明显,这是函数重载实现的(《C++ PP》讲的是这么的慢,小笨球总结的谭浩强那本都讲完重载了,这个还在讲cin)。

2014/10/09 01:00 上午 posted in  C++

C++ 复合类型

C++11使得大括号初始化成为通用初始化,可用于所有类型,甚至可以省略等号的赋值。

cin和scanf一样,对字符串不会录入空格,在istream中的类cin提供了一些面向行的类成员函数:getline()和get(),这两个函数都读取一行输入,直到到达换行符,然而,getline将舍弃换行符,而get将换行符保留在输入序列中。

getline输入两个参数,第一个参数是存储输入行的数组名称,第二个参数是要读取的字符数,

cin.getline(name,20);

其实getline还有第3个参数,只不过第4章木有讲~

对于get()来说,一定要注意的是get并不在读取并丢弃换行符,而是将其留在输入队列中,如果连续两次调用get()

cin.get(name,ArSize);
cin.get(dessert,ArSize);

因为当第一行录入成功之后,因为没有把换行符录入进去,而运行到下一行,

但是换行符留在了输入缓冲中,第二行没有获得任何东西便读到了换行符,也就是dessert没有得到任何东西,这样,如果不借助帮助,这条语句就无法被跳过。

所幸,因为函数重载,get还有另外一种使用方法:

cin.get(name,ArSize);
cin.get();
cin.get(dessert,ArSize);

第二行,这样使用可以吃掉一个任意字符,包括换行符。

其实还有一种炫酷的使用方法,

cin.get(name,ArSize).get();

因为get会返回cin,便可以继续“.”下去~~

不光get,getline也可以。炫酷技能get it (⊙v⊙)。

《C++ PP》推荐使用get而不是getline,原因有二:一是getline在老版本中并没有,也就是说老版本编译器支持性不好,二是如果一行文字录入完成之后,怎么判断是因为录入到换行符才结束的还是因为超出固定长度而结束的?用get只需要判断输入缓冲中最前面那个字符是不是换行符即可。

失效位问题,像封装好的类,里面总有各种各样的标记,而istream中有个失效位标记,标记着是否还能被录入进去数据。

get在读取空行的时候,便会设置失效位,导致后面所有的输入语句失效,

当输入的语句比设置长度要长,get和getline都会只录入规定长度的内容,其他的保留在缓冲区中,但不同的是getline还会设置失效位,关闭后续的输入,在一定长度上讲,起到了保护后续数据的作用。

其实非法输入,EOF等都可以引起失效,失效的解决方法就是清除函数

cin.clear();

其实这样讲,我认为getline也可以判断到底是因为输入过长还是确实是行结束,判断失效位就可以了。

换行符问题,如果是这样的代码:

cin >> year;
cin.getline(address,80);

第二行会被录入什么东西呢?其实只会被录入一个换行符,因为录入year之后,换行符留在了缓冲区,最后被address吃掉了。

和之前敲代码的时候在scanf中加%*c的原因相同,这个也要相似处理,当然,又是一个高大上的语句

(cin >> year).get();

灵活的语句,十分炫酷。

因为string类不需要规定长度,因此有个不是cin成员函数的getline,

string str;
getline(cin,str);

他将cin作为参数而不是以cin的成员函数使用,其实就是因为string出现的晚,cin没有支持string 的成员函数,便加声明了getline以支持string。

面向对象编程与传统的过程性编程的区别在于OOP强调的是在运行阶段而不是编译阶段,最好的诠释就是动态分配,用指针等,在运行过程中决定使用多大的空间而不是在编译的时候决定,更加灵活。

C++中添加了vector作为数组的代替品,vector总的来说属于动态数组,功能要比数组强大,但付出的代价是效率低下。

但在C++11标准中,增加了array类,他的长度和数组一样是固定的,可以认为是定长数组,但是存储在栈(静态内存分配)而不是自由存储区,因此和数组一样快,并且同样强大。

2014/10/08 00:59 上午 posted in  C++

C++ 数据处理与规范

面向对象(OOP)的本质是设计并拓展自己的数据类型C++的命名规则,与C语言一样,但一般以两个下划线或下划线和大写字母打头的名称被保留给实现(编译器及其使用的资源)使用。以一个下划线开头的名称被保留给实现,用作全局标识符。

在C++所有主观风格中,一致性和精度是最重要的。

头文件climits(见下表)定义了符号常量,来表示类型的限制

define编译指令是C语言遗留下来的,C++有一种更好的创建符号常量的方法(使用关键字const)

C++11更广泛的支持大括号初始化器。对于变量初始化可以:

int emus{7};
int rheas = {12};

其次,大括号内可以不包含任何东西,在这种情况下,变量将被初始化为零。

以前,C++使用不同的方式来初始化不同的类型,初始化不同类变量的方式不于初始化常规结构的方式,而初始化常规的方式不同于初始化简单变量的方式,通过使用C++新增的大括号初始化器,初始化常规变量的方式与初始化类变量的方式更像。C++11使得将大括号初始化器用于任何类型(可以使用等号,也可以不使用),这是一种通用的初始化语法。

int被设置为对目标计算机而言最“自然”的长度。自然长度止的是计算机处理起来效率最高的长度。如果没有非常有说服力的理由来选择其他类型,则应使用int。

仅当有大整数数组时,才有必要使用short,尽管有时其长度和int是一样的,但要将程序从16位操作系统移动到32位操作系统,则用于存储int数组的内存量将加倍,而short数组不受影响,记住,节省一点就是赢一点

如果要让cout输出十进制、十六进制和八进制,可以使用控制符dec,hex和oct,用来修改格式,使用方式,如:

cout

C++是如何确定常量的类型呢?如cout但由于l和1很像,一般使用大写L。

char可用作字符和小整数

cout.put()函数用来打印一个字符(C++的历史遗留的原因)

基于字符字符的八进制和十六进制编码来使用转义序列,如ctrl+Z的ASCII码为26,对应的八进制为032,十六进制为0x1a,可以用转义序列来便是该字符如�32,x1a。

C++有一种表示特殊字符的机制,它独立于任何特定的键盘,使用的是通用字符名。

使用通用字符名类似于转义序列,通用字符名可以用u或U打头,u后是8个十六进制位,U后面是16个十六进制位。

与int不同的是,char在默认情况下既不是没有符号的,也不是有符号的,是否有符号由C++决定(这也就是用char和wchar_t表示中文时,正数负数均表示“你好”,见下文wchar_t部分)。

如果用char来存储数值,则unsigned char和signed char的差别将非常重要,前者可以表示0~255,后者为-128~127。

如果程序要处理的字符集无法用一个8位的字节表示,如日文汉字系统。对于这种情况,C++的处理方式有两种,首先如果大型字符是实现的基本的字符集,则编译器厂商可以将char定义为一个16位的字节或则更长的字节,其次,使用一个较大的拓展字符集wchar_t(宽字符类型)

wchar_t是一种整数类型,它有足够的空间,可以表示系统使用的最大拓展字符集。

但cin和cout将输入输出看做char流,因此,适用于处理wchar_t类型,iostream头文件的最新版本提供了作用相似的工具——wcin和wcout,可用于处理wchar_t流,另外,还可以单纯加上前缀L来指示宽字符常量和宽字符串。

在进行国际编程或使用Unicode或ISO10646时应注意使用宽字符类型。

在进行字符串编码是,如果有特定长度和符号特征的类型,将很有帮助,因此,C++11使用前缀u(这回注意大小写)来表示char16_t字符常量和字符串常量,用前缀U来表示char32_t常量。

和wchar_t一样,chat16_t和chat32_t也都有底层类型也都有底层类型(一种内置的整型),但底层类型可能随系统不同而不不同。

const常量比define常量要好些,首先,前者可以明确常量类型,其次,可以使用C++的作用域规则将定义限制在特定范围的函数或者文件中,第三,const可被用于更复杂的数据类型。

C++有3中浮点类型:float、double、long double,float至少32位,double至少48位且不小于float,long double至少和double一样长,通常float为32位,double为64位,long double为80、96、128位(区分在系统),它们的存储范围在cfloat(见下表)头文件中找到。

name value stands for expresses
FLT_RADIX 2 or greater RADIX Base for all floating-point types (floatdouble and long double).
FLT_MANT_DIG DBL_MANT_DIG LDBL_MANT_DIG   MANTissa DIGits Precision of significand, i.e. the number of digits that conform thesignificand.
FLT_DIG DBL_DIG
LDBL_DIG 6 or greater 10 or greater
10 or greater DIGits Number of decimal digits that can be rounded into a floating-point and back without change in the number of decimal digits.
FLT_MIN_EXP DBL_MIN_EXP
LDBL_MIN_EXP   MINimum EXPonent Minimum negative integer value for the exponent that generates a normalized floating-point number.
FLT_MIN_10_EXP DBL_MIN_10_EXP
LDBL_MIN_10_EXP -37 or smaller -37 or smaller
-37 or smaller MINimum base-10 EXPonent Minimum negative integer value for the exponent of a base-10 expression that would generate a normalized floating-point number.
FLT_MAX_EXP DBL_MAX_EXP
LDBL_MAX_EXP   MAXimum EXPonent Maximum integer value for the exponent that generates a normalized floating-point number.
FLT_MAX_10_EXP DBL_MAX_10_EXP
LDBL_MAX_10_EXP 37 or greater 37 or greater
37 or greater MAXimum base-10 EXPonent Maximum integer value for the exponent of a base-10 expression that would generate a normalized floating-point number.
FLT_MAX DBL_MAX
LDBL_MAX 1E+37 or greater 1E+37 or greater
1E+37 or greater MAXimum Maximum finite representable floating-point number.
FLT_EPSILON DBL_EPSILON
LDBL_EPSILON 1E-5 or smaller 1E-9 or smaller
1E-9 or smaller EPSILON Difference between 1 and the least value greater than 1 that is representable.
FLT_MIN DBL_MIN
LDBL_MIN 1E-37 or smaller 1E-37 or smaller
1E-37 or smaller MINimum Minimum representable floating-point number.
FLT_ROUNDS   ROUND Rounding behavior. Possible values: -1 undetermined

 0 toward zero
 1 to nearest
 2 toward positive infinity
 3 toward negative infinity
Applies to all floating-point types (floatdouble and long double). |
| FLT_EVAL_METHOD |   | EVALuation METHOD | Properties of the evaluation format. Possible values: -1 undetermined
 0 evaluate just to the range and precision of the type
 1 evaluate float and double as double, and long double as long double.
 2 evaluate all as long double Other negative values indicate an implementation-defined behavior.
Applies to all floating-point types (floatdouble and long double). |
| DECIMAL_DIG |   | DECIMAL DIGits | Number of decimal digits that can be rounded into a floating-point type and back again to the same decimal digits, without loss in precision. |

附中文参考:

FLT_RADIX 用于表述三种浮点数类型的基数(Radix)
DECIMAL_DIG C++11一个可以与 long double 类型互相转化而不会损失精度的十进制数中的数字个数的最大值
FLT_MIN float类型的最小值
DBL_MIN double类型的最小值
LDBL_MIN long double 类型的最小值
FLT_MAX float 类型的最大值
DBL_MAX double类型的最大值
LDBL_MAX long double 类型的最大值
FLT_EPSILON 返回 float 类型的机器精度(Machine epsilon),即 1.0 与下一个可被 float 类型描述的值的差(Difference)
DBL_EPSILON 返回 double 类型的机器精度,即 1.0 与下一个可被 double 类型描述的值的差
LDBL_EPSILON 返回 long double 类型的机器精度,即 1.0 与下一个可被 long double 类型描述的值的差
FLT_DIG 返回在不损失精度的前提下,float 类型可描述的基于基数 10 的数的最大数字(Digit)个数
DBL_DIG 返回在不损失精度的前提下,double 类型可描述的基于基数 10 的数的最大数字个数
LDBL_DIG 返回在不损失精度的前提下,long double 类型可描述的基于基数 10 的数的最大数字个数
FLT_MANT_DIG 返回在不损失精度的前提下,float 类型可描述的基于基数 FLT_RADIX 的数的最大数字个数
DBL_MANT_DIG 返回在不损失精度的前提下,double 类型可描述的基于基数 FLT_RADIX 的数的最大数字个数
LDBL_MANT_DIG 返回在不损失精度的前提下,long double 类型可描述的基于基数 FLT_RADIX 的数的最大数字个数
FLT_MIN_EXP 用 FLT_RADIX 的 x-1 次幂表示 float 类型的规格化(Normalized)时,x 所能取的最小负整数值
DBL_MIN_EXP 用 FLT_RADIX 的 x-1 次幂表示 double 类型的规格化时,x 所能取的最小负整数值
LDBL_MIN_EXP 用 FLT_RADIX 的 x-1 次幂表示 long double 类型的规格化时,x 所能取的最小负整数值
FLT_MIN_10_EXP 用 10 的 x 次幂表示 float 类型的规格化时,x 所能取的最小负整数值
DBL_MIN_10_EXP 用 10 的 x 次幂表示 double 类型的规格化时,x 所能取的最小负整数值
LDBL_MIN_10_EXP 用 10 的 x 次幂表示 long double 类型的规格化时,x 所能取的最小负整数值
FLT_MAX_EXP 用 FLT_RADIX 的 x-1 次幂表示 float 类型的规格化(Normalized)时,x 所能取的最大正整数值
DBL_MAX_EXP 用 FLT_RADIX 的 x-1 次幂表示 double 类型的规格化时,x 所能取的最大正整数值
LDBL_MAX_EXP 用 FLT_RADIX 的 x-1 次幂表示 long double 类型的规格化时,x 所能取的最大正整数值
FLT_MAX_10_EXP 用 10 的 x 次幂表示 float 类型的规格化时,x 所能取的最大正整数值
DBL_MAX_10_EXP 用 10 的 x 次幂表示 double 类型的规格化时,x 所能取的最大正整数值
LDBL_MAX_10_EXP 用 10 的 x 次幂表示 long double 类型的规格化时,x 所能取的最大正整数值
FLT_ROUNDS 默认的浮点数类型的舍入(Rounding)模式
FLT_EVAL_METHOD C++11默认的浮点数类型的反规格化(Denormalization)模式

计算机默认将浮点型常量看做double类型,如果希望为float。则使用后缀f,如果希望long double则使用后缀L(一样大小写任意)。

C++11将使用大括号的初始化称为列表初始化,因为这种初始化常用与给复杂的数据类型提供值列表,它对类型转换的要求更严格。具体的说,列表初始化不允许“缩窄”,即变量的类型可能无法表示赋给它的值(就是我们说的精度损失)。

C++想让强制转换就像函数一样调用,因此允许

typeName(Value);

这样强制转换。

C++认为C语言的强制转换是危险的,便引入了static_cast<>,用法是:

static_cast (Value);

C++11新增了以一个工具,让编译器根据初始值的类型推断变量的类型,为此,它重新定义了auto的含义,使得auto称为不指定变量类型,编译器将把变量的类型设置于初始值相同,在STL中,auto将发挥巨大的作用!

auto i = 1; //i将为int类型
auto d = 1.0; //d将为double类型

2014/09/26 00:53 上午 posted in  C++

C++ 基本概念

又回到了刚开始大学生活的感觉,当时在啃蓝书,厚厚的一本,感觉没有尽头。现在的C++更厚,而且,做笔记看书是最慢的,感觉没有尽头。


C++能够使用printf,scanf和其他所有标准C的输入输出函数,只需要包含常规C语言的stdio.h头文件。

 

C++和C一样,也是用终止符,而不是分隔符,终止符是一个分毫,它是语句的结束标记,是语句的组成部分。而不是语句之间的标记。

C++句法要求main()函数的定义以函数头int main()开始,main函数有返回值是个好习惯,到现在为止上课老师依然是void实在蛋疼。

Main函数如果没有参数,则应加上void。对于main函数来说,可以不加return 0,ANSI/ISO C++标准允许这么做,当不加return语句时会自动补上return 0,但是这个标准不适用于其他函数,当然,不加return 是个不好的习惯。

 

像iostream这样的文件叫做包含文件,C语言的传统是头文件使用拓展名.h,将其作为一种通过名称标识文件类型的简单方式,而C++的头文件没有拓展名,有些头文件被转换为C++头文件,这些文件被重新命名,去掉了拓展名.h,并加上了前缀c,如stdio.h变为cstdio。对于去掉h,,不是C++形式上的变化,没有h的头文件可以包含名称空间。

 

如果使用iostream而不是iostream.h(C++旧式风格)应使用using namespace std;名称空间编译指令来使iostream中的定义对程序可用。

名称空间支持是一项C++的特性,旨在编写大型程序以及将多个厂商现有的代码组合起来的程序时更容易。

名称空间::内容;

按着这种方法,类、函数和变量便是C++编辑器的标准组件。

 

“C++拓展了运算符重载的概念允许为用户定义的类型(类)重定义运算符的含义。

 

诸如endl等对cout来说有特殊含义的特殊符号被称为控制符。

C++也支持C的旧式方法换行“n”,但与endl的区别是endl确保程序继续运行前刷新输出(刷新缓冲区,立即显示在屏幕上),而是用“n”不能提供这样的保证。

C++源代码的风格

  1. 每条语句占一行
  2. 每个函数都有一个开始花括号和一个结束花括号,这两个花括号各占一行
  3. 函数中的语句都相对于花括号进行缩进
  4. 与函数名称相关的圆括号周围没有空白

空行将声明语句与程序其它部分非开,这是C常用方法但在C++中不那么常见。

与printf相比,cont能识别类型,cout的设计更灵活,更好用,另外,它是可扩展的,也就是说可以重新定义“<<”运算符,使cout能够识别和显示所开发的新数据类型,如果喜欢printf提供的细致的控制功能,可以使用更高级的cout来获得相同的效果。(C的输入输出和C++的输入输出是两个不同的缓存区,导致C++输入输出较慢,如何解决C++输入慢)。

类之于对象,如同数据类型之于变量,类定义描述了数据格式及其用法。类描述了一种数据类型的全部属性(包括可执行的操作)。

C++程序应当为程序中使用的每个函数提供原理。

在特定函数中使用类似using std::cont这样的编译命令而不是using namespace std;更节省。

个人命名风格特别值得注意,它有助于保持一致性和精确性,精确、让人一目了然的个人命名约定是良好的软件工程的标识。

C++有六种类型的语句:

  1. 声明语句
  2. 赋值语句
  3. 消息语句:将消息发送给对象,激发某种行为
  4. 函数调用
  5. 函数原型
  6. 返回语句

类是用户定义的数据类型规范,详细描述了如何表示信息以及可对数据执行哪些操作,对象是根据类规范创建的实体。


C++ PP前十章的内容算是过第二遍了,而前七章和蓝书无差,都看烦了= =,感觉再看下去就要背下来了。不过再简单的东西,为了十章以后的深入,就这样忍了吧。

2014/09/17 00:52 上午 posted in  C++

C++ 预备知识

C++在C的基础上深加了对面向对象编程泛型编程的支持。

C++面向对象的新技术是:对象、类、封装、数据隐藏、多态、继承。

C++融合了3种不同的编程方式,C代表的过程性语言,C++在C语言基础上添加的类代表的面向对象语言、C++模板支持的泛型编程。

使用C++的原因之一是为了利用其面向对象的特征,要利用这种特征,必须对C语言有较深入的了解。因为它提供了基本类型、运算符、控制结构和语法规则。从C过渡到C++的时候不再是仅仅学习更多的关键字(学习C的过程就是学习关键字的过程)和新的数据结构,从C过渡到C++的学习量就像从头学习C的内容一样大,在过渡到C++的时候,必须摒弃一些编程习惯,学习C++需要更多的拓展思维

20世纪70年代,贝尔实验室的Dennis Ritche致力于开发UNIX操作系统,希望有一种语言能将低级语言的效率、硬件访问能力和高级语言的通性、可移植性融合在一起,于是他在旧语言的基础上开发了C语言。其所遵循的旧理念是强调程序的算法方面。从概念上说过程化编程首先要确定计算机应采用的操作,然后使用编程语言来实现这些操作。C语言还采用了结构化编程和自顶向下的设计(C将大型程序分解为小型、编辑管理的任务)

面向对象编程(OOP)强调的是数据,OOP不同于过程性语言试图使问题满足语言的过程新方法,而是试图让语言来满足问题的要求。其理念是设计与问题本质特性相对应的数据格式。

在C++中,类是一种规范,它描述了这种新型数据格式对象是根据这种规范构造的特定数据结构。

类规定了可使用哪些数据来表示对象,以及可以对这些数据执行哪些操作。

OOP程序设计方法首先设计类,他们准确的表示了程序要处理的东西,然后设计一个使用这些类的对象的程序,从低级组织(如类)到高级组织(如程序)的处理过程叫做自下向上的编程。

OOP程序设计不仅仅是将数据和方法合并为类定义。多态能够为数算符和函数创建多个定义(通过编程上下文来确定使用哪个定义),继承让能使用旧类派生出新类。

OOP引入了很多新的理念,使用的编程方法不同于过程性编程。它不是将重点放在任务上,而是放在表示概念上。

设计有用、可靠的类是一项很艰巨的任务,幸运的是在编程中可以使用已有的类(STL),C++真正的优点之一是:可以方便的重(chong)用和修改现有的经过只系测试过的代码。

泛型编程强调的是独立于特定数据结构,和OOP侧重点不同,OOP是一个管理大型项目的工具,而泛型编程提供了执行常见任务的工具。术语泛型指的是创建独立于类型的代码。

OOP不凡赋予了C++语言将问题所涉及的感念联系起来的能力。C部分则赋予了C++语言紧密联系硬件的能力。如果忽略C++面向对象的特性,将错过很多有用的东西。

2014/09/14 00:51 上午 posted in  C++