程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C Run-Time Library函數__isascii&iswascii& __toascii

C Run-Time Library函數__isascii&iswascii& __toascii

編輯:關於C語言

Determines whether a particular character is an ASCII character.

int __isascii(
int c
);
int iswascii(
wint_t c
);

測試程序:

#include "stdafx.h"
#include "ctype.h"
#include "locale.h"
#include "stdio.h"

void CheckCharAndPrint(char acChar)
{
if(__isascii(acChar))
{
printf("char %c is a ascii char.\n",acChar);
}
else
{
// 此處無法正常輸出中文,沒有深入研究了
printf("char %c is not a ascii char.\n",acChar);
}
}

void CheckWCharAndPrint(wchar_t awcChar)
{
if(iswascii(awcChar))
{
wprintf(L"wchar %c is a ascii char.\n",awcChar);
}
else
{
setlocale(LC_ALL,"");
wprintf(L"wchar %c is not a ascii char.\n",awcChar);
}
}

int _tmain(int argc, _TCHAR* argv[])
{
char lcC = 'a';
char lcD = '中';

CheckCharAndPrint(lcC);
CheckCharAndPrint(lcD);

wchar_t lwcC = L'a';
wchar_t lwcD = L'中';

CheckWCharAndPrint(lwcC);
CheckWCharAndPrint(lwcD);

return 0;
}

說明:

__isascii是一個比較特殊的函數,因為它以兩個前置下劃線開頭。這在C語言中並不多見。(起碼我看到的比較少)

此函數應該不屬於標准庫函數,《TCPL》中,《C語言參考》中並沒有描述,但是gcc中有此函數。也就是說linux下也能正常使用此函數。

iswascii這個__isascii函數的寬字節版本,如同很多寬字節版本的函數一樣,這個函數屬於MS自己擴的,於是。。linux下無法使用此函數,要使用,只能自己實現羅。

實現:

MS:

#define __isascii(_Char) ( (unsigned)(_Char) < 0x80 )
inline int __cdecl iswascii(wint_t _C) {return ((unsigned)(_C) < 0x80); }
gcc:
#define __isascii(c) (((c) & ~0x7f) == 0) /* if C is a 7 bit value*/

__isascii都是一個簡單的宏。MS的iswascii原理和其__isascii都一樣,僅僅是一個內聯的函數。

微軟的實現是依賴於字符小於128(0x80),這裡還做了一次強轉,不是太理解,因為實際char可以直接作為整數來比較,也許僅僅是為了屏蔽warning?

gcc的實現是依賴於字符除低七位外無任何其他值。即先將127(0x7f)取反,再與字符位與。實際就是取得字符c除了低七位以外的值。再比較此值是否為零。

想不到一個這樣簡單的函數,MS,gcc的實現差別都這麼大,相對而言MS的實現自然是比較淺顯易懂的,但是gcc用這麼復雜的實現,應該有更好的效率。

就分析而言,強轉+小於操作 運行時間大於 一次取反一次位與一次等於操作。還真不容易知道誰的效率真的更高。那麼就測試一下吧。

效率測試:

#include "jtianling.h"
#define __isasciims(_Char) ( (unsigned)(_Char) < 0x80 )
#define __isasciigcc(c) (((c) & ~0x7f) == 0) /* if C is a 7 bit value*/

const int DEF_TEST_TIMES = 1000000000;

void CheckMS(char ac)
{
double ldTimeLast = jtianling::GetTime();
for (int i=0; i<DEF_TEST_TIMES ; ++i)
{

__isasciims(ac);

}
double ldTimePast = jtianling::GetTime() - ldTimeLast;

printf("__isasciims %c run %d times cost %lf secs.\n", ac, DEF_TEST_TIMES, ldTimePast);
}

void Checkgcc(char ac)
{
double ldTimeLast = jtianling::GetTime();
for (int i=0; i<DEF_TEST_TIMES ; ++i)
{

__isasciigcc(ac);

}
double ldTimePast = jtianling::GetTime() - ldTimeLast;

printf("__isasciigcc %c run %d times cost %lf secs.\n", ac, DEF_TEST_TIMES, ldTimePast);
}

int _tmain(int argc, _TCHAR* argv[])
{
char lc = 'a';
char lc2 = '中';
CheckMS(lc);
Checkgcc(lc);
CheckMS(lc);
Checkgcc(lc2);

return 0;
}

至於GetTime函數的意義,請參考我以前寫的庫,無非就是獲取當前時間,不知道也沒有關系。你可以用time(NULL)來替代,只不過精度沒有這個函數高而已。

實際的測試結果很讓人失望,在測試了幾乎無數次以後,MS和gcc的實現效率都幾乎相同,在10億這個級別,gcc也不過有時快0.1秒而已,而且多次運行,還不是太穩定。看來並不是復雜的實現就一定好。。。

相關函數:

msdn:
Converts characters.
int __toascii(
int c
);

這個函數也是一個雙前置下劃線的函數,MS,gcc中都有實現。而且在此時,實現都是一樣的。

#define __toascii(_Char) ( (_Char) & 0x7f )

gcc注釋到 “mask off high bits.”

這裡和gcc中__isascii函數實現的前一部分很像,一個是去除低七位,一個是保留低七位。看了這個以後才知道gcc為什麼想到這樣實現__isascii了。

個人想法:

這兩個函數在實際中我從來沒有用到過,假如不是我工作范圍太窄那就是這兩個函數的使用性並不強了,的確,我沒有事去把一個值轉為ascii?是ascii的話就沒有意義,不是的話,原來的含義還能保留嗎?至於__isascii函數可能還在某些情況下有用吧,只不過我沒有用到過,誰有實際中使用此兩個函數的代碼可以告訴我一下。

另外,總結的是,雖然C Runtime庫MS也有源碼,但是完全沒有任何注釋。相對而言gcc的注釋就算是很豐富和詳細了,呵呵,畢竟開源代碼就是不一樣啊,做來就是給人看的,想想這樣分析下去,光是看源代碼收獲都不會太小。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved