2011-11-04 15:27:00 weixin_34221332 阅读数 12
  • VC++动态链接库(dll)编程视频教学

    动态链接库的开发编译属于VC++程序员技能。 本课程学习之后能够理解动态链接库原理,学会编译静态库、动态库,学会通过lib和头文件链接动态库,学会直接通过代码访问dll中函数

    10392 人正在学习 去看看 夏曹俊

转载自:http://www.vckbase.com/study/article/data_convert.htm

读者层次:初学

刚接触VC编程的朋友往往对许多数据类型的转换感到迷惑不解,本文将介绍一些常用数据类型的使用。

我们先定义一些常见类型变量借以说明

int i = 100;
long l = 2001;
float f=300.2;
double d=12345.119;
char username[]="程佩君";
char temp[200];
char *buf;
CString str;
_variant_t v1;
_bstr_t v2;

一、其它数据类型转换为字符串

  • 短整型(int)
    itoa(i,temp,10);///将i转换为字符串放入temp中,最后一个数字表示十进制
    itoa(i,temp,2); ///按二进制方式转换
  • 长整型(long)
    ltoa(l,temp,10);
  • 浮点数(float,double)
    用fcvt可以完成转换,这是MSDN中的例子:
    int decimal, sign; 
    char *buffer; 
    double source = 3.1415926535; 
    buffer = _fcvt( source, 7, &decimal, &sign ); 
    运行结果:source: 3.1415926535 buffer: '31415927' decimal: 1 sign: 0
    decimal表示小数点的位置,sign表示符号:0为正数,1为负数
  • CString变量
    str = "2008北京奥运";
    buf = (LPSTR)(LPCTSTR)str;
  • BSTR变量
    BSTR bstrValue = ::SysAllocString(L"程序员"); 
    char * buf = _com_util::ConvertBSTRToString(bstrValue); 
    SysFreeString(bstrValue); 
    AfxMessageBox(buf); 
    delete(buf);
  • CComBSTR变量
    CComBSTR bstrVar("test"); 
    char *buf = _com_util::ConvertBSTRToString(bstrVar.m_str); 
    AfxMessageBox(buf); 
    delete(buf); 
  • _bstr_t变量
    _bstr_t类型是对BSTR的封装,因为已经重载了=操作符,所以很容易使用
    _bstr_t bstrVar("test"); 
    const char *buf = bstrVar;///不要修改buf中的内容 
    AfxMessageBox(buf); 

  • 通用方法(针对非COM数据类型)
    用sprintf完成转换
    char  buffer[200];
    char  c = '1';
    int   i = 35;
    long  j = 1000;
    float f = 1.7320534f;
    sprintf( buffer, "%c",c);
    sprintf( buffer, "%d",i);
    sprintf( buffer, "%d",j);
    sprintf( buffer, "%f",f);
    

二、字符串转换为其它数据类型
strcpy(temp,"123");

  • 短整型(int)
    i = atoi(temp);
  • 长整型(long)
    l = atol(temp);
  • 浮点(double)
    d = atof(temp);
  • CString变量
    CString name = temp;
  • BSTR变量 
    BSTR bstrValue = ::SysAllocString(L"程序员"); 
    ...///完成对bstrValue的使用
    SysFreeString(bstrValue); 
  • CComBSTR变量
    CComBSTR类型变量可以直接赋值
    CComBSTR bstrVar1("test");
    CComBSTR bstrVar2(temp);
  • _bstr_t变量
    _bstr_t类型的变量可以直接赋值
    _bstr_t bstrVar1("test"); 
    _bstr_t bstrVar2(temp); 

三、其它数据类型转换到CString
使用CString的成员函数Format来转换,例如:

  • 整数(int)
    str.Format("%d",i);
  • 浮点数(float)
    str.Format("%f",i);
  • 字符串指针(char *)等已经被CString构造函数支持的数据类型可以直接赋值
    str = username;
  • 对于Format所不支持的数据类型,可以通过上面所说的关于其它数据类型转化到char *的方法先转到char *,然后赋值给CString变量。

四、BSTR、_bstr_t与CComBSTR

  • CComBSTR 是ATL对BSTR的封装,_bstr_t是C++对BSTR的封装,BSTR是32位指针,但并不直接指向字串的缓冲区。
    char *转换到BSTR可以这样: 
    BSTR b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上comutil.h和comsupp.lib
    SysFreeString(bstrValue); 
    反之可以使用
    char *p=_com_util::ConvertBSTRToString(b);
    delete p;
    具体可以参考一,二段落里的具体说明。

    CComBSTR与_bstr_t对大量的操作符进行了重载,可以直接进行=,!=,==等操作,所以使用非常方便。
    特别是_bstr_t,建议大家使用它。

 

五、VARIANT 、_variant_t 与 COleVariant

  • VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。
    对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相同数据类型的变量赋值,举个例子:
    VARIANT va;
    int a=2001;
    va.vt=VT_I4;///指明整型数据
    va.lVal=a; ///赋值

    对于不马上赋值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系:

    Byte bVal; // VT_UI1.
    Short iVal; // VT_I2.
    long lVal; // VT_I4.
    float fltVal; // VT_R4.
    double dblVal; // VT_R8.
    VARIANT_BOOL boolVal; // VT_BOOL.
    SCODE scode; // VT_ERROR.
    CY cyVal; // VT_CY.
    DATE date; // VT_DATE.
    BSTR bstrVal; // VT_BSTR.
    DECIMAL FAR* pdecVal // VT_BYREF|VT_DECIMAL.
    IUnknown FAR* punkVal; // VT_UNKNOWN.
    IDispatch FAR* pdispVal; // VT_DISPATCH.
    SAFEARRAY FAR* parray; // VT_ARRAY|*.
    Byte FAR* pbVal; // VT_BYREF|VT_UI1.
    short FAR* piVal; // VT_BYREF|VT_I2.
    long FAR* plVal; // VT_BYREF|VT_I4.
    float FAR* pfltVal; // VT_BYREF|VT_R4.
    double FAR* pdblVal; // VT_BYREF|VT_R8.
    VARIANT_BOOL FAR* pboolVal; // VT_BYREF|VT_BOOL.
    SCODE FAR* pscode; // VT_BYREF|VT_ERROR.
    CY FAR* pcyVal; // VT_BYREF|VT_CY.
    DATE FAR* pdate; // VT_BYREF|VT_DATE.
    BSTR FAR* pbstrVal; // VT_BYREF|VT_BSTR.
    IUnknown FAR* FAR* ppunkVal; // VT_BYREF|VT_UNKNOWN.
    IDispatch FAR* FAR* ppdispVal; // VT_BYREF|VT_DISPATCH.
    SAFEARRAY FAR* FAR* pparray; // VT_ARRAY|*.
    VARIANT FAR* pvarVal; // VT_BYREF|VT_VARIANT.
    void FAR* byref; // Generic ByRef.
    char cVal; // VT_I1.
    unsigned short uiVal; // VT_UI2.
    unsigned long ulVal; // VT_UI4.
    int intVal; // VT_INT.
    unsigned int uintVal; // VT_UINT.
    char FAR * pcVal; // VT_BYREF|VT_I1.
    unsigned short FAR * puiVal; // VT_BYREF|VT_UI2.
    unsigned long FAR * pulVal; // VT_BYREF|VT_UI4.
    int FAR * pintVal; // VT_BYREF|VT_INT.
    unsigned int FAR * puintVal; //VT_BYREF|VT_UINT.
  • _variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。
    使用时需加上#include <comdef.h>
    例如:
    long l=222;
    ing i=100;
    _variant_t lVal(l);
    lVal = (long)i;

  • COleVariant的使用与_variant_t的方法基本一样,请参考如下例子:
    COleVariant v3 = "字符串", v4 = (long)1999;
    CString str =(BSTR)v3.pbstrVal;
    long i = v4.lVal;

六、其它一些COM数据类型

  • 根据ProgID得到CLSID
    HRESULT CLSIDFromProgID( LPCOLESTR lpszProgID,LPCLSID pclsid);
    CLSID clsid;
    CLSIDFromProgID( L"MAPI.Folder",&clsid);
  • 根据CLSID得到ProgID
    WINOLEAPI ProgIDFromCLSID( REFCLSID clsid,LPOLESTR * lplpszProgID); 
    例如我们已经定义了 CLSID_IApplication,下面的代码得到ProgID
    LPOLESTR pProgID = 0;
    ProgIDFromCLSID( CLSID_IApplication,&pProgID);
    ...///可以使用pProgID 
    CoTaskMemFree(pProgID);//不要忘记释放 

七、ANSI与Unicode
Unicode称为宽字符型字串,COM里使用的都是Unicode字符串。

  • 将ANSI转换到Unicode
    (1)通过L这个宏来实现,例如: CLSIDFromProgID( L"MAPI.Folder",&clsid);
    (2)通过MultiByteToWideChar函数实现转换,例如:
    char *szProgID = "MAPI.Folder";
    WCHAR szWideProgID[128];
    CLSID clsid;
    long lLen = MultiByteToWideChar(CP_ACP,0,szProgID,strlen(szProgID),szWideProgID,sizeof(szWideProgID));
    szWideProgID[lLen] = '\0'; 
    (3)通过A2W宏来实现,例如: 
    USES_CONVERSION; 
    CLSIDFromProgID( A2W(szProgID),&clsid);
  • 将Unicode转换到ANSI
    (1)使用WideCharToMultiByte,例如:
    // 假设已经有了一个Unicode 串 wszSomeString... 
    char szANSIString [MAX_PATH]; 
    WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, wszSomeString, -1, szANSIString, sizeof(szANSIString), NULL, NULL ); 
    (2)使用W2A宏来实现,例如:
    USES_CONVERSION;
    pTemp=W2A(wszSomeString);

八、其它

  • 对消息的处理中我们经常需要将WPARAM或LPARAM等32位数据(DWORD)分解成两个16位数据(WORD),例如:
    LPARAM lParam;
    WORD loValue = LOWORD(lParam);///取低16位
    WORD hiValue = HIWORD(lParam);///取高16位

  • 对于16位的数据(WORD)我们可以用同样的方法分解成高低两个8位数据(BYTE),例如:
    WORD wValue;
    BYTE loValue = LOBYTE(wValue);///取低8位
    BYTE hiValue = HIBYTE(wValue);///取高8位

  • 两个16位数据(WORD)合成32位数据(DWORD,LRESULT,LPARAM,或WPARAM)
    LONG MAKELONG( WORD wLow, WORD wHigh );
    WPARAM MAKEWPARAM( WORD wLow, WORD wHigh ); 
    LPARAM MAKELPARAM( WORD wLow, WORD wHigh );
    LRESULT MAKELRESULT( WORD wLow, WORD wHigh ); 

  • 两个8位的数据(BYTE)合成16位的数据(WORD)
    WORD MAKEWORD( BYTE bLow, BYTE bHigh ); 

  • 从R(red),G(green),B(blue)三色得到COLORREF类型的颜色值
    COLORREF RGB( BYTE byRed,BYTE byGreen,BYTE byBlue );
    例如COLORREF bkcolor = RGB(0x22,0x98,0x34);

  • 从COLORREF类型的颜色值得到RGB三个颜色值
    BYTE Red = GetRValue(bkcolor); ///得到红颜色
    BYTE Green = GetGValue(bkcolor); ///得到绿颜色
    BYTE Blue = GetBValue(bkcolor); ///得到兰颜色
2008-05-28 00:41:00 CSU305 阅读数 2370
  • VC++动态链接库(dll)编程视频教学

    动态链接库的开发编译属于VC++程序员技能。 本课程学习之后能够理解动态链接库原理,学会编译静态库、动态库,学会通过lib和头文件链接动态库,学会直接通过代码访问dll中函数

    10392 人正在学习 去看看 夏曹俊

一.              VC常用数据类型列表

二.              常用数据类型转化

2.1数学类型变量与字符串相互转换

2.2 CString及string,char *与其他数据类型的转换和操作

●CString,string,char*的综合比较

●数学类型与CString相互转化

●CString与char*相互转换举例

●CString 与 BSTR 型转换

●VARIANT 型转化成 CString 型

2.3 BSTR、_bstr_t与CComBSTR

2.4 VARIANT 、_variant_t 与 COleVariant

附录CString及字符串转及操作详解

 

参考书籍:CSDN,<<MFC深入浅出(Second Edit)>>

一.VC常用数据类型列表

 

 

Type

Default Size

Description

 

 

 

 

 

 

说明:这些基础数据类型对于MFC还是API都是被支持的

boolean

unsigned 8 bit ,

取值TRUE/FALSE

byte

unsigned 8 bit,

整数,输出按字符输出

char

unsigned 8 bit,

字符

double

signed 64 bit

浮点型

float

signed32 bit

浮点型

handle_t

 

Primitive handle type

hyper

signed 64 bit

整型

int

signed 32 bit

整型

long

signed 32 bit

整型

short

signed 16 bit

整型

small

signed 8 bit

整型

void *

32-bit

指向未知类型的指针

wchar_t

unsigned 16 bit

16位字符,比char可容纳更多的字符

 

 

 

Win32

API

 

说明: 这些Win32API支持的简单数据类型主要是用来定义函数返回值,消息参数,结构成员。这类数据类型大致可以分为五大类:字符型、布尔型、整型、指针型和句柄型(?). 总共大概有100多种不同的类型,

BOOL/BOOLEAN

8bit,TRUE/FALSE

布尔型

BYTE

unsigned 8 bit

 

BSTR

CComBSTR

_bstr_t

32 bit

BSTR是指向字符串的32位指针

是对BSTR的封装

是对BSTR的封装

CHAR

8 bit

(ANSI)字符类型

COLORREF

32 bit

RGB颜色值 整型

DWORD

unsigned 32 bit

整型

FLOAT

float型

float型

HANDLE

 

Object句柄

HBITMAP

 

bitmap句柄

HBRUSH

 

brush句柄

HCURSOR

 

cursor句柄

HDC

 

设备上下文句柄

HFILE

 

OpenFile打开的File句柄

HFONT

 

font句柄

HHOOK

 

hook句柄

HKEY

 

注册表键句柄

HPEN

 

pen句柄

HWND

 

window句柄

INT

--------

--------

LONG

--------

---------

LONGLONG

 

64位带符号整型

LPARAM

32 bit

消息参数

LPBOOL

 

BOOL型指针

LPBYTE

 

BYTE型指针

LPCOLOREF

 

COLORREF型指针

LPCSTR/LPSTR/PCSTR

 

指向8位(ANSI)字符串类型指针

LPCWSTR/LPWSTR/PCWSTR

 

指向16位Unicode字符串类型

LPCTSTR/LPTSTR/PCTSTR

 

指向一8位或16位字符串类型指针

LPVOID

 

指向一个未指定类型的32位指针

LPDWORD

 

指向一个DWORD型指针

其他相似类型: LPHANDLE、LPINT、LPLONG、LPWORD、LPRESULT

PBOOL、PBOOLEAN、PBYTE、PCHAR、PDWORD、PFLOAT、PHANDLE、PINT、PLONG、PSHORT……

说明:(1)在16位系统中 LP为16bit,P为8bit,在32位系统中都是32bit(此时等价)

(2)LPCSTR等 中的C指Const,T表示TCHAR模式即可以工作在ANSI下也可UNICODE

SHORT

usigned

整型

其他UCHAR、UINT、ULONG、ULONGLONG、USHORT为无符号相应类型

TBYTE

 

WCHAR型或者CHAR型

TCHAR

 

ANSI与unicode均可

VARIANT

_variant_t

COleVariant

 

一个结构体参考OAIDL.H

_variant_t是VARIANT的封装类

COleVariant也是VARIANT的封装类

 

 

 

 

 

 

WNDPROC

 

指向一个窗口过程的32位指针

WCHAR

 

16位Unicode字符型

WORD

 

16位无符号整型

WPARAM

 

消息参数

MFC

独有

数据

类型

下面两个数据类型是微软基础类库中独有的数据类型

POSITION

标记集合中一个元素的位置的值,被MFC中的集合类所使用

LPCRECT

指向一个RECT结构体常量(不能修改)的32位指针

CString

其实是MFC中的一个类

 

 

 

说明:

(1)-------表示省略

(2)1Byte=8Bit,

字与机器有关,在8位系统中:字=1字节,16位系统中,1字=2字节,32位中:1字=4字节,

64位中1字=8字节.不要搞混这些概念.

 

 

二.常用数据类型转化及操作

2.1 数学类型变量与字符串相互转换(这些函数都在STDLIB.H里)

(1)将数学类型转换为字符串可以用以下一些函数:

举例: _CRTIMP char * __cdecl _itoa(int, char *, int);//这是一个将数字转换为一个字符串类型的函数,最后一个int表示转换的进制

如以下程序:

int iTyep=3;

char *szChar;

itoa(iType,szChar,2);

cout<<szChar;//输出为1010

类似函数列表:

_CRTIMP char * __cdecl _itoa(int, char *, int);//为了完整性,也列在其中

_CRTIMP char * __cdecl _ultoa(unsigned long, char *, int);

_CRTIMP char * __cdecl _ltoa(long, char *, int);

_CRTIMP char * __cdecl _i64toa(__int64, char *, int);

_CRTIMP char * __cdecl _ui64toa(unsigned __int64, char *, int);

_CRTIMP wchar_t * __cdecl _i64tow(__int64, wchar_t *, int);

_CRTIMP wchar_t * __cdecl _ui64tow(unsigned __int64, wchar_t *, int);

_CRTIMP wchar_t * __cdecl _itow (int, wchar_t *, int);//转换为长字符串类型

_CRTIMP wchar_t * __cdecl _ltow (long, wchar_t *, int);

_CRTIMP wchar_t * __cdecl _ultow (unsigned long, wchar_t *, int);

还有很多,请自行研究

(2)将字符串类型转换为数学类型变量可以用以下一些函数:

举例: _CRTIMP int  __cdecl atoi(const char *);//参数一看就很明了

char *szChar=”88”;

int temp(0);

temp=atoi(szChar);

cout<<temp;

类似的函数列表:

_CRTIMP int    __cdecl atoi(const char *);

_CRTIMP double __cdecl atof(const char *);

_CRTIMP long   __cdecl atol(const char *);

_CRTIMP long double __cdecl _atold(const char *);

_CRTIMP __int64 __cdecl _atoi64(const char *);

_CRTIMP double __cdecl strtod(const char *, char **);//

_CRTIMP long   __cdecl strtol(const char *, char **, int);//

_CRTIMP long double __cdecl _strtold(const char *, char **);

_CRTIMP unsigned long __cdecl strtoul(const char *, char **, int);

_CRTIMP double __cdecl wcstod(const wchar_t *, wchar_t **);//长字符串类型转换为数学类型

_CRTIMP long   __cdecl wcstol(const wchar_t *, wchar_t **, int);

_CRTIMP unsigned long __cdecl wcstoul(const wchar_t *, wchar_t **, int);

_CRTIMP int __cdecl _wtoi(const wchar_t *);

_CRTIMP long __cdecl _wtol(const wchar_t *);

_CRTIMP __int64   __cdecl _wtoi64(const wchar_t *);

