xiaoxiaoling

C++博客 首页 新随笔 联系 聚合 管理
  17 Posts :: 2 Stories :: 9 Comments :: 0 Trackbacks

#

1)打开资源文件,把LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US修改为
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
2)关闭资源文件
3)打开对话框,输入汉字,并保存
4)右击资源文件属性,选择Resources->General->Culture,设置为:中文(中国) (0x804)
5)编译,测试
posted @ 2008-12-11 17:53 clcl 阅读(369) | 评论 (0)编辑 收藏

前言  
  看到有些人对位运算还存在问题,于是决定写这篇文章作个简要说明。  
   
  什么是位(bit)?  
   
  很简单,位(bit)就是单个的0或1,位是我们在计算机上所作一切的基础。计算机上的所有数据都是用位来存储的。一个字节(BYTE)由八个位组成,一个字(WORD)是二个字节或十六位,一个双字(DWORD)是二个字(WORDS)或三十二位。如下所示:  
   
      0   1   0   0   0   1   1   1   1   0   0   0   0   1   1   1   0   1   1   1   0   1   0   0   0   1   1   1   1   0   0   0  
  |   |                             |                               |                               |                             |   |  
  |   +-   bit   31             |                               |                               |               bit   0   -+   |  
  |                                 |                               |                               |                                 |  
  +--   BYTE   3   ----   -+----   BYTE   2   ---+----   BYTE   1   ---+---   BYTE   0   -----+  
  |                                                                 |                                                                 |  
  +------------   WORD   1   ------------+-----------   WORD   0   -------------+  
  |                                                                                                                                   |  
  +-----------------------------   DWORD   -----------------------------+  
   
  使用位运算的好处是可以将BYTE,   WORD   或   DWORD   作为小数组或结构使用。通过位运算可以检查位的值或赋值,也可以对整组的位进行运算。  
   
  16进制数及其与位的关系  
  用0或1表示的数值就是二进制数,很难理解。因此用到16进制数。  
   
  16进制数用4个位表示0   -   15的值,4个位组成一个16进制数。也把4位成为半字节(nibble)。一个BYTE有二个nibble,因此可以用二个16进制数表示一个BYTE。如下所示:  
   
  NIBBLE       HEX   VALUE  
  ======       =========  
    0000                 0  
    0001                 1  
    0010                 2  
    0011                 3  
    0100                 4  
    0101                 5  
    0110                 6  
    0111                 7  
    1000                 8  
    1001                 9  
    1010                 A  
    1011                 B  
    1100                 C  
    1101                 D  
    1110                 E  
    1111                 F  
   
  如果用一个字节存放字母"r"(ASCII码114),结果是:  
  0111   0010         二进制  
      7         2           16进制  
   
  可以表达为:'0x72'  
   
  有6种位运算:  
        &       与运算  
        |       或运算  
        ^       异或运算  
        ~       非运算(求补)  
      >>       右移运算  
      <<       左移运算  
   
  与运算(&)  
  双目运算。二个位都置位(等于1)时,结果等于1,其它的结果都等于0。  
        1       &       1       ==       1  
        1       &       0       ==       0  
        0       &       1       ==       0  
        0       &       0       ==       0  
   
  与运算的一个用途是检查指定位是否置位(等于1)。例如一个BYTE里有标识位,要检查第4位是否置位,代码如下:  
   
  BYTE   b   =   50;  
  if   (   b   &   0x10   )  
          cout   <<   "Bit   four   is   set"   <<   endl;  
  else  
          cout   <<   "Bit   four   is   clear"   <<   endl;  
   
  上述代码可表示为:  
   
          00110010     -   b  
      &   00010000     -   &   0x10  
    ----------------------------  
          00010000     -   result  
   
  可以看到第4位是置位了。  
   
  或运算(   |   )  
  双目运算。二个位只要有一个位置位,结果就等于1。二个位都为0时,结果为0。  
        1       |       1       ==       1  
        1       |       0       ==       1  
        0       |       1       ==       1  
        0       |       0       ==       0  
   
  与运算也可以用来检查置位。例如要检查某个值的第3位是否置位:  
   
  BYTE   b   =   50;  
  BYTE   c   =   b   |   0x04;  
  cout   <<   "c   =   "   <<   c   <<   endl;  
   
  可表达为:  
   
          00110010     -   b  
      |   00000100     -   |   0x04  
      ----------  
          00110110     -   result  
   
  异或运算(^)  
  双目运算。二个位不相等时,结果为1,否则为0。  
   
        1       ^       1       ==       0  
        1       ^       0       ==       1  
        0       ^       1       ==       1  
        0       ^       0       ==       0  
   
  异或运算可用于位值翻转。例如将第3位与第4位的值翻转:  
   
  BYTE   b   =   50;  
  cout   <<   "b   =   "   <<   b   <<   endl;  
  b   =   b   ^   0x18;  
  cout   <<   "b   =   "   <<   b   <<   endl;  
  b   =   b   ^   0x18;  
  cout   <<   "b   =   "   <<   b   <<   endl;  
   
  可表达为:  
   
          00110010     -   b  
      ^   00011000     -   ^0x18  
      ----------  
          00101010     -   result  
   
          00101010     -   b  
      ^   00011000     -   ^0x18  
      ----------  
          00110010     -   result  
   
  非运算(~)  
  单目运算。位值取反,置0为1,或置1为0。非运算的用途是将指定位清0,其余位置1。非运算与数值大小无关。例如将第1位和第2位清0,其余位置1:  
   
  BYTE   b   =   ~0x03;  
  cout   <<   "b   =   "   <<   b   <<   endl;  
  WORD   w   =   ~0x03;  
  cout   <<   "w   =   "   <<   w   <<   endl;  
   
  可表达为:  
   
          00000011     -   0x03  
          11111100     -   ~0x03     b  
   
          0000000000000011     -   0x03  
          1111111111111100     -   ~0x03     w  
   
  非运算和与运算结合,可以确保将指定为清0。如将第4位清0:  
   
  BYTE   b   =   50;  
  cout   <<   "b   =   "   <<   b   <<   endl;  
  BYTE   c   =   b   &   ~0x10;  
  cout   <<   "c   =   "   <<   c   <<   endl;  
   
  可表达为:  
   
          00110010     -   b  
      &   11101111     -   ~0x10  
      ----------  
          00100010     -   result  
   
  移位运算(>>   与   <<)  
  将位值向一个方向移动指定的位数。右移   >>   算子从高位向低位移动,左移   <<   算子从低位向高位移动。往往用位移来对齐位的排列(如MAKEWPARAM,   HIWORD,   LOWORD   宏的功能)。  
   
  BYTE   b   =   12;  
  cout   <<   "b   =   "   <<   b   <<   endl;  
  BYTE   c   =   b   <<   2;  
  cout   <<   "c   =   "   <<   c   <<   endl;  
  c   =   b   >>   2;  
  cout   <<   "c   =   "   <<   c   <<   endl;  
   
  可表达为:  
          00001100     -   b  
          00110000     -   b   <<   2  
          00000011     -   b   >>   2  
   
  译注:以上示例都对,但举例用法未必恰当。请阅文末链接的文章,解释得较为清楚。  
   
  位域(Bit   Field)  
  位操作中的一件有意义的事是位域。利用位域可以用BYTE,   WORD或DWORD来创建最小化的数据结构。例如要保存日期数据,并尽可能减少内存占用,就可以声明这样的结构:  
   
  struct   date_struct   {  
          BYTE       day       :   5,       //   1   to   31  
                        month   :   4,       //   1   to   12  
                        year     :   14;     //   0   to   9999  
          }date;  
           
  在结构中,日期数据占用最低5位,月份占用4位,年占用14位。这样整个日期数据只需占用23位,即3个字节。忽略第24位。如果用整数来表达各个域,整个结构要占用12个字节。  
   
  |   0   0   0   0   0   0   0   0   |   0   0   0   0   0   0   0   0   |   0   0   0   0   0   0   0   0   |  
        |                                                           |                   |                     |  
        +-------------   year   --------------+   month+--   day   --+  
   
  现在分别看看在这个结构声明中发生了什么  
   
  首先看一下位域结构使用的数据类型。这里用的是BYTE。1个BYTE有8个位,编译器将分配1个BYTE的内存。如果结构内的数据超过8位,编译器就再分配1个BYTE,直到满足数据要求。如果用WORD或DWORD作结构的数据类型,编译器就分配一个完整的32位内存给结构。  
   
  其次看一下域声明。变量(day,   month,   year)名跟随一个冒号,冒号后是变量占用的位数。位域之间用逗号分隔,用分号结束。  
   
  使用了位域结构,就可以方便地象处理普通结构数据那样处理成员数据。尽管我们无法得到位域的地址,却可以使用结构地址。例如:  
  date.day   =   12;  
  dateptr   =   &date;  
  dateptr->year   =   1852;
