C++函数学习(三)

来源:互联网 发布:东营区一中知校二维码 编辑:程序博客网 时间:2024/04/30 06:11
60  size 的用法

size是由string vector 和bitset定义的函数,分别用于返回字符个数,元素个数和二进制位的数。string和vector的size成员函数用以返回size_type类型的值。bitset返回size_t的值。

 

用法,例如string

string st("fddddddddgs");

cout<<"the sizeof"<<st<<"is"<<st.size();

打印st中的字符个数

size其实就是计算不同类型容器中的元素个数的。

61  fopen()函数 
    fopen函数用于打开文件, 其调用格式为: 
     FILE *fopen(char*filename, *type); 

在介绍这个函数之;前, 先了解一下下面的知识。 
    (1) 流(stream)和文件(file) 
    流和文件在Turbo C2.0中是有区别的, Turbo C2.0 为编程者和被访问的设 
备之间提供了一层抽象的东西, 称之为"流", 而将具体的实际设备叫做文件。 
流是一个逻辑设备, 具有相同的行为。因此, 用来进行磁盘文件写的函数也同样 
可以用来进行打印机的写入。在Turbo C2.0中有两种性质的流:   文字流( text 
stream)和二进制(binary stream)。对磁盘来说就是文本文件和二进制文件。本 
软件为了便于让读者易理解Turbo C2.0语言而没有对流和文件作特别区分。 
    (2) 文件指针FILE 
    实际上FILE是一个新的数据类型。它是Turbo C2.0的基本数据类型的集合, 
称之为结构指针。有关结构的概念将在第四节中详细介绍, 这里只要将FILE理解 
为一个包括了文件管理有关信息的数据结构, 即在打开文件时必须先定义一个文 
件指针。 
    (3) 以后介绍的函数调用格式将直接写出形式参数的数据类型和函数返回值 
的数据类型。例如: 上面打开文件的函数, 返回一个文件指针, 其中形式参数有 
两个, 均为字符型变量(字符串数组或字符串指针)。本软件不再对函数的调用格 
式作详细说明。 
    现在再来看打开文件函数的用法。 
    fopen()函数中第一个形式参数表示文件名, 可以包含路径和文件名两部分。 
如: 
    "B:TEST.DAT" 
    "C:\\TC\\TEST.DAT" 
    如果将路径写成"C:\TC\TEST.DAT"是不正确的, 这一点要特别注意。 
    第二个形式参数表示打开文件的类型。关于文件类型的规定参见下表。 
                      表  文件操作类型 
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 
         字符               含义 
   ──────────────────────────── 
          "r"           打开文字文件只读 
          "w"           创建文字文件只写 
          "a"           增补, 如果文件不存在则创建一个 
          "r+"          打开一个文字文件读/写 
          "w+"          创建一个文字文件读/写 
          "a+"          打开或创建一个文件增补 
          "b"           二进制文件(可以和上面每一项合用) 
          "t"           文这文件(默认项) 
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 
    如果要打开一个CCDOS子目录中, 文件名为CLIB的二进制文件, 可写成: 
    fopen("c:\\ccdos\\clib", "rb"); 
    如果成功的打开一个文件, fopen()函数返回文件指针,  否则返回空指针 
(NULL)。由此可判断文件打开是否成功。 
    2. fclose()函数 
    fclose()函数用来关闭一个由fopen()函数打开的文件 , 其调用格式为: 
      int fclose(FILE*stream); 
    该函数返回一个整型数。当文件关闭成功时, 返回0, 否则返回一个非零值。 
可以根据函数的返回值判断文件是否关闭成功。 
    例10: 
     #iclude 
     main() 
     { 
         FILE *fp;               /*定义一个文件指针*/ 
         int i; 
         fp=fopen("CLIB", "rb");  /*打开当前目录名为CLIB的文件只读*/ 
         if(fp==NULL)            /*判断文件是否打开成功*/ 
            puts("File open error");/*提示打开不成功*/ 
         i=fclose(fp);           /*关闭打开的文件*/ 
         if(i==0)                /*判断文件是否关闭成功*/ 
           printf("O,K");         /*提示关闭成功*/ 
         else 
           puts("File close error");/*提示关闭不成功*/ 
     } 

62  strchr()函数

 函数原型:extern char *strchr(char*str,char character)

参数说明:str为一个字符串的指针,character为一个待查找字符。
所在库名:#include<string.h>
函数功能:从字符串str中寻找字符character第一次出现的位置。
返回说明:返回指向第一次出现字符character位置的指针,如果没找到则返回NULL

其它说明:还有一种格式char *strchr(const char *string, int c ),这里字符串是以int型给出的。

实例:

#include<string.h>
#include<stdio.h>
int main()
{
    char *str="Hello,I am sky2098,I liking programing!";
    char character='k' ;  //指定一个字符
    char *strtemp;

    strtemp=strchr(str,character);
    if(strtemp!=NULL)
    {
        printf("%s ",strtemp);
    }
    else
    {
        printf("can not find %c !",strtemp);
    }
    return 0;
}

VC++ 6.0编译运行:

注意返回字符串包含我们character字符。 

我们把下面定义:

char character='k' ;  //指定一个字符

改写成:

int character='k' ;  //指定一个字符

也同样能够实现。

63  clear()函数

清除并发队列,销毁所有当前已排入队列的元素。 此方法不是并发安全方法。

template<

typename _Ty,

class _Ax

void concurrent_queue<_Ty,_Ax>::clear();

clear()函数删除所有的元素(清空集合)

64  memcpy()函数

原型:externvoid *memcpy(void *dest, void *src, unsigned int count);
  用法:#include<string.h>
  功能:由src所指内存区域复制count个字节到dest所指内存区域。
  说明:srcdest所指内存区域不能重叠,函数返回指向dest的指针。
  举例:
  // memcpy.c
  #include <syslib.h>
  #include <string.h>

  main()
  {
  char *s="Golden Global View";
  char d[20];
  clrscr();
  memcpy(d,s,strlen(s));
  d[strlen(s)]=0;
  printf("%s",d);
  getchar();
  return 0;
  }
65  memcpy_s, wmemcpy_s

Copies bytes between buffers.These are versions ofmemcpy,wmemcpy with security enhancements asdescribed inSecurityFeatures in the CRT.

副本之间的缓冲区的字节。这些都是memcpy的的版本wmemcpy与安全性增强,在CRT的安全功能描述。

errno_t memcpy_s(

void *dest,

size_t numberOfElements,

const void *src,

size_t count

);

errno_t wmemcpy_s(

   wchar_t *dest,

size_t numberOfElements,

const wchar_t *src,

size_t count

);

 

dest

New buffer.:新的缓冲区。

numberOfElements

Size of the destination buffer.:目标缓冲区的大小。

src

Buffer to copy from.:缓冲区复制。

count

Number of characters to copy.:要复制的字符数。

66  stl list 使用begin()函数和end()函数输出结果

//所有容器类别都提供一些成员函数,使得获得迭代器并以之遍访所有元素,这些函数如下:
//begin()返回一个迭代器,指向容器起始点,也就是第一元素的位置
//end()返回一个迭代器,指向容器结束点。结束点在最后一个元素之后

//stl/list2.cpp
#include <iostream>
#include <list>
using namespace std;
int main(){
list<char> coll;//list container forcharacter elements
//append elements from 'a' to 'z'
for( char c = 'a'; c <='z';c ++ )
coll.push_back(c);
/*print all element
* iterate over all elements
*/
list<char >::const_iterator pos;
for(pos = coll.begin();pos !=coll.end();++pos){
cout<< *pos <<"";        
}
cout<<endl;
system("pause");
} 

67  #ifndef 和#define 在C++中什么意思?

#ifndef xxx//如果没有定义xxx

#define xxx//定义xxx

#endif //结束如果

这个用法主要是在头文件中,主要是为了防止类重复的include,所以在类的头文件之前加上前面两个,用类名替代xxx,在最后加上最后一句。

68 如何使用微软提供的TCHAR.H头文件?  

如果你现在写的代码使用的是SBCS (ASCII)字符集,但是过一段时间后某个客户跟你说他们现在的系统只支持Unicode (wide-character)字符集,你怎么办呢?问题的答案就在微软给我们提供的tchar.h头文件里面!

这样我们就可以使用TCHAR.H头文件中的定义的这些mapping写出可以运行于不同字符集上的通用代码;你所需要做的就是在包含该头文件后在编译器选项里面定义好所需要的宏或者在你的源文件里使用#define定义所需要的宏也可以。

69  各个头文件的作用?

#pragma   once        //确保文件的头文件只包含一次 

#ifndef   __AFXWIN_H__  //确保已经包含WINDOW.H文件 

 #ifdef  _DEBUG     //调试程序时使用,release下并不编译,因此去掉也不会影响。 

70  afxwin.h和stdafx.h主要说明了些

stdafx.h用来作为precomplied   file.包含了MFC中的其他.h文件. 
afxwin.h用来宣布MFC的所有类;

afxwin.hMFC编程的必需文件,其中包含如CStringCEdit类运行所必需的头文件,最好保证该句在头文件首行;它还会调用windows.h,改头文件包含有数据类型的定义、API入口点定义和其它有用的参数信息;

71  assert用法总结

assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:
#include <assert.h>
void assert( int expression );

assert的作用是现计算表达式 expression,如果其值为假(即为0),那么它先向stderr打印一条出错信息,
然后通过调用 abort来终止程序运行。

72  _T( " ")

_T什么意思?

使之成为UNICODE编码。

_T:如果编译时指定生成UNICODE版本,则将字符串转换成UNICODE;如果编译是没有指定UNICODE,则就是一般的窄字符。

73  _tcsdup()函数

_tcsdup

复制字符串,申请的内存与字符串大小相同.

char *_strdup( const char *strSource );

74 _tcsncpy()函数

_tcsncpy(lpBuffer,m_pszPathName, dwBufSize)  把m_pszPathName复制给lpBuffer,复制长度为dwBufSize;

75  _tcslen()函数

dwLen =_tcslen(lpBuffer);   获取字符串的长度;

76  #pragma warning作用及使用方法 

(1)#pragmawarning只对当前文件有效(对于.h,对包含它的cpp也是有效的),而不是对整个工程的所有文件有效。当该文件编译结束,设置也就失去作用。

(2)#pragmawarning(push)

存储当前报警设置。

#pragma warning(push, n)

存储当前报警设置,并设置报警级别为nn为从14的自然数。

(3 )#pragmawarning(pop)

恢复之前压入堆栈的报警设置。在一对pushpop之间作的任何报警相关设置都将失效。

(4) #pragmawarning(disable: n)

将某个警报置为失效

(5) #pragmawarning(default: n)

将报警置为默认

77 char * const prt1char const * ptr2

char * const prt1 = stringprt1; 
  其中,ptr1是一个常量指针。因此,下面赋值是非法的。 
  ptr1 = stringprt2; 
  而下面的赋值是合法的: 
  *ptr1 = "m"; 
  因为指针ptr1所指向的变量是可以更新的,不可更新的是常量指针ptr1所指的方向(别的字符串)。 
  下面定义了一个指向字符串常量的指针: 
  const * ptr2 = stringprt1; 
  其中,ptr2是一个指向字符串常量的指针。ptr2所指向的字符串不能更新的,而ptr2是可以更新的。因此, 
  *ptr2 = "x"; 
  是非法的,而: 
  ptr2 = stringptr2; 
  是合法的。 
  所以,在使用const修饰指针时,应该注意const的位置。定义一个指向字符串的指针常量和定义一个指向字符串常量的指针时,const修饰符的位置不同,前者const放在*和指针名之间,后者const放在类型说明符前。 

78  c++中explicit关键字的含义和用法

c++中的explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?

如果c++类的构造函数有一个参数,那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象,如下面所示:

class MyClass

           {

           public:

           MyClass(int num );

           }

           ....

           MyClassobj = 10; //ok,convert int to MyClass

在上面的代码中编译器自动将整型转换为MyClass类对象,实际上等同于下面的操作:

   MyClass temp(10);

   MyClass obj = temp

   上面的所有的操作即是所谓的"隐式转换".

   如果要避免这种自动转换的功能,我们该怎么做呢?嘿嘿这就是关键字explicit的作用了,将类的构造函数声明为"显示",也就是在声明构造函数的时候 前面添加上explicit即可,这样就可以防止这种自动的转换操作,如果我们修改上面的MyClass类的构造函数为显示的,那么下面的代码就不能够编 译通过了,如下所示:

 classMyClass

            {

            public:

            explicitMyClass( int num );

            }

            ....

            MyClassobj = 10; //err,can't non-explict convert

 

classisbn_mismatch:public std::logic_error{

            public:

            explicitisbn_missmatch(const std::string &s):std:logic_error(s){}

            isbn_mismatch(conststd::string &s,const std::string &lhs,const std::string &rhs):

            std::logic_error(s),left(lhs),right(rhs){} 

            conststd::string left,right;

            virtual~isbn_mismatch() throw(){}

            };

            Sales_item&operator+(const Sales_item &lhs,const Sales_item rhs)

            {

            if(!lhs.same_isbn(rhs))

              throwisbn_mismatch("isbn missmatch",lhs.book(),rhs.book());

            Sales_itemret(lhs);

            ret+rhs;

            returnret;

            }

            Sales_itemitem1,item2,sum;

            while(cin>>item1>>item2)

            {

            try{

              sun=item1+item2;

            }catch(constisbn_mismatch &e)

            {

              cerr<<e.what()<<"leftisbn is:"<<e.left<<"right isbnis:"<<e.right<<endl;

            }

            }

用于用户自定义类型的构造函数,指定它是默认的构造函数,不可用于转换构造函数。因为构造函数有三种:1拷贝构造函数2转换构造函数3一般的构造函数(我自己的术语^_^)另:如果一个类或结构存在多个构造函数时,explicit 修饰的那个构造函数就是默认的

classisbn_mismatch:public std::logic_error{

           public:

           explicitisbn_missmatch(const std::string &s):std:logic_error(s){}

           isbn_mismatch(conststd::string &s,const std::string &lhs,const std::string &rhs):

           std::logic_error(s),left(lhs),right(rhs){}

           conststd::string left,right;

           virtual~isbn_mismatch() throw(){}

           };

           Sales_item&operator+(const Sales_item &lhs,const Sales_item rhs)

           {

           if(!lhs.same_isbn(rhs))

             throwisbn_mismatch("isbn missmatch",lhs.book(),rhs.book());

           Sales_itemret(lhs);

           ret+rhs;

           returnret;

           }

           Sales_itemitem1,item2,sum;

           while(cin>>item1>>item2)

           {

           try{

             sun=item1+item2;

           }catch(constisbn_mismatch &e)

           {

             cerr<<e.what()<<"leftisbn is:"<<e.left<<"right isbnis:"<<e.right<<endl;

           }

           }

这个《ANSI/ISO C++ Professional Programmer'sHandbook》是这样说的

79  c++ 类名称后带&符号是什么意思

是引用的意思,一般对于类或者结构体变量,如果直接返回,是有些问题的,所以我们一般用指针或者引用返回。C++推荐用引用返回,因为其实效率上和指针类似,又避免了指针的一些问题。你看多了就习惯了。

比如,要把这个类增加个重载运算符<<,也是这样写:

class Screen {

...

friend ostream & operator << (ostream & o,Screen & s)

{

      o <<"[" << s.x << "," << s.y <<"]";

return o;

}

...

然后你使用的时候可以这样写:class Screen s; cout << s <<endl;

这样写的好处就是你把变量当成普通的结构体或者类变量用就行,而且效率很高。

80 C++中成员初始化列表的使用

C++在类的构造函数中,可以两种方式初始化成员数据(data member)

1,在构造函数的实现中,初始类的成员数据。诸如:

class point
{
private:
 int x,y;
public:
 point(int m=0,int n=0)
 {
  x=m;
  y=n;
 }

 int GetX()
 {
  return x;
 }
 int GetY()
 {
  return y;
 }
};

2,还可以定义初始化成员列表(Initializer list)来初始化成员数据(data member)

  改写构造函数如下:

 point(int m=0,int n=0):x(m),y(n)
 {
 }

这样咋一看没有什么不同,确实,对于上面的这种简单列子来说,也真的没有太大不同。

那我们为什么要用初始化成员列表,什么时候用初始化成员列表来初始化成员数据呢?Lippman的《C++ Primer》中提到在以下三种情况下需要使用初始化成员列表:

一,需要初始化的数据成员是对象的情况;

二,需要初始化const修饰的类成员;

三,需要初始化引用成员数据;

现在分别举例说明:

一,需要初始化的数据成员是对象。

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

#include <stdio.h>

class point
{
protected:
 int m_x,m_y;
public:
 point(int m=0,int n=0)
 {
  m_x = m;
  m_y = n;
  printf("constructor called!/n");
 }
 point(point& p)
 {
  m_x = p.GetX();
  m_y = p.GetY();
  printf("copy constructor called!/n");
 }
 int GetX()
 {
  return m_x;
 }
 int GetY()
 {
  return m_y;
 }
};

 

class point3d
{
private:
 point m_p;
 int m_z;
public:
 point3d(point p, int k)
 {
  m_p = p;                            //
这里是m_p的赋值
  m_z=k;
 }
 point3d(int i,int j, int k):m_p(i,j)   //
相当于 point m_p(i,j)这样m_p初始化
 {
  m_z=k;
 }

