posts - 195, comments - 34, trackbacks - 0, articles - 1

生成zigzag序,
1、分析关键,在以zigzag序的每一行,以上三角为计算对象分别以i或j的增序排列,因此利用这一点就可以得出结果。
    程序中s即为zigzag行号,而变换则以i和j交替。所以程序很简单。

 

#include<iostream>
#include<iomanip>

using namespace std;

#define M 255

void zigzag(const int N)
{
    int squa = N * N;
    int a[M][M]={0};
    for (int i = 0;i < N; i++)
    {
        for (int j = 0;j < N;j++)
        {
            int s = i + j;
            if ( s < N)
            {
                 a[i][j] = s * (s+1)/2 + ( (s %2 !=0)?i:j);//注意?:的优先级低于+
            }
            else
            {
                int sn = (N-1-i) + (N-1-j);
                a[i][j] = squa - sn * (sn+1)/2 - (N - ( (sn%2 != 0)? i:j));
            }
        }
    }

    for (int i=0; i < N; i++)
    {
        for (int j = 0;j < N;j++)
        {

            cout<<setw(4)<<a[i][j]<<",";
        }
        cout<<endl<<endl;
    }
}

int main()
{
 zigzag(5);
 cout<<endl;
 
 zigzag(8);
 cout<<endl;

    return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void zigzag(int n)
{
int **a =(int**) malloc(n*sizeof(int *)); //分配空间

if(NULL == a)
return ;
int i;
for(i = 0; i < n; i++) {
        if((a[i] =(int*) malloc(n * sizeof(int))) == NULL) {
            while(--i>=0)
                free(a[i]);
            free(a);
            return;
        }
    }

bool flag = false; //这个标志位用来判断是从45度角生成还是225度角生成
int count = 0;
for(i=0; i<n; i++) //生成的上半部分的数据
{

if(flag)
{
   for(int r = 0; r<=i; r++)
   {
    a[r][i-r] = count;
    count++;
   }
   flag = false;
}
else
{
   for(int r = i; r>=0; r--)
   {
    a[r][i-r] = count;
    count++;
   }
   flag = true;
}
}
for(i=n-1; i>=0; i--) //生成的是下半部分的数据
{
// cout<<i<<endl;
if(flag)
{
   for(int r = 0; r<=i-1; r++)
   {
    int r1 = n-i+r;       //代表当前行
    int c1 = 2*n-i-1-r1; //代表当前列
    a[r1][c1] = count;
    count++;
   }
   flag = false;
}
else
{
   for(int r = i-1; r>=0; r--)
   {
    cout<<"ddd"<<endl;
    int r1 = n-i+r;
    int c1 = 2*n-i-1-r1;
//   cout<<r1<<","<<c1<<endl;
    a[r1][c1] = count;
    count++;
   }
   flag = true;
}
}
for(int r = 0; r<n; r++)
{
for(int c=0; c<n; c++)
   cout<<a[r][c]<<",";
cout<<endl;
}
}
int main()
{
int n;
cin>>n;
zigzag(n);
return 0;
}
网上还有一个人写了一个比较巧的算法:
/**
* 得到如下样式的二维数组
* zigzag(jpeg编码里取象素数据的排列顺序)
*
*   0, 1, 5, 6,14,15,27,28,
*   2, 4, 7,13,16,26,29,42,
*   3, 8,12,17,25,30,41,43,
*   9,11,18,24,31,40,44,53,
*   10,19,23,32,39,45,52,54,
*   20,22,33,38,46,51,55,60,
*   21,34,37,47,50,56,59,61,
*   35,36,48,49,57,58,62,63
*/

#include <stdio.h>
int main()
{
    int N;
    int s, i, j;
    int squa;
    scanf("%d", &N);
    /* 分配空间 */
    int **a = malloc(N * sizeof(int *));
    if(a == NULL)
        return 0;
    for(i = 0; i < N; i++) {
        if((a[i] = malloc(N * sizeof(int))) == NULL) {
            while(--i>=0)
                free(a[i]);
            free(a);
            return 0;
        }
    }
    /* 数组赋值 */
    squa = N*N;   
    for(i = 0; i < N; i++)
        for(j = 0; j < N; j++) {
            s = i + j;
            if(s < N)
                a[i][j] = s*(s+1)/2 + (((i+j)%2 == 0)? i : j);
            else {
                s = (N-1-i) + (N-1-j);
                a[i][j] = squa - s*(s+1)/2 - (N - (((i+j)%2 == 0)? i : j));
            }
        }
    /* 打印输出 */   
    for(i = 0; i < N; i++) {
        for(j = 0; j < N; j++)
            printf("%-6d", a[i][j]);
        printf("\n");
    }
    return 0;
}

posted @ 2010-05-03 17:26 小强摩羯座 阅读(257) | 评论 (0)编辑 收藏

几道面试笔试题
2008-02-26 18:38

一、如何判断一个单链表是有环的?(注意不能用标志位,最多只能用两个额外指针)
   struct node { char val; node* next;}
   bool check(const node* head) {} //return false : 无环;true: 有环
    一种O(n)的办法就是(搞两个指针,一个每次递增一步,一个每次递增两步,如果有环的话两者必然重合,反之亦然):
    bool check(const node* head)
    {
         if(head==NULL)
              return false;  
         node *low=head, *fast=head->next;
         while(fast!=NULL && fast->next!=NULL)
        {
               low=low->next;
               fast=fast->next->next;
               if(low==fast)
                    return true;
        }
       return false;
   }

二、删除一个单项链表的最中间的元素,要求时间尽可能短(不能使用两次循环)
struct link
{
    int data;
    struct link *next;
};
void delMiddle(link *head)
{
    if(head == NULL)
           return;
    else if(head->next == NULL)
    {
            delete head;
            return;
    }
    else
    {
            link *low = head;
            link *fast = head->next;
            while(fast != NULL && fast->next != NULL)
            {  
                       fast = fast->next->next;
                       if(fast == NULL)
                                    break;
                       low = low->next;
            }
            link *temp = low->next;
            low->next = low->next->next;
            delete temp;

    }
}
int main()
{
       struct link *head,*l;
       struct link *s;
       head = (link*)malloc(sizeof(link));
       head->data=0;
       head->next = NULL;
       l = head;
       for(int i=1; i<9; i++)
       {
            s = (link*)malloc(sizeof(link));
            s->data = i;
            s->next = NULL;
            l->next= s;
            l = l->next;
       }
       print(head);
       delMiddle(head);
       print(head);
       return 0;
}

三、输入n,求一个n*n矩阵,规定矩阵沿45度线递增(威盛)
/**
* 得到如下样式的二维数组
* zigzag(jpeg编码里取象素数据的排列顺序)
*
*   0, 1, 5, 6,14,15,27,28,
*   2, 4, 7,13,16,26,29,42,
*   3, 8,12,17,25,30,41,43,
*   9,11,18,24,31,40,44,53,
*   10,19,23,32,39,45,52,54,
*   20,22,33,38,46,51,55,60,
*   21,34,37,47,50,56,59,61,
*   35,36,48,49,57,58,62,63
*/
void zigzag(int n)
{
int **a =(int**) malloc(n*sizeof(int *)); //分配空间

if(NULL == a)
return ;
int i;
for(i = 0; i < n; i++) {
        if((a[i] =(int*) malloc(n * sizeof(int))) == NULL) {
            while(--i>=0)
                free(a[i]);
            free(a);
            return;
        }
    }

bool flag = false; //这个标志位用来判断是从45度角生成还是225度角生成
int count = 0;
for(i=0; i<n; i++) //生成的上半部分的数据
{

if(flag)
{
   for(int r = 0; r<=i; r++)
   {
    a[r][i-r] = count;
    count++;
   }
   flag = false;
}
else
{
   for(int r = i; r>=0; r--)
   {
    a[r][i-r] = count;
    count++;
   }
   flag = true;
}
}
for(i=n-1; i>=0; i--) //生成的是下半部分的数据
{
// cout<<i<<endl;
if(flag)
{
   for(int r = 0; r<=i-1; r++)
   {
    int r1 = n-i+r;       //代表当前行
    int c1 = 2*n-i-1-r1; //代表当前列
    a[r1][c1] = count;
    count++;
   }
   flag = false;
}
else
{
   for(int r = i-1; r>=0; r--)
   {
    cout<<"ddd"<<endl;
    int r1 = n-i+r;
    int c1 = 2*n-i-1-r1;
//   cout<<r1<<","<<c1<<endl;
    a[r1][c1] = count;
    count++;
   }
   flag = true;
}
}
for(int r = 0; r<n; r++)
{
for(int c=0; c<n; c++)
   cout<<a[r][c]<<",";
cout<<endl;
}
}
int main()
{
int n;
cin>>n;
zigzag(n);
return 0;
}
网上还有一个人写了一个比较巧的算法:
/**
* 得到如下样式的二维数组
* zigzag(jpeg编码里取象素数据的排列顺序)
*
*   0, 1, 5, 6,14,15,27,28,
*   2, 4, 7,13,16,26,29,42,
*   3, 8,12,17,25,30,41,43,
*   9,11,18,24,31,40,44,53,
*   10,19,23,32,39,45,52,54,
*   20,22,33,38,46,51,55,60,
*   21,34,37,47,50,56,59,61,
*   35,36,48,49,57,58,62,63
*/

#include <stdio.h>
int main()
{
    int N;
    int s, i, j;
    int squa;
    scanf("%d", &N);
    /* 分配空间 */
    int **a = malloc(N * sizeof(int *));
    if(a == NULL)
        return 0;
    for(i = 0; i < N; i++) {
        if((a[i] = malloc(N * sizeof(int))) == NULL) {
            while(--i>=0)
                free(a[i]);
            free(a);
            return 0;
        }
    }
    /* 数组赋值 */
    squa = N*N;   
    for(i = 0; i < N; i++)
        for(j = 0; j < N; j++) {
            s = i + j;
            if(s < N)
                a[i][j] = s*(s+1)/2 + (((i+j)%2 == 0)? i : j);
            else {
                s = (N-1-i) + (N-1-j);
                a[i][j] = squa - s*(s+1)/2 - (N - (((i+j)%2 == 0)? i : j));
            }
        }
    /* 打印输出 */   
    for(i = 0; i < N; i++) {
        for(j = 0; j < N; j++)
            printf("%-6d", a[i][j]);
        printf("\n");
    }
    return 0;
}


四、打印1到1000的整数,不能使用流程控制语句(for,while,goto等)也不能使用递归
1.
typedef struct _test{
    static int a;
    _test(){
        printf("%d\n",_test::a);
        a++;
    }
}Test;
int Test::a = 1;

int   main()  
{  
    Test tt[1000];
    return 0;
}  
2.
#include   <stdio.h>
#define   B   P,P,P,P,P,P,P,P,P,P
#define   P   L,L,L,L,L,L,L,L,L,L
#define   L   I,I,I,I,I,I,I,I,I,I,N
#define   I   printf( "%3d   ",i++)
#define   N   printf( "\n ")
int main()
{
    int   i   =   1;
    B;
}

#define A(x) x;x;x;x;x;x;x;x;x;x;
int main ()
{
    int n = 1;
    A(A(A(printf ("%d ", n++))));

    return 0;
}

 

五、struct   S   {
        int   i;
        int   *   p;
};
void   main()
{
        S   s;
        int   *   p   =   &s.i;
        p[0]   =   4;
        p[1]   =   3;
        s.p   =   p;
        s.p[1]   =   1;
        s.p[0]   =   2;
}
问程序会在哪一行死掉。 (microsoft)
解: S   s;
         int   *   p   =   &s.i;        //s.i的地址存储在p里
        p[0]   =   4;                    //修改了s.i
         p[1]   =   3;                    //修改了s.p
         s.p   =   p;                    //s.p指向s.i
         s.p[1]   =   1;               //修改s.p本身
        s.p[0]   =   2;               //s.p指向的是0x00000001,尝试向这里写,出错
     s.p[0]       =       2;   时出错
     因为s.p存的是s.i的地址,s.p[1]为s.p,当s.p[1]=1时,s.p此时存放的是1了,而不是地址s.i,故在s.p[0]   =   2时出错.
此时相当于s.p=ox00000001;地址ox0000001   =   2;当然就出错了

如果语句s.p[0]   =2   先于s.p[1]=1则程序就不会出错.此时语句相当于s.i=2;s.p=1;


六、题目描述:
1.   int   swap(int   *x,int   *y)
{
    if(x==NULL   | |   y==NULL)
        return   -1;
    *x   +=   *y;
    *y   =   *x-   *y;
    *x   -=   *y;
      return   1;
}
请改错,溢出已经考虑,不是错误
2.
void   foo(int   *x,   int   *y)
{
    *x   +=   *y;
    *x   +=   *y;
}
void   fun(int   *x,   int   *y)
{  
    *x   +=   2   *   (*y);
}
问两个函数是否等价,能否互换
解答:第一题的函数是交换。但假如考虑x,   y都是指向同一个变量,结果是这个变量的值为0.
第二题的两个函数是有区别的,也考虑x,y是指向同一个变量.这样第一个函数的结果是这个变量的4倍.但第二个函数的结果是变量的3倍.

posted @ 2010-05-03 17:25 小强摩羯座 阅读(136) | 评论 (0)编辑 收藏

C++ placement new 用法举例zz
2009-12-17 16:16

在处理内存分配的时候,C++程序员会用new操作符(operator new)来分配内存,并用delete操作符(operator delete)来释放内存。这是一个new操作符的例子。

class CTest
{
     
/* 成员函数和成员数据 */
};

// . . . 代码

//
分配一个对象
CTest * pTest = new Test;
// 分配一个有十个对象的数组 (CTest 要有缺省构造函数(default constuctor)
CTest * p10Tests = new Test[ 10];

虽然这种写法在大多数时候都工作得很好,但还是有些情况下使用new是很烦人的,比如当你想重新分配一个数组或者当你想在预分配的内存上构造一个对象的时候。

比如第一种情况,重新分配一个数组效率是很低的:

// 分配一个有10个对象的数组
CTest * pTests = new Test[ 10];
// . . .
//
假设现在我们需要11个对象
CTest * pNewTests = new Test[ 11];
// . . . 我们必须把原来的对象拷贝到新分配的内存中
for ( int i = 0; i < 10; i++)
     pNewTests[ i] = pTests[ i];
delete pTests;
pTests = pNewTests;

如果你想在预分配的内存上创建对象,用缺省的new操作符是行不通的。要解决这个问题,你可以用placement new构造。它允许你构造一个新对象到预分配的内存上:

// buffer 是一个void指针 (void *)
//
用方括号[] 括起来的部分是可选的
[CYourClass * pValue = ] new( buffer) CYourClass[( parameters)];

下面是一些例子:

#include <new>

class CTest
{
public:
     CTest()
     {}
     CTest( int)
     {}
    
/* 代码*/
};

int main(int argc, char* argv[])
{

     //
由于这个例子的目的,我们不考虑内存对齐问题
     char strBuff[ sizeof( CTest) * 10 + 100];
     CTest * pBuffer = ( CTest *)strBuff;

    
// 缺省构造
     CTest * pFirst = new(pBuffer) CTest;

    
// 缺省构造
     CTest * pSecond = new(pBuffer + 1) CTest;
    
    
// 带参数的构造;
     //
不理会返回的指针
     new(pBuffer + 2) CTest( 5);

    
// 带参数的构造
     CTest * pFourth = new( pBuffer + 3) CTest( 10);

    
// 缺省构造
     CTest * pFifth = new(pBuffer + 4) CTest();

    
// 构造多个元素(缺省构造)
     CTest * pMultipleElements = new(pBuffer + 5) CTest[ 5];
     return 0;
}

当你有自己的内存缓冲区或者在你实现自己的内存分配策略的时候,placement new会很有用。事实上在STL中广泛使用了placement new来给容器分配内存;每个容器类都有一个模版参数说明了构造/析构对象时所用的分配器(allocator)。

在使用placement new的时候,你要记住以下几点:

  • 加上头文件#include <new>
  • 你可以用placement new构造一个数组中的元素。
  • 要析构一个用placement new分配的对象,你应该手工调用析构函数(并不存在一个“placement delete”)。它的语法如下:

pFirst->~CTest();
pSecond->~CTest();

前段事件,我问过关于placement new的问题,一位仁兄讲了一些道理,他说道:

::栈上的对象(注意,是类对象,char类型就无需了,后面还会提到)保证放在对齐地址上. 

但是,个人实验了一下,发现并不是这样

例如:
int main()
{
char c1 = 'A' ;
char c2 = 'B' ;
char c3 = 'C' ;
char c4 = 'D' ;
char c5 = 'E' ;

//-------- 验证这四个地址是否是 4 的倍数 --------------//
if ( ((int)(&c1)) % 4 == 0 )
cout << "c1:Yes" << endl ;

if ( ((int)(&c2)) % 4 == 0 )
cout << "c2:Yes" << endl ;

if ( ((int)(&c3)) % 4 == 0 )
cout << "c3:Yes" << endl ;

if ( ((int)(&c4)) % 4 == 0 )
cout << "c4:Yes" << endl ;

if ( ((int)(&c5)) % 4 == 0 )
cout << "c5:Yes" << endl ;

cout << (int)(&c1) << endl // 输出四个字符所在的地址(输出结果都是 4 的倍数)
 << (int)(&c2) << endl 
 << (int)(&c3) << endl 
 << (int)(&c4) << endl 
 << (int)(&c5) << endl ;
}
-----------------------------
上面的执行结果在VC下运行都是 4 的倍数
--------------

--> 问题1:连栈上分配的空间地址都是 4 的倍数,那就说明系统分配的空间都是 4 的倍数吧???

--> 问题2:如果万一,如果放一个对象的地址不是4的倍数,那么会出现什么情况??可以给简单说一下吗?

--> 问题3:地址对齐的通用性???
   -------------
   程序1:
Class C1
{
int i ;
char c ;
} ;
cout << sizeof(C1) << endl ;// 输出结果: 8 (是 4 的倍数)
   程序2:
class C2
{
char c1 ;
char c2 ;
} ;
cout << sizeof(C2) << endl ;// 输出结果:2 ( 上一个中char类型也给了4个字节,怎么这个地方都给了一个字节??)
--> 问题4:由上面的程序2 引出下面的程序
class C2// sizeof(C2) =2 ,在VC实验下的结果,不是 4
{
char c1 ;
char c2 ;
} ;
//----------用placement new方法建立对象----------------
void *ptr = operator new(100) ;// 分配内存
C2 *POINTER = (C2*)ptr ;// 类型转换
String *str1 = new (POINTER) C2() ;// 建立一C2对象
String *str2 = new (POINTER+1) C2() ;// 再建立一个对象
String *str3 = new (POINTER+2) C2() ;// 再建立一个对象

cout << (int)(str1) << endl// 结果:3608720(  是4的倍数)
      << (int)(str2) << endl // 结果:3608722(不是4的倍数)!!
                     << (int)(str3) << endl ;// 结果:3608724(不是4的倍数)!!

posted @ 2010-04-20 17:15 小强摩羯座 阅读(3771) | 评论 (0)编辑 收藏

很实用的word的高级用法总汇2009-04-23 16:26

 

任意放大/变小 字体

快捷键ctrl+] 放大 字体      ctrl+[ 缩小字体

把文字替换成图片
首先把图片复制到 剪贴板中,然后打开替换对话框,在“查找内容”框中输入将被替换的文字,接着在 “替换为”框中输入“^c”(注意:输入的一定要是半角字符,c要小写),单击替换 即可。说明:“^c”的意思就是指令Word XP以剪贴板中的内容替换“查找内容”框中的内 容。按此原理,“^c”还可替换包括回车符在内的任何可以复制到剪贴板的可视内容,甚至Excel表格。

三招去掉页眉那条横线
1、在页眉中,在“格式”-“边框和底纹”中设置表格和边框为“无”,应用于“段落”
2、同上,只是把边框的颜色设置为白色(其实并没有删的,只是看起来没有了,呵呵)
3、在“样式”栏里把“页眉”换成“正文”就行了——强烈推荐!
会多出--(两个横杠) 这是用户不愿看到的,又要多出一步作删除--
解决方法:替换时在前引号前加上一个空格 问题就解决了

插入日期和时间的快捷键
Alt+Shift+D:当前日期
Alt+Shift+T:当前时间

批量转换全角字符为半角字符
首先全选。然后“格式”→“更改大小写”,在对话框中先选中“半角”,确定即可


Word启动参数简介
单击“开始→运行”命令,然后输入Word所在路径及参数确定即可运行,如“C:\ PROGRAM FILES \MICROSOFT Office \Office 10\ WINWord.EXE /n”,这些常用的参数及功能如下:
/n:启动Word后不创建新的文件。
/a:禁止插件和通用模板自动启动。
/m:禁止自动执行的宏。
/w:启动一个新Word进程,独立与正在运行的Word进程。
/c:启动Word,然后调用Netmeeting。
/q:不显示启动画面。
另外对于常需用到的参数,我们可以在Word的快捷图标上单击鼠标右键,然后在“目标”项的路径后加上该参数即可。

快速打开最后编辑的文档
如果你希望Word在启动时能自动打开你上次编辑的文档,可以用简单的宏命令来完成:
(1)选择“工具”菜单中的“宏”菜单项,单击“录制新宏”命令打开“录制宏”对话框;
(2)在“录制宏”对话框中,在“宏名”输入框中输入“autoexec”,点击“确定”;
(3)从菜单中选择“文件”,点击最近打开文件列表中显示的第一个文件名;并“停止录制”。保存退出。下次再启动Word时,它会自动加载你工作的最后一个文档。

格式刷的使用
1、设定好文本1的格式。
2、将光标放在文本1处。
3、单击格式刷按钮。
4、选定其它文字(文本2),则文本2的格式与文本1 一样。
若在第3步中单击改为双击,则格式刷可无限次使用,直到再次单击格式刷(或按Esc键)为止。

删除网上下载资料的换行符(象这种“↓”)
在查找框内输入半角^l(是英文状态下的小写L不是数字1),在替换框内不输任何内容,单击全部替换,就把大量换行符删掉啦。

选择性删除文件菜单下的最近使用的文件快捷方式。
工具→选项→常规把“列出最近使用文件数改为0”可以全部删除,若要选择性删除,可以按ctrl+Alt+ -三个键,光标变为一个粗减号后,单击文件,再单击要删除的快捷方式就行了。

建立一个矩形选区:
一般的选区建立可用鼠标左键,或用shift键配合pgup、pgdn、home、end、箭头等功能键,当复制一个规则的矩形区域时,可先按住Alt键,然后用鼠标左键来选。我一般用此来删除段首多余的成块的空格。大家试一试*^_^*

将字体快速改为上标或下标的方法:
本人在一次无意间发现了这个方法,选定你要下标的字,然后在英文状态下按住Ctrl,再按一下BASKSPACE旁的+/=的键,就可以了。上标只要在按Ctrl的同时也按住Shift,大家可以试试。

让Word表格快速一分为二
将光标定位在分开的表格某个位置上,按下“Ctrl+Shift+Enter”组合键。这时你就会发现表格中间自动插入一个空行,这样就达到了将一个表格一分为二的目的。

用Word来拆字
首先点击“工具/自定义/命令/分解图片”,按住鼠标左键把它拖放到工具栏任意位置即可;然后点击“插入/图片/艺术字”,例如输入空心字“心”,选择该“心”字剪切,在选择性粘贴中选图片(Windows图元文件),选中该字,点击工具栏中的“分解图片”按钮,这样可以选择“心”中的任意笔画进行一笔一画的拆分了。

快速删除段前段后的任意多个空格
选定这些段段落,单击居中按钮,然后再单击原来的那种对齐方式按钮(如果原来是居中对齐的,先单击其它对齐方式按钮,再单击居中按钮就行了),是不是这些空格全不见了?


只要打开WORD新建一个空文档的时候,出现的不是空的文档,而是我以前打的一份文档
首先:将资源管理器设置为显示所有文件和文件夹;
然后:
C:\Documents and Settings\Administrator\Application Data\Microsoft\Templates文件夹下将所有Normal.doc文件删掉;
然后:OK(XP系统)

快速输入平方的方法
先输入2,然后选重后,按ctrl加shift加+就可以了.

WORD中表格的选择性录入
1.设置好表格,选定表格-视图-工具-窗体-插入下拉型窗体域
2.输入数据,完成
3.点击锁按钮,保护,输入完后再点击进行其它的输入.

标点符号的全角/半的转换用:Ctrl+.
数字字母的全角/半的转换用:Shift+空格

轻松了解工具栏按钮的作用
按下“shift+F1”键,鼠标指针旁多了一个“?”号,想知道哪个按钮
的作用,就用鼠标单击哪个。

要经常在文档中插入自己公司的信息
公司名称
公司住址
联系电话
联系人姓名
QQ号码
可以先选定这些内容,再单击工具→自动更正→在替换框中输入标记名称(如“公司信息”)→添加→确定,以后凡是在文档中要用到这个信息的地方键入“公司信息”(不要引号)这几个字后就自动替换成:
公司名称
公司住址
联系电话
联系人姓名
QQ号码
说明:有些输入法不支持这个功能,键入标记名称后要按一下空格才行。

快速换页的方法
双击某页的右下脚,光标即可定位在那里,然后按回车直到换页。ctrl+回车点插入按纽,分隔符,选中分页符,然后确认就OK了 !!!

表格的简单调整宽度
鼠标放在表格的右边框上带鼠标变成可以调整大小的时候
双击
根据表格内的内容调节表格大小

代替金山词霸
点工具——语言——翻译,在右边出现的搜索框中输入要查的单词,回车就可以翻译了。可以选择英语翻成中文或中文翻成英语。
第一次使用可能要安装。

[Alt]键实现标尺的精确定位
如果你经常使用水平标尺来精确定位标签、页边框、首字缩进及页面对象的位置,那么你点击标尺设置页边框或标签时,您只可以将其设置为1字符或2字符,但不能设为1.5字符!要想设置更为精确的度量单位(例如百分之几字符),在按住[Alt]键的同时,点击并移动标尺或边框,此时标尺将用数字精确显示出当前的位置为百分之几字符位置。

用“记事本”去除格式
网页上COPY下来的东西往往都是有网格的,如果直接粘贴在WORD中会杂乱无章。先粘贴到记事本当中,再粘贴到WORD中,就可以去除网格等格式,再全选选择清除格式,居中再取消居中即可取消所有格式。可以直接在WORD中进行:(菜单)编辑/选择性粘贴……/无格式文本/确定。这样省事多了。

快速将文档转换成图片
先把欲想转换的文档保存退出.如:保存在桌面
然后新建一个文件.把想转换的文档(鼠标左建按住该文档不放)直接施放在页面上

恢复office的默认设置
比如不小心把word设置乱了(如删了菜单栏等等).
查找normal.dot直接删除.
下一次启动word会恢复默认值.

让Word只粘贴网页中的文字而自动去除图形和版式
方法一、选中需要的网页内容并按“Ctrl+C”键复制,打开Word,选择菜单“编辑”→“选择性粘贴”,在出现的对话框中选择“无格式文本”。
方法二、选中需要的网页内容并按“Ctrl+C” 键复制,打开记事本等纯文本编辑工具,按“Ctrl+V”键将内容粘贴到这些文本编辑器中,然后再复制并粘贴到Word中。

ctrl+alt+f可以输入脚注
这个对于经常写论文的朋友应该有点帮助。

将阿拉伯数字转换成中文数字或序号
1、先输入阿拉伯数字(如1234),全选中,单击“插入/数字/数字类型(壹、贰……)/确定”,即变为大写数字(如壹仟贰佰叁拾肆),会计朋友非常适用。
2、其他像一千二百三十四,甲、乙……,子、丑……,罗马数字等的转换,可参考上法。

Word中的常用快捷键吧
“字体”对话框     Ctrl+D
选择框式工具栏中的“字体”框     Ctrl+Shift+F
加粗 Ctrl+B
倾斜 Ctrl+I
下划线Ctrl+U
“上标”效果     Ctrl+Shift+=
“下标”效果     Ctrl+=
“关闭”命令     Ctrl+W
Word快捷键一览表
序号       快捷键CTRL+       代表意义
1…………Z…………撤消
2…………A…………全选
3…………X…………剪切
4…………C…………复制
5…………V…………粘贴
6…………S…………保存
7…………B…………加粗
8………… Q…………左对齐
9…………E…………据中
10…………R…………右对齐
11…………]…………放大
22…………[…………缩小
12…………N…………新建文档
13…………I…………字体倾斜
14…………W…………退出
15…………P…………打印
16…………U…………下划线
17…………O…………打开
18…………k…………插入超级连接
19…………F…………查找
20…………H…………替换
21…………G…………定位
23…Ctrl+Alt+L……带括号的编号
24…Ctrl+Alt+.________…
25…Alt+数字………区位码输入
26…Ctrl+Alt+Del………关机
27…Ctrl+Alt+Shift+?……¿
28…Ctrl+Alt+Shift+!……¡
29…Alt+Ctrl+E……………?
30…Alt+Ctrl+R……………®
31…Alt+Ctrl+T……………™
32…Alt+Ctrl+Ctrl…………©
33……Ctrl+D……………格式字体
34……Ctrl+Shift+= ………上标
35……Ctrl+=………………下标
36……Ctrl+Shift+>……放大字体
37……Ctrl+Shift+< ……缩小字体
38……Alt+Ctrl+I………打印预览
39……Alt+Ctrl+O………大刚示图
40……Alt+Ctrl+P………普通示图
41……Alt+Ctrl+M………插入批注
42……Alt+菜单上字母………打开该菜单

无级微调
打开“绘图”工具栏-点开下拉菜单-绘图网格...-将水平间距和垂直间距调到最小0.01-确定,这样你就可以无级微调

把work设置成在线打开,但不能修改‘只读’怎搞啊?
文件夹共享为只读

在WORD中输入三个等号然后回车。。。出来的是双横线哦。。。
同样的方法也可以做出波浪线单横线哦!~~~~~ ,
###为中间粗上下细的三线, ***为点线, ~~~为波浪线, ---为单线

输入拼音字母的音调怎么输入
用智能ABC,键入v9,然后自己挑选吧!

页码设置
1、打开页眉/页脚视图,点击插入页码按钮,将页码插入(此时所有的页码是连续编号的) 2、切换到页面视图,在需要从1计数的页面上插入连续分节符(插入--分隔符--分节符--连续) 3、再次换到页眉/页脚视图,点击设置页码格式按钮,将页码编排-起始页码设置为1

把Excel中的表格以图片形式复制到Word中
除了用抓图软件和全屏拷贝法外还有更简单的呢
先选定区域,按住Shift健点击"编辑"会出现"复制图片""粘贴图片",复制了后,在Word中选"粘贴图片"就可像处理图片一样处理Excel表格了!

Ctrl+鼠标滑轮(左右键中间的那个轮子)可以迅速调节显示比例的大小(100%)。向上滑扩大,向下滑缩小。


快速调整页眉横线长度
在word插入页眉后,会自动在此位置添加一条长横线。如果需要调整此线的长度及其水平位置,可以首先激活页眉,选择格式下的段落命令,调整一下左右缩进的字符值,确定可以看到最终效果了!

快速浏览图片
在WORD2003中,如果插入的图片过多,会影响打开和翻滚的速度。其实,我们可以通过改变图片的显示方式改变浏览速度。
工具--选项--视图--图片框
这样,先显示的是图片框,需要看的时候,停留,即可显示!

WORD 中如何输入分数
1、打开word,点击工具菜单栏的“插入”,在下拉菜单中点“域”。
2、在打开的复选框中的类别栏中“选等式公式”,域名中“EQ”。然后点击“选项”,在出现的菜单选项中选“F(,)”,接着点击“添加到域”并“确定”。
3、然后在输入F(,)数字,如要输入23 只需在F(,)输入F(2,3)就能得到2/3

怎样使WORD 文档只有第一页没有页眉,页脚
答:页面设置-页眉和页脚,选首页不同,然后选中首页页眉中的小箭头,格式-边框和底纹,选择无,这个只要在“视图”——“页眉页脚”,其中的页面设置里,不要整个文档,就可以看到一个“同前”的标志,不选,前后的设置情况就不同了

Word中双击鼠标的妙用
在Word的程序窗口中不同位置上双击,可以快速实现一些常用功能,我们归纳如下:
在标题栏或垂直滚动条下端空白区域双击,则窗口在最大化和原来状态之间切换;
将鼠标在标题栏最左边WORD文档标记符号处双击,则直接退出WORD(如果没有保存,会弹出提示保存对话框);
将鼠标移到垂直滚动条的上端成双向拖拉箭头时双击,则快速将文档窗口一分为二;
将鼠标移到两个窗口的分界线处成双向拖拉箭头时双击,则取消对窗口的拆分;
在状态栏上的“修订”上双击,则启动“修订”功能,并打开“审阅”工具栏。再次双击,则关闭该功能,但“审阅”工具栏不会被关闭;
在状态栏上的“改写”上双击,则转换为“改写”形式(再次“双击”,转换为“插入”形式);
如果文档添加了页眉(页脚),将鼠标移到页眉(页脚)处双击,则激活页眉(页脚)进入编辑状态,对其进行编辑;在空白文档处双击,则启动“即点即输”功能;
在标尺前端空白处双击,则启动“页面设置”对话框。


在word编辑中经常要调整字休大小来满足编辑要求
选中要修改的文字,按ctrl+]或ctrl+[来改变字体的大小!
这个方法可以微量改字体大小~



文本框的线条
1. 制作好文档后,通过“视图→页眉页脚”命令,调出“页眉页脚”工具栏,单击其中的“显示→隐藏文档正文文字”按钮,隐藏正文部分的文字内容。
2. 选择“插入”菜单中的“文本框”命令,在页眉的下方插入一个空文本框。
3. 在文本框内加入作为水印的文字、图形等内容,右击图片,选择快捷菜单中的“设置图片格式”命令,在对话框中“图片”选项卡下,通过“图像控制”改变图像的颜色,对比度和亮度,并手动调整图片的大小。   
4. 通过“设置文本框格式”命令,把文本框的线条色改为无线条色。
5. 单击“页眉页脚”工具栏的“关闭”按钮,退出“页眉页脚”编辑。

每页添加水印的操作
1. 制作好文档后,通过“视图→页眉页脚”命令,调出“页眉页脚”工具栏,单击其中的“显示→隐藏文档正文文字”按钮,隐藏正文部分的文字内容。
2. 选择“插入”菜单中的“文本框”命令,在页眉的下方插入一个空文本框。
3. 在文本框内加入作为水印的文字、图形等内容,右击图片,选择快捷菜单中的“设置图片格式”命令,在对话框中“图片”选项卡下,通过“图像控制”改变图像的颜色,对比度和亮度,并手动调整图片的大小。   
4. 通过“设置文本框格式”命令,把文本框的线条色改为无线条色。
5. 单击“页眉页脚”工具栏的“关闭”按钮,退出“页眉页脚”编辑。
6. 完成上述步骤的操作,水印制作得以完成,这样就为每一页都添加了相同的水印。

让Word页面快速一分为二
将光标定位在想分开的位置上,按下“Ctrl+Shift+Enter”组合键。


使Word中的字体变清晰
Word文档中使用 “仿宋” 字体很淡,可按以下方法使字体更清晰:
右击桌面,点 “属性”,点 “外观”,点 “效果”,选中“使用下列方式使屏幕字体的边缘平滑”选“清晰”,确定。

Word双面打印技巧
   我们平时用电脑的时候可能都少不了打印材料,Word是我们平常用的最多的Office软件之一。有时我们要用Word打印许多页的文档,出于格式要求或为了节省纸张,会进行双面打印

  我们一般常用的操作方法是:选择“打印”对话框底部的“打印”下拉列表框中的“打印奇数页”或“打印偶数页”,来实现双面打印。我们设定为先打印奇数页。等奇数页打印结束后,将原先已打印好的纸反过来重新放到打印机上,选择该设置的“打印偶数页”,单击“确定”按钮。这样通过两次打印命令就可以实现双面打印。

  我们也可以利用另一种更灵活的双面打印方式:打开“打印”对话框,选中“人工双面打印”,确定后就会出现一个“请将出纸器中已打印好的一面的纸取出并将其放回到送纸器中,然后‘确定’按键,继续打印”的对话框并开始打印奇数页,打完后将原先已打印好的纸反过来重新放到打印机上,然后按下该对话框的“确定”按键,Word就会自动再打印偶数页,这样只用一次打印命令就可以了。

  两种方法对比,后者较前者更为方便。

posted @ 2010-04-20 10:26 小强摩羯座 阅读(231) | 评论 (0)编辑 收藏

字符串拆分的中文处理问题

容健行@20077

转载请注明出处

原文出处:http://www.devdiv.net/home/space.php?uid=125&do=blog&id=365

概述:

拆分一个字符串在程序中使用非常广泛,特别是我们经常跟表格打交道的程序员们。所谓拆分字符串,就是将一个字符串中间以某个(或某些)字符为分隔,拆分成多个字符串。如 std::string s = "abc | ddd | 中国";    如果以竖线“|”拆分,可以将这个字符串拆分成三个字符串。

当然字符串拆分还包括通过正则表达式来拆分,为了简化问题,我们以单个字符做分隔的拆分,因为这种拆分用得最多。代码使用C++来讲解。

问题:

问题来源于实际,是之前我们组和其他组都有遇上的。先看一个例子,使用"|"拆分以下字符串,看起来怎么数都是分为48列,但我看到好几个版本的字符串拆分函数却报有49列:

"AGZGY1000004|200|刘瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾晓翔||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||"

原因分析:

让我们先把以上字符串放到UltraEdit中,并切换到16进制的编辑模式,看看它的编码。

原因是原来的字符串拆分函数只是简单的查找“|”(编码为0x7c,而没有考虑到中文的处理(源代码太多,且有好几个版本,这里略去)。

boss中,c++程序使用的编码方式几乎全为ansi,而在ansi中,表示中文是用两个字符,且第一个字符是一个大于0x80的字符(字符的第一位为1),第二个字符为任意字符。这里引起一个问题:

当我们要分割字符串时,假如用"|"(0x7c)作为分割符,当分析上面这个字符遇到""(编码为0xad,0x7c)这个字符时,会把它第二个字符作为了分割符,结果就多出了一列。

解决方案:

问题原因找到了,重新写了一下字符串拆分函数-Split,这里使用的方法是:找到分隔符后,再向前查找字符看一下它前一个字符是否为东亚文字的第一个字符编码(编码大于0x80)。

考虑到以后支持unicode,这里使用了模板。以下可能不是最高效简单的实现,但如果以后遇上这种问题,可以参考一下。

#include "stdafx.h"

#include <stdio.h>

#include <tchar.h>

#include <iostream>

#include <string>

#include <vector>

#include <algorithm>

#include <fstream>

// unicode 分割策略

inline

    bool __SplitPolicy(

    const std::wstring& s,

    const std::wstring& splitchar,

    std::wstring::size_type& pos)

{

    pos = s.find_first_of(splitchar, pos);

    return pos != std::string::npos;

}

// ansi 分割策略

inline

    bool __SplitPolicy(

    const std::string& s,

    const std::string& splitchar,

    std::string::size_type& pos)

{

    pos = s.find_first_of(splitchar, pos);

    if (pos != std::string::npos)

    {

       // 如果前一个字符的第一位为1,且当前字符是在东亚文字的第二个字符,

       // 则认为该字符是东亚字的其中一个字符,要跳过,不作为分割符。

       std::string::size_type i = 1;

       for (; i < pos; ++i)

       {

           if (!((char)(s[pos - i]) & 0x80)) // 判断第一位是否为1。(0x80的二进制为 10000000)

              break;

       }

       if (!(i % 2)) // 看一下当前字符是否为东亚文字的第二个字符

       {

           ++pos;

           __SplitPolicy(s, splitchar, pos);

       }

    }

    return pos != std::string::npos;

}

template<typename char_type> inline

    int Split(

    const std::basic_string<char_type>& s,

    const std::basic_string<char_type>& splitchar,

    std::vector<std::basic_string<char_type> >& vec)

{

    typedef std::basic_string<char_type>   string_t;

    typedef typename string_t::size_type   size_t;

    string_t tmpstr;

    size_t pos = 0, prev_pos = 0;

    vec.clear();

    while (__SplitPolicy(s, splitchar, pos))

    {

       tmpstr = s.substr(prev_pos, pos - prev_pos);

       vec.push_back(tmpstr);

       prev_pos = ++pos;

    }

    size_t len = s.length() - prev_pos;

    if (len > 0)

       vec.push_back(s.substr(prev_pos, len));

    return static_cast<int>(vec.size());

}

// ansi版本测试

void testSplit()

{

    std::vector<std::string> vec;

    const std::string str = "AGZGY1000004|200|刘瓅瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾晓翔||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||a";

    const std::string sp = "|";

    int count = Split(str, sp, vec);

    for (std::vector<std::string>::const_iterator it = vec.begin(); it != vec.end(); ++it)

       std::cout << *it << " ";

}

// unicode版本测试

void testSplitW()

{

    std::vector<std::wstring> vec;

    const std::wstring str = L"AGZGY1000004|200|刘瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾晓翔||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||";

    const std::wstring sp = L"|";

    Split(str, sp, vec);

    const char head[3] = {0xff, 0xfe, 0};

    const wchar_t line[3] = L" ";

    // 控制台输出不了unicode字符,使用输出到文件的方式

    std::ofstream fileOut("C:/out.txt");

    fileOut.write(head, 2);

    for (std::vector<std::wstring>::iterator it = vec.begin(); it != vec.end(); ++it)

    {

       fileOut.write((const char*)it->c_str(), it->length() * 2);

       fileOut.write((const char*)line, 2);

    }

}

int main()

{

    testSplit();

    testSplitW();

}

参考:

1http://unicode.org/

2《谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词》

posted @ 2010-04-19 01:47 小强摩羯座 阅读(745) | 评论 (0)编辑 收藏

关于C++中文字符的处理

一 引入问题
代码 wchar_t a[3]=L”中国”,编译时出错,出错信息为:数组越界。但wchar_t 是一个宽字节类型,数组a的大小应为6个字节,而两个汉字的的unicode码占4个字节,再加上一个结束符,最多6个字节,所以应该不会越界。难道是编译器出问题了?
二 解决引入问题所需的知识
   主要需两方面的知识,第一个为字符尤其是汉字的编码,以及语言和工具的支持情况,第二个是vc/c++中MutiByte Charater Set 和 Wide Character Set有关内存分配的情况.
三 汉字的编码方式及在vc/c++中的处理
1.汉字编码方式的介绍
对英文字符的处理,7位ASCII码字符集中的字符即可满足使用需求,且英文字符在计算机上的输入及输出也非常简单,因此,英文字符的输入、存储、内部处理和输出都可以只用同一个编码(如ASCII码)。
而汉字是一种象形文字,字数极多(现代汉字中仅常用字就有六、七千个,总字数高达5万个以上),且字形复杂,每一个汉字都有"音、形、义"三要素,同音字、异体字也很多,这些都给汉字的的计算机处理带来了很大的困难。要在计算机中处理汉字,必须解决以下几个问题:首先是汉字的输入,即如何把结构复杂的方块汉字输入到计算机中去,这是汉字处理的关键;其次,汉字在计算机内如何表示和存储?如何与西文兼容?最后,如何将汉字的处理结果从计算机内输出?
为此,必须将汉字代码化,即对汉字进行编码。对应于上述汉字处理过程中的输入、内部处理及输出这三个主要环节,每一个汉字的编码都包括输入码、交换码、内部码和字形码。在计算机的汉字信息处理系统中,处理汉字时要进行如下的代码转换:输入码→交换码→内部码→字形码。
(1)输入码: 作用是,利用它和现有的标准西文键盘结合来输入汉字。输入码也称为外码。主要归为四类:
a)      数字编码:数字编码是用等长的数字串为汉字逐一编号,以这个编号作为汉字的输入码。例如,区位码、电报码等都属于数字编码。
b)      拼音码:拼音码是以汉字的读音为基础的输入办法。
c)      字形码:字形码是以汉字的字形结构为基础的输入编码。例如,五笔字型码(王码)。
d)      音形码:音形码是兼顾汉字的读音和字形的输入编码。
(2)交换码:用于汉字外码和内部码的交换。交换码的国家标准代号为GB2312-80。
(3)内部码:内部码是汉字在计算机内的基本表示形式,是计算机对汉字进行识别、存储、处理和传输所用的编码。内部码也是双字节编码,将国标码两个字节的最高位都置为"1",即转换成汉字的内部码。
(4)字形码:字形码是表示汉字字形信息(汉字的结构、形状、笔划等)的编码,用来实现计算机对汉字的输出(显示、打印)。
2.VC中汉字的编码方式
     vc/c++正是采用了GB2312内部码作为汉字的编码方式,因此vc/c++中的各种输入输出方法,如cin/wcin,cout/wcout,scanf/wsanf,printf/wprintf...都是基于GB2312的,如果汉字的内码不是这种编码方式,那么利用上述各种方法就不会正确的解析汉字。
