??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV网站在线观看,亚洲国产精品一区二区第四页,亚洲av永久无码精品天堂久久http://m.tkk7.com/neumqp/zh-cnMon, 12 May 2025 02:44:58 GMTMon, 12 May 2025 02:44:58 GMT60递归删除cvshttp://m.tkk7.com/neumqp/archive/2007/04/17/111308.html铁?/dc:creator>铁?/author>Tue, 17 Apr 2007 06:32:00 GMThttp://m.tkk7.com/neumqp/archive/2007/04/17/111308.htmlhttp://m.tkk7.com/neumqp/comments/111308.htmlhttp://m.tkk7.com/neumqp/archive/2007/04/17/111308.html#Feedback0http://m.tkk7.com/neumqp/comments/commentRss/111308.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/111308.html

]]>
filter得到request的body/contenthttp://m.tkk7.com/neumqp/archive/2006/10/25/77235.html铁?/dc:creator>铁?/author>Wed, 25 Oct 2006 09:01:00 GMThttp://m.tkk7.com/neumqp/archive/2006/10/25/77235.htmlhttp://m.tkk7.com/neumqp/comments/77235.htmlhttp://m.tkk7.com/neumqp/archive/2006/10/25/77235.html#Feedback1http://m.tkk7.com/neumqp/comments/commentRss/77235.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/77235.html
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;

        int length = req.getContentLength();
        if (length > 0) {
            BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(req,length);

            InputStream is = bufferedRequest.getInputStream();
            byte[] content = new byte[length];
           
            int pad = 0;
            while(pad < length){
                pad += is.read(content, pad, length);
            }

            request = bufferedRequest;
        }
        chain.doFilter(request, response);      
    }


BufferedRequestWrapper .java

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class BufferedRequestWrapper extends HttpServletRequestWrapper {

    ByteArrayInputStream bais;

    BufferedServletInputStream bsis;

    byte[] buffer;

    public BufferedRequestWrapper(HttpServletRequest req,int length) throws IOException {
        super(req);
        // Read InputStream and store its content in a buffer.
        InputStream is = req.getInputStream();
        buffer = new byte[length];

        int pad = 0;
        while(pad < length){
            pad += is.read(buffer, pad, length);
        }
    }

    public ServletInputStream getInputStream() {
        try {
            // Generate a new InputStream by stored buffer
            bais = new ByteArrayInputStream(buffer);
            // Istantiate a subclass of ServletInputStream
            // (Only ServletInputStream or subclasses of it are accepted by the
            // servlet engine!)
            bsis = new BufferedServletInputStream(bais);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
        }
        return bsis;
    }

}




BufferedServletInputStream .java

import java.io.*;
import javax.servlet.ServletInputStream;

/*
 Subclass of ServletInputStream needed by the servlet engine.
 All inputStream methods are wrapped and are delegated to
 the ByteArrayInputStream (obtained as constructor parameter)!
 */
public class BufferedServletInputStream extends ServletInputStream {

    ByteArrayInputStream bais;

    public BufferedServletInputStream(ByteArrayInputStream bais) {
        this.bais = bais;
    }

    public int available() {
        return bais.available();
    }

    public int read() {
        return bais.read();
    }

    public int read(byte[] buf, int off, int len) {
        return bais.read(buf, off, len);
    }

}



]]>
begin linux programhttp://m.tkk7.com/neumqp/archive/2006/07/10/57506.html铁?/dc:creator>铁?/author>Mon, 10 Jul 2006 06:54:00 GMThttp://m.tkk7.com/neumqp/archive/2006/07/10/57506.htmlhttp://m.tkk7.com/neumqp/comments/57506.htmlhttp://m.tkk7.com/neumqp/archive/2006/07/10/57506.html#Feedback0http://m.tkk7.com/neumqp/comments/commentRss/57506.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/57506.htmlwill compile and link a program called x11fred using the version of the library libX11 found in the
/usr/openwin/lib directory.

]]>
java 发mailhttp://m.tkk7.com/neumqp/archive/2006/05/10/45516.html铁?/dc:creator>铁?/author>Wed, 10 May 2006 10:02:00 GMThttp://m.tkk7.com/neumqp/archive/2006/05/10/45516.htmlhttp://m.tkk7.com/neumqp/comments/45516.htmlhttp://m.tkk7.com/neumqp/archive/2006/05/10/45516.html#Feedback1http://m.tkk7.com/neumqp/comments/commentRss/45516.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/45516.html有发送h名称中文支持Q支持bytes格式附gQ附件中文支?br />
  public static boolean send(String fromName, String fromAddr, String to, String subject, String
                             body, String fileName, byte[] file) throws
      Exception {
        //发送h名称Q用base64~码Q再加上Ҏ标志
        fromName = "=?GB2312?B?" + new String(base64.encode((fromName).getBytes()))  + "?=";
    Properties props = new Properties();
    Session session = Session.getInstance(props, null);
    props.put("mail.smtp.host", Constants.mailhost);
    props.put("mail.smtp.auth", "false"); 
    Message msg = new MimeMessage(session);
      msg.setFrom(new InternetAddress(fromAddr,fromName));
//后面的BodyPart加入到此处创徏的Multipart?br />    Multipart mp = new MimeMultipart();
// Create the message part
    BodyPart messageBodyPart = new MimeBodyPart();

    // Fill the message
    messageBodyPart.setText(body);

    mp.addBodyPart(messageBodyPart);

      /*发送附?/
     if (file != null && file.length > 0) {
       //利用枚D器方便的遍历集合
         MimeBodyPart mbp = new MimeBodyPart(); 
//         File fileTmp = null;
         //得到数据?br />//         FileDataSource fds = new FileDataSource(fileTmp);
         //得到附g本nq至入BodyPart
         mbp.setDataHandler(new DataHandler(new ByteArrayDataSource(file,"application/octet-stream")));
         //得到文g名同栯入BodyPart
         mbp.setFileName(MimeUtility.encodeWord(fileName,"GB2312",null));
         mp.addBodyPart(mbp);
     }
   
    //Multipart加入C?br />    msg.setContent(mp);

    msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
    msg.setSubject(subject);

    msg.setHeader("X-Mailer", "personal Email Sender");
    msg.setSentDate(new Date());

    Transport transport = session.getTransport("smtp");

    //d认证信息
    transport.connect(Constants.mailhost, Constants.user, Constants.pwd);
    transport.sendMessage(msg, msg.getRecipients(Message.RecipientType.TO));
    transport.close();
    return true;
  }




import java.io.*;
import javax.activation.*;

public class ByteArrayDataSource implements DataSource {
    /** * Data to write. */
    private byte[] _data;

    /** * Content-Type. */
    private String _type;

    /* Create a datasource from an input stream */
    public ByteArrayDataSource(InputStream is, String type) {
        _type = type;
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            int ch;

            // XXX : must be made more efficient by
            // doing buffered reads, rather than one byte reads
            while ((ch = is.read()) != -1)
                os.write(ch);
            _data = os.toByteArray();
        } catch (IOException ioe) {
        }
    }

    /* Create a datasource from a byte array */
    public ByteArrayDataSource(byte[] data, String type) {
        _data = data;
        _type = type;
    }

    /* Create a datasource from a String */
    public ByteArrayDataSource(String data, String type) {
        try {
            // Assumption that the string contains only ascii
            // characters ! Else just pass in a charset into this
            // constructor and use it in getBytes()
            _data = data.getBytes("iso-8859-1");
        } catch (UnsupportedEncodingException uee) {
        }
        _type = type;
    }

    public InputStream getInputStream() throws IOException {
        if (_data == null)
            throw new IOException("no data");
        return new ByteArrayInputStream(_data);
    }

    public OutputStream getOutputStream() throws IOException {
        throw new IOException("cannot do this");
    }

    public String getContentType() {
        return _type;
    }

    public String getName() {
        return "dummy";
    }
}



]]>
C/C++头文件一览(转)http://m.tkk7.com/neumqp/archive/2006/03/09/34506.html铁?/dc:creator>铁?/author>Thu, 09 Mar 2006 08:55:00 GMThttp://m.tkk7.com/neumqp/archive/2006/03/09/34506.htmlhttp://m.tkk7.com/neumqp/comments/34506.htmlhttp://m.tkk7.com/neumqp/archive/2006/03/09/34506.html#Feedback0http://m.tkk7.com/neumqp/comments/commentRss/34506.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/34506.htmlC/C++头文件一?/SPAN>

C、传l?C++

#include <assert.h>    //讑֮插入?BR>#include <ctype.h>     //字符处理
#include <errno.h>     //定义错误?BR>#include <float.h>     //点数处?BR>#include <fstream.h>    //文g输入Q输?BR>#include <iomanip.h>    //参数化输入/输出
#include <iostream.h>   //数据输入/输出
#include <limits.h>    //定义各种数据cd最值常?BR>#include <locale.h>    //定义本地化函?BR>#include <math.h>     //定义数学函数
#include <stdio.h>     //定义输入Q输出函?BR>#include <stdlib.h>    //定义杂项函数及内存分配函?BR>#include <string.h>    //字符串处?BR>#include <strstrea.h>   //Z数组的输入/输出
#include <time.h>     //定义关于旉的函?BR>#include <wchar.h>     //宽字W处理及输入Q输?BR>#include <wctype.h>    //宽字W分c?BR>
//////////////////////////////////////////////////////////////////////////