posted @ 2008-11-11 22:21 clcl 阅读(211) | 评论 (0)编辑 收藏

CButtonT           CButton           CTrackBarCtrlT         CTrackBarCtrl
CListBoxT          CListBox          CUpDownCtrlT           CUpDownCtrl
CComboBoxT         CComboBox         CProgressBarCtrlT      CProgressBarCtrl
CEditT             CEdit             CHotKeyCtrlT           CHotKeyCtrl
CScrollBarT        CScrollBar        CAnimateCtrlT          CAnimateCtrl
CToolTipCtrlT CToolTipCtrl      CRichEditCtrlT         CRichEditCtrl
CHeaderCtrlT       CHeaderCtrl       CReBarCtrlT            CReBarCtrl
CListViewCtrlT     CListViewCtrl     CMonthCalendarCtrlT    CMonthCalendarCtrl
CTreeViewCtrlT     CTreeViewCtrl     CDateTimePickerCtrlT  CDateTimePickerCtrl
CToolBarCtrlT CToolBarCtrl      CIPAddressCtrlT        CIPAddressCtrl
CStatusBarCtrlT    CStatusBarCtrl    CPagerCtrlT            CPagerCtrl
CTabCtrlT          CTabCtrl
posted @ 2008-11-11 17:02 clcl 阅读(1418) | 评论 (0)编辑 收藏

   char file[MAX_PATH];
   TCHAR Tchartmp[MAX_PATH];

sprintf_s(file, "fileName%d", 134);

   CString strUnicode = file;

   wcscpy(Tchartmp,strUnicode);
posted @ 2008-10-14 15:00 clcl 阅读(876) | 评论 (1)编辑 收藏

TCHAR tcScriptName[MAX_PATH];
tcScriptName = "filename";
size_t i;
  char tmp[MAX_PATH];
  mbstate_t       mbstate;

  // Reset to initial shift state
  ::memset((void*)&mbstate, 0, sizeof(mbstate));

  const wchar_t* wt = tcScriptName;
  wcsrtombs_s(&i, tmp, MAX_PATH, &wt, MAX_PATH,&mbstate);


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


char * input = null;
wchar_t wc_input[MAX_USERNAME_LEN] = L"test";

  int nLen = WideCharToMultiByte( CP_ACP, 0, wc_input, -1, NULL, 0, NULL, NULL );
  int i = wcslen(wc_input)*sizeof(wchar_t);
  input = (char*)realloc(input,i+1);
  if (!input)
  {
   free(input);
   input = (char*)malloc(i + 1);
  }
  WideCharToMultiByte( CP_ACP, 0, wc_input, -1, input, nLen, NULL, NULL );


 

posted @ 2008-10-14 14:26 clcl 阅读(7977) | 评论 (4)编辑 收藏

继承是类与类的关系。
重载是方法与方法之间的关系。

继承是一个类需要另一个类的属性和方法,所以用到继承,这是发生在两个类之间的事情。
重载是指一个方法与另一个方法的方法名相同而参数列表不相同,这样的情况叫重载,属于多态。这是发生在一个类中的事情。

一个子类继承另外一个类,可以对父类中的方法进行重写,说到这里应该可以看出,继承和重载没什么关系了。而重写却与继承有很大的关系。
因为重写一般都发生在有继承的情况下,就是子类重写父类的方法。


重载和重写有什么区别和联系:

先说联系:
都是发生在同名方法之间的事情。

区别:
重载是发生在一个类中,根据参数列表的不同来区分两个同名的方法。
重写是发生在两个又继承关系的类中,根据方法体不同来区分两个同名方法。



memcpy
开放分类: C语言函数

  原型:extern void *memcpy(void *dest, void *src, unsigned int count);
  用法:#include <string.h>
 
  功能:由src所指内存区域复制count个字节到dest所指内存区域。
 
  说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。
 
  举例:
      // memcpy.c
     
      #include <syslib.h>
      #include <string.h>
      main()
      {
        char *s="Golden Global View";
        char d[20];
       
        clrscr();
       
        memcpy(d,s,strlen(s));
        d[strlen(s)]=0;
        printf("%s",d);
        getchar();
        return 0;
      }
 

 

 

strcat
 
 

  原型:extern char *strcat(char *dest,char *src);
       
  用法:#include <string.h>
 
  功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
 
  说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
        返回指向dest的指针。
 
  举例:


      // strcat.c
     
      #include <syslib.h>
      #include <string.h>

      main()
      {
        char d[20]="Golden Global";
        char *s=" View";
       
        clrscr();
       
        strcat(d,s);
        printf("%s",d);

        getchar();
        return 0;
      }

 

 