仔细观察ASCII字符表,从第161个字符开始,后面的字符并不经常为用户所使用,负值也未使用。GB2312编码方式充分利用这一特性,将161-255(-95~-1)之间的数值空间作为汉字的标识码。既然255-161 = 94不能满足汉字容量的要求,就将每两个字符并在一块(即一个汉字占两个字节),显然,94* 94 =8836基本上已经满足了常用汉字个数的要求。计算机处理字符时,当连续处理到两个大与160(或-95~-1)的字节时,就认为这两个字节存放了一个汉字字符。可以用下面的Demo程序来模拟vc/c++中输出汉字字符的过程。
    unsigned char input[50];
cin>>input;
    int flag=0;
     for(int i =0 ;i < 50 ;i++)
      {
         if(input[i] > 0xa0 && input[i] != 0)
          {
              if(flag == 1)
               {
                    cout<<"chinese character"<<endl;
                    flag = 0;
               }
              else
               {
                    flag++;
               }
          }
         else if(input[i] == 0)
          {
              break;
          }
         else
          {
               cout<<"english character"<<endl;
          }
}
输入:Hello中国 (“中国”对应的GB2312内码为:214 208,185 250)
输出:english character
english character
english character
english character
english character
chinese character
chinese character
vc/c++中的英文字符仍然采用ASCII编码方式。可以设想,其他国家程序员利用vc/c++编写程序输入本国字符时,vc/c++则会采用该国的字符编码方式来处理这些字符。
    问题又产生了,韩国的vc/c++程序在中国的vc/c++上运行时,如果没有相应的内码库,则对韩语字符的显示有可能出现乱码。我个人猜测,vc安装程序中应该带有不同国家的内码库,这样一来肯定会占用很大的空间。如果所有的国家使用统一的编码方式,且所有的程序设计语言和开发工具都支持这种编码方式该多好!而现实中,确实已经有这种编码方式了,且许多新的语言也都支持这种编码方式,如Java、C#等,它就是下面的Unicode编码
