留学资讯 一手掌握

加拿大C++补习,留学生C++在线辅导

时间: 2017-01-05 文章来源: 洋蜜蜂

C++是一门比较复杂的课程,很多留学生学习起来比较吃力,这也是一门枯燥的课程,但是还有很多的留学生报这门课,虽然难,但是学好的话对以后出来找工作有很大的帮助。下面洋蜜蜂的online tutor就给各位留学生在线辅导下关于C++的一些基础。

 

1union

联合和struct是几乎一样的语法,所不同的就是内存结构上,union的各个元素共享一个空间,union的总体空间以元素的最空间为准。一次只有一个元素有效(最后一个被赋值的元素有效),其他的元素如果在没有被赋值的情况下的值,是一个不确定的值。

union就像是一个对于一段内存空间,向外可以表现出各种类型。

union test

{

  int a;

  int b;

  char c;

  short d;

  float e;

  char * f;

}test1;

由于不管哪种数据在内存空间中都是以0101来存储的,所以这使得,union成为可能。也就是说,不同的数据类型从同一个内存空间读出来的是不通的(解码的规则不同)。

事实上,union用于表达一个事物属性有可能的不同数据类型,所以,同一时刻只应该有一个元素被使用,并且该元素是最近一次被赋值的。

但是其它的元素,在没有被赋值的情况下,也可以读出数据来,但是这个时候由于该内存空间中的0101代码不是为该类数据类型个设定的(但有可能是同类型,或者相容类型)。所以用户读出来的结果是不确定了。

兼容的数据类型之间(intcharshort)这种转换是可以的,但是intfloat之间却是不能访问的。

test1.a=97;

test1.b==97,test1.c=='a' test1=97.因为他们是兼容的。

但是这个时候.

test1.e==0.0000,说明它与intchar这样的不兼容。

后来再输出test1.a发现等于97.

所以对于union改变该内存空间数据的只有赋值,使用哪种元素读(不管能不能正确读出),只是对该内存空间的不同解释罢了,float就无法解释int的内存空间,所以返回的结果是0.000.但是,内存空间并不会因为这次的读而发生改变。

注意,这个结构体的最后一项,也就是指向字符的指针,如果使用%s,基本时出现段错误,因为%s输出的时候,从该地址开始一直到\0结束。

 

union的一个应用就是拆分数据的字节。一个int内省在C++中有四个字节,我们可以通过如下方式分别得到这是个字节

union test

{

  int a;

  char b[4];

}testT;

testT.a=0x01202343;

printf("%x,%x,%x,%x",testT.b[0],testT.b[1],testT.b[2],testT[3]);

输出结果为43,23,20,01。分别输出来了,但是顺序有点奇怪,这是为什么呢?

这就是,很多系统存储数据的时候的高地位问题,经常是数的低位字节放在低地址,高位字节放在高位地址。通常我们表达地址时,是从左到右,地址增高(从低地址到高地址)。而我们平时看number的时候是从左到右,字节从高到低,所以恰好相反。这就是我们要注意的。

 

2)无符号整数和有符号整数的转换

整数分为无符号和有符号,通常无符号整数用户作为序号,所以也就没有正负的概念,也就可以省出1各位来存放更大的数。但是,同样是我们前面的将的,两者之间的转换并不牵涉内存空间上的0101代码出现变动,只是程序、系统将该部分内存空间怎么读取而已。

int a=-10;

unsigned int b=-10;

的内存空间上的内容是一样的,为什么呢?不管是那个赋值语句,-10这个常量的内容是确定好的,分别拷贝在ab空间中,所不同的是,系统读取a时认为第一个位是代码符号位;而读取b是,第一个位仍然是数。

 

所以,当某个变量已经是一个无符号整数的时候,不要用有符号整数的相关语句来操作它(尤其它负数),基本南辕北辙。这里就有一个陷阱题。

 

int a=6;

unsigned int b=-20;

print("%d",a+b);

print("%d",(a+b)>6);

分别输出的是-141.

有人会说这矛盾,但是这只是你写错了。因为a+b已经变成了unsigned int(想大转换原理)。所以第一个输出应该用%u 来输出。(a+b)>6判断的时候,由于我们系统已经制定a+b是一个unsigned int,所以它自然是一个很大的所谓的正数。

其实我们要注意的是,a+b,本来就很有争议,因为运算器,接收ab,他们虽然会被转换成无符号数,但是,仍然使用那种相加(以有符号模式相加,这也是使用补码的格式保存负数的原因)。所以计算出来的结果使用%d输出自然是-14,你这种输出,更使用%d输出字符元素是一回事,a+b这个变量存储的是一个无符号整数,系统比较它和6时是把它当成一个很大的正数来比较的。

 

使用补码保存负数,让计算机中的计算器的加法和减法统一,利于设计。对于CPU的运算器(加减法)来说,它只知道接收两个寄存器上的数据(对它来说,没有正负之分),然后进行最简单的二进制加法。结果就是正确的结果。所以a+b在运算器中的运算结果是一致的,不会因为你是无符号还是有符号,关键在于如何去解码运算器的结果。

 

 

 

(3)printf输出格式控制

1.转换说明符

      %a(%A)     浮点数、十六进制数字和p-(P-)记数法(C99)

      %c             字符

      %d             有符号十进制整数

      %f              浮点数(包括floatdoulbe)

      %e(%E)     浮点数指数输出[e-(E-)记数法]

      %g(%G)     浮点数不显无意义的零"0"

      %i              有符号十进制整数(%d相同)

      %u             无符号十进制整数

      %o             八进制整数    e.g.     0123

      %x(%X)      十六进制整数0f(0F)   e.g.   0x1234

      %p             指针

      %s             字符串

      %%            "%"