标准 C++ Q同上的不再注释Q?BR>
#include <algorithm>    //STL 通用法
#include <bitset>     //STL 位集容器
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>     //复数c?BR>#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>      //STL 双端队列容器
#include <exception>    //异常处理c?BR>#include <fstream>
#include <functional>   //STL 定义q算函数Q代替运符Q?BR>#include <limits>
#include <list>      //STL U性列表容?BR>#include <map>       //STL 映射容器
#include <iomanip>
#include <ios>       //基本输入Q输出支?BR>#include <iosfwd>     //输入Q输出系l用的前置声明
#include <iostream>
#include <istream>     //基本输入?BR>#include <ostream>     //基本输出?BR>#include <queue>      //STL 队列容器
#include <set>       //STL 集合容器
#include <sstream>     //Z字符串的?BR>#include <stack>      //STL 堆栈容器    
#include <stdexcept>    //标准异常c?BR>#include <streambuf>    //底层输入Q输出支?BR>#include <string>     //字符串类
#include <utility>     //STL 通用模板c?BR>#include <vector>     //STL 动态数l容?BR>#include <cwchar>
#include <cwctype>

using namespace std;

//////////////////////////////////////////////////////////////////////////

C99 增加

#include <complex.h>   //复数处理
#include <fenv.h>    //点环境
#include <inttypes.h>  //整数格式转换
#include <stdbool.h>   //布尔环境
#include <stdint.h>   //整型环境
#include <tgmath.h>   //通用cd数学?/FONT>



]]>
string.h中的函数(?http://m.tkk7.com/neumqp/archive/2006/03/09/34505.html铁?/dc:creator>铁?/author>Thu, 09 Mar 2006 08:54:00 GMThttp://m.tkk7.com/neumqp/archive/2006/03/09/34505.htmlhttp://m.tkk7.com/neumqp/comments/34505.htmlhttp://m.tkk7.com/neumqp/archive/2006/03/09/34505.html#Feedback0http://m.tkk7.com/neumqp/comments/commentRss/34505.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/34505.htmlstring.h中的函数

@函数名称:   strdup
函数原型:   char *strdup(const char *s)
函数功能:   字符串拷贝,目的I间p函数分配
函数q回:   指向拯后的字符串指?BR>参数说明:   src-待拷贝的源字W串
所属文?   <string.h>

#include <stdio.h>
#include <string.h>
#include <alloc.h>
int main()
{
  char *dup_str, *string="abcde";
  dup_str=strdup(string);
  printf("%s", dup_str);
  free(dup_str);
  return 0;
}


@函数名称:   strcpy
函数原型:   char* strcpy(char* str1,char* str2);
函数功能:   把str2指向的字W串拯到str1中去
函数q回:   q回str1,x向str1的指?BR>参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>
int main()
{
  char string[10];
  char *str1="abcdefghi";
  strcpy(string,str1);
  printf("the string is:%s\n",string);
  return 0;
}


@函数名称:   strncpy
函数原型:   char *strncpy(char *dest, const char *srcQint count)
函数功能:   字W串src中的count个字W拷贝到字符串dest中去
函数q回:   指向dest的指?BR>参数说明:   dest-目的字符Ԍsrc-源字W串Qcount-拯的字W个?BR>所属文?   <string.h>

#include <stdio.h>
#include <string.h>
int main()
{
  char string[10];
  char *str1="abcdefghi";
  strncpy(string,str1,3);
  string[3]='\0';
  printf("%s",string);
  return 0;
}


@函数名称:   strcat
函数原型:   char* strcat(char * str1,char * str2);
函数功能:   把字W串str2接到str1后面,str1最后的'\0'被取?BR>函数q回:   str1
参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>

int main()
{
  char buffer[80];

  strcpy(buffer,"Hello ");
  strcat(buffer,"world");
  printf("%s\n",buffer);
  return 0;
}


@函数名称:   strncat
函数原型:   char *strncat(char *dest, const char *src, size_t maxlen)
函数功能:   字W串src中前maxlen个字W连接到dest?BR>函数q回:
参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>

char buffer[80];

int main()
{
  strcpy(buffer,"Hello ");
  strncat(buffer,"world",8);
  printf("%s\n",buffer);
  strncat(buffer,"*************",4);
  printf("%s\n",buffer);
  return 0;
}


@函数名称:   strcmp
函数原型:   int strcmp(char * str1,char * str2);
函数功能:   比较两个字符串str1,str2.
函数q回:   str1<str2,q回负数; str1=str2,q回 0; str1>str2,q回正数.
参数说明:
所属文?   <string.h>

#include <string.h>
#include <stdio.h>
int main()
{
  char *buf1="aaa", *buf2="bbb", *buf3="ccc";
  int ptr;
  ptr=strcmp(buf2, buf1);
  if(ptr>0)
    printf("buffer 2 is greater than buffer 1\n");
  else
    printf("buffer 2 is less than buffer 1\n");
  ptr=strcmp(buf2, buf3);
  if(ptr>0)
    printf("buffer 2 is greater than buffer 3\n");
  else
    printf("buffer 2 is less than buffer 3\n");
  return 0;
}


@函数名称:   strncmp
函数原型:   int strncmp(char *str1,char *str2,int count)
函数功能:   对str1和str2中的前count个字W按字典序比较
函数q回:   于0Qstr1<str2Q等?Qstr1=str2Q大?Qstr1>str2
参数说明:   str1,str2-待比较的字符Ԍcount-比较的长?BR>所属文?   <string.h>

#include <string.h>
#include <stdio.h>
int main()
{
  int ptr;
  char *buf1="aaabbb",*buf2="bbbccc",*buf3="ccc";
  ptr=strncmp(buf2,buf1,3);
  if (ptr>0)
    printf("buffer 2 is greater than buffer 1");
  else
    printf("buffer 2 is less than buffer 1");
    ptr=strncmp(buf2,buf3,3);
  if (ptr>0)
    printf("buffer 2 is greater than buffer 3");
  else
    printf("buffer 2 is less than buffer 3");
  return(0);
}


@函数名称:   strpbrk
函数原型:   char *strpbrk(const char *s1, const char *s2)
函数功能:   得到s1中第一个“同时也出现在s2中”字W的位置指针
函数q回:   位置指针
参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>
int main()
{
char *p="Find all vowels";

while(p)
{
  printf("%s\n",p);
  p=strpbrk(p+1,"aeiouAEIOU");
}
return 0;
}


@函数名称:   strcspn
函数原型:   int strcspn(const char *s1, const char *s2)
函数功能:   l计s1中从头开始直到第一个“来自s2中的字符”出现的长度
函数q回:   长度
参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>

int main()
{
  printf("%d\n",strcspn("abcbcadef","cba"));
  printf("%d\n",strcspn("xxxbcadef","cba"));
  printf("%d\n",strcspn("123456789","cba"));
  return 0;
}


@函数名称:   strspn
函数原型:   int strspn(const char *s1, const char *s2)
函数功能:   l计s1中从头开始直到第一个“不来自s2中的字符”出现的长度
函数q回:   位置指针
参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>
#include <alloc.h>
int main()
{
  printf("%d\n",strspn("out to lunch","aeiou"));
  printf("%d\n",strspn("out to lunch","xyz"));
  return 0;
}


@函数名称:   strchr
函数原型:   char* strchr(char* str,char ch);
函数功能:   扑ևstr指向的字W串中第一ơ出现字Wch的位|?BR>函数q回:   q回指向该位|的指针,如找不到,则返回空指针
参数说明:   str-待搜索的字符Ԍch-查找的字W?BR>所属文?   <string.h>

#include <string.h>
#include <stdio.h>
int main()
{
  char string[15];
  char *ptr, c='r';
  strcpy(string, "This is a string");
  ptr=strchr(string, c);
  if (ptr)
    printf("The character %c is at position: %d\n",c,ptr-string);
  else
    printf("The character was not found\n");
  return 0;
}


@函数名称:   strrchr
函数原型:   char *strrchr(const char *s, int c)
函数功能:   得到字符串s中最后一个含有c字符的位|指?BR>函数q回:   位置指针
参数说明:
所属文?   <string.h>

#include <string.h>
#include <stdio.h>
int main()
{
  char string[15];
  char *ptr,c='r';
  strcpy(string,"This is a string");
  ptr=strrchr(string,c);
  if (ptr)
    printf("The character %c is at position:%d",c,ptr-string);
  else
    printf("The character was not found");
  return 0;
}


@函数名称:   strstr
函数原型:   char* strstr(char* str1,char* str2);
函数功能:   扑ևstr2字符串在str1字符串中W一ơ出现的位置(不包括str2的串l束W?
函数q回:   q回该位|的指针,如找不到,q回I指?BR>参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>
int main()
{
  char *str1="Open Watcom C/C++",*str2="Watcom",*ptr;
  ptr=strstr(str1,str2);
  printf("The substring is:%s\n",ptr);
  return 0;
}


@函数名称:   strrev
函数原型:   char *strrev(char *s)
函数功能:   字W串中的所有字W颠倒次序排?BR>函数q回:   指向s的指?
参数说明:
所属文?   <string.h>

#include <string.h>
#include <stdio.h>
int main()
{
  char *forward="string";
  printf("Before strrev():%s",forward);
  strrev(forward);
  printf("After strrev(): %s",forward);
  return 0;
}


@函数名称:   strnset
函数原型:   char *strnset(char *s, int ch, size_t n)
函数功能:   字W串s中前n个字W设|ؓch的?BR>函数q回:   指向s的指?BR>参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>
int main()
{
  char *string="abcdefghijklmnopqrstuvwxyz";
  char letter='x';
  printf("string before strnset: %s",string);
  strnset(string,letter,13);
  printf("string after strnset: %s",string);
  return 0;
}


@函数名称:   strset
函数原型:   char *strset(char *s, int ch)
函数功能:   字W串s中所有字W设|ؓch的?BR>函数q回:   指向s的指?
参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>
int main()
{
  char string[10]="123456789";
  char symbol='c';
  printf("Before strset(): %s", string);
  strset(string, symbol);
  printf("After strset(): %s", string);
  return 0;
}


@函数名称:   strtok
函数原型:   char *strtok(char *s1, const char *s2)
函数功能:   分解s1字符串ؓ用特定分隔符分隔的多个字W串(一般用于将英文句分解ؓ单词)
函数q回:   字符串s1中首ơ出现s2中的字符前的子字W串指针
参数说明:   s2一般设|ؓs1中的分隔字符
        规定q行子调用时Q即分割s1的第二、三及后l子ԌW一参数必须是NULL
        在每一ơ匹配成功后Q将s1中分割出的子串位|替换ؓNULL(摘下链中W一个环)Q因此s1被破坏了
        函数会记忆指针位|以供下一ơ调?BR>       
所属文?   <string.h>

#include <string.h>
#include <stdio.h>
int main()
{
  char *p;
  char *buffer;
  char *delims={ " .," };

  buffer=strdup("Find words, all of them.");
  printf("%s\n",buffer);
  p=strtok(buffer,delims);
  while(p!=NULL){
    printf("word: %s\n",p);
    p=strtok(NULL,delims);
  }
  printf("%s\n",buffer);
  return 0;
}


@函数名称:   strupr
函数原型:   char *strupr(char *s)
函数功能:   字W串s中的字符变ؓ大写
函数q回:
参数说明:
所属文?   <string.h>

#include <stdio.h>
#include <string.h>
int main()
{
  char *string="abcdefghijklmnopqrstuvwxyz",*ptr;
  ptr=strupr(string);
  printf("%s",ptr);
  return 0;
}


@函数名称:   strlwr
函数原型:   char *strlwr(char *s)
函数功能:   字W串中的字符变ؓ写字符
函数q回:   指向s的指?BR>参数说明:
所属文?   <string.h>

#include<string.h>
int main()
{
  char str[]="HOW TO SAY?";
  printf("%s",strlwr(str));
  return 0;
}


@函数名称:   strlen
函数原型:   unsigned int strlen(char * str);
函数功能:   l计字符串str中字W的个数(不包括终止符'\0')
函数q回:   q回字符串的长度.
参数说明:
所属文?   <string.h>

#include <stdio.h>
#include<string.h>
int main()
{
  char str[]="how are you!";
  printf("the lence is:%d\n",strlen(str));
  return 0;
}


@函数名称:   strerror
函数原型:   char *strerror(int errnum)
函数功能:   得到错误信息的内容信?BR>函数q回:   错误提示信息字符串指?BR>参数说明:   errnum-错误~号
所属文?   <string.h>

#include <stdio.h>
#include <errno.h>
int main()
{
  char *buffer;
  buffer=strerror(errno);
  printf("Error: %s",buffer);
  return 0;
}


@函数名称:   memcpy
函数原型:   void *memcpy(void *dest, const void *src, size_t n)
函数功能:   字符串拷?BR>函数q回:   指向dest的指?BR>参数说明:   src-源字W串Qn-拯的最大长?BR>所属文?   <string.h>,<mem.h>

#include <stdio.h>
#include <string.h>
int main()
{
  char src[]="******************************";
  char dest[]="abcdefghijlkmnopqrstuvwxyz0123456709";
  char *ptr;
  printf("destination before memcpy:%s\n",dest);
  ptr=memcpy(dest,src,strlen(src));
  if (ptr)
    printf("destination after memcpy:%s\n",dest);
  else
    printf("memcpy failed");
  return 0;
}


@函数名称:   memccpy
函数原型:   void *memccpy(void *dest, const void *src, int c, size_t n)
函数功能:   字符串拷贝,到指定长度或遇到指定字符时停止拷?BR>函数q回:
参数说明:   src-源字W串指针Qc-中止拯查字W,n-长度,dest-拯底目的字W串指针
所属文?   <string.h>,<mem.h>

#include <string.h>
#include <stdio.h>
int main()
{
  char *src="This is the source string";
  char dest[50];
  char *ptr;
  ptr=memccpy(dest,src,'c',strlen(src));
  if (ptr)
  {
    *ptr='\0';
    printf("The character was found:%s",dest);
  }
  else
    printf("The character wasn't found");
  return 0;
}


@函数名称:   memchr
函数原型:   void *memchr(const void *s, int c, size_t n)
函数功能:   在字W串中第开始n个字W中L某个字符c的位|?BR>函数q回:   q回c的位|指针,q回NULL时表C未扑ֈ
参数说明:   s-要搜索的字符Ԍc-要寻扄字符Qn-指定长度
所属文?   <string.h>,<mem.h>

#include <string.h>
#include <stdio.h>
int main()
{
  char str[17];
  char *ptr;
  strcpy(str,"This is a string");
  ptr=memchr(str,'r',strlen(str));
  if (ptr)
  printf("The character 'r' is at position: %d",ptr-str);
  else
  printf("The character was not found");
  return 0;
}


@函数名称:   memcmp
函数原型:   int memcmp(const void *s1, const void *s2,size_t n)
函数功能:   按字兔R序比较两个串s1和s2的前n个字?
函数q回:   <0,=0,>0分别表示s1<,=,>s2
参数说明:   s1,s2-要比较的字符Ԍn-比较的长?BR>所属文?   <string.h>,<mem.h>

#include <stdio.h>
#include <string.h>
int main()
{
  char *buf1="ABCDE123";
  char *buf2="abcde456";
  int stat;
  stat=memcmp(buf1,buf2,5);
  printf("The strings to position 5 are ");
  if(stat) printf("not ");
  printf("the same\n");
  return 0;
}



@函数名称:   memicmp
函数原型:   int memicmp(const void *s1, const void *s2, size_t n)
函数功能:   按字兔R序、不考虑字母大小写对字符串s1,s2前n个字W比?BR>函数q回:   <0,=0,>0分别表示s1<,=,>s2
参数说明:   s1,s2-要比较的字符Ԍn-比较的长?BR>所属文?   <string.h>,<mem.h>

#include <stdio.h>
#include <string.h>
int main()
{
  char *buf1="ABCDE123";
  char *buf2="abcde456";
  int stat;
  stat=memicmp(buf1,buf2,5);
  printf("The strings to position 5 are ");
  if(stat) printf("not");
  printf("the same");
  return 0;
}


@函数名称:   memmove
函数原型:   void *memmove(void *dest, const void *src, size_t n)
函数功能:   字符串拷?BR>函数q回:   指向dest的指?BR>参数说明:   src-源字W串Qn-拯的最大长?BR>所属文?   <string.h>,<mem.h>

#include <string.h>
#include <stdio.h>
int main()
{
  char dest[40]="abcdefghijklmnopqrstuvwxyz0123456789";
  printf("destination prior to memmove:%s\n",dest);
  memmove(dest+1,dest,35);
  printf("destination after memmove:%s",dest);
  return 0;
}


@函数名称:   memset
函数原型:   void *memset(void *s, int c, size_t n)
函数功能:   字符串中的n个字节内容设|ؓc
函数q回:
参数说明:   s-要设|的字符Ԍc-讄的内容,n-长度
所属文?   <string.h>,<mem.h>

#include <string.h>
#include <stdio.h>
#include <mem.h>
int main()
{
  char buffer[]="Hello world";
  printf("Buffer before memset:%s\n",buffer);
  memset(buffer,'*',strlen(buffer)-1);
  printf("Buffer after memset:%s",buffer);
  return 0;
}



]]>
C++字符串完全指?转蝲)http://m.tkk7.com/neumqp/archive/2006/03/09/34504.html铁?/dc:creator>铁?/author>Thu, 09 Mar 2006 08:52:00 GMThttp://m.tkk7.com/neumqp/archive/2006/03/09/34504.htmlhttp://m.tkk7.com/neumqp/comments/34504.htmlhttp://m.tkk7.com/neumqp/archive/2006/03/09/34504.html#Feedback3http://m.tkk7.com/neumqp/comments/commentRss/34504.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/34504.htmlC++字符串完全指?- Win32字符~码Q一Q?BR>

前言

字符串的表现形式各异Q象TCHARQstd::stringQBSTR{等Q有时还会见到怪怪的用_tcs起头的宏。这个指南的目的是说明各种字符串类型及其用途,q说明如何在必要时进行类型的怺转换?/P>

在指南的W一部分Q介l三U字W编码格式。理解编码的工作原理是致为重要的。即使你已经知道字符串是一个字W的数组q样的概念,也请阅读本文Q它会让你明白各U字W串cM间的关系?/P>

指南的第二部分,阐q各个字W串c,什么时候用哪U字W串c,及其怺转换?/P>

字符串基 - ASCII, DBCS, Unicode

所有的字符串类都v源于C语言的字W串Q而C语言字符串则是字W的数组。首先了解一下字W类型。有三种~码方式和三U字W类型?/P>

W一U编码方式是单字节字W集Q称之ؓSBCSQ它的所有字W都只有一个字节的长度。ASCII码就是SBCS。SBCS字符串由一个零字节l尾?/P>

W二U编码方式是多字节字W集Q称之ؓMBCSQ它包含的字W中有单字节长的字符Q也有多字节长的字符。Windows用到的MBCS只有二种字符cdQ单字节字符和双字节字符。因此Windows中用得最多的字符是双字节字符集,即DBCSQ通常用它来代替MBCS?/P>

在DBCS~码中,用一些保留值来指明该字W属于双字节字符。例如,Shift-JIS(通用日语)~码中,?x81-0x9F ?0xE0-0xFC 的意思是Q“这是一个双字节字符Q下一个字节是q个字符的一部分”。这L值通常UCؓ前导字节(lead byte)QL大于0x7F。前导字节后面是跟随字节(trail byte)。DBCS的跟随字节可以是M非零倹{与SBCS一PDBCS字符串也׃个零字节l尾?/P>

W三U编码方式是Unicode。Unicode~码标准中的所有字W都是双字节ѝ有时也UnicodeUCؓ宽字W集(wide characters)Q因为它的字W比单字节字W更?使用更多内存)。注意,Unicode不是MBCS - 区别在于MBCS~码中的字符长度是不同的。Unicode字符串用二个零字节字W结?一个宽字符的零值编??/P>

单字节字W集是拉丁字母,重音文字Q用ASCII标准定义Q用于DOS操作pȝ。双字节字符集用于东亚和中东语言。Unicode用于COM和Windows NT内部?/P>

读者都很熟悉单字节字符集,它的数据cd是char。双字节字符集也使用char数据cd(双字节字W集中的许多古怪处之一)。Unicode字符集用wchar_t数据cd。Unicode字符串用L前缀起头Q如Q?/P>

  wchar_t  wch = L'1';      // 2 个字? 0x0031

  wchar_t* wsz = L"Hello";  // 12 个字? 6 个宽字符

字符串的存储

单字节字W串序存放各个字符Qƈ用零字节表示字符串结。例如,字符?Bob"的存储格式ؓQ?/P>

Unicode~码中,L"Bob"的存储格式ؓQ?/P>

?x0000 (Unicode的零~码)l束字符丌Ӏ?/P>

DBCS 看上L点象SBCS。以后我们会看到在串处理和指针用上是有微妙差别的。字W串"日本? (nihongo) 的存储格式如?用LB和TB分别表示前导字节和跟随字?Q?/P>

注意Q?ni"的g是WORD?xFA93。?3和FA序l合~码为字W?ni"?在高位优先CPU中,存放序正如上所q??/P>

字符串处理函?/B>

C语言字符串处理函敎ͼ如strcpy(), sprintf(), atol(){只能用于单字节字符丌Ӏ在标准库中有只用于Unicode字符串的函数Q如wcscpy(), swprintf(), _wtol()?/P>

微Y在Cq行?CRT)中加入了对DBCS字符串的支持。对应于strxxx()函数QDBCS使用_mbsxxx()函数。在处理DBCS字符?如日语,中文Q或其它DBCS)Ӟp用_mbsxxx()函数。这些函C能用于处理SBCS字符?因ؓDBCS字符串可能就只含有单字节字符)?/P>