 void Print()
 {
  printf("%d,%d,%d /n",m_p.GetX(),m_p.GetY(),m_z);
 }
};

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

上述代码中Point3d是一个3D坐标,他有一个point2D坐标和一个成员组成。

我们现在想定义一个3D坐标p3d,可以这样实现:

void main()
{
 point p(1,2);    //
先定义一个2D坐标

 point3d p3d(p,3);

 p3d.Print();
}
point3d实现体可以看出,我们是通过对m_p进行赋值,这样不仅调用copy constructor产生临时对象而且是对m_p的一个赋值操作。

而如果使用成员初始化列表,我们则可以这样:

void main()
{
 point p(1,2);

 point3d p3d(1,2,3);

 p3d.Print();
}

p3d中的point型成员是通过调用初始化的方式构建的。由于对象赋值比初始化要麻烦的多,因此也带来的性能上的消耗。(可以参见Scott Meyers著《effective C++》条款12)。

这也是我们在对成员数据是对象成员的采用初始化列表进行初始始化的主要原因。

 

二,需要初始化const修饰的类成员;

三,需要初始化引用成员数据;

对于类成员是const修饰,或是引用类型的情况,是不允许赋值操作的,(显然嘛,const就是防止被错误赋值的,引用类型必须定义赋值在一起)因此只能用初始化列表对齐进行初始化。

上面两点比较好明白,可以用一个例子加以说明:

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

#include <stdio.h>

class base
{
private:
 const int a;
 int& b;

public:
// base(int m, int n)
// {
//  a = m;
//  b = n;
// }

 base(int m, int n):a(m),b(n)
 {}
};

 

void main()
{
 base ba(1,2);
}
---------------------------

上面红色的部分初始化的方式是不允许的通不过编译,通过初始化列表则可以很好的定义。

81  _MSC_VER代表什么?

#ifdefined(_MSC_VER) && (_MSC_VER >= 1200) &&(_MSC_VER < 1300)

_MSC_VER代表操作系统的版本号

定义编译器的版本,VC++6.0就是1200 
#if   _MSC_VER   >   1000的意思就是如果编译器版本高于1000(VC++5.0)

计算结果为主要的和次要的组件数量的编译器的版本号。主要的号码是第一个组件的period-delimited版本号和次要版本号是第二个组件。    例如,如果这个版本号的Visual c++编译器15.00.20706.01,_MSC_VER宏观计算为1500。    在Visual Studio 2010,_MSC_VER被定义为1600

82 友元函数 友元类

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。 
  友元函数 
  友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样。下面举一例子说明友元函数的应用。 
  #include   
  #include   
  class   Point 
  { 
  public: 
    Point(double   xx,   double   yy)  {   x=xx;   y=yy;   } 
    void   Getxy(); 
    friend   double   Distance(Point  &a,   Point   &b); 
  private: 
    double   x,   y; 
  }; 
  void   Point::Getxy() 
  { 
  cout << "( " < 
  } 
  double   Distance(Point   &a,  Point   &b) 
  { 
  double   dx   =   a.x   -  b.x; 
  double   dy   =   a.y   -  b.y; 
  return   sqrt(dx*dx+dy*dy); 
  } 
  void   main() 
  { 
  Point   p1(3.0,   4.0),   p2(6.0,  8.0); 
  p1.Getxy(); 
  p2.Getxy(); 
  double   d   =   Distance(p1,  p2); 
  cout << "Distance   is "< 
  } 