3.新的内码标准---Unicode
Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。随着计算机工作能力的增强,Unicode也在面世以来的十多年里得到普及。最新版本的 Unicode 是 2005年3月31推出的Unicode 4.1.0 。另外,5.0 Beta已于2005年12月12日推出,以供各会员评价。
Unicode 编码系统可分为编码方式和实现方式两个层次。
编码方式:Unicode 的编码方式与 ISO 10646 的通用字符集(Universal Character Set,UCS)概念相对应,目前的用于实用的 Unicode 版本对应于 UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。这样理论上一共最多可以表示 216 个字符。基本满足各种语言的使用。实际上目前版本的 Unicode 尚未填充满这16位编码,保留了大量空间作为特殊使用或将来扩展。
实现方式:Unicode 的实现方式不同于编码方式。一个字符的 Unicode 编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对 Unicode 编码的实现方式有所不同。Unicode 的实现方式称为Unicode转换格式(Unicode Translation Format,简称为 UTF)。如,UTF-8 编码,这是一种变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0)。而遇到与其他 Unicode 字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1进行识别。
Java与C#语言都是采用Unicode编码方式,在这两种语言中定义一个字符,在内存中存放的就是这个字符的两字节Unicode码。如下所示:
char a='我';     => 内存中存放的Unicode码为:25105
4.内码的相互转换
(1)vc中的实现方法
   利用Windows系统提供的API:::MultiByteToWideChar::WideCharToMultiByte
