|
生成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;
}
幾道面試筆試題
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倍.
|
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的倍數)!!
|
很實用的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就會自動再打印偶數頁,這樣只用一次打印命令就可以了。
兩種方法對比,后者較前者更為方便。
|
字符串拆分的中文處理問題
容健行@2007年7月
轉載請注明出處
原文出處: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();
}
參考:
1.http://unicode.org/
2.《談談Unicode編碼,簡要解釋UCS、UTF、BMP、BOM等名詞》
一 引入問題
代碼 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類型的變量,因此賦值時會越界。
//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 , ??這詞詞認識,放一起讀不出來表示什么
意思
摘要: 1
2
3
4#include<cstdio>
5#include<iostream>
6#include<cstdlib>
7#include<typeinfo>&nbs... 閱讀全文
摘要: 1
2
3// realize a SingleList class
4/**//*
5實現方法
6add()
7add2Head(dd);
8del
... 閱讀全文
/**
* 實現測試:串匹配和詞頻統計功能
*/
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
|