memset
在你申请了一块内存之后,
比如
int *p=NULL;
p=malloc(10*sizeof(int));//申请了10个int型内存
memset(p,0,10*sizeof(int));//全部初始化为0

memset的作用就是把你快连续的内存初始化为你给的值。
Example
/* MEMSET.C: This program uses memset to
* set the first four bytes of buffer to "*".
*/

#include <memory.h>
#include <stdio.h>

void main( void )
{
char buffer[] = "This is a test of the memset function";

printf( "Before: %s\n", buffer );
memset( buffer, '*', 4 );
printf( "After: %s\n", buffer );
}

Output
Before: This is a test of the memset function
After: **** is a test of the memset function

 

 

 

 

 

ftell
开放分类: 计算机语言、计算机技术、编程、程序、函数

函数名: ftell
功  能: 返回当前文件指针
用  法: long ftell(FILE *stream);
程序例:

#include <stdio.h>

int main(void)
{
   FILE *stream;

   stream = fopen("MYFILE.TXT", "w+");
   fprintf(stream, "This is a test");
   printf("The file pointer is at byte \
          %ld\n", ftell(stream));
   fclose(stream);
   return 0;
}

 

 

 


fopen
开放分类: 计算机语言、计算机技术、编程、程序、函数

fopen(打开文件)
相关函数  open,fclose
表头文件  #include<stdio.h>
定义函数  FILE * fopen(const char * path,const char * mode);
函数说明  参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。
mode有下列几种形态字符串:
r 打开只读文件,该文件必须存在。
r+ 打开可读写的文件,该文件必须存在。
w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b 字符用来告诉函数库打开的文件为二进制文件,而非纯文字文件。不过在POSIX系统,包含Linux都会忽略该字符。由fopen()所建立的新文件会具有S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)权限,此文件权限也会参考umask 值。
返回值
文件顺利打开后,指向该流的文件指针就会被返回。若果文件打开失败则返回NULL,并把错误代码存在errno 中。
附加说明
一般而言,开文件后会作一些文件读取或写入的动作,若开文件失败,接下来的读写动作也无法顺利进行,所以在fopen()后请作错误判断及处理。

【例程】
#include <stdlib.h>
#include <stdio.h>
#include <dir.h>

int main(void)
{
    char *s;
    char drive[MAXDRIVE];
    char dir[MAXDIR];
    char file[MAXFILE];
    char ext[MAXEXT];
    int flags;

    s=getenv("COMSPEC"); /* get the comspec environment parameter */
    flags=fnsplit(s,drive,dir,file,ext);

    printf("Command processor info:\n");
    if(flags & DRIVE)
       printf("\tdrive: %s\n",drive);
    if(flags & DIRECTORY)
       printf("\tdirectory: %s\n",dir);
    if(flags & FILENAME)
       printf("\tfile: %s\n",file);
    if(flags & EXTENSION)
       printf("\textension: %s\n",ext);

    return 0;
}
 

 

 

fseek
开放分类: 计算机语言、计算机技术、编程、程序、函数

函数名: fseek
功  能: 重定位流上的文件指针
用  法: int fseek(FILE *stream, long offset, int fromwhere);
程序例:

#include <stdio.h>

long filesize(FILE *stream);

int main(void)
{
   FILE *stream;

   stream = fopen("MYFILE.TXT", "w+");
   fprintf(stream, "This is a test");
   printf("Filesize of MYFILE.TXT is %ld bytes\n", filesize(stream));
   fclose(stream);
   return 0;
}

long filesize(FILE *stream)
{
   long curpos, length;

   curpos = ftell(stream);
   fseek(stream, 0L, SEEK_END);
   length = ftell(stream);
   fseek(stream, curpos, SEEK_SET);
   return length;
}


int fseek( FILE *stream, long offset, int origin );
第一个参数stream为文件指针,offset为偏移,比如你要从文件的第10000个字节开始读取的话,offset就应该为10000,origin 为标志是从文件开始还是末尾。
origin 的取值:
SEEK_CUR Current position of file pointer
SEEK_END End of file
SEEK_SET Beginning of file
那么fseek(fp,-size,1)中-size和1是否应理解为,从文件倒说第一个文件开始读取
fseek最后一个参数最好不要直接指定一个数值,比如1,
要使用SEEK_CUR,SEEK_END,SEEK_SET
第二个参数表示相对于第三个参数的偏移,整数表示正向偏移,负数表示负向偏移,比如
fseek(fp,-size,SEEK_CUR);
从当前位置向文件后方(比如文件有123三个数字,那么2在三的后方,3在2的前方)
fseek(fp,size,SEEK_SET);
从文件开始位置向前移动size