  说明:在该程序中的Point类中说明了一个友元函数Distance(),它在说明时前边加friend关键字,标识它不是成员函数,而是友元函数。它的定义方法与普通函数定义一样,而不同于成员函数的定义,因为它不需要指出所属的类。但是,它可以引用类中的私有成员,函数体中a.x,b.x,a.y,b.y都是类的私有成员,它们是通过对象引用的。在调用友元函数时,也是同普通函数的调用一样,不要像成员函数那样调用。本例中,p1.Getxy()和p2.Getxy()这是成员函数的调用,要用对象来表示。而Distance(p1,   p2)是友元函数的调用,它直接调用,不需要对象表示,它的参数是对象。(该程序的功能是已知两点坐标,求出两点的距离。) 
  友元类 
  友元除了前面讲过的函数以外,友元还可以是类,即一个类可以作另一个类的友元。当一个类作为另一个类的友元时,这就意味着这个类的所有成员函数都是另一个类的友元函数。 

83 c++ 里面类名后面跟一个&*是什么意思,有什么区别?

GetInstance和myInstance是classA里定义的对象:

static classA& GetInstance();

static classA* myInstance;

之后引用,下面这两条语句是什么意思?&和*分别代表什么意思?谢谢!

classA * classA::myInstance = NULL;  

classA& classA::GetInstance()

{}

*  表示指针

&表示取地址符

定义的class A这个类的对象mylnstance 的值是空

取classA从Getlinstace里面的地址

84  C++技巧之operator操作符

operator它有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换)。

1.operatoroverloading
C++可以通过operator重载操作符,格式如下:类型Toperator 操作符 (),如比重载+,如下所示

[cpp] viewplaincopy

  1. template<typename T> class A  
  2. {  
  3. public:  
  4.     const T operator + (const T& rhs)  
  5.     {  
  6.      return this->m_ + rhs;  
  7.     }  
  8. private:  
  9.     T m_;  
  10. };  


又比如STL中的函数对象,重载(),这是C++中较推荐的写法,功能与函数指针类似,如下所示

[c-sharp] viewplaincopy

  1. template<typename T> struct A  
  2. {  
  3.    T operator()(const T& lhs, const T& rhs){ return lhs-rhs;}  
  4. };  


2 operator casting
C++可以通过operator重载隐式转换,格式如下:operator 类型T (),如下所示

[cpp] viewplaincopy

  1. class A  
  2. {  
  3. public:  
  4.    operator B* () { return this->b_;}   
  5.    operator const B* () const {return this->b_;}      
  6.    operator B& () { return *this->b_;}  
  7.    operator const B& () const {return *this->b_;}   
  8.   
  9. private:  
  10.    B* b_;  
  11. };  


A a;
当if(a),编译时,其中它转换成if(a.operatorB*()),其实也就是判断if(a.b_)

85 strcasecmp函数用法

1.功能:忽略大小写比较字符串

2.头文件《string.h》

3. 函数说明 strcasecmp()用来比较参数s1和s2字符串,比较时会自动忽略大小写的差异

4.  返回值 :若参数s1和s2字符串相同则返回0。s1长度大于s2长度则返回大于0 的值,s1 长度若小于s2 长度则返回小于0的值

5.例子:

 #include<string.h>

  main()

  {

  char*a="aBcDeF";

  char*b="AbCdEf";

  if(!strcasecmp(a,b))

  printf("%s=%s/n",a,b);

}

 执行 aBcDeF=AbCdE

86  stricmp()作用也是比较两个字符串,但字母不区分大小,也包括在string.h里面
87  STL之set使用方法小结

/*
set/multiset会根据待定的排序准则,自动将元素排序。两者不同在于前者不允许元素重复,而后者允许。
1) 不能直接改变元素值,因为那样会打乱原本正确的顺序,要改变元素值必须先删除旧元素,则插入新元素
2) 不提供直接存取元素的任何操作函数,只能通过迭代器进行间接存取,而且从迭代器角度来看,元素值是常数
3) 元素比较动作只能用于型别相同的容器(即元素和排序准则必须相同)
set模板原型://Key为元素(键值)类型
template <class Key, class Compare=less<Key>, class Alloc=STL_DEFAULT_ALLOCATOR(Key) >
从原型可以看出,可以看出比较函数对象及内存分配器采用的是默认参数,因此如果未指定,它们将采用系统默认方式,
另外,利用原型,可以有效地辅助分析创建对象的几种方式
*/

http://www.cppblog.com/huyutian/articles/107457.html

88  endl

终止一个行和刷新缓冲区。

template class<_Elem, _Tr>

  basic_ostream<_Elem, _Tr>&endl(

     basic_ostream<_Elem, _Tr>& _Ostr

   );

_Elem

The element type.该元素类型。

_Ostr

An object of typebasic_ostream.basic_ostream类型的一个对象。

_Tr

Character traits.性格特征。

89  mbstowcs()/wcstombs()的使用