::MultiByteToWideChar实现当前码到Unicode码的转换;
::WideCharToMultiByte实现Unicode码到当前码的转换;
(2)Java中的实现方法
    String vcString=new String(javaString.getBytes("UTF-8"),"gb2312");
java的编码应该是UTF-8
(3)C#中的实现方法
    ??
四 vc中的MutiByte Charater Set 和 Wide Character Set
1.MultiByte Charater Set方式
   这种方式以按字节为单位存放字符,即如果一个字符码为两字节,则在内存中占两字节,字符码为一字节,就占一字节。例如,字符串“中国abc”的编码为:中(0xd6、0xd0)、国(0xb9、0xfa)、a(0x61)、b(0x62)、c(0x63)、\0(0x00),就存为如下方式:
对应的类型,方法有:
char、scanf、printf、cin、cout …
2.Wide Character Set
这种方式是以两字节为单位存放字符,即如果一个字符码为两字节,则在内存中占四字节,字符码为一字节,就占两字节。例如,字符串“中国abc”就存为如下方式:
对应的类型,方法有:
wchar_t、wscanf、wprintf、wcin、wcout …
造成上面存储方式的根本原因在于,wchar_t类型其实是一个unsigned short 类型。如,存储上面字符串的数组的定义为:wchar_t buffer[8] 等价于unsigned short buffer[8].而所有以字母w开头的方法也都是以unsigned short类型,即两字节为单位来处理字符,因此,存储在wchar_t类型数组中的字符串无法用cout显示,只能用wcout方法来显示。
由于Unicode码也是采用两个字节,因此Wide Character Set方式能够很好的支持Unicode码的存储,但是在vc的环境下要将一个Unicode码存入两字节而不是四字节内存中,必须通过上面的API函数::MultiByteToWideChar首先,将当前的编码转换为Unicode码,然后,将每个字符的Unicode码放入每一个wchar_t类型的变量中。以下是一个实例代码:
char input[50];
cin>>input;
int size;
size=::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,NULL,0);
if(size==0)
     return -1;