这里默认size是正数
 

 

 

 

fwrite
开放分类: 计算机语言、计算机技术、编程、程序、函数

函数名: fwrite
功  能: 写内容到流中
用  法:fwrite(buffer,size,count,fp);
  (1)buffer:是一个指针,对fwrite来说,是要输出数据的地址。
  (2)size:要读写的字节数;
  (3)count:要进行读写多少个size字节的数据项;
  (4)fp:文件型指针。
程序例:

#include <stdio.h>

struct mystruct
{
  int i;
  char ch;
};

int main(void)
{
   FILE *stream;
   struct mystruct s;

   if ((stream = fopen("TEST.$$$", "wb")) == NULL) /* open file TEST.$$$ */
   {
      fprintf(stderr, "Cannot open output file.\n");
      return 1;
   }
   s.i = 0;
   s.ch = 'A';
   fwrite(&s, sizeof(s), 1, stream); /* write struct s to file */
   fclose(stream); /* close file */
   return 0;
}
 

 

 

 


fread
开放分类: 计算机语言、计算机技术、编程、程序、函数

函数名: fread
功  能: 从一个流中读数据
用  法: int fread(void *ptr, int size, int nitems, FILE *stream);
参  数:用于接收数据的地址(字符型指针)(ptr)
        单个元素的大小(size)
        元素个数(nitems)
        提供数据的文件指针(stream)
返回值:成功读取的元素个数


程序例:

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

int main(void)
{
   FILE *stream;
   char msg[] = "this is a test";
   char buf[20];

   if ((stream = fopen("DUMMY.FIL", "w+"))
       == NULL)
   {
      fprintf(stderr,
              "Cannot open output file.\n");
      return 1;
   }

   /* write some data to the file */
   fwrite(msg, strlen(msg)+1, 1, stream);

   /* seek to the beginning of the file */
   fseek(stream, SEEK_SET, 0);

   /* read the data and display it */
   fread(buf, 1, strlen(msg)+1, stream);
   printf("%s\n", buf);

   fclose(stream);
   return 0;
}

 

 

 

 

 

FindFirstFile

void CFindFilesDlg::OnBnClickedButton1()
{
 // TODO: 在此添加控件通知处理程序代码
 CString c1;
 CString stredit;
 CString strtemp;
 HANDLE hFile;
 WIN32_FIND_DATA fileinfo;
 DWORD errorcode = 0;
 m_Edit1.GetWindowText(c1);   //要熟悉控件的基本使用
 if(!c1.IsEmpty())
 {
       hFile=FindFirstFile("f:\\*.*",&fileinfo);
    while(hFile!=INVALID_HANDLE_VALUE&&errorcode!=ERROR_NO_MORE_FILES)
    {
     //
   strtemp=fileinfo.cFileName;
   stredit=stredit+"\r\n";
   stredit=stredit+strtemp;
   FindNextFile(hFile,&fileinfo);
   errorcode=GetLastError();
    }
    if(errorcode==ERROR_NO_MORE_FILES)
    {
     m_cedit1.SetWindowText(stredit);
     MessageBox("检索结束");
    }
    CloseHandle(hFile);
 }
}


在上述代码中

FindFirstFile第一个个参数需要一个路径,但要写*.*,表示从所有文件中找到的第一个.但写f:或者f:双斜杠都返回无效句柄.

如果f:\\1.txt 则对特定文件进行搜索,返回找到的第一个

找到的文件的文件结构被记录在WIN32_FIND_DATA结构体里

FindNextFile第一个参数是FindFirstFile的返回值,可以接着上次结果继续寻找

但注意!!!!

但一个目录的文件被搜索一遍后,FindNextFile返回的WIN32_FIND_DATA结构体将重复找到最后一个找到的文件,而不会终止.

让循环结束的方法就是找上一次的报错码,然后看有没有ERROR_NO_MORE_FILES信息发生.

hFile的有效与否个人觉得还是取决于第一次的FindFirstFile结果,本程序后半段的运行主要还是errorcode!=ERROR_NO_MORE_FILES在控制.

 

 

 


 


 一、 内联汇编的一般原则:

1、 自由使用通用寄存器;(EAX,EBX,ECX和EDX)
2、 其它寄存器利用堆栈保留,使用,最后恢复;
一般的像下面这样:

__asm{
 push ebp
 push esp
 ……….//使用EBP和ESP
 pop esp
 pop ebp
}

 二、 内联汇编__asm可以单独使用:
例如:__asm mov eax,anyval1
__asm mov ebx,anyval2

 三、 函数返回值可以直接放到eax中,可以不理会警告
例如: int anyfun(……/*anyparm*/)
{
 int irtn; //函数返回值
 ……        //函数语句
 __asm mov eax,irtn    //代替return irtn;但编译器会发出警告,可以不理它
}

 四、 内联汇编不区分大小写,语法同普通汇编

例如:__asm{
 mov eax,ebx
 MOV EAX,EBX  //同上一句
}

注意:C++的变量还是区分大小写的

 五、 内联汇编尽量使用__asm或_asm关键字,而不用标准C++的asm关键字(这个是微软说的)
以上只是一些关于内联汇编的补充,我将出一系列围绕内联汇编的文章,下面接着上一次的话题详细一点地讲一下MMX指令的调用

1、 MMX指令集简介:

[数据传输指令]
movq //传输64位整数
movd //传输32位整数

[数据打包转换指令]
PACKSSWB //Pack words into bytes with signed saturation.
PACKSSDW //Pack doublewords into words with signed saturation.
PACKUSWB //Pack words into bytes with unsigned saturation.
PUNPCKHBW //Unpack high-order bytes.
PUNPCKHWD //Unpack high-order words.
PUNPCKHDQ //Unpack high-order doublewords.
PUNPCKLBW //Unpack low-order bytes.
PUNPCKLWD //Unpack low-order words.
PUNPCKLDQ //Unpack low-order doublewords.
注:这一组指令我没有具体用过,不知道是干什么的,请高手赐教!小弟先谢了!

[ 算术指令]
PADDB
PADDW
PADDD
PADDSB
PADDSW
PADDUSB
PADDUSW
PSUBB
PSUBW
PSUBD
PSUBSB
PSUBSW
PSUBUSB
PSUBUSW
PMULHW
PMULLW
PMADDWD

[ 比较指令]
PCMPEQB Compare packed bytes for equal.
PCMPEQW Compare packed words for equal.
PCMPEQD Compare packed doublewords for equal.
PCMPGTB Compare packed signed byte integers for greater than.
PCMPGTW Compare packed signed word integers for greater than.
PCMPGTD Compare packed signed doubleword integers for greater than.
这组指令用于成组比较数据

[ 位逻辑指令]
PAND Bitwise logical AND.
PANDN Bitwise logical AND NOT.
POR Bitwise logical OR.
PXOR Bitwise logical exclusive OR.
这组指令与AND,XOR基本相同,都是按位进行逻辑运算。

[ 移位和循环移位指令]
PSLLW //Shift packed words left logical.
PSLLD //Shift packed doublewords left logical.
PSLLQ //Shift packed quadword left logical.
PSRLW //Shift packed words right logical.
PSRLD //Shift packed doublewords right logical.
PSRLQ //Shift packed quadword right logical.
PSRAW //Shift packed words right arithmetic.
PSRAD //Shift packed doublewords right arithmetic.

[ 状态管理指令]
EMMS //Empty MMX state.
在VC中要求所有的MMX指令调用完毕后都要调用这个指令清空
例如:__asm{
 …..MMX 语句
 EMMS   //清空状态
}

以上是所有的MMX指令,你可以测试使用其中的指令,他的工作原理就是单指令,多数据
2、 使用MMX指令集的注意事项

由于在CPU内部,FPU寄存器和MMX寄存器是同一组寄存器,所以在同时引用上面寄存器时要注意正确的状态转换,具体做法以后在探讨。你只要先记住不能简单的混合以上两种指令集即可。
每次调用之前要先检测cpu是否支持MMX指令集,以免发生异常。具体做法看下列示例:


mov EAX, 1 ; request for feature flags
CPUID ; 0Fh, 0A2h CPUID instruction
test EDX, 00800000h ; Is IA MMX technology bit (Bit 23 of EDX)
; in feature flags set?
jnz MMX_Technology_Found

这段代码来自Intel的参考手册,所以你可以放心的使用。

3、 下面用一段示例代码来说明一下怎样用MMX指令 __int8 i8_a[2][16];  //字节操作数,两组,每组16个
 __int16 i16_a[8];   //字操作数
 __int32 i32_a[4];
 __int64 i64_a[2];

 i64_a[0]=0;
 i64_a[1]=0;

 i32_a[0]=1000;
 i32_a[1]=1000;
 i32_a[2]=3;
 i32_a[3]=4;

 i16_a[0]=10;
 i16_a[1]=20;
 i16_a[2]=30;
 i16_a[3]=40;
 i16_a[4]=50;
 i16_a[5]=60;
 i16_a[6]=70;
 i16_a[7]=80;
 
 i8_a[0][0]=1;
 i8_a[0][1]=1;
 i8_a[0][2]=1;
 i8_a[0][3]=1;
 i8_a[0][4]=1;
 i8_a[0][5]=1;
 i8_a[0][6]=1;
 i8_a[0][7]=1;
 i8_a[0][8]=1;
 i8_a[0][9]=1;
 i8_a[0][10]=1;
 i8_a[0][11]=1;
 i8_a[0][12]=1;
 i8_a[0][13]=1;
 i8_a[0][14]=1;
 i8_a[0][15]=1;

 i8_a[1][0]=2;
 i8_a[1][1]=2;
 i8_a[1][2]=2;
 i8_a[1][3]=2;
 i8_a[1][4]=2;
 i8_a[1][5]=2;
 i8_a[1][6]=2;
 i8_a[1][7]=2;
 i8_a[1][8]=2;
 i8_a[1][9]=2;
 i8_a[1][10]=2;
 i8_a[1][11]=2;
 i8_a[1][12]=2;
 i8_a[1][13]=2;
 i8_a[1][14]=2;
 i8_a[1][15]=2;

 __asm{
  movq mm1,[i64_a]
  movq mm2,[i64_a]
  
  movq mm2, [i32_a+8]
  psubd mm2, [i32_a]
  movq [i32_a],mm2
  
  movq mm1,[i16_a]
  paddsw mm1,[i16_a+8]
  movq [i16_a],mm1

  movq mm1,[i8_a]
  movq mm2,[i8_a+8]
  paddb mm1,[i8_a+16]
  paddb mm2,[i8_a+24]
  movq [i8_a],mm1
  movq [i8_a+8],mm2
  
  emms   //最后清除MMX状态寄存器,正确返回给系统
 }


你可以通过设置断点,和watch的方法来观察寄存器以及变量的变化情况,这里只是引用了一部分的指令,那么最引人注意的是对i16_a、i8_a、以及i32_a数组的操作,我是随便对他们进行了算术运算,大家可以看到我加两组字节数组数据时只用了两条加指令,这是普通的指令集望尘莫及的。这就是单指令,多数据的魅力。同时你也可以看到对64位整数的操作也简单多了。但是要注意的是,MMX指令集里好像没有提供除法操作。所以你需借助算法来实现。另外要补充的是MMX寄存器是从MM0-MM7命名的一组64位寄存器。



sscanf
开放分类: c函数