本文介绍两个由C语言提供的宽字符(wchar_t类型)和多字节字符(一个字符用一个或者多个字节表示)转换函数,因此具有通用性(在Windows/Linux系统中都可以使用):

所需头文件stdlib.h

#include<stdlib.h>

( 1 )mbstowcs()

功能:

把多字节字符转换成宽字符

原型: 

size_t mbstowcs(
   wchar_t *wcstr,
const char *mbstr,
size_t count 
);

参数:

1>wcstr 目标缓存,用来存放转换之后的宽字节字符;当取值为NULL时,返回值为目标缓存所需wchar_t类型的个数

2>mbstr 用来存放待转换的多字节字符串

3>count 用来指定最多转换多少Byte。当wcstr取值为NULL时,该值无用

返回值:

转换成功,且wcstr == NULL时,返回目标缓存所需的大小(wchar_t类型个数,但不含终结符);

转换成功,且wcstr != NULL时,返回转换的字节数;

转换不成功,返回(size_t) (-1)

使用步骤:

1) 调用mbstowcs()函数,设置参数 wcstrNULL(用以获取转换所需的接收缓冲区大小);

2) 给目标缓存区分配足够的内存块,用于存放转换后的wchar_t字符串;

注意:该内存块的大小由首次调用mbstowcs()函数的返回值来决定(该返回值不包含终止符的空间)

3) 再次调用mbstowcs()函数,这次将目标缓存的地址作为wcstr参数来传递;

代码示例:

[cpp] view plaincopy

1. strcpy(sBuf, "我最棒");  

2. size_t sSize=strlen(sBuf);  

3.   

4. wchar_t * dBuf=NULL;  

5.   

6. <span style="color:#ff0000;">//注意:需要多分配一个空间,以存放终止符</span>  

7. int dSize=mbstowcs(dBuf, sBuf, 0)+1;  

8.   

9. dBuf=new wchar_t[dSize];  

10. wmemset(dBuf, 0, dSize);  

11.   

12. int nRet=mbstowcs(dBuf, sBuf, sSize);  

13. if(nRet<=0)  

14. {  

15.     printf("转换失败\n");  

16. }  

17. else  

18. {  

19.     printf("转换成功%d字符\n", nRet);  

20.     wprintf(L"%ls\n", dBuf);  

21. }  

( 2) wcstombs()

功能:

把宽字符把转换成多字节字符串

原型:

size_t wcstombs(
char *mbstr,
const wchar_t *wcstr,
size_t count 
);

参数:

1>wcstr 目标缓存,用来存放转换之后的多字节字符;当取值为NULL时,返回值为目标缓存所需wchar_t类型的个数;

2>mbstr 用来存放待转换的宽字符;

3>count 用来指定接收缓存里能够存储的最大的字节数;

返回值:

转换成功,且mbstr == NULL时,返回目标缓存所需的大小(char类型个数,但不含终结符);

转换成功,且mbstr != NULL时,返回转换的字节数;

转换不成功,返回(size_t)(-1)

注意:

 If wcstombs encountersa wide character it cannot be convert to a multibyte character, it returns –1cast to type size_t.

使用方法:

mbstowcs()方法类似

示例代码:

[cpp] view plaincopy

1. wchar_t sBuf[20]={0};  

2. wcscpy(sBuf, L"Hello");  

3. size_t sSize=wcslen(sBuf);  

4.   

5.   

6. char * dBuf=NULL;  

7.   

8.   

9. int dSize=wcstombs(dBuf, sBuf, 0)+1;  

10. printf("需要%d Char\n", dSize);  

11.   

12. dBuf=new char[dSize];  

13. memset(dBuf, 0, dSize);  

14.   

15.   

16. int nRet=wcstombs(dBuf, sBuf, dSize);  

17.   

18. if(nRet<=0)  

19. {  

20.     printf("转换失败\n");  

21. }  

22. else  

23. {  

24.     printf("转换成功%d字符\n", nRet);  

25.     printf("%s\n", dBuf);  

26. }  

上面的代码在转换英文的时候没有问题,在转换中文时,wcstombs()函数会返回-1

注意:

宽字节,即wchar_t类型采用Unicode编码方式,在Windows中为utf-16,在Linux中为utf-32

而多字节则可能是其他很多编码方式,如utf-8GB232....

因此,需要指定多字节编码类型,才能进行正常的转换过程。

设置或获取多字节编码方式用函数:setlocale()

所需头文件:locale.h

#include<locale.h>