wchar_t *widebuff=new wchar_t[size];
::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,widebuff,size);
输入:中国abc
Debug断点调试:
size==6
数组widebuff[0-size]占12字节,存放了6个字符的Unicode码,码值为:
中(0x4e2d) 国(0x56fd) a(0x0061) b(0x0062) c(0x0063) d(0x0000)
这时,数组的大小size等于输入的字符个数加上一个结束符,符合我们的想象。
五 引入问题的错误分析
(1) 没有理解编译器中的编码方式
    虽然vc/c++中汉字的编码占两个字节,但并不是Unicode码,是GB2312码。
(2) 没有理解MutiByte Charater Set 和 Wide Character Set的存储原则;
    在vc/c++中,“中国”按char[5]来对待,而wchar_t a[3]实际上是三个unsigned short类型的变量,因此赋值时会越界。

posted @ 2010-04-18 01:10 小强摩羯座 阅读(208) | 评论 (0)编辑 收藏

    

//gameloft 笔试题
/*
1、RGB值转灰度值对32位整数取R,G,B对应的8位并加权合成。
2、求一个字符串中出现频率最高的字符。字符范围并涡有说明,通常应
指ASCII字符集,可是当时考虑复杂了,于是想到了stl的map来做。
结果没有写完。就交了。
*/
#include<iostream>