还有很多,请自行研究

2.2.CString及string,char *与其他数据类型的转换和操作

(1)CString,string,char*的综合比较(这部分CSDN上的作者joise的文章

<< CString,string,char*的综合比较>>写的很详细,请大家在仔细阅读他的文章.

地址: http://blog.csdn.net/joise/

或参考附录:

(2)转换:

●数学类型与CString相互转化

 数学类型转化为CString

可用Format函数,举例:

CString s;

int i = 64;

s.Format("%d", i)

CString转换为数学类型:举例CString strValue("1.234");

double dblValue;

dblValue = atof((LPCTSTR)strValue);

●CString与char*相互转换举例

CString strValue(“Hello”);

char *szValue;

szValue=strValue.GetBuffer(szValue);

也可用(LPSTR)(LPCTSTR)对CString//  进行强制转换.  

szValue=(LPSTR)(LPCTSTR)strValue;

反过来可直接赋值:

char *szChar=NULL;

CString strValue;

szChar=new char[10];

memset(szChar,0,10);

strcpy(szChar,”Hello”);

strValue=szChar;

●CString 与 BSTR 型转换

CString 型转化成 BSTR 型

当我们使用 ActiveX 控件编程时,经常需要用到将某个值表示成 BSTR 类型.BSTR 是一种记数字符串,Intel平台上的宽字符串(Unicode),并且可以包含嵌入的 NULL 字符。

可以调用 CString 对象的 AllocSysString 方法将 CString 转化成 BSTR:

CString str;

str = .....; // whatever

BSTR bStr = str.AllocSysString();

 

BSTR型转换为CString

如果你在 UNICODE 模式下编译代码,你可以简单地写成:

CString convert(BSTR bStr)

{

    if(bStr == NULL)

        return CString(_T(""));

    CString s(bStr); // in UNICODE mode

    return s;

}

如果是 ANSI 模式

CString convert(BSTR b)

{

    CString s;

    if(b == NULL)

       return s; // empty for NULL BSTR

#ifdef UNICODE

    s = b;

#else

    LPSTR p = s.GetBuffer(SysStringLen(b) + 1);

    ::WideCharToMultiByte(CP_ACP,            // ANSI Code Page

                          0,                 // no flags

                          b,                 // source widechar string

                          -1,                // assume NUL-terminated

                          p,                 // target buffer

                          SysStringLen(b)+1, // target buffer length

                          NULL,              // use system default char

                          NULL);             // don''t care if default used

    s.ReleaseBuffer();

#endif

    return s;

}

 

●VARIANT 型转化成 CString 型

VARIANT 类型经常用来给 COM 对象传递参数,或者接收从 COM 对象返回的值。你也能自己编写返回 VARIANT 类型的方法,函数返回什么类型 依赖可能(并且常常)方法的输入参数(比如,在自动化操作中,依赖与你调用哪个方法。IDispatch::Invoke 可能返回(通过其一个参数)一个 包含有BYTE、WORD、float、double、date、BSTR 等等 VARIANT 类型的结果,(详见 MSDN 上的 VARIANT 结构的定义)。在下面的例子中,假设 类型是一个BSTR的变体,也就是说在串中的值是通过 bsrtVal 来引用,其优点是在 ANSI 应用中,有一个构造函数会把 LPCWCHAR 引用的值转换为一个 CString(见 BSTR-to-CString 部分)。在 Unicode 模式中,将成为标准的 CString 构造函数,参见对缺省::WideCharToMultiByte 转换的告诫,以及你觉得是否可以接受(大多数情况下,你会满意的)。VARIANT vaData;

vaData = m_com.YourMethodHere();

ASSERT(vaData.vt == VT_BSTR);

CString strData(vaData.bstrVal);

你还可以根据 vt 域的不同来建立更通用的转换例程。为此你可能会考虑:

CString VariantToString(VARIANT * va)

{

    CString s;

    switch(va->vt)

      { /* vt */

       case VT_BSTR:

          return CString(vaData->bstrVal);

       case VT_BSTR | VT_BYREF:

          return CString(*vaData->pbstrVal);

       case VT_I4:

          s.Format(_T("%d"), va->lVal);

          return s;

       case VT_I4 | VT_BYREF:

          s.Format(_T("%d"), *va->plVal);

       case VT_R8:

          s.Format(_T("%f"), va->dblVal);

          return s;

       ... 剩下的类型转换由读者自己完成

       default:

          ASSERT(FALSE); // unknown VARIANT type (this ASSERT is optional)

          return CString("");

      } /* vt */

}

 

2.3 BSTR、_bstr_t与CComBSTR

CComBSTR、_bstr_t是对BSTR的封装,BSTR是指向字符串的32位指针。

char *转换到BSTR可以这样:

BSTR b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上头文件comutil.h

反之可以使用char *p=_com_util::ConvertBSTRToString(b);

2.4(引)VARIANT 、_variant_t 与 COleVariant

VARIANT的结构可以参考头文件VC98/Include/OAIDL.H中关于结构体tagVARIANT的定义。

对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相同数据类型的变量赋值,举个例子:

VARIANT va;

int a=2001;

va.vt=VT_I4;///指明整型数据

va.lVal=a; ///赋值

对于不马上赋值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系:

unsigned char bVal; VT_UI1

short iVal; VT_I2

long lVal; VT_I4

float fltVal; VT_R4

double dblVal; VT_R8

VARIANT_BOOL boolVal; VT_BOOL

SCODE scode; VT_ERROR

CY cyVal; VT_CY

DATE date; VT_DATE

BSTR bstrVal; VT_BSTR

IUnknown FAR* punkVal; VT_UNKNOWN

IDispatch FAR* pdispVal; VT_DISPATCH

SAFEARRAY FAR* parray; VT_ARRAY|*

unsigned char FAR* pbVal; VT_BYREF|VT_UI1

short FAR* piVal; VT_BYREF|VT_I2

long FAR* plVal; VT_BYREF|VT_I4

float FAR* pfltVal; VT_BYREF|VT_R4

double FAR* pdblVal; VT_BYREF|VT_R8

VARIANT_BOOL FAR* pboolVal; VT_BYREF|VT_BOOL

SCODE FAR* pscode; VT_BYREF|VT_ERROR

CY FAR* pcyVal; VT_BYREF|VT_CY

DATE FAR* pdate; VT_BYREF|VT_DATE

BSTR FAR* pbstrVal; VT_BYREF|VT_BSTR

IUnknown FAR* FAR* ppunkVal; VT_BYREF|VT_UNKNOWN

IDispatch FAR* FAR* ppdispVal; VT_BYREF|VT_DISPATCH

SAFEARRAY FAR* FAR* pparray; VT_ARRAY|*

VARIANT FAR* pvarVal; VT_BYREF|VT_VARIANT

void FAR* byref; VT_BYREF

_variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。

例如:

long l=222;

ing i=100;

_variant_t lVal(l);

lVal = (long)i;

COleVariant的使用与_variant_t的方法基本一样,请参考如下例子:

COleVariant v3 = "字符串", v4 = (long)1999;

CString str =(BSTR)v3.pbstrVal;

long i = v4.lVal;

posted on 2005-11-13 00:30 痛并快乐着 阅读(9512) 评论(6)  编辑 收藏 所属分类: Visual C++

评论

 

VC++.NET中字符串之间的转换


 一、BSTR、LPSTR和LPWSTR

  在Visual C++.NET的所有编程方式中,我们常常要用到这样的一些基本字符串类型,如BSTR、LPSTR和LPWSTR等。之所以出现类似上述的这些数据类型,是因为不同编程语言之间的数据交换以及对ANSI、Unicode和多字节字符集(MBCS)的支持。

  那么什么是BSTR、LPSTR以及LPWSTR呢?

  BSTR(Basic STRing,Basic字符串)是一个OLECHAR*类型的Unicode字符串。它被描述成一个与自动化相兼容的类型。由于操作系统提供相应的 API函数(如SysAllocString)来管理它以及一些默认的调度代码,因此BSTR实际上就是一个COM字符串,但它却在自动化技术以外的多种场合下得到广泛使用。图1描述了BSTR的结构,其中DWORD值是字符串中实际所占用的字节数,且它的值是字符串中Unicode字符的两倍。

  LPSTR和LPWSTR是Win32和VC++所使用的一种字符串数据类型。LPSTR被定义成是一个指向以NULL(‘/0’)结尾的8位ANSI 字符数组指针,而LPWSTR是一个指向以NULL结尾的16位双字节字符数组指针。在VC++中,还有类似的字符串类型,如LPTSTR、 LPCTSTR等,它们的含义如图2所示。

  例如,LPCTSTR是指“long pointer to a constant generic string”,表示“一个指向一般字符串常量的长指针类型”,与C/C++的const char*相映射,而LPTSTR映射为 char*。

  一般地,还有下列类型定义:

#ifdef UNICODE
 typedef LPWSTR LPTSTR;
 typedef LPCWSTR LPCTSTR;
#else
 typedef LPSTR LPTSTR;
 typedef LPCSTR LPCTSTR;
#endif

  二、CString、CStringA 和 CStringW

  Visual C++.NET中将CStringT作为ATL和MFC的共享的“一般”字符串类,它有CString、CStringA和CStringW三种形式,分别操作不同字符类型的字符串。这些字符类型是TCHAR、char和wchar_t。TCHAR在Unicode平台中等同于WCHAR(16位 Unicode字符),在ANSI中等价于char。wchar_t通常定义为unsigned short。由于CString在MFC应用程序中经常用到,这里不再重复。

  三、VARIANT、COleVariant 和_variant_t

  在OLE、ActiveX和COM中,VARIANT数据类型提供了一种非常有效的机制,由于它既包含了数据本身,也包含了数据的类型,因而它可以实现各种不同的自动化数据的传输。下面让我们来看看OAIDL.H文件中VARIANT定义的一个简化版:

struct tagVARIANT {
 VARTYPE vt;
 union {
  short iVal; // VT_I2.
  long lVal; // VT_I4.
  float fltVal; // VT_R4.
  double dblVal; // VT_R8.
  DATE date; // VT_DATE.
  BSTR bstrVal; // VT_BSTR.
  …
  short * piVal; // VT_BYREF|VT_I2.
  long * plVal; // VT_BYREF|VT_I4.
  float * pfltVal; // VT_BYREF|VT_R4.
  double * pdblVal; // VT_BYREF|VT_R8.
  DATE * pdate; // VT_BYREF|VT_DATE.
  BSTR * pbstrVal; // VT_BYREF|VT_BSTR.
 };
};

  显然,VARIANT类型是一个C结构,它包含了一个类型成员vt、一些保留字节以及一个大的union类型。例如,如果vt为VT_I2,那么我们可以从iVal中读出VARIANT的值。同样,当给一个VARIANT变量赋值时,也要先指明其类型。例如:

VARIANT va;
:: VariantInit(&va); // 初始化
int a = 2002;
va.vt = VT_I4; // 指明long数据类型
va.lVal = a; // 赋值

  为了方便处理VARIANT类型的变量,Windows还提供了这样一些非常有用的函数:

  VariantInit —— 将变量初始化为VT_EMPTY;

  VariantClear —— 消除并初始化VARIANT;

  VariantChangeType —— 改变VARIANT的类型;

  VariantCopy —— 释放与目标VARIANT相连的内存并复制源VARIANT。

  COleVariant类是对VARIANT结构的封装。它的构造函数具有极为强大大的功能,当对象构造时首先调用VariantInit进行初始化,然后根据参数中的标准类型调用相应的构造函数,并使用VariantCopy进行转换赋值操作,当VARIANT对象不在有效范围时,它的析构函数就会被自动调用,由于析构函数调用了VariantClear,因而相应的内存就会被自动清除。除此之外,COleVariant的赋值操作符在与VARIANT类型转换中为我们提供极大的方便。例如下面的代码:

COleVariant v1("This is a test"); // 直接构造
COleVariant v2 = "This is a test";
// 结果是VT_BSTR类型,值为"This is a test"
COleVariant v3((long)2002);
COleVariant v4 = (long)2002;
// 结果是VT_I4类型,值为2002

  _variant_t是一个用于COM的VARIANT类,它的功能与COleVariant相似。不过在Visual C++.NET的MFC应用程序中使用时需要在代码文件前面添加下列两句:

  #include "comutil.h"

  #pragma comment( lib, "comsupp.lib" )
四、CComBSTR和_bstr_t

  CComBSTR是对BSTR数据类型封装的一个ATL类,它的操作比较方便。例如:

CComBSTR bstr1;
bstr1 = "Bye"; // 直接赋值
OLECHAR* str = OLESTR("ta ta"); // 长度为5的宽字符
CComBSTR bstr2(wcslen(str)); // 定义长度为5
wcscpy(bstr2.m_str, str); // 将宽字符串复制到BSTR中
CComBSTR bstr3(5, OLESTR("Hello World"));
CComBSTR bstr4(5, "Hello World");
CComBSTR bstr5(OLESTR("Hey there"));
CComBSTR bstr6("Hey there");
CComBSTR bstr7(bstr6);
// 构造时复制,内容为"Hey there"

  _bstr_t是是C++对BSTR的封装,它的构造和析构函数分别调用SysAllocString和SysFreeString函数,其他操作是借用BSTR API函数。与_variant_t相似,使用时也要添加comutil.h和comsupp.lib。

  五、BSTR、char*和CString转换

  (1) char*转换成CString

  若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如:

char chArray[] = "This is a test";
char * p = "This is a test";

  或

LPSTR p = "This is a test";

  或在已定义Unicode应的用程序中

TCHAR * p = _T("This is a test");

  或

LPTSTR p = _T("This is a test");
CString theString = chArray;
theString.Format(_T("%s"), chArray);
theString = p;

  (2) CString转换成char*

  若将CString类转换成char*(LPSTR)类型,常常使用下列三种方法:

  方法一,使用强制转换。例如:

CString theString( "This is a test" );
LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;

  方法二,使用strcpy。例如:

CString theString( "This is a test" );
LPTSTR lpsz = new TCHAR[theString.GetLength()+1];
_tcscpy(lpsz, theString);

  需要说明的是,strcpy(或可移值Unicode/MBCS的_tcscpy)的第二个参数是 const wchar_t* (Unicode)或const char* (ANSI),系统编译器将会自动对其进行转换。

  方法三,使用CString::GetBuffer。例如:

CString s(_T("This is a test "));
LPTSTR p = s.GetBuffer();
// 在这里添加使用p的代码
if(p != NULL) *p = _T('/0');
s.ReleaseBuffer();
// 使用完后及时释放,以便能使用其它的CString成员函数

  (3) BSTR转换成char*

  方法一,使用ConvertBSTRToString。例如:

#include
#pragma comment(lib, "comsupp.lib")
int _tmain(int argc, _TCHAR* argv[]){
BSTR bstrText = ::SysAllocString(L"Test");
char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
SysFreeString(bstrText); // 用完释放
delete[] lpszText2;
return 0;
}

  方法二,使用_bstr_t的赋值运算符重载。例如:

_bstr_t b = bstrText;
char* lpszText2 = b;

  (4) char*转换成BSTR

  方法一,使用SysAllocString等API函数。例如:

BSTR bstrText = ::SysAllocString(L"Test");
BSTR bstrText = ::SysAllocStringLen(L"Test",4);
BSTR bstrText = ::SysAllocStringByteLen("Test",4);

  方法二,使用COleVariant或_variant_t。例如:

//COleVariant strVar("This is a test");
_variant_t strVar("This is a test");
BSTR bstrText = strVar.bstrVal;

  方法三,使用_bstr_t,这是一种最简单的方法。例如:

BSTR bstrText = _bstr_t("This is a test");

  方法四,使用CComBSTR。例如:

BSTR bstrText = CComBSTR("This is a test");

  或

CComBSTR bstr("This is a test");
BSTR bstrText = bstr.m_str;

  方法五,使用ConvertStringToBSTR。例如:

char* lpszText = "Test";
BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);

  (5) CString转换成BSTR

  通常是通过使用CStringT::AllocSysString来实现。例如:

CString str("This is a test");
BSTR bstrText = str.AllocSysString();

SysFreeString(bstrText); // 用完释放

  (6) BSTR转换成CString

  一般可按下列方法进行:

BSTR bstrText = ::SysAllocString(L"Test");
CStringA str;
str.Empty();
str = bstrText;

  或

CStringA str(bstrText);

  (7) ANSI、Unicode和宽字符之间的转换

  方法一,使用MultiByteToWideChar将ANSI字符转换成Unicode字符,使用WideCharToMultiByte将Unicode字符转换成ANSI字符。

  方法二,使用“_T”将ANSI转换成“一般”类型字符串,使用“L”将ANSI转换成Unicode,而在托管C++环境中还可使用S将ANSI字符串转换成String*对象。例如:

TCHAR tstr[] = _T("this is a test");
wchar_t wszStr[] = L"This is a test";
String* str = S”This is a test”;

  方法三,使用ATL 7.0的转换宏和类。ATL7.0在原有3.0基础上完善和增加了许多字符串转换宏以及提供相应的类,它具有如图3所示的统一形式:

  其中,第一个C表示“类”,以便于ATL 3.0宏相区别,第二个C表示常量,2表示“to”,EX表示要开辟一定大小的缓冲。SourceType和DestinationType可以是A、 T、W和OLE,其含义分别是ANSI、Unicode、“一般”类型和OLE字符串。例如,CA2CT就是将ANSI转换成一般类型的字符串常量。下面是一些示例代码:

LPTSTR tstr= CA2TEX<16>("this is a test");
LPCTSTR tcstr= CA2CT("this is a test");
wchar_t wszStr[] = L"This is a test";
char* chstr = CW2A(wszStr);

  六、结语

  几乎所有的程序都要用到字符串,而Visual C++.NET由于功能强大、应用广泛,因而字符串之间的转换更为频繁。本文几乎涉及到目前的所有转换方法。当然对于.NET框架来说,还可使用Convert和Text类进行不同数据类型以及字符编码之间的相互转换。
#1楼 [楼主]   回复  引用  查看    
2009-11-06 10:27:00 gwwgle 阅读数 1099
  • VC++动态链接库(dll)编程视频教学

    动态链接库的开发编译属于VC++程序员技能。 本课程学习之后能够理解动态链接库原理,学会编译静态库、动态库,学会通过lib和头文件链接动态库,学会直接通过代码访问dll中函数

    10392 人正在学习 去看看 夏曹俊

 最好先看下我博客里的<<JPEG文件格式简单分析>>一文

JPEG文件分为两个部分,标记码(Tag)和压缩数据。

码流格式设计依次为:SOI、APP0info、DQTinfo、DRIinfo、SOFinfo、DHTinfo、SOSinfo和EOI。具体结构如下:

#define BYTE unsigned char
#define WORD unsigned short int

#define SOI 0xFFD8     // Start of Image
#define EOI 0xFFD9     // End of Image

static struct APP0info{
 WORD marker;                    // 0xFFE0
 WORD length;     // 16 for usual JPEG
 BYTE JFIFsignature[5];   // ="JFIF",'/0'=0x4A,0x46,0x49,0x46,0x00
 WORD version;     // 0x0101,0x0102
 BYTE xyunits;     // 0 for default
 WORD xdensity;    
 WORD ydensity;
 BYTE num_of_x;
 BYTE num_of_y;
//RGB0---RGBn ??
}APP0info;

static struct DQTinfo{    // Define quantization table
 WORD marker;     // 0xFFDB
 WORD length;     // 132 for usual case
 BYTE QTYinfo;     // Pq(7:4)=0,1:8bit or 16bit precision; Tq(3:0)=0,1,2,3:id of QT table
 BYTE Ytable[64];    // may be WORD size according to Pq,zigzag arrange
 BYTE QTCbCrinfo;
 BYTE CbCrtable[64];
}DQTinfo;

static struct DRIinfo{    // Define Start interval
 WORD marker;     // 0xFFDD
 WORD length;
 WORD RI;
}DRIinfo;

static struct SOFinfo{    //Start of Frame
 WORD marker;     // 0xFFC0
 WORD length;     //=17 for a true color YCbCr
 BYTE precision;     // for basemode:0x08, 8bit/sample
 WORD height;
 WORD width;
 BYTE num_of_component;   // 0x01 for grayscale, 0x03 for YCrCb
 BYTE IdY;
 BYTE Y_SFactor;
 BYTE QTY;
 BYTE IdCb;
 BYTE Cb_SFactor;
 BYTE QTCb;
 BYTE IdCr;
 BYTE Cr_SFactor;
 BYTE QTCr;
}SOFinfo;

static struct DHTinfo{    // Define Huffman Table
 WORD marker;     // 0xFFC4
 WORD length;     // =0x01A2
 BYTE HT_YDC_info;    // Tc(7:4):0 for DC and 1 for AC, Th(3:0): for base mode, it can be 0,1
 BYTE YDC_index[16];
 BYTE YDC_values[12];
 BYTE HT_YAC_info;    // 0x10
 BYTE YAC_index[16];
 BYTE YAC_value[162];
 BYTE HT_CbCrDC_info;
 BYTE CbCrDC_index[16];
 BYTE CbCrDC_value[12];
 BYTE HT_CbCrAC_info;   // 0x11
 BYTE CbCrAC_index[16];
 BYTE CbCrAC_values[162];
}DHTinfo;

static struct SOSinfo{
 WORD marker;     // 0xFFDA
 WORD length;     // =12
 BYTE num_scan_component;  // for base mode 1,3
 BYTE IdY;
 BYTE HTY;
 BYTE IdCb;
 BYTE HTCb;
 BYTE IdCr;
 BYTE HTCr;
 BYTE Ss,Se,Bf;     // 0x00, 0x3F, 0x00
}SOSinfo;

 

2013-11-07 18:25:00 weixin_33755649 阅读数 13
  • VC++动态链接库(dll)编程视频教学

    动态链接库的开发编译属于VC++程序员技能。 本课程学习之后能够理解动态链接库原理,学会编译静态库、动态库,学会通过lib和头文件链接动态库,学会直接通过代码访问dll中函数

    10392 人正在学习 去看看 夏曹俊
1、	迷宫问题求解
#include <stdio.h>
#define m 8 //迷宫内有8列
#define n 8 //迷宫内有8行
#define MAXSIZE 100//栈尺寸最大为100
int maze[m+2][n+2]=   //迷宫情况,见书P50页图3.4,    1代表不可走,0代表可走
	{
	 {1,1,1,1,1,1,1,1,1,1},
	 {1,0,0,1,0,0,0,1,0,1},
	 {1,0,0,1,0,0,0,1,0,1},
	 {1,0,0,0,0,1,1,0,0,1},
	 {1,0,1,1,1,0,0,0,0,1},
	 {1,0,0,0,1,0,0,0,0,1},
	 {1,0,1,0,0,0,1,0,0,1},
	 {1,0,1,1,1,0,1,1,0,1},
	 {1,1,0,0,0,0,0,0,0,1},
	 {1,1,1,1,1,1,1,1,1,1}
	 };


typedef struct{
	int x;		//x坐标
	int y;		//y坐标
	int d;		//行走的方向
}DataType;		//每个点的情况,入栈的点结构

typedef struct{
	DataType point[MAXSIZE];
	int top;
	int stacksize;
}SeqStack;		//顺序栈的数据结构,用于存放行走的路线

typedef struct{
	int x;
	int y;
}item;			//按指定方向行走要对x,y所做的修改

void initStack(SeqStack *s)			//路线栈初始化
{
	s->top=-1;
}

int stackEmpty(SeqStack s)			//判断是否为空栈
{
	if(s.top==-1)return 1;
	return 0;
}

void push(SeqStack *s, DataType e)			//新点入路线栈,即前进一步
{
	int top;
	if(s->top==MAXSIZE-1){printf("Stack is full!\n");return;}
	s->top++;

	top=s->top;
	s->point[top].x=e.x;
	s->point[top].y=e.y;
	s->point[top].d=e.d;
}

void pop(SeqStack *s, DataType *e)			//从路线栈中弹出一个点,即回退一步
{
	if(s->top==-1){printf("Stack is empty!\n");return ;}
	e->x=s->point[s->top].x;
	e->y=s->point[s->top].y;
	e->d=s->point[s->top].d;

	s->top--;

}

void StackTravel(SeqStack s)		//将路线栈中的元素依次输出
{
	int i=1;
	DataType e;
	printf("\nNO.---------> x       y        direction\n");
	while(!stackEmpty(s))
	{
		pop(&s,&e);
		printf("%2d %10d%10d%10d\n",i++,e.x,e.y,e.d);
	}
}



int path(int maze[m+2][n+2],item move[]) //迷宫找路算法
{
	SeqStack S;
	DataType temp;
	int x,y,d;
	int i,j;
	initStack(&S);
	temp.x=1; temp.y=1; temp.d=-1;//第一个点为1,1,起始方向为-1
	push(&S,temp);//第一个点进栈
	while(!stackEmpty(S))//如果栈中有元素则还可以进行试探,否则回退到了起点则表明此迷宫无路可行
	{
		pop(&S,&temp);//先退回一步
		x=temp.x;
		y=temp.y;
		d=temp.d+1;//将原栈顶点的坐标和行走方向记录下来
		while(d<4)//检查是否已经试探了4个方向.如果小于4个方向则更换试探方向,并根据试探方向修改新点的坐标
		{
			i=x+move[d].x;//新点的x
			j=y+move[d].y;//新点的y
			if(maze[i][j]==0)//如果新点是可通的,即maze[i][j]为0
			{
				temp.x=x;
				temp.y=y;
				temp.d=d;
				push(&S,temp);//新点记录下来并进栈
				x=i;y=j;//将新点变为当前点
				maze[x][y]=-1;//将进栈点打上"走过"标记,即设置为-1
				if(x==m&&y==n)//如果坐标与出口坐标一致则表明到达出口
				{
					StackTravel(S);
					return 1;
				}
				else d=0;
			}/* if(maze)==0)*/
			else d++;//新点不可通行则调整行进方向
		}/*end while(d<4)所有方向均试探完毕*/
	}/*end while(!stackEmpty(S))回到了入口位置*/
	return 0;
}


main()
{
	item move[4]={{0,1},{1,0},{0,-1},{-1,0},};//由方向决定如何移动,按东南西北四个方向
	int result;
	result=path(maze,move);
	if(result==1)printf("I find the path!\n");//结果为1表明找到了出路
	else printf("I can't find the path!\n");//否则表明找不到出路,迷宫不可通行
}




2、	表达式求值
#define stackinitsize 20
#define stackincrement 8
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
char table[7][8]={">><<<>>",">><<<>>",">>>><>>",
       ">>>><>>","<<<<<= ",">>>> > ","<<<<< ="};
char *s_operator="+-*/()#";
char *validchar="+-*/()#0123456789";

typedef struct{
  int *base;
  int *top;
  int stacksize;
}sqstack;

int  initstack(sqstack *s)
  {(*s).base=(int * ) malloc(stackinitsize*sizeof(int));
   (*s).top=(*s).base;
   (*s).stacksize=stackinitsize;
   return 1;
   }

int push(sqstack *s,int e)
 {
   *((*s).top)=e;
   (*s).top++;
   return 1;
 }

int gettop(sqstack s)
{
  return *(s.top-1);
 }

int emptystack(sqstack s)
  {if (s.top==s.base)  return 1;
   else return 0;
   }

int pop(sqstack *s,int *e)
   { if (emptystack(*s)) return 0;
     --(*s).top;
     *e=*(*s).top;
    return 1;
     }

void print(sqstack s)
 { int t;
    while(!emptystack(s))
     {pop(&s,&t);
      printf("%d ",t);
      }
     printf("\n");
 }


int ctoi(char ch)
{ switch(ch)
  {case '+':return 0;
   case '-':return 1;
   case '*':return 2;
   case '/':return 3;
   case '(':return 4;
   case ')':return 5;
   case '#':return 6;
 }
}

char precede(char c1,char c2)
 { return table[ctoi(c1)][ctoi(c2)];
 }

int in(char c1,char *op)
 {  char *s;
    s=op;
    while (*s&&*s!=c1) s++;
    if (*s)  return 1;
      else return 0;
 }

int valid(char c1,char *op)
 {  char *s;
    s=op;
    while (*s&&*s!=c1) s++;
    if (*s)  return 1;
      else return 0;
 }

int operate(int a,int theta,int b)
{ switch(theta)
   {case '+':return(a+b);
    case '-':return(a-b);
    case '*':return(a*b);
    case '/':return(a/b);
   }
}

int val(char ch)
{ return (ch-'0');
}

int evaluteexpression()
 { sqstack opnd,optr;
   int ch,x,curint,theta,a,b;
   initstack(&optr);
   initstack(&opnd);
   push(&optr,'#');
   ch=getche();
   while (ch!='#' ||gettop(optr)!='#')
   { if (!valid(ch,validchar)) ch=getche(); //去掉非法字符
     else
      if (!in(ch,s_operator))//ch为操作数,则压栈
       { curint=0;
         while(valid(ch,validchar)&&!in(ch,s_operator))
   	 {curint=10*curint+val(ch);
	  ch=getche();
          }
	  push(&opnd,curint);}
      else
       {switch(precede(gettop(optr),ch))
	 {case '<': push(&optr,ch);ch=getche();break;
	  case '=': pop(&optr,&x);ch=getche();break;
	  case '>': pop(&optr,&theta);
		    pop(&opnd,&b);
		    pop(&opnd,&a);
		    push(&opnd,operate(a,theta,b));break;
	  case ' ':printf("\nerror");exit(1);
	}
       }
     }
     return gettop(opnd);
   }

void main()
{ int x;
  printf("\n请输入一个算术表达式( 每个运算量只限输入整数据,且以#结束)\n");
  x=evaluteexpression();
  printf("\n该表达式的结果是:%d",x);
  }






3、	KMP算法
#include <stdio.h>
  #include <stdlib.h>
 #define maxstrlen 255      //用可以在255以内定义最大串长
 int next[7];
 typedef unsigned char SString[maxstrlen+1]; //0好单元可以存放串的长度
 void get_next(SString T) 
{      //求模式串T的next函数值并存入数组next。
      int i,j;
      i=1; next[1]=0; j=0;//
      while(i<T[0]){
	if(j==0||T[i]==T[j]) {++i;  ++j;  next[i]=j;}
	else j=next[j];
      }
      printf("\nnext[j] is:");
      for(i=1;i<=6;i++)
	 printf("%d",next[i]);

 }//get_next

 int index_kmp(SString S,SString T,int pos) {
      //利用模式串T的next函数求T在主串S中第pos个字符之后的位置
      //kmp算法。其中T非空,1<=pos<=strlength(s).
      int i,j;
      i=pos;j=1;
      while(i<=S[0]&&j<=T[0]) {
	if(j==0||S[i]==T[j]) {++i;++j;}
	else
	   j=next[j];
      }
      if(j>T[0]) return i-T[0];
      else
	 return 0;
 }//index_kmp

 void main()
 {
   SString S={17,'a','c','a','b','a','a','b','a','a','b','c','a','c','a','a','b','c'};
   SString T={6,'a','b','a','a','b','c'};
   //S[0]=17;   T[0]=6;
   get_next(T);
   printf("\nit is :%d ",index_kmp(S,T,1));
 }




4. 稀疏矩阵的三元组顺序表

#define MAXSIZE  100  //假设非零元个数的最大值为100
#define ROW 7
#define COL 7
#define OK  1
#define FALSE 0

#include "stdlib.h"
#include "stdio.h"
#include "conio.h"

int a[ROW][COL]={{0,12,9,0,0,0,0}, {0,0,0,0,0,0,0}, {-3,0,0,0,0,14,0},
	         {0,0,24,0,0,0,0}, {0,18,0,0,0,0,0}, {15,0,0,-7,0,0,0}, {0,0,0,0,0,0,-5}};

typedef int ElemType;
typedef int Status;

typedef  struct{
  int  i,j;      //该非零元的行下标和列下标
  ElemType  e;
   }Triple;

typedef  union{
    Triple data[MAXSIZE+1];      //非零元三元组表,  data[0]未用
    int mu,nu,tu;                //矩阵的行数、列数和非零元个数
   }TSMatrix;

void InitTSMatrix(TSMatrix &T)
{ T.tu=0;
  }

Status ChangeArrayToMS(int a[][COL],TSMatrix &T)
{ int i,j,k=0;
  for(i=0;i<ROW;i++)
  for(j=0;j<COL;j++)
    if (a[i][j])
       {++k;
	T.data[k].i=i+1;T.data[k].j=j+1;T.data[k].e=a[i][j];
       }

  T.mu=ROW;T.nu=COL;T.tu=k;
  return OK;
}

void PrintTSmatrix(TSMatrix T)
{ //以三元组格式输出稀疏矩阵
 int k;
 if(T.tu>0)
  { printf("\n row   col   val\n");
    printf("------------------\n");
    for(k=1;k<=T.tu;k++)
       printf("(%4d%5d%5d)\n",T.data[k].i,T.data[k].j,T.data[k].e);
  }
 }
 
Status TransposeSMatrix(TSMatrix M, TSMatrix &T) {
//采用三元组表存储表示,稀疏矩阵M的转置T
int q,p,col;
T.mu=M.nu;T.nu=M.mu;T.tu =M.tu;
if(T.tu) {
  q = 1;
  for (col=1 ;col<=M.nu; ++col)
  for (p=1; p<=M.tu; ++p)
  if (M.data[p].j==col){
      T.data[q].i=M.data[p].j ; T.data[q].j=M.data[p].i;
      T.data[q].e=M.data[p].e; ++q;}
  }     
  return OK;
} // TrazlsposeSMatrix

Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T){
//采用三元组表存储表示,稀疏矩阵M的转置T(快速转换)
 int t,col,p,q,num[COL+1],cpot[COL+1];
 T.mu=M.nu;T.nu=M.mu;T.tu= M.tu;
if(T.tu) {
  for (col = 1; col<= M.mu;++col) num[col] = 0;
  for (t=1;t<=M.tu;++t)  ++num[M.data[t].j]; //求M中每一列含非0元素的个数
  cpot[ 1 ] = 1 ;
  // 求第 col列中第一个非0元素在 b. data 中的序号
  for (col = 2;col<= M.nu; ++col) cpot[col]=cpot[col-1] + num[col-1];
  for (p=1; p<=M.tu;++p)
  { col=M.data[p].j;q=cpot[col];
    T. data[q].i=M.data[p].j; T.data[q].j=M.data[p].i;
    T. data[q].e=M.data[p].e; ++cpot[col];
  }
}
 return OK ;
} // FastTransposeSMatrix