名称:
sscanf() - 从一个字符串中读进与指定格式相符的数据.
函数原型:
Int  sscanf( string str, string fmt, mixed var1, mixed var2 ... );
int  scanf( const char *format [,argument]... );
说明:
sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号}
注:
1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中)
2、{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
3、width表示读取宽度。
4、{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
5、type :这就很多了,就是%s,%d之类。
6、特别的:%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值
  
支持集合操作:

     %[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)

     %[aB'] 匹配a、B、'中一员,贪婪性

     %[^a] 匹配非a的任意字符,贪婪性

例子:
1. 常见用法。
    char buf[512] = ;
    sscanf("123456 ", "%s", buf);
printf("%s\n", buf);

结果为:123456

2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
    sscanf("123456 ", "%4s", buf);
printf("%s\n", buf);

结果为:1234

3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
    sscanf("123456 abcdedf", "%[^ ]", buf);
printf("%s\n", buf);

结果为:123456

4.  取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
    sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
printf("%s\n", buf);

结果为:123456abcdedf

5.  取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
    sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
printf("%s\n", buf);

结果为:123456abcdedf
  
6、给定一个字符串iios/12DDWDFF@122,获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中
sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);
printf("%s\n", buf);

结果为:12DDWDFF

7、给定一个字符串““hello, world”,仅保留world。(注意:“,”之后有一空格)
sscanf(“hello, world”,  "%*s%s",  buf);   
printf("%s\n", buf);

结果为:world

%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了

如果没有空格则结果为NULL。

sscanf的功能很类似于正则表达式, 但却没有正则表达式强大,所以如果对于比较复杂的字符串处理,建议使用正则表达式.
//-------------------------------------------------------
sscanf,表示从字符串中格式化输入
上面表示从str中,输入数字给x,就是32700
久以前,我以为c没有自己的split string函数,后来我发现了sscanf;一直以来,我以为sscanf只能以空格来界定字符串,现在我发现我错了。
sscanf是一个运行时函数,原形很简单:
int sscanf(
const char *buffer,
const char *format [,
argument ] ...
);
它强大的功能体现在对format的支持上。
我以前用它来分隔类似这样的字符串2006:03:18:
int a, b, c;
sscanf("2006:03:18", "%d:%d:%d", a, b, c);
以及2006:03:18 - 2006:04:18:
char sztime1[16] = "", sztime2[16] = "";
sscanf("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2);
但是后来,我需要处理2006:03:18-2006:04:18
仅仅是取消了‘-’两边的空格,却打破了%s对字符串的界定。
我需要重新设计一个函数来处理这样的情况?这并不复杂,但是,为了使所有的代码都有统一的风格,我需要改动很多地方,把已有的sscanf替换成我自己的分割函数。我以为我肯定需要这样做,并伴随着对sscanf的强烈不满而入睡;一觉醒来,发现其实不必。
format-type中有%[]这样的type field。如果读取的字符串,不是以空格来分隔的话,就可以使用%[]。
%[]类似于一个正则表达式。[a-z]表示读取a-z的所有字符,[^a-z]表示读取除a-z以外的所有字符。
所以那个问题也就迎刃而解了:
sscanf("2006:03:18 - 2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2);
在softmse (Jake) 的问题贴http://community.csdn.net/Expert/topic/4843/4843294.xml?temp=.4321558中 ,周星星给出了一个很cool的sscanf用例,而后通过学习,发现sscanf真棒,现做一总结。
原问题:
iios/12DDWDFF@122
获取/和@之间的字符串怎么做
C程序里面有什么函数吗?
周星星的代码:
#include <stdio.h>
int main()
{
const char* s = "iios/12DDWDFF@122";
char buf[20];
sscanf( s, "%*[^/]/%[^@]", buf );
printf( "%s\n", buf );
return 0;
}
结果为:12DDWDFF
sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
函数原型:
int scanf( const char *format [,argument]... );
其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号},
注:{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。

width:宽度,一般可以忽略,用法如:
const char sourceStr[] = "hello, world";
char buf[10] = ;
sscanf(sourceStr, "%5s", buf); //%5s,只取5个字符
cout << buf<< endl;
结果为:hello
{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
type :这就很多了,就是%s,%d之类。

特别的:
%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值。如:
const char sourceStr[] = "hello, world";
char buf[10] = ;
sscanf(sourceStr, "%*s%s", buf); //%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
cout << buf<< endl;
结果为:world
支持集合操作:
%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
%[aB'] 匹配a、B、'中一员,贪婪性
%[^a] 匹配非a的任意字符,贪婪性
是不是感觉眼熟了啊,不错,这和正则表达式很相似,而且仍然支持过滤,即可以有%*[a-z].如:
星星大哥例子回顾:
const char* s = "iios/12DDWDFF@122";
char buf[20];
sscanf( s, "%*[^/]/%[^@]", buf );
printf( "%s\n", buf );
先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中,cool.得到结果。
PS: 向星星大哥和softmse (Jake) 致谢了,有了你们才有它啊

 

posted @ 2008-08-19 09:14 clcl 阅读(381) | 评论 (0)编辑 收藏








   第一篇文章不知道写什么,就当是对我入行几个月的一个save吧,第一个项目,2D的地图编辑器,3个人一起做的(主程有先搭个框架),我负责的是用OGRE在视图中显示地形和物件管理还有阻挡等,后来还做了机器人的寻路,资源暂时用的是魔兽(觉得美工做的地形的图没有魔兽的美 =  = |||)。
   OGRE确实是好东西,不过可能是不够熟悉的原因吧,经常被小问题还有没有考虑到的因素绊了好久,又是上网搜又是群里问才解决。
   额· · · 实在不知道说什么,先这样吧,以后慢慢补充·   ·  ·

PS:关于两个房子是透明的是因为我在调试OGRE的材质里的PASS 中设置ALPHA通道的几个参数
posted @ 2008-08-18 22:36 clcl 阅读(370) | 评论 (2)编辑 收藏

仅列出标题
共2页: 1 2