using namespace std;
#define CHARNUM 256 
//计算一个串最出现频率最高的字符

char mostFreq(const char* str)
{
 int freq[CHARNUM]= {0};
 int firstPos[CHARNUM] = {0};
 int pos = 0;
 const char* p = str;
 while( *p != '\0')
 {
  if(freq[*p] == 0)
  {
   firstPos[*p] = pos; 
  }
  freq[*p++]++;
   pos++;
  }
  int maxF = -1;
  int ch = '\0';
  for(int i = 1;i < 256;i++)
  {
   if( freq[i] > maxF)
   {
    ch = i;
   maxF = freq[i];
   }
   if( freq[i] == maxF)
   {
    if( firstPos[i] < firstPos[ch])
    {
     ch = i; 
    }
   }    
  }
  cout<<" maxF ="<<maxF<<endl;
 
  return (char)ch;
}
 
int main()
{
 int* a[9][4][5];
 
 
 int b = a[5] - a[3];
 cout<<"b = "<<b<<endl;
 
 int* c[3];
 
 char * str = "aabyebbdfdf 1`5454545$$$#$#$2788kldef";
 
 char ch;
 ch = mostFreq( str);
 
 cout<<"ch = " <<ch<<endl;
}
4.给出一个CThing 类的源代码让分析,其中有三个语句要求解释语句作用。
一个填空,分析时有点忙了,应该一个函数一个函数的分析,或许会有清晰思路。
将各个类的名称和功能整理下会理出些思路。
5、给出strcpy的源代码让说明其功能,并指出参数设置上只少一人错误
6、给出一个将整数i转换为8进制的方法,要求对其进行改进。
src:
void count(int i, char* str)
{
     map[
 sorry, 记忆不清楚了

7、给几个名词让解释placement new,ARM, GCC, android, 还有一人??
 8、英文解释题目。第一个还好。第二个说游戏加速的
 
 increment  ...update frame , ??这词词认识,放一起读不出来表示什么
 意思

posted @ 2010-04-17 01:38 小强摩羯座 阅读(181) | 评论 (0)编辑 收藏

     摘要:   1   2   3   4#include<cstdio>   5#include<iostream>   6#include<cstdlib>   7#include<typeinfo>&nbs...  阅读全文

posted @ 2010-04-16 10:31 小强摩羯座 阅读(220) | 评论 (0)编辑 收藏

     摘要:   1   2   3// realize a SingleList class   4/**//*   5实现方法   6add()   7add2Head(dd);   8del ...  阅读全文

posted @ 2010-04-16 10:30 小强摩羯座 阅读(165) | 评论 (0)编辑 收藏

/**
  * 实现测试:串匹配和词频统计功能
  */
 public  void largerTextExample()
 {
  String text = "你好abc,ac,abc,def,ac,okt, ac,dfdfe, ac , what is it 你好啊,bc";
  String[] terms = {"你好","ac", "abc", "bc"};
  for (int i = 0; i < terms.length; i++)
  {
   
   tree.add(terms[i].getBytes(), terms[i]);
   System.out.println( terms[i]);
  }
  tree.prepare();

  Set termsThatHit = new HashSet();
  Iterator iter = tree.search(text.getBytes());
  
//  统计词频
  Map<String, Integer> freqCount = new HashMap<String, Integer>();
  for (; iter.hasNext();)
  {
   SearchResult result = (SearchResult) iter.next();
   Set set = result.getOutputs();
   System.out.println(set);
   for(Iterator it = set.iterator();it.hasNext();)
   {
    String str = (String)it.next();
    if( freqCount.get(str) == null)
     freqCount.put(str, 1);
    else
     freqCount.put(str, freqCount.get(str)+1);
   }
  }
  for(String key: freqCount.keySet())
  {
   System.out.println( "key = " + key + ", value "+ freqCount.get(key) );
  }

------------结果-------------------------
你好
ac
abc
bc
[你好]
[abc, bc]
[ac]
[abc, bc]
[ac]
[ac]
[ac]
[你好]
[bc]
key = abc, value 2
key = 你好, value 2
key = ac, value 4
key = bc, value 3

posted @ 2010-01-21 23:46 小强摩羯座 阅读(1211) | 评论 (0)编辑 收藏

仅列出标题
共20页: 上一页 1 2 3 4 5 6 7 8 9 下一页 Last