Status AddTSMatrix(TSMatrix A,TSMatrix B,TSMatrix &C)
{ //A+B==>C 两个稀疏矩阵相加结果存于C中
  //此算法类似于顺序表的归并算法
 int p,q,k;
 p=q=k=1;
 if (A.mu!=B.mu||A.nu!=B.nu)
   return FALSE;
 if(A.tu==0&&B.tu==0) {C.tu=0;return OK;}
 C.mu=A.mu;C.nu=A.nu;
 while(p<=A.tu&&q<=B.tu)
  {if ((A.data[p].i==B.data[q].i)&&(A.data[p].j==B.data[q].j))
    { if (A.data[p].e+B.data[q].e)
       { C.data[k].i=B.data[q].i;C.data[k].j=B.data[q].j;
	 C.data[k].e=A.data[q].e+B.data[q].e;
       }
      p++;q++;k++;
    }
   else if((A.data[p].i>B.data[q].i)||
            ((A.data[p].i==B.data[q].i)&&(A.data[p].j>B.data[q].j)))
         {C.data[k].i=B.data[q].i;C.data[k].j=B.data[q].j;
	  C.data[k].e=B.data[q].e;q++;k++;}
         else 
	 {C.data[k].i=A.data[p].i;C.data[k].j=A.data[p].j;
	  C.data[k].e=A.data[p].e;p++;k++;}
   }
  while (p<=A.tu)
    {C.data[k].i=A.data[p].i;C.data[k].j=A.data[p].j;
      C.data[k].e=A.data[p].e;p++;k++;}
  while (q<=B.tu)
    {C.data[k].i=B.data[q].i;C.data[k].j=B.data[q].j;
      C.data[k].e=B.data[q].e;q++;k++;}
   C.tu=k-1;
   return OK;
  }

 
void main()
{ TSMatrix T,T1,T2;
  InitTSMatrix(T);getch();
  ChangeArrayToMS(a,T);
  PrintTSmatrix(T);getch();
  TransposeSMatrix(T,T1);
  PrintTSmatrix(T1);getch();
  FastTransposeSMatrix(T,T1);
  PrintTSmatrix(T1);getch();
  AddTSMatrix(T,T1,T2);
  PrintTSmatrix(T2);
  }

5.	 二叉树算法
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#define stackinitsize 100
#define OK 1
#define ERROR 0
#define OVERFLOW -1

typedef int TElemType ;
typedef int Status;

       //一一一一一二叉树的二叉链表存储表示一一一一一
typedef struct  BiTNode{ 
     TElemType   data;
     struct  BiTNode  *lchild,*rchild;   //左右孩子指针
   }BiTnode,*SElemType,*BiTree;

typedef struct{
  //该堆栈的元素是指针类型的
  //base和top均是指向指针的指针
  SElemType *base;
  SElemType *top;
  int stacksize;
}sqstack;//堆栈结构

         //一一一一一基本操作的函数原型说明(部分)一一一一一
    Status CreateBitree(BiTree &T);
        //按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树。
        //构造二叉链表表示的二叉树T.
    Status  PreOrderTraverse(BiTree T,Status(*Visit)(TElemType e));
        //采用二叉链表存储结构,visit是对结点操作的应用函数。
        //先序遍历二叉树T,对每个结点调用函数Visit一次且仅一次。
        //一旦visit()失败,则操作失败。
    Status  InorderTraverse(BiTree T,Status(*Visit)(TElemType e));
        //采用二叉链表存储结构,Visit是对结点操作的应用函数。
        //中序遍历二叉树T,对每个结点调用函数Visit一次且仅一次。
        //一旦visit()失败,则操作失败。
    Status  PostorderTraverse(BiTree T,Status(*Visit)(TElemType e));
        //采用二叉链表存储结构,visit是对结点操作的应用函数。
        //后序遍历二叉树T,对每个结点调用函数Visit一次且仅一次。
        //一旦visit()失败,则操作失败。
    Status  LevelIOrderTraverse(BiTree T,Status(*Visit)(TElemType e));
        //采用二又链表存储结构,Visit是对结点操作的应用函数。
        //层序遍历二叉树T,对每个结点调用函数Visit一次且仅一次。
	//一旦visit()失败,则操作失败



 sqstack *InitStack()//初始化堆栈
 {sqstack *s;
  s->base=(SElemType*)malloc(100*sizeof(SElemType));
  if(!s->base) return NULL;
  s->top=s->base;
  s->stacksize=100;
  return s;
 }

int StackEmpty(sqstack *s) //栈空判别
 {return(s->top==s->base);
 }

void Pop(sqstack *s,SElemType &e)//弹栈
 {
   e=*--s->top;
 }

Status GetTop(sqstack *s,SElemType &e)
 { 
   if(s->top==s->base) return ERROR;
   e=*(s->top-1);
   return OK;
 }

void Push(sqstack *s,SElemType e)//将元素压入堆栈
 {SElemType t;
  *s->top++=e;
 }


Status  CreateBiTree(BiTree &T){
    //按先序次序输入二叉树中结点的值(一个字符),空格字符表示空树。
    //构造二叉链表表示的二叉树T.
    char ch;
    ch=getche(); 
    if(ch==' ') T=NULL;
     else{
        if(!(T=(BiTNode *)malloc(sizeof(BiTNode)))) return(OVERFLOW);
        T->data=ch;             //生成根结点
        CreateBiTree(T->lchild);//构造左子树
        CreateBiTree(T->rchild);//构造右子树
    }
      return  OK;
    }//CreateBiTree

Status  PreOrderTraverse(BiTree T,Status(*Visit)(TElemType e))
       //采用二叉链表存储结构,visit是对数据元素操作的应用函数,
       //先序遍历二叉树T的递归算法,对每个数据元素调用函数visit。
       //调用实例:  PreOrderTraverse(T,printElement);
   {
       if(T){
       if (Visit(T->data))
            if (PreOrderTraverse(T->lchild,Visit))
              if  (PreOrderTraverse(T->rchild,Visit)) return  OK;
            return  ERROR;
	}else  return  OK;
       }//preOrderTraVerse

Status InOrderTraverse(BiTree T,Status(*Visit)(TElemType e))
       //采用二叉链表存储结构,visit是对数据元素操作的应用函数,
       //中序遍历二叉树T的递归算法,对每个数据元素调用函数visit。
   {
       if(T){
             if (InOrderTraverse(T->lchild,Visit))
	       if (Visit(T->data))
	         if (InOrderTraverse(T->rchild,Visit))   return  OK;
            return  ERROR;
	}else  return  OK;
       }//preOrderTraVerse

Status  PostOrderTraverse(BiTree T,Status(*Visit)(TElemType e))
       //采用二叉链表存储结构,visit是对数据元素操作的应用函数,
       //后序遍历二叉树T的递归算法,对每个数据元素调用函数visit。
   {
       if(T){
            if (PostOrderTraverse(T->lchild,Visit))
	      if  (PostOrderTraverse(T->rchild,Visit))
		if (Visit(T->data)) return  OK;
            return  ERROR;
	}else  return  OK;
       }//preOrderTraVerse


Status  PrintElement(TElemType  e)
       {   //输出元素e的值
           printf("%c",e);        
           return  OK;
	}

Status  InorderTraverseNoRecursion1(BiTree T,Status(*Visit)(TElemType e))
	        
    //采用二叉链表存储结构,visit是对数据元素操作的应用函数。
    //中序遍历二叉树T的非递归算法,对每个数据元素调用函数visit。
   {sqstack *s;
    BiTree p;
    s=InitStack();p=T; 
    while(p||!StackEmpty(s))
      {
        if(p){ Push(s,p);p=p->lchild;}//根指针进栈,遍历左子树
        else{       //根指针退栈,访问根结点,遍历右子树
	  Pop(s,p);if(!Visit(p->data))  return  ERROR;
	  p=p->rchild;
        }//else
      }//while
    return  OK;
  }//InorderTraVerse1

Status  InorderTraverseNoRecursion2(BiTree T,Status(*Visit)(TElemType e))
	        
    //采用二叉链表存储结构,visit是对数据元素操作的应用函数。
    //中序遍历二叉树T的非递归算法,对每个数据元素调用函数visit。
   {sqstack *s;
    BiTree p;
    s=InitStack();Push(s,T); 
    while(!StackEmpty(s))
      {
       while(GetTop(s,p)&&p) Push(s,p->lchild);//向左走到尽头
       Pop(s,p);                               //空指针退栈
       if(!StackEmpty(s)) {                    //访问结点,向右一步
	 Pop(s,p);if(!Visit(p->data))  return  ERROR;
	 Push(s,p->rchild);
       }//if
      }//while
    return  OK;
  }//InorderTraVerse1

void main()
{
  BiTree t;
    printf("\n请按先序遍历输入二叉树(当左右子树为空时用空格输入)\n");
  CreateBiTree(t);
  printf("\n该二叉树的先序遍历为:\n");
  PreOrderTraverse(t,PrintElement);
    printf("\n该二叉树的中序遍历为:\n");
  InOrderTraverse(t,PrintElement);
    printf("\n该二叉树的后序遍历为:\n");
  PostOrderTraverse(t,PrintElement); 
    printf("\n该二叉树的中序遍历为:(用非递归调用1)\n");
  InorderTraverseNoRecursion1(t,PrintElement);
    printf("\n该二叉树的中序遍历为:(用非递归调用2)\n");
  InorderTraverseNoRecursion2(t,PrintElement);
}




6、哈夫曼编码

#include "stdlib.h"
#include "stdio.h"
#include "conio.h"
#include "string.h"
#define ERROR 0;
#define OK 1;

typedef int Status ;

//哈夫曼树的存储和哈夫曼编码的存储
typedef struct{
      unsigned int weight;
      unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;       //动态分配数组存储哈夫曼树

typedef char **HuffmanCode; //动态分配数组存储哈夫曼编码表

Status Select(HuffmanTree HT,int n,int &s1,int &s2) {
  //在哈夫曼树HT[1..n] 搜索最大权值和最小权值并用s1,s2 返回它们的下标
  unsigned int temp=9999;
  int i;
  s1=0;s2=0;
  for(i=1;i<=n;i++) 
    if((HT[i].weight<temp)&&(HT[i].parent==0))
      {
        s1=i;temp=HT[i].weight;
      }
  temp=9999;
  for(i=1;i<=n;i++)
    if((HT[i].weight<temp)&&(HT[i].parent==0)&&(i!=s1))
      {
        s2=i;temp=HT[i].weight;
      }
  if((s1==0)&&(s2==0)) return ERROR;
  return OK;
}//select

  

 //求huffman编码的算法:
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int w[],int n)
{
  //w存放N个字符的权值(均?>0),构造hufmantree HT,并求N个字符有huffman编码HC
  HuffmanTree p;
  char *cd;
  int s1,s2,i,c,m,start,f;
  if(n<1) return ;
  m=2*n-1;                                       //哈夫曼树的结点数 
  HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));  //0号单元未用
    p=HT;p++;
    for(i=1;i<=n;++i)
      {
       p->weight=w[i-1];
       p->parent=0;
       p->lchild=0;
       p->rchild=0;
       p++;
      }//将各结点赋初值
    for(;i<=m;++i,++p)
      {
       p->weight=0;
       p->parent=0;
       p->lchild=0;
       p->rchild=0;
      }//后续结点赋初值
   
    for(i=n+1;i<=m;++i) 
   {  Select(HT,i-1,s1,s2);
      //在HT[1..i-1]选择parent为0且weight最小的两个结点,其序号为S1,S2
      //每次创建的树放在i的位置其中(i>n)
      HT[s1].parent=i;HT[s2].parent=i;
      HT[i].lchild=s1;HT[i].rchild=s2;
      HT[i].weight=HT[s1].weight+HT[s2].weight;
   }

  printf("\nthe huffmantree is:\n");
  printf("     NO [weight  parent  lchild  rchild]\n");
  printf("        --------------------------------\n");
  for(i=1;i<=m;i++)
     printf("%6d [%6d,%6d,%6d,  %6d ]\n",i,HT[i].weight,HT[i].parent,HT[i].lchild,HT[i].rchild);

  //从叶子到根逆向求每个字符的Huffman  编码
  HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
  cd=(char *)malloc(n*sizeof(char));
  cd[n-1]='\0';
  for(i=1;i<=n;++i)
  {  start=n-1;
     for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
       if(HT[f].lchild==c)  cd[--start]='0';
       else  cd[--start]='1';
     HC[i]=(char*)malloc((n-start)*sizeof(char));
     strcpy(HC[i],&cd[start]);
  }
  free(cd);
}//end  huffmancoding

void main()
{
 HuffmanTree HT;
 int n,i,w[20];
 HuffmanCode HC;
 printf("please intput n=\n");
 scanf("%d",&n);
 printf("please input w[%d]:\n",n);
 for(i=0;i<n;i++)
    scanf("%d",&w[i]);
 HuffmanCoding(HT,HC,w,n);
 getch();
 printf("\nthe HuffmanCoding is:\n");
 for(i=1;i<=n;i++)
  printf("%s\n",HC[i]);

}




7、	最短路径的dijkstra算法
#include <stdio.h>
#define max 1000
#define n 6
typedef int Graph[n][n];
typedef int vertex;
void shortp(Graph G,vertex v,int dist[n])
{
  int i,wm,u,num=1,S[n];
  for(i=0;i<n;i++)
   {
     dist[i]=G[v][i];
     S[i]=0;/*数组dist及集合S赋初值*/
   }
  S[v]=1;  /*把顶点v加入集合S中*/

do{
   wm=max;
   u=v;
   for(i=0;i<n;i++)  /*选择顶点u*/
     if(S[i]==0)
      if(dist[i]<wm)
	{
	  u=i;
	  wm=dist[i];
	}
   S[u]=1;
   for(i=0;i<n;i++)
     if(S[i]==0)
       if(dist[u]+G[u][i]<dist[i])
	    dist[i]=dist[u]+G[u][i];
   num++;
   }while(num!=n-1);
}
void main()
  {
   Graph G;
   vertex v=0;
   int dist[n],i,j;
   printf("please input weight of Graph:\n");
   for(i=0;i<n;i++)
     for(j=0;j<n;j++)
	scanf("%d",&G[i][j]);
   shortp(G,v,dist);
   for(i=0;i<n;i++)
     printf("the shortest path of v[%d]->v[%d] is:%d\n",v,i,dist[i]);
  }



8、	普里姆算法求最小生成树
# include "alloc.h"
# include "conio.h"
# include "stdlib.h"
# include "stdio.h"
# include "limits.h"
//-------图的数组(邻接矩阵)存储表示--------
#define INFINITY INT_MAX            //整型最大值
#define MAX_VERTEX_NUM 20           //最大顶点个数
#define ERROR     0
#define OK        1
#define OVERFLOW -2

typedef struct{
 char v;
 int  i;
}VertexType;

typedef int VRType;
typedef int Status;

typedef enum{DG=0,DN=1,AG=2,AN=3}GraphKind; //{有向图、有向网、无向图、无向网}

typedef struct ArcCell{
   VRType adj;//VRType是定点关系类型。对无权图,用0和1
	      //表示相邻否。对待有权图,则表示权值类型
}ARcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct{
  VertexType  vexs[MAX_VERTEX_NUM]; //顶点向量
  AdjMatrix  arcs;                  //邻接矩阵
  int vexnum,arcnum;                //图的当前顶点数和弧数
  GraphKind kind;                   //图的种类标志
}MGraph;

struct {
       VertexType adjvex;  //顶点
       VRType lowcost;     //权值
}closedge[MAX_VERTEX_NUM]; //全局变量

Status CreateUDN(MGraph &G) {
  //采用数组(邻接矩阵)表示法,构造无相网G。
  int i,j,v1,v2,w,k;
  printf("\nplease input vexnum and arcnum:\n");
  scanf("%d,%d",&G.vexnum,&G.arcnum);
  for(i=0;i<G.vexnum;++i)
     {G.vexs[i].v='v';G.vexs[i].i=i+1;}
  for(i=0;i<G.vexnum;i++)
     for(j=0;j<G.vexnum;j++)
	G.arcs[i][j].adj=INFINITY;
  for(k=0;k<G.arcnum;k++) {
     printf("\nplease input v1,v2,w:\n");
     scanf("%d,%d,%d",&v1,&v2,&w);
     i=v1-1;j=v2-1;
     G.arcs[i][j].adj=w;
     G.arcs[j][i].adj=G.arcs[i][j].adj;
  }
  return OK;
}//CreateUND

Status CreateGraph(MGraph &G) {
       //采用数组表示法,构造图G
       return CreateUDN(G);
}//CreateGraph

int minimum(MGraph G){
  // min{closedge[vi].lowcost||closedge[vi].lowcost>0,vi in V-U}
  int i,k,min=INFINITY;
  printf("\n closedge:\n");
  for(i=0;i<G.vexnum;++i)
     printf(" %d",closedge[i].lowcost);
  printf("\n");
  for(i=0;i<G.vexnum;++i)
     if((closedge[i].lowcost)>0&&(closedge[i].lowcost<min))
	{
         k=i;min=closedge[i].lowcost;
	}
  return k;
}

void MinSpanTree_PRIM(MGraph G,VertexType u) {
   //用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边
   //记录从顶点u到V-u的代价最小的彼岸的辅助数组定义:
   //struct {
   //    VertexType adjvex;  //顶点
   //    VRType lowcost;     //权值
   //}closedge[MAX_VERTEX_NUM];
   int k,j,i;
   k=u.i-1;
   for(j=0;j<G.vexnum;++j)
      if(j!=k){
	  closedge[j].adjvex.v=u.v;
	  closedge[j].adjvex.i=u.i;
	  closedge[j].lowcost=G.arcs[k][j].adj;
      }//end for .辅助数组初始化
   closedge[k].lowcost=0;    //初始,U={u}
   for(i=1;i<G.vexnum;++i) { //选择其余G.vexnum-1个顶点
      k=minimum(G);
      printf("k=%d",k);
       //此时closedge[k].lowcost=
       //          min{closedge[vi].lowcost||closedge[vi].lowcost>0,vi in V-U}
      printf(" \nv%d-->v%d",closedge[k].adjvex.i,G.vexs[k].i);//输出生成树的边
      closedge[k].lowcost=0;
      for(j=0;j<=G.vexnum;++j)
	 if(G.arcs[k][j].adj<closedge[j].lowcost)
	     {
	      closedge[j].adjvex.i=G.vexs[k].i;
              closedge[j].lowcost=G.arcs[k][j].adj;
	     }
    }//end for
}//minispenTree


void main()
{
  MGraph G;
  VertexType u={'v',1};
  int i,j;
  CreateGraph(G);
  for(i=0;i<G.vexnum;i++)
  {
     printf("\n");
     for(j=0;j<G.vexnum;j++)
       if (G.arcs[i][j].adj!=INFINITY)
	  printf(" %d ",G.arcs[i][j].adj);
       else
	  printf(" ∞");
   }
  MinSpanTree_PRIM(G,u);
}


9、五种排序算法
#include "stdio.h"
#include “conio.h”
#include "stdlib.h"
#include "math.h"
#include "dos.h"

#define Max 100
typedef int sqlist[Max+1];

void insertsort(sqlist a,int n)
{
  int i,j;
  for(i=2;i<=n;i++)
  {
    if(a[i]<a[i-1])
    {
      a[0]=a[i];
      for(j=i-1;a[0]<a[j];--j)
	 a[j+1]=a[j];
      a[j+1]=a[0];
     }
  }
}

void shellsort(sqlist r,int n)
{
  int i,j,gap,x;
  gap=n/2;
  while(gap>0)
   {
     for(i=gap+1;i<=n;i++)
      {
       j=i-gap;
       while(j>0)
	 if(r[j]>r[j+gap])
	   {
	    x=r[j];
	    r[j]=r[j+gap];
	    r[j+gap]=x;
	    j=j-gap;
	   }
	 else j=0;
      }
     gap=gap/2;
   }
}
void bubblesort(sqlist r,int n)
{
  int i,j,w;
  for(i=1;i<=n-1;i++)
    for(j=n;j>=i+1;j--)
       if(r[j]<r[j-1])
	{
	 w=r[j];
	 r[j]=r[j-1];
	 r[j-1]=w;
	}
}

void selectsort(sqlist r,int n)
{
 int i,j,k,temp;
 for(i=1;i<=n-1;i++)
   {
    k=i;
    for(j=i+1;j<=n;j++)
      if(r[j]<r[k]) k=j;
    temp=r[i];
    r[i]=r[k];
    r[k]=temp;
   }
}

int partion( sqlist a,int n,int low,int high)
{
  int p,i;
  p=a[low];
  a[0]=a[low];
  while(low<high)
    {
      while(low<high&&a[high]>=p)  --high;
      a[low]=a[high];
      while(low<high&&a[low]<=p) ++low;
      a[high]=a[low];
   }
  a[low]=a[0];
/* for(i=1;i<=n;i++)
    printf("%d ",a[i]);
  printf("\n\n");*/
  return low;
}

void quicksort(sqlist a,int n,int low,int high)
{
  int p,i;
  if(low<high)
    {
      p=partion(a,n,low,high);
      quicksort(a,n,low,p-1);
      quicksort(a,n,p+1,high);
    }
}


 void main()
 {
  int i,n=10;
  char ch;
  sqlist a;
  for(i=1;i<=10;i++)
    a[i]=11-i;
  printf("\n\n");
  printf("   ┌─────────────┐\n");
  printf("   │      1---插入排序        │\n");
  printf("   │      2---希尔排序        │\n");
  printf("   │      3---冒泡排序        │\n");
  printf("   │      4---选择排序        │\n");
  printf("   │      5---快速排序        │\n");
  printf("   │        请选择(1--5)      │\n");
  printf("   └─────────────┘\n");
  ch=getch();
  if(ch=='1')     {printf("插入排序的结果是:\n");insertsort(a,n);}
  else if(ch=='2'){printf("希尔排序的结果是:\n");shellsort(a,n);}
  else if(ch=='3'){printf("冒泡排序的结果是:\n");bubblesort(a,n);}
  else if(ch=='4'){printf("选择排序的结果是:\n");selectsort(a,n);}
  else if(ch=='5'){printf("快速排序的结果是:\n");quicksort(a,n,1,n);}
  else printf("对不起,你选择的参数不对!");
  for(i=1;i<=10;i++)
    printf("%5d",a[i]);
 }

  

转载于:https://www.cnblogs.com/wc1903036673/p/3413000.html

数据结构环境准备vc6.0

博文 来自: wh2691259
没有更多推荐了,返回首页