2.标志

      左对齐:"-"   e.g.   "%-20s"

      右对齐:"+" e.g.   "%+20s"

      空格:若符号为正,则显示空格,负则显示"-"   e.g.   "% 6.2f"    

      #:对c,s,d,u类无影响;对o类,在输出时加前缀o;对x类,在输出时加前缀0x

           e,g,f 类当结果有小数时才给出小数点。

3.格式字符串(格式)

      [标志][输出最少宽度][.精度][长度]类型

     "-md" :左对齐,若m比实际少时,按实际输出。

     "%m.ns":输出m位,取字符串(左起)n位,左补空格,当n>m or m省略时m=n

                      e.g.    "%7.2s"   输入CHINA

                                             输出"     CH"

     "%m.nf":输出浮点数,m为宽度,n为小数点右边数位

                      e.g.    "%3.1f"    输入3852.99

                                               输出3853.0

      长度:为h短整形量,l为长整形量

printf的格式控制的完整格式:

% - 0 m.n lh 格式字符

下面对组成格式说明的各项加以说明:

%:表示格式说明的起始符号,不可缺少。

-:有-表示左对齐输出,如省略表示右对齐输出。

0:有0表示指定空位填0,如省略表示指定空位不填。

m.nm指域宽,即对应的输出项在输出设备上所占的字符数。N指精度。用于说明输出的实型数的小数位数。为指定n时,隐含的精度为n=6位。

lh:l对整型指long型,对实型指double型。h用于将整型的格式字符修正为short型。

---------------------------------------

格式字符

格式字符用以指定输出项的数据类型和输出格式。

d格式:用来输出十进制整数。有以下几种用法:

%d:按整型数据的实际长度输出。

%mdm为指定的输出字段的宽度。如果数据的位数小于m,则左端补以空格,若大于m,则按实际位数输出。

%ld:输出长整型数据。

o格式:以无符号八进制形式输出整数。对长整型可以用"%lo"格式输出。同样也可以指定字段宽度用“%mo”格式输出。

例:

   main()

   { int a = -1;

     printf("%d, %o", a, a);

   }

运行结果:-1,177777

程序解析:-1在内存单元中(以补码形式存放)为(1111111111111111)2,转换为八进制数为(177777)8

x格式:以无符号十六进制形式输出整数。对长整型可以用"%lx"格式输出。同样也可以指定字段宽度用"%mx"格式输出。

u格式:以无符号十进制形式输出整数。对长整型可以用"%lu"格式输出。同样也可以指定字段宽度用“%mu”格式输出。

c格式:输出一个字符。

s格式:用来输出一个串。有几中用法

%s:例如:printf("%s", "CHINA")输出"CHINA"字符串(不包括双引号)。

%ms:输出的字符串占m列,如字符串本身长度大于m,则突破获m的限制,将字符串全部输出。若串长小于m,则左补空格。

%-ms:如果串长小于m,则在m列范围内,字符串向左靠,右补空格。

%m.ns:输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的右侧,左补空格。

%-m.ns:其中mn含义同上,n个字符输出在m列范围的左侧,右补空格。如果n>m,则自动取n值,即保证n个字符正常输出。

f格式:用来输出实数(包括单、双精度),以小数形式输出。有以下几种用法:

%f:不指定宽度,整数部分全部输出并输出6位小数。

%m.nf:输出共占m列,其中有n位小数,如数值宽度小于m左端补空格。

%-m.nf:输出共占n列,其中有n位小数,如数值宽度小于m右端补空格。

e格式:以指数形式输出实数。可用以下形式:

%e:数字部分(又称尾数)输出6位小数,指数部分占5位或4位。

%m.ne%-m.nemn和”-”字符含义与前相同。此处n指数据的数字部分的小数位数,m表示整个输出数据所占的宽度。

g格式:自动选f格式或e格式中较短的一种输出,且不输出无意义的零。

---------------------------------------

关于printf函数的进一步说明:

如果想输出字符"%",则应该在“格式控制”字符串中用连续两个%表示,如:

printf("%f%%", 1.0/3);

输出0.333333%

---------------------------------------

对于单精度数,使用%f格式符输出时,仅前7位是有效数字,小数6位.

对于双精度数,使用%lf格式符输出时,前16位是有效数字,小数6位.

######################################拾遗 ########################################

由高手指点

对于m.n的格式还可以用如下方法表示(例)

char ch[20];

printf("%*.*s\n",m,n,ch);

前边的*定义的是总的宽度,后边的定义的是输出的个数。分别对应外面的参数mn 。我想这种方法的好处是可以在语句之外对参数mn赋值,从而控制输出格式。

--------------------------------------------------------------------------------

今天(06.6.9)又看到一种输出格式 %n 可以将所输出字符串的长度值赋绐一个变量, 见下例:

int slen;

printf("hello world%n", &slen);

执行后变量被赋值为11

C++作为世界上的运用最多的计算机语言,获得很多留学生的青睐,该语言支持数据封装和数据隐藏,支持继承和重用,支持多态性。其实学起来也不是很难,学好C++后去学习一些延续性的计算机语言就轻而易举了。洋蜜蜂-----北美留学生们的专业课程在线辅导平台。