现在用一个示例来说明字符串处理函数的不同。如有Unicode字符串L"Bob"Q?/P>

x86 CPU的排列顺序是低位优先(little-endian)的,?x0042的存储顺序ؓ42 00。这时如用strlen()函数求字W串的长度就发生问题。函数找到第一个字?2Q然后是00Q意味着字符串结,于是q回1。反之,用wcslen()函数?Bob"的长度更p糕。wcslen()首先扑ֈ0x6F42Q然后是0x0062Q以后就在内存缓冲内不断地寻?0 00直至发生一般性保护错(GPF)?/P>

strxxx()及其对应的_mbsxxx()I竟是如何运作的Q二者之间的不同是非帔R要的Q直接媄响到正确遍历DBCS字符串的Ҏ。下面先介绍字符串遍历,然后再回来讨论strxxx()?_mbsxxx()?/P>

字符串遍?/B>

我们中的大多Ch都是从SBCS成长q来的,都习惯于用指针的 ++ ?-- 操作W来遍历字符Ԍ有时也用数l来处理字符串中的字W。这二种Ҏ对于SBCS ?Unicode 字符串的操作都是正确无误的,因ؓ二者的字符都是{长的,~译器能够的正确q回我们L的字W位|?/P>

但对于DBCS字符串就不能q样了。用指针讉KDBCS字符串有二个原则Q打破这二个原则׃造成错误?/P>

1. 不可使用 ++ 子Q除非每ơ都查是否ؓ前导字节?/P>

2. l不可?-- 子来向后遍历?/P>

先说明原?Q因为很Ҏ扑ֈ一个非Zؓ的示例。假设,有一个配制文ӞE序启动时要从安装\径读取该文gQ如QC:\Program Files\MyCoolApp\config.bin。文件本w是正常的?/P>

假设用以下代码来配制文g名:

bool GetConfigFileName ( char* pszName, size_t nBuffSize )
{
char szConfigFilename[MAX_PATH];
    // q里从注册表d文g的安装\径,假设一切正常?/FONT>
    // 如果路径末尾没有反斜U,加上反斜线?/FONT>
    // 首先Q用指针指向l尾Ӟ
char* pLastChar = strchr ( szConfigFilename, '\0' );
    // 然后向后退一个字W:
    pLastChar--;  
    if ( *pLastChar != '\\' )
        strcat ( szConfigFilename, "\\" );
    // 加上文g名:
    strcat ( szConfigFilename, "config.bin" );
    // 如果字符串长度够,q回文g名:
    if ( strlen ( szConfigFilename ) >= nBuffSize )
        return false;
    else
        {
        strcpy ( pszName, szConfigFilename );
        return true;
        }
}

q段代码的保护性是很强的,但用到DBCS字符串还是会出错。假如文件的安装路径用日语表达:C:\ヨウユソQ该字符串的内存表达为:

q时用上面的GetConfigFileName()函数来检查文件\径末是否含有反斜线׃出错Q得到错误的文g名?BR>
错在哪里Q注意上面的二个十六q制?x5C(蓝色)。前面的0x5C是字W?\"Q后面则是字W?3 5CQ代表字W??。可是函数把它误认ؓ反斜U了?/P>

正确的方法是用DBCS函数指针指向恰当的字符位置Q如下所C:

bool FixedGetConfigFileName ( char* pszName, size_t nBuffSize )
{
char szConfigFilename[MAX_PATH];
    // q里从注册表d文g的安装\径,假设一切正常?/FONT>
    // 如果路径末尾没有反斜U,加上反斜线?/FONT>
    // 首先Q用指针指向l尾Ӟ
char* pLastChar = _mbschr ( szConfigFilename, '\0' );
    // 然后向后退一个双字节字符Q?/FONT>
    pLastChar = CharPrev ( szConfigFilename, pLastChar );
    if ( *pLastChar != '\\' )
        _mbscat ( szConfigFilename, "\\" );
    // 加上文g名:
    _mbscat ( szConfigFilename, "config.bin" );
    // 如果字符串长度够,q回文g名:
    if ( _mbslen ( szInstallDir ) >= nBuffSize )
        return false;
    else
        {
        _mbscpy ( pszName, szConfigFilename );
        return true;
        }
} 

q个改进的函数用CharPrev() API 函数指针pLastChar向后Ud一个字W。如果字W串末尾的字W是双字节字W,向后移?个字节。这时返回的l果是正的Q因Z会将字符误判为反斜线?/P>

现在可以惛_到第一原则了。例如,要遍历字W串L字符":"Q如果不使用CharNext()函数而?+子Q当跟随字节值恰好也?:"时就会出错?/P>

与原?相关的是数组下标的用:

 2a. l不可在字符串数l中使用递减下标?/P>

出错原因与原?相同。例如,讄指针pLastChar为:

char* pLastChar = &szConfigFilename [strlen(szConfigFilename) - 1];

l果与原?的出错一栗下标减1是指针向后Ud一个字节,不符原则2?/P>

再谈strxxx() ?/B>_mbsxxx()

现在可以清楚Z么要?_mbsxxx() 函数了。strxxx() 函数不认识DBCS字符?_mbsxxx()认识。如果调用strrchr("C:\\", '\\')函数可能会出错,?_mbsrchr()认识双字节字W,所以能q回指向最后出现反斜线字符的指针位|?/P>

最后提一下strxxx() ?_mbsxxx() 函数族中的字W串长度量函数Q它们都q回字符串的字节数。如果字W串含有3个双字节字符Q_mbslen()返?。而Unicode的函数返回的是wchar_ts的数量,如wcslen(L"Bob") q回3

C++字符串完全指?- Win32字符~码Q二Q?BR>译Q连?
15/11/2002
URL: http://www.zdnet.com.cn/developer/tech/story/0,2000081602,39098306,00.htm

Win32 API中的MBCS ?/B> Unicode

API的二个字W集

也许你没有注意到QWin32的API和消息中的字W串处理函数有二U,一UؓMCBS字符Ԍ另一UؓUnicode字符丌Ӏ例如,Win32中没有SetWindowText()q样的接口,而是用SetWindowTextA()?SetWindowTextW()函数。后~A (表示ANSI)指明是MBCS函数Q后~W(表示宽字W?指明是Unicode函数?/P>

~写WindowsE序Ӟ可以选择用MBCS或Unicode API接口函数。用VC AppWizards向导Ӟ如果不修攚w处理器设|,~省使用的是MBCS函数。但是在API接口中没有SetWindowText()函数Q该如何调用呢?实际上,在winuser.h头文件中做了以下定义Q?/P>

BOOL WINAPI SetWindowTextA ( HWND hWnd, LPCSTR lpString );
BOOL WINAPI SetWindowTextW ( HWND hWnd, LPCWSTR lpString );
#ifdef UNICODE
 #define SetWindowText  SetWindowTextW
#else
 #define SetWindowText  SetWindowTextA
#endif

~写MBCS应用Ӟ不必定义UNICODEQ预处理为:

#define SetWindowText  SetWindowTextA

然后SetWindowText()处理为真正的API接口函数SetWindowTextA() (如果愿意的话Q可以直接调用SetWindowTextA() 或SetWindowTextW()函数Q不q很有此需??/P>

如果要将~省应用接口改ؓUnicodeQ就到预处理讄的预处理标记中去?_MBCS标记Q加入UNICODE ?_UNICODE (二个标记都要加入Q不同的头文件用不同的标记)。不q,q时要处理普通字W串反而会遇到问题。如有代码:

HWND hwnd = GetSomeWindowHandle();
char szNewText[] = "we love Bob!";
SetWindowText ( hwnd, szNewText );

~译器将"SetWindowText"|换?SetWindowTextW"后,代码变ؓQ?/P>

HWND hwnd = GetSomeWindowHandle();
char szNewText[] = "we love Bob!";
SetWindowTextW ( hwnd, szNewText );

看出问题了吧Q这里用一个Unicode字符串处理函数来处理单字节字W串?/P>

W一U解军_法是使用宏定义:
HWND hwnd = GetSomeWindowHandle();
#ifdef UNICODE
 wchar_t szNewText[] = L"we love Bob!";
#else
 char szNewText[] = "we love Bob!";
#endif
SetWindowText ( hwnd, szNewText );

要对每一个字W串都做q样的宏定义昄是o人头痛的。所以用TCHAR来解册个问题:

TCHAR的救火角?/H5>

TCHAR 是一U字W类型,适用于MBCS ?Unicode二种~码。程序中也不必到处用宏定义?/P>

TCHAR的宏定义如下Q?/P>

#ifdef UNICODE
 typedef wchar_t TCHAR;
#else
 typedef char TCHAR;
#endif

所以,TCHAR中在MBCSE序中是charcdQ在Unicode中是 wchar_t cd?/P>

对于Unicode字符Ԍq有?_T() 宏,用于解决 L 前缀Q?/P>

#ifdef UNICODE
 #define _T(x) L##x
#else
 #define _T(x) x
#endif

## 是预处理子Q将二个变量_脓在一赗不什么时候都对字W串?_T 宏处理,q样可以在Unicode~码中给字符串加上L前缀Q如Q?/P>

TCHAR szNewText[] = _T("we love Bob!");

SetWindowTextA/W 函数族中q有其它隐藏的宏可以用来代替strxxx() ?_mbsxxx() 字符串函数。例如,可以?_tcsrchr 宏取代strrchr()Q_mbsrchr()Q或 wcsrchr()函数。_tcsrchr Ҏ~码标记为_MBCS ?UNICODEQ将叛_函数做相应的扩展处理。宏定义ҎcM于SetWindowText?/P>

不止strxxx()函数族中有TCHAR宏定义,其它一些函C也有。例如,_stprintf (取代sprintf()和swprintf())Q和 _tfopen (取代fopen() ?_wfopen())。MSDN的全部宏定义?Generic-Text Routine Mappings"栏目下?/P>

String ?TCHAR cd定义

Win32 API 文g中列出的函数名都是通用??SetWindowText")Q所有的字符串都按照TCHARcd处理?只有XP除外QXP只用Unicodecd)。下面是MSDNl出的常用类型定义:

 

cd

MBCS ~码中的意义

Unicode ~码中的意义

WCHAR

wchar_t

wchar_t

LPSTR

zero-terminated string of char (char)

zero-terminated string of char (char)

LPCSTR

constant zero-terminated string of char (constchar)

constant zero-terminated string of char (constchar)

LPWSTR

zero-terminated Unicode string ()

zero-terminated Unicode string ()

LPCWSTR

constant zero-terminated Unicode string (const)

constant zero-terminated Unicode string (const)

TCHAR

char

wchar_t

LPTSTR

zero-terminated string of ()

zero-terminated string of ()

LPCTSTR

constant zero-terminated string of (const)

constant zero-terminated string of (const)

何时使用TCHAR 和Unicode

可能会有疑问Q“ؓ什么要用UnicodeQ我一直用的都是普通字W串。?/P>

在三U情况下要用到UnicodeQ?/P>

  1. E序只运行于Windows NT?/DIV>
  2. 处理的字W串长于MAX_PATH定义的字W数?
  3. E序用于Windows XP中的新接口,那里没有A/W版本之分?

大部分Unicode API不可用于Windows 9x。所以如果程序要在Windows 9x上运行的话,要强制用MBCS API (微Y推出一个可q行于Windows 9x的新库,叫做Microsoft Layer for Unicode。但我没有试用过Q无法说明它的好?。相反,NT内部全部使用Unicode~码Q用Unicode API可以加速程序运行。每当将字符串处理ؓMBCS APIӞ操作pȝ都会字W串转换为Unicodeq调用相应的Unicode API 函数。对于返回的字符Ԍ操作pȝ要做同样的{换。尽这些{换经q了高度优化Q模块尽可能地压~到最,但毕竟会影响到程序的q行速度?/P>

NT允许使用长文g?长于MAX_PATH 定义?60)Q但只限于Unicode API使用。Unicode API的另外一个优ҎE序能够自动处理输入的文字语a。用户可以؜合输入英文,中文和日文作为文件名。不必用其它代码来处理Q都按照Unicode~码方式处理?/P>

最后,作ؓWindows 9x的结局Q微软似乎抛弃了MBCS API。例如,SetWindowTheme() 接口函数的二个参数只支持Unicode~码。用Unicode~码省却了MBCS与Unicode之间的{换过E?/P>

如果E序中还没有使用到Unicode~码Q要坚持使用TCHAR和相应的宏。这样不但可以长期保持程序中DBCS~码的安全性,也利于将来扩展用到Unicode~码。那时只要改变预处理中的讄卛_Q?BR>
C++字符串完全指?2) - 各种字符串类Q一Q?BR>译Q连?
19/11/2002
URL: http://www.zdnet.com.cn/developer/tech/story/0,2000081602,39098621,00.htm

前言

C语言的字W串Ҏ出错Q难以管理,q且往往是黑客到处寻扄目标。于是,出现了许多字W串包装cR可惜,Zq不很清楚什么情况下该用哪个c,也不清楚如何C语言字符串{换到包装cR?/P>

本文涉及到Win32 APIQMFCQSTLQWTL和Visual C++q行库中使用到的所有的字符串类型。说明各个类的用法,如何构造对象,如何q行c{换等{。Nish为本文提供了Visual C++ 7的managed string cȝ用法?/P>

阅读本文之前Q应完全理解本指南第一部分中阐q的字符cd和编码?/P>

字符串类的首要原则:

不要随便使用cd强制转换Q除非{换的cd是明由文档规定的?/P>

之所以撰写字W串指南q二文章,是因为常有h问到如何Xcd的字W串转换到Zcd。提问者用了强制cd转换(cast)Q但不知道ؓ什么不能{换成功。各U各L字符串类型,特别是BSTRQ在M场合都不是三a二语可以讲清的。因此,我以些提问者是惌强制cd转换来处理一切?/P>

除非明确规定了{换算子,不要Q何其它类型数据强制{换ؓstring。一个字W串不能用强制类型{换到stringcR例如:

void SomeFunc ( LPCWSTR widestr );
main()
{
  SomeFunc ( (LPCWSTR) "C:\\foo.txt" );  // 错!
}

q段代码100%错误。它可以通过~译Q因为类型强制{换超了~译器的cd验。但是,能够通过~译Qƈ不证明代码是正确的?/P>

下面Q我指Z么时候用cd强制转换是合理的?BR>C语言字符串与cd定义

如指南的W一部分所qͼWindows API定义了TCHAR术语。它可用于MBCS或Unicode~码字符Q取决于预处理设|ؓ_MBCS ?_UNICODE标记。关于TCHAR的详l说明请阅指南的W一部分。ؓ便于叙述Q下面给出字W类型定义:

Type

Meaning

WCHAR

Unicode character ()

TCHAR

MBCS or Unicode character, depending on preprocessor settings

LPSTR

string of char (char)

LPCSTR

constant string of char (constchar)

LPWSTR

string of ()

LPCWSTR

constant string of (const)

LPTSTR

string of ()

LPCTSTR

constant string of (const)

另外q有一个字W类型OLECHAR。这是一U对象链接与嵌入的数据类?比如嵌入Word文档)。这个类型通常定义为wchar_t。如果将预处理设|定义ؓOLE2ANSIQOLECHAR被定义为charcd。现在已l不再定义OLE2ANSI(它只在MFC 3以前版本中?Q所以我OLECHAR作ؓUnicode字符处理?/P>

下面是与OLECHAR相关的类型定义:

Type

Meaning

OLECHAR

Unicode character ()

LPOLESTR

string of ()

LPCOLESTR

constant string of (const)

q有以下二个宏让相同的代码能够适用于MBCS和Unicode~码Q?/P>

Type

Meaning

_T(x)

Prepends to the literal in Unicode builds.

OLESTR(x)

Prepends to the literal to make it an .

宏_T有几UŞ式,功能都相同。如Q?-- TEXT, _TEXT, __TEXT, ?__Tq四U宏的功能相同?/P>

COM中的字符?/B> - BSTR ?/B> VARIANT

许多COM接口使用BSTR声明字符丌ӀBSTR有一些缺P所以我在这里让它独立成章?/P>

BSTR是Pascalcd字符?字符串长度值显式地与数据存攑֜一?和Ccd字符?字符串长度必通过L到结N字符来计?的؜合型字符丌ӀBSTR属于Unicode字符Ԍ字符串中预置了字W串长度|q且用一个零字符来结。下面是一?Bob"的BSTR字符Ԍ

注意Q字W串长度值是一个DWORDcd|l出字符串的字节长度Q但不包括结N。在上例Q?Bob"含有3个Unicode字符(不计l尾?Q?个字节长。因为明给Z字符串长度,所以当BSTR数据在不同的处理器和计算Z间传送时QCOM库能够知道应该传送的数据量?/P>

附带说一下,BSTR可以包含M数据块,不单是字W。它甚至可以包容内嵌零字W数据。这些不在本文讨围?/P>

C++中的BSTR变量其实是指向字符串首字符的指针。BSTR是这样定义的Q?/P>

typedef OLECHAR* BSTR;

q个定义很糟p,因ؓ事实上BSTR与Unicode字符串不一栗有了这个类型定义,pq了cd查,可以混合使用LPOLESTR和BSTR。向一个需要LPCOLESTR (?LPCWSTR)cd数据的函C递BSTR数据是安全的Q反之则不然。所以要清楚了解函数所需的字W串cdQƈ向函C递正类型的字符丌Ӏ?/P>

要知道ؓ什么向一个需要BSTRcd数据的函C递LPCWSTRcd数据是不安全的,别忘了BSTR必须在字W串开头的四个字节保留字符串长度倹{但LPCWSTR字符串中没有q个倹{当其它的处理过E?如Word)要寻找BSTR的长度值时׃扑ֈ一堆垃圾或堆栈中的其它数据或其它随机数据。这导致方法失效,当长度值太大时导致崩溃?/P>

许多应用接口都用BSTRQ但都用C个最重要的函数来构造和析构BSTR。就是SysAllocString()和SysFreeString()函数。SysAllocString()Unicode字符串拷贝到BSTRQSysFreeString()释放BSTR。示例如下:

BSTR bstr = NULL;
bstr = SysAllocString ( L"Hi Bob!" );
if ( NULL == bstr )
    // 内存溢出
   // q里使用bstr
SysFreeString ( bstr );

当然Q各UBSTR包装c都会小心地理内存?/P>

自动接口中的另一个数据类型是VARIANT。它用于在无cd语言Q诸如JScriptQVBScriptQ以及Visual BasicQ之间传递数据。VARIANT可以包容许多不用cd的数据,如long和IDispatch*。如果VARIANT包含一个字W串Q这个字W串是BSTRcd。在下文的VARIANT包装cM我还会谈及更多的VARIANT?BR>C++字符串完全指?2) - 各种字符串类- CRTc?BR>译Q连?
20/11/2002
URL: http://www.zdnet.com.cn/developer/tech/story/0,2000081602,39098682,00.htm

_bstr_t

字符串包装类

我已l说明了字符串的各种cdQ现在讨论包装类。对于每个包装类Q我都会说明它的对象构造过E和如何转换成Ccd字符串指针。应用接口的调用Q或构造另一个不同类型的字符串类Q大多都要用到Ccd指针。本文不涉及cȝ其它操作Q如排序和比较等?/P>

再强调一下,在完全了解{换结果之前不要随意用强制类型{换?/P>

CRTc?/H5>

_bstr_t

_bstr_t 是BSTR的完全包装类。实际上Q它隐含了BSTR。它提供多种构造函敎ͼ能够处理隐含的Ccd字符丌Ӏ但它本w却不提供BSTR的处理机Ӟ所以不能作为COMҎ的输出参数[out]。如果要用到BSTR* cd数据Q用ATL的CComBSTRcL为方ѝ?/P>

_bstr_t 数据可以传递给需要BSTR数据的函敎ͼ但必L以下三个条Ӟ

首先Q_bstr_t h能够转换为wchar_t*cd数据的函数?/P>

其次Q根据BSTR定义Q得wchar_t* 和BSTR对于~译器来说是相同的?/P>

W三Q_bstr_t内部保留的指向内存数据块的指?wchar_t* 要遵循BSTR格式?/P>

满q些条gQ即使没有相应的BSTR转换文档Q_bstr_t 也能正常工作。示例如下:

 // 构?/FONT>
_bstr_t bs1 = "char string";        // 从LPCSTR构?/FONT> 
_bstr_t bs2 = L"wide char string"; // 从LPCWSTR构?/FONT>
_bstr_t bs3 = bs1;              // 拯另一?_bstr_t
_variant_t v = "Bob";
_bstr_t bs4 = v;              // 从一个含有字W串?_variant_t 构?/FONT>
// 数据萃取
LPCSTR psz1 = bs1;              // 自动转换到MBCS字符?/FONT>
LPCSTR psz2 = (LPCSTR) bs1;     // cast OK, 同上
LPCWSTR pwsz1 = bs1;            // q回内部的Unicode字符?/FONT>
LPCWSTR pwsz2 = (LPCWSTR) bs1;  // cast OK, 同上
BSTR    bstr = bs1.copy();      // 拯bs1, q回BSTR
// ...
  SysFreeString ( bstr );

注意Q_bstr_t 也可以{换ؓchar* ?wchar_t*。这是个设计问题。虽然char* ?wchar_t*不是帔R指针Q但不能用于修改字符Ԍ因ؓ可能会打破内部BSTRl构?/P>

_variant_t
_variant_t

_variant_t 是VARIANT的完全包装类。它提供多种构造函数和数据转换函数。本文仅讨论与字W串有关的操作?/P>

// 构?/FONT>
_variant_t v1 = "char string"; // 从LPCSTR 构?/FONT>
_variant_t v2 = L"wide char string"; // 从LPCWSTR 构?/FONT>
_bstr_t bs1 = "Bob";
_variant_t v3 = bs1; // 拯一?_bstr_t 对象
// 数据萃取
_bstr_t bs2 = v1; // 从VARIANT中提取BSTR
_bstr_t bs3 = (_bstr_t) v1; // cast OK, 同上

注意Q_variant_t Ҏ在{换失败时会抛出异常,所以要准备用catch 捕捉_com_error异常?/P>

另外要注?_variant_t 不能直接转换成MBCS字符丌Ӏ要建立一个过渡的_bstr_t 变量Q用其它提供转换Unicode到MBCS的类函数Q或ATL转换宏来转换?/P>

与_bstr_t 不同Q_variant_t 数据可以作ؓ参数直接传送给COMҎ。_variant_t l承了VARIANTcdQ所以在需要用VARIANT的地方用_variant_t 是C++语言规则允许的?BR>C++字符串完全指?2) - STL和ATLc?BR>译Q连?
21/11/2002
URL: http://www.zdnet.com.cn/developer/tech/story/0,2000081602,39098845,00.htm

STLc?/FONT>

STLc?/H5>

STL只有一个字W串c,即basic_string。basic_string理一个零l尾的字W数l。字W类型由模板参数军_。通常Qbasic_string被处理ؓ不透明对象。可以获得一个只L针来讉K~冲区,但写操作都是由basic_string的成员函数进行的?/P>

basic_string预定义了二个特例QstringQ含有charcd字符QwhichQ含有wchar_tcd字符。没有内建的TCHAR特例Q可用下面的代码实现Q?/P>

// 特例?/FONT>
typedef basic_string tstring; // TCHAR字符?/FONT>
// 构?/FONT>
string str = "char string"; // 从LPCSTR构?/FONT>
wstring wstr = L"wide char string"; // 从LPCWSTR构?/FONT>
tstring tstr = _T("TCHAR string"); // 从LPCTSTR构?/FONT>
// 数据萃取
LPCSTR psz = str.c_str(); // 指向str~冲区的只读指针
LPCWSTR pwsz = wstr.c_str(); // 指向wstr~冲区的只读指针
LPCTSTR ptsz = tstr.c_str(); // 指向tstr~冲区的只读指针

与_bstr_t 不同Qbasic_string不能在字W集之间q行转换。但是如果一个构造函数接受相应的字符cdQ可以将由c_str()q回的指针传递给q个构造函数。例如:

// 从basic_string构造_bstr_t 
_bstr_t bs1 = str.c_str();  // 从LPCSTR构?_bstr_t
_bstr_t bs2 = wstr.c_str(); // 从LPCWSTR构?_bstr_t
ATLc?/H5>
CComBSTR

CComBSTR 是ATL的BSTR包装cR某些情况下比_bstr_t 更有用。最主要的是QCComBSTR允许操作隐含BSTR。就是说Q传递一个CComBSTR对象lCOMҎӞCComBSTR对象会自动管理BSTR内存。例如,要调用下面的接口函数Q?/P>

// 单接?/FONT>
struct IStuff : public IUnknown
{
  // 略去COME序...
  STDMETHOD(SetText)(BSTR bsText);
  STDMETHOD(GetText)(BSTR* pbsText);
};

CComBSTR 有一个BSTR操作ҎQ能BSTR直接传递给SetText()。还有一个引用操?operator &)ҎQ返回BSTR*Q将BSTR*传递给需要它的有兛_数?/P>

CComBSTR bs1;
CComBSTR bs2 = "new text";
pStuff->GetText ( &bs1 );       // ok, 取得内部BSTR地址
  pStuff->SetText ( bs2 );        // ok, 调用BSTR转换
  pStuff->SetText ( (BSTR) bs2 ); // cast ok, 同上

CComVariant
CComBSTR有类g _bstr_t 的构造函数。但没有内徏MBCS字符串的转换函数。可以调用ATL宏进行{换?/P>

// 构?/FONT>
CComBSTR bs1 = "char string"; // 从LPCSTR构?/FONT>
CComBSTR bs2 = L"wide char string"; // 从LPCWSTR构?/FONT>
CComBSTR bs3 = bs1; // 拯CComBSTR
CComBSTR bs4;
bs4.LoadString ( IDS_SOME_STR ); // 从字W串表加?/FONT>
// 数据萃取
BSTR bstr1 = bs1; // q回内部BSTRQ但不可修改Q?/FONT>
BSTR bstr2 = (BSTR) bs1; // cast ok, 同上
BSTR bstr3 = bs1.Copy(); // 拯bs1, q回BSTR
BSTR bstr4;
bstr4 = bs1.Detach(); // bs1不再理它的BSTR
// ...
SysFreeString ( bstr3 );
SysFreeString ( bstr4 );

上面的最后一个示例用CDetach()Ҏ。该Ҏ调用后,CComBSTR对象׃再管理它的BSTR或其相应内存。所以bstr4必调用SysFreeString()?/P>

最后讨Z下引用操作符(operator &)。它的超得有些STL集合(如list)不能直接使用CComBSTR。在集合上用引用操作返回指向包容类的指针。但是在CComBSTR上用引用操作,q回的是BSTR*Q不是CComBSTR*。不q可以用ATL的CAdaptcL解决q个问题。例如,要徏立一个CComBSTR的队列,可以声明为:

  std::list< CAdapt> bstr_list;

CAdapt 提供集合所需的操作,是隐含于代码的。这时用bstr_list p在操作一个CComBSTR队列?/P>

CComVariant

CComVariant 是VARIANT的包装类。但?_variant_t 不同Q它的VARIANT不是隐含的,可以直接操作c里的VARIANT成员。CComVariant 提供多种构造函数和多类型操作。这里只介绍与字W串有关的操作?/P>

// 构?/FONT>
CComVariant v1 = "char string";       // 从LPCSTR构?/FONT>
CComVariant v2 = L"wide char string"; // 从LPCWSTR构?/FONT>
CComBSTR bs1 = "BSTR bob";
CComVariant v3 = (BSTR) bs1;          // 从BSTR拯
// 数据萃取
CComBSTR bs2 = v1.bstrVal;            // 从VARIANT提取BSTR

跟_variant_t 不同QCComVariant没有不同VARIANTcd之间的{换操作。必ȝ接操作VARIANT成员Qƈ定该VARIANT的类型无误。调用ChangeType()Ҏ可将CComVariant数据转换为BSTR?/P>

CComVariant v4 = ... // 从某U类型初始化 v4
CComBSTR bs3;
if ( SUCCEEDED( v4.ChangeType ( VT_BSTR ) ))
    bs3 = v4.bstrVal;

?_variant_t 一PCComVariant不能直接转换为MBCS字符丌Ӏ要建立一个过渡的_bstr_t 变量Q用其它提供转换Unicode到MBCS的类函数Q或ATL转换宏来转换?/P>

ATL转换?/FONT>

ATL转换?/H5>

ATL的字W串转换宏可以方便地转换不同~码的字W,用在函数中很有效。宏按照[source type]2[new type] ?[source type]2C[new type]格式命名。后者{换ؓ一个常量指?(名字内含"C")。类型羃写如下:


 AQMBCS字符Ԍchar* (A for ANSI)
 WQUnicode字符Ԍwchar_t* (W for wide)
 TQTCHAR字符ԌTCHAR*
 OLEQOLECHAR字符ԌOLECHAR* (实际{于W)
 BSTRQBSTR (只用于目的类?

例如QW2A() Unicode字符串{换ؓMBCS字符ԌT2CW()TCHAR字符串{换ؓUnicode字符串常量?/P>

要用宏转换Q程序中要包含atlconv.h头文件。可以在非ATLE序中用宏转换Q因为头文g不依赖其它的ATLQ也不需?_Module全局变量。如在函C使用转换宏,在函数v始处先写上USES_CONVERSION宏。它表明某些局部变量由宏控制用?/P>

转换得到的结果字W串Q只要不是BSTRQ都存储在堆栈中。如果要在函数外使用q些字符Ԍp这些字W串拯到其它的字符串类。如果结果是BSTRQ内存不会自动释放,因此必须返回值分配给一个BSTR变量或BSTR的包装类Q以避免内存泄露?/P>

下面是若q宏转换CZQ?/P>

// 带有字符串的函数Q?/FONT>
void Foo ( LPCWSTR wstr );
void Bar ( BSTR bstr );
// q回字符串的函数Q?/FONT>
void Baz ( BSTR* pbstr );
#include 
main()
{
using std::string;
USES_CONVERSION;    // 声明局部变量由宏控制?/FONT>
// CZ1Q送一个MBCS字符串到Foo()
LPCSTR psz1 = "Bob";
string str1 = "Bob";
Foo ( A2CW(psz1) );
  Foo ( A2CW(str1.c_str()) );
// CZ2Q将MBCS字符串和Unicode字符串送到Bar()
LPCSTR psz2 = "Bob";
LPCWSTR wsz = L"Bob";
BSTR bs1;
CComBSTR bs2;
bs1 = A2BSTR(psz2);         // 创徏 BSTR
  bs2.Attach ( W2BSTR(wsz) ); // 同上Q分配到CComBSTR
Bar ( bs1 );
  Bar ( bs2 );
SysFreeString ( bs1 );      // 释放bs1
  // 不必释放bs2Q由CComBSTR释放?/FONT>
// CZ3Q{换由Baz()q回的BSTR
BSTR bs3 = NULL;
string str2;
Baz ( &bs3 );          // Baz() 填充bs3内容
str2 = W2CA(bs3);      // 转换为MBCS字符?/FONT>
  SysFreeString ( bs3 ); // 释放bs3
}

可以看到Q向一个需要某U类型参数的函数传递另一U类型的参数Q用宏{换是非常方便的?BR>C++字符串完全指?2) - MFCc?BR>译Q连?
22/11/2002
URL: http://www.zdnet.com.cn/developer/tech/story/0,2000081602,39098983,00.htm

MFCc?/FONT>

MFCc?/H5>

CString

MFC的CString含有TCHARQ它的实际字W类型取决于预处理标记的讄。通常QCString象STL字符串一h不透明对象Q只能用CString的方法来修改。CString比STL字符串更优越的是它的构造函数接受MBCS和Unicode字符丌Ӏƈ且可以{换ؓLPCTSTRQ因此可以向接受LPCTSTR的函数直接传递CString对象Q不必调用c_str()Ҏ?/P>

// 构?
CString s1 = "char string"; // 从LPCSTR构?
CString s2 = L"wide char string"; // 从LPCWSTR构?
CString s3 ( ' ', 100 ); // 预分?00字节Q填充空?
CString s4 = "New window text";
// 可以在LPCTSTR处用CStringQ?
SetWindowText ( hwndSomeWindow, s4 );
// 或者,昑ּ地做强制cd转换Q?
SetWindowText ( hwndSomeWindow, (LPCTSTR) s4 );

也可以从字符串表加蝲字符丌ӀCString通过LoadString()来构造对象。用Format()Ҏ可有选择C字符串表d一定格式的字符丌Ӏ?/P>

// 从字W串表构?加蝲
CString s5 ( (LPCTSTR) IDS_SOME_STR );  // 从字W串表加?
CString s6, s7;
// 从字W串表加?
  s6.LoadString ( IDS_SOME_STR );
// 从字W串表加载打印格式的字符?
  s7.Format ( IDS_SOME_FORMAT, "bob", nSomeStuff, ... );

W一个构造函数看上去有点怪,但它的确是文档标定的字符串加载方式?/P>

注意QCString只允怸U强制类型{换,卛_制{换ؓLPCTSTR。强制{换ؓLPTSTR (非常量指?是错误的。按照老习惯,CString强制转换为LPTSTR只能伤害自己。有时在E序中没有发现出错,那只是碰巧。{换到非常量指针的正确Ҏ是调用GetBuffer()Ҏ?/P>

下面以往队列加入元素Z说明如何正确C用CStringQ?/P>

CString str = _T("new text");
LVITEM item = {0};
item.mask = LVIF_TEXT;
  item.iItem = 1;
  item.pszText = (LPTSTR)(LPCTSTR) str; // 错!
  item.pszText = str.GetBuffer(0);      // 正确
ListView_SetItem ( &item );
  str.ReleaseBuffer();  // 队列返回给str

pszText成员是LPTSTRQ一个非帔R指针Q因此要用str的GetBuffer()。GetBuffer()的参数是CString分配的最缓冲区。如果要分配一?K的TCHARQ调用GetBuffer(1024)。参Cؓ0Q只q回指向字符串的指针?/P>

上面CZ的出错语句可以通过~译Q甚臛_以正常工作,如果恰好是q个cd。但q不证明语法正确。进行非帔R的强制类型{换,打破了面向对象的装原则Qƈ逾越了CString的内部操作。如果你习惯q行q样的强制类型{换,l会遇到出错Q可你未必知道错在何处,因ؓ你到处都在做q样的{换,而代码也都能q行?/P>

知道Z么h们d抱怨有~陷的Y件吗Q不正确的代码就臭虫的滋生地。然道你愿意~写明知有错的代码让臭虫有机可乘Q还是花些时间学习CString的正用法让你的代码能够100%的正吧?/P>

CStringq有二个函数能够从CString中得到BSTRQƈ在必要时转换成Unicode。那是AllocSysString()和SetSysString()。除了SetSysString()使用BSTR*参数外,二者一栗?/P>

// 转换成BSTR
CString s5 = "Bob!";
BSTR bs1 = NULL, bs2 = NULL;
bs1 = s5.AllocSysString();
  s5.SetSysString ( &bs2 );
// ...
  SysFreeString ( bs1 );
  SysFreeString ( bs2 );

COleVariant 与CComVariant 非常怼。COleVariant l承于VARIANTQ可以传递给需要VARIANT的函数。但又与CComVariant 不同QCOleVariant 只有一个LPCTSTR的构造函敎ͼ不提供单独的LPCSTR和LPCWSTR的构造函数。在大多情况下,没有问题Q因为L愿意把字W串处理为LPCTSTR。但你必ȝ道这炏VCOleVariant 也有接受CString的构造函数?/P>

// 构?
CString s1 = _T("tchar string");
COleVariant v1 = _T("Bob"); // 从LPCTSTR构?
COleVariant v2 = s1; // 从CString拯

对于CComVariantQ必ȝ接处理VARIANT成员Q用ChangeType()Ҏ在必要时其转换为字W串。但是,COleVariant::ChangeType() 在{换失败时会抛出异常,而不是返回HRESULT的出错码?/P>

// 数据萃取
COleVariant v3 = ...; // 从某U类型构造v3
BSTR bs = NULL;
try
    {
    v3.ChangeType ( VT_BSTR );
    bs = v3.bstrVal;
    }
  catch ( COleException* e )
    {
    // 出错Q无法{?
    }
SysFreeString ( bs );

WTLc?/FONT>

WTLc?/H5>

CString

WTL的CString与MFC的CString的行为完全相同,参阅上面关于MFC CString的说明即可?/P>

CLR ?VC 7 c?/H5>

System::String ?NET的字W串cR在其内部,String对象是一个不变的字符序列。Q何操作String对象的StringҎ都返回一个新的String对象Q因为原有的String对象要保持不变。StringcL一个特性,当多个String都指向同一l字W集Ӟ它们其实是指向同一个对象。Managed Extensions C++ 的字W串有一个新的前~SQ用来表明是一个managed string字符丌Ӏ?/P>

// 构?
String* ms = S"This is a nice managed string";

可以用unmanaged string字符串来构造String对象Q但不如用managed string构造String对象有效。原因是所有相同的hS前缀的字W串都指向同一个对象,而unmanaged string没有q个特点。下面的例子可以说明得更清楚些:

String* ms1 = S"this is nice";
String* ms2 = S"this is nice";
String* ms3 = L"this is nice";
Console::WriteLine ( ms1 == ms2 ); // 输出true
Console::WriteLine ( ms1 == ms3);  // 输出false

要与没有S前缀的字W串做比较,用String::CompareTo()Ҏ来实玎ͼ如:

  Console::WriteLine ( ms1->CompareTo(ms2) );
  Console::WriteLine ( ms1->CompareTo(ms3) );

二者都输出0Q说明字W串相等?/P>

在String和MFC 7的CString之间转换很容易。CString可以转换为LPCTSTRQString有接受char* ?wchar_t* 的二U构造函数。因此可以直接把CString传递给String的构造函敎ͼ

  CString s1 ( "hello world" );
  String* s2 ( s1 );  // 从CString拯

反向转换的方法也cMQ?/P>

  String* s1 = S"Three cats";
  CString s2 ( s1 );

可能有点qh。从VS.NET开始,CString有一个接受String对象的构造函敎ͼ所以是正确的?/P>

  CStringT ( System::String* pString );

Z加速操作,有时可以用基字符?underlying string)Q?/P>

String* s1 = S"Three cats";
Console::WriteLine ( s1 );
const __wchar_t __pin* pstr = PtrToStringChars(s1);
for ( int i = 0; i < wcslen(pstr); i++ )
    (*const_cast<__wchar_t*>(pstr+i))++;
Console::WriteLine ( s1 );

PtrToStringChars() q回指向基础字符串的 const __wchar_t* 指针Q可以防止在操作字符串时Q垃圾收集器去除该字W串?BR>C++字符串完全指?2) - ȝ
译Q连?
23/11/2002
URL: http://www.zdnet.com.cn/developer/tech/story/0,2000081602,39099061,00.htm

字符串类的打印格式函?/H5>

对字W串包装cM用printf()或其它类似功能的函数时要特别心。包括sprintf()函数及其变种Q以及TRACE 和ATLTRACE 宏。它们的参数都不做类型检验,一定要l它们传递C语言字符Ԍ而不是整个string对象?/P>

例如Q要向ATLTRACE()传递一个_bstr_t 里的字符Ԍ必须昑ּ?LPCSTR)?(LPCWSTR)q行强制cd转换Q?/P>

  _bstr_t bs = L"Bob!";
  ATLTRACE("The string is: %s in line %d\n", (LPCSTR) bs, nLine);

如果忘了用强制类型{换,直接把整?_bstr_t 对象传递给ATLTRACEQ跟t消息将输出无意义的东西Q因为_bstr_t 变量内的所有数据都q栈了?/P>

所有类的ȝ

常用的字W串cM间的转换Ҏ是:源字符串{换ؓCcd字符串指针,然后该指针传递给目标cȝ构造函数。下面列出将字符串{换ؓCcd指针的方法,以及哪些cȝ构造函数接受Ccd指针?/P>

Class

string
type

convert to char?

convert to constchar?

convert to ?

convert to const?

convert to ?

construct from char?

construct from ?

_bstr_t

BSTR

yes, cast1

yes, cast

yes, cast1

yes, cast

yes2

yes

yes

_variant_t

BSTR

no

no

no

cast to
3

cast to
3

yes

yes

string

MBCS

no

yes, c_str()
method

no

no

no

yes

no

wstring

Unicode

no

no

no

yes, c_str()
method

no

no

yes

CComBSTR

BSTR

no

no

no

yes, cast
to

yes, cast

yes

yes

CComVariant

BSTR

no

no

no

yes4

yes4

yes

yes

CString

TCHAR

no6

in MBCS
builds, cast

no6

in Unicode
builds, cast

no5

yes

yes

COleVariant

BSTR

no

no

no

yes4

yes4

in MBCS builds

in Unicode builds

附注Q?/B>

  1. 虽然 _bstr_t 可以转换为非帔R指针Q但对内部缓冲区的修改可能导致内存溢出,或在释放BSTR时导致内存泄霌Ӏ?/DIV>
  2. bstr_t 的BSTR内含 wchar_t* 变量Q所以可const wchar_t* 转换到BSTR。但q个用法来可能会改变,使用时要心?
  3. 如果转换到BSTRp|Q将抛出异常?
  4. 用ChangeType()处理VARIANT的bstrVal。在MFCQ{换失败将抛出异常?
  5. 虽然没有BSTR的{换函敎ͼ但AllocSysString()可返回一个新的BSTR?
  6. 用GetBuffer()Ҏ可时得C个非帔RTCHAR指针?


]]>
log4j资料http://m.tkk7.com/neumqp/archive/2006/03/09/34478.html铁?/dc:creator>铁?/author>Thu, 09 Mar 2006 07:08:00 GMThttp://m.tkk7.com/neumqp/archive/2006/03/09/34478.htmlhttp://m.tkk7.com/neumqp/comments/34478.htmlhttp://m.tkk7.com/neumqp/archive/2006/03/09/34478.html#Feedback0http://m.tkk7.com/neumqp/comments/commentRss/34478.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/34478.htmlhttp://dev.csdn.net/article/82070.shtm
http://blog.csdn.net/lxblg/archive/2004/09/14/104207.aspx

]]>
Iptables 指南 1.1.19http://m.tkk7.com/neumqp/archive/2006/03/09/34477.html铁?/dc:creator>铁?/author>Thu, 09 Mar 2006 07:07:00 GMThttp://m.tkk7.com/neumqp/archive/2006/03/09/34477.htmlhttp://m.tkk7.com/neumqp/comments/34477.htmlhttp://m.tkk7.com/neumqp/archive/2006/03/09/34477.html#Feedback0http://m.tkk7.com/neumqp/comments/commentRss/34477.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/34477.html阅读全文

]]>
rmi找不到stub问题http://m.tkk7.com/neumqp/archive/2006/03/08/34203.html铁?/dc:creator>铁?/author>Wed, 08 Mar 2006 03:20:00 GMThttp://m.tkk7.com/neumqp/archive/2006/03/08/34203.htmlhttp://m.tkk7.com/neumqp/comments/34203.htmlhttp://m.tkk7.com/neumqp/archive/2006/03/08/34203.html#Feedback0http://m.tkk7.com/neumqp/comments/commentRss/34203.htmlhttp://m.tkk7.com/neumqp/services/trackbacks/34203.html启动server时如果遇到找不到stub问题Q原因是rmiregistry找不到stubQ而不是java com.Server找不到stubQ解x法,在stub的类同一个目录下启动rmiregistry



]]>
վ֩ģ壺 ҹƵվ| ëƬvipԱ߿| ޺ݺۺϾþѿ| ˳ɫ99999߹ۿ| ѾƷԲ߹ۿ | Ļ뱬av| ƷƵ߹ۿ| ۺһ| Ʒ˿һҳ| ɫwwwƷƵѿ| ҹѿƬڵ | ղҹҹƵ | ޾Ʒva߹ۿѿ| ۺϾþϵ| þþþþƷAV| ëƬѹۿȫ| Ʒ˳Ƶapp| ѹۿ| ɫҳѹۿ| ɫĻAV| ޵һ͵Ľ| ҹϼӰԺ| ֻѵAVߵӰ| ۺɫһ| ɫ͵͵ͼۺ| ޾ƷƵ߹ۿ| Ʒһ | ޾Ʒ߹ۿ| jizzjizzƵѿ| þþþþþùѿ| 鶹Ʒѹۿ| ޵Ӱһ| ӰƬ鶹ӰƬѹۿ| ޹Ѽһ| 337Pձŷ޴ͼ | һëƬѲ| ĻӰѹۿ| 99ѹۿ| ձĻ| 뾫Ʒһ | ۺ޾Ʒ|