C++字符串完全指引之一 —— Win32 字符编码 (转载)

C++字符串完全指引之一 —— Win32 字符编码


原著:Michael Dunn

翻译:Chengjie Sun



原文出处:CodeProject:The Complete Guide to C++ Strings, Part I

paragraph 引言

  毫无疑问,我们都看到过像 TCHAR, std::string, BSTR 等各种各样的字符串类型,还有那些以 _tcs 开头的奇怪的宏。你也许正在盯着显示器发愁。本指引将总结引进各种字符类型的目的,展示一些简单的用法,并告诉您在必要时,如何实现各种字符串类型之间的转换。
  在第一部分,我们将介绍3种字符编码类型。了解各种编码模式的工作方式是很重要的事情。即使你已经知道一个字符串是一个字符数组,你也应该阅读本部分。一旦你了解了这些,你将对各种字符串类型之间的关系有一个清楚地了解。
  在第二部分,我们将单独讲述string类,怎样使用它及实现他们相互之间的转换。

paragraph 字符基础 -- ASCII, DBCS, Unicode

  所有的 string 类都是以C-style字符串为基础的。C-style 字符串是字符数组。所以我们先介绍字符类型。这里有3种编码模式对应3种字符类型。第一种编码类型是单子节字符集(single-byte character set or SBCS)。在这种编码模式下,所有的字符都只用一个字节表示。ASCII是SBCS。一个字节表示的0用来标志SBCS字符串的结束。
  第二种编码模式是多字节字符集(multi-byte character set or MBCS)。一个MBCS编码包含一些一个字节长的字符,而另一些字符大于一个字节的长度。用在Windows里的MBCS包含两种字符类型,单字节字符(single-byte characters)和双字节字符(double-byte characters)。由于Windows里使用的多字节字符绝大部分是两个字节长,所以MBCS常被用DBCS代替。
  在DBCS编码模式中,一些特定的值被保留用来表明他们是双字节字符的一部分。例如,在Shift-JIS编码中(一个常用的日文编码模式),0x81-0x9f之间和 0xe0-oxfc之间的值表示"这是一个双字节字符,下一个子节是这个字符的一部分。"这样的值被称作"leading bytes",他们都大于0x7f。跟随在一个leading byte子节后面的字节被称作"trail byte"。在DBCS中,trail byte可以是任意非0值。像SBCS一样,DBCS字符串的结束标志也是一个单字节表示的0。
  第三种编码模式是Unicode。Unicode是一种所有的字符都使用两个字节编码的编码模式。Unicode字符有时也被称作宽字符,因为它比单子节字符宽(使用了更多的存储空间)。注意,Unicode不能被看作MBCS。MBCS的独特之处在于它的字符使用不同长度的字节编码。Unicode字符串使用两个字节表示的0作为它的结束标志。
  单字节字符包含拉丁文字母表,accented characters及ASCII标准和DOS操作系统定义的图形字符。双字节字符被用来表示东亚及中东的语言。Unicode被用在COM及Windows NT操作系统内部。
  你一定已经很熟悉单字节字符。当你使用char时,你处理的是单字节字符。双字节字符也用char类型来进行操作(这是我们将会看到的关于双子节字符的很多奇怪的地方之一)。Unicode字符用wchar_t来表示。Unicode字符和字符串常量用前缀L来表示。例如:

wchar_t wch = L''1''; // 2 bytes, 0x0031
wchar_t* wsz = L"Hello"; // 12 bytes, 6 wide characters

paragraph 字符在内存中是怎样存储的

  单字节字符串:每个字符占一个字节按顺序依次存储,最后以单字节表示的0结束。例如。"Bob"的存贮形式如下:

426F6200
BobBOS

Unicode的存储形式,L"Bob"

42 00 6F 0062 0000 00
BobBOS

使用两个字节表示的0来做结束标志。

  一眼看上去,DBCS 字符串很像 SBCS 字符串,但是我们一会儿将看到 DBCS 字符串的微妙之处,它使得使用字符串操作函数和永字符指针遍历一个字符串时会产生预料之外的结果。字符串" " ("nihongo")在内存中的存储形式如下(LB和TB分别用来表示 leading byte 和 trail byte)

93 FA96 7B8C EA00
LB TBLB TBLB TBEOS
ri ben yu EOS

值得注意的是,"ni"的值不能被解释成WORD型值0xfa93,而应该看作两个值93和fa以这种顺序被作为"ni"的编码。

paragraph 使用字符串处理函数

  我们都已经见过C语言中的字符串函数,strcpy(), sprintf(), atoll()等。这些字符串只应该用来处理单字节字符字符串。标准库也提供了仅适用于Unicode类型字符串的函数,比如wcscpy(), swprintf(), wtol()等。
  微软还在它的CRT(C runtime library)中增加了操作DBCS字符串的版本。Str***()函数都有对应名字的DBCS版本_mbs***()。如果你料到可能会遇到DBCS字符串(如果你的软件会被安装在使用DBCS编码的国家,如中国,日本等,你就可能会),你应该使用_mbs***()函数,因为他们也可以处理SBCS字符串。(一个DBCS字符串也可能含有单字节字符,这就是为什么_mbs***()函数也能处理SBCS字符串的原因)
  让我们来看一个典型的字符串来阐明为什么需要不同版本的字符串处理函数。我们还是使用前面的Unicode字符串 L"Bob":

42 00 6F 0062 0000 00
BobBOS

  因为x86CPU是little-endian,值0x0042在内存中的存储形式是42 00。你能看出如果这个字符串被传给strlen()函数会出现什么问题吗?它将先看到第一个字节42,然后是00,而00是字符串结束的标志,于是strlen()将会返回1。如果把"Bob"传给wcslen(),将会得出更坏的结果。wcslen()将会先看到0x6f42,然后是0x0062,然后一直读到你的缓冲区的末尾,直到发现00 00结束标志或者引起了GPF。
  到目前为止,我们已经讨论了str***()和wcs***()的用法及它们之间的区别。Str***()和_mbs**()之间的有区别区别呢?明白他们之间的区别,对于采用正确的方法来遍历DBCS字符串是很重要的。下面,我们将先介绍字符串的遍历,然后回到str***()与_mbs***()之间的区别这个问题上来。

paragraph 正确的遍历和索引字符串

  因为我们中大多数人都是用着SBCS字符串成长的,所以我们在遍历字符串时,常常使用指针的++-和-操作。我们也使用数组下标的表示形式来操作字符串中的字符。这两种方式是用于SBCS和Unicode字符串,因为它们中的字符有着相同的宽度,编译器能正确的返回我们需要的字符。
  然而,当碰到DBCS字符串时,我们必须抛弃这些习惯。这里有使用指针遍历DBCS字符串时的两条规则。违背了这两条规则,你的程序就会存在DBCS有关的bugs。

  • 1.在前向遍历时,不要使用++操作,除非你每次都检查lead byte;
  • 2.永远不要使用-操作进行后向遍历。
  •   我们先来阐述规则2,因为找到一个违背它的真实的实例代码是很容易的。假设你有一个程序在你自己的目录里保存了一个设置文件,你把安装目录保存在注册表中。在运行时,你从注册表中读取安装目录,然后合成配置文件名,接着读取该文件。假设,你的安装目录是C:\Program Files\MyCoolApp,那么你合成的文件名应该是C:\Program Files\MyCoolApp\config.bin。当你进行测试时,你发现程序运行正常。
      现在,想象你合成文件名的代码可能是这样的:

    bool GetConfigFileName ( char* pszName, size_t nBuffSize )
    {char szConfigFilename[MAX_PATH];// Read install dir from registry... we''ll assume it succeeds.// Add on a backslash if it wasn''t present in the registry value.// First, get a pointer to the terminating zero.char* pLastChar = strchr ( szConfigFilename, ''\0'' );// Now move it back one character.pLastChar--;  if ( *pLastChar != ''\\'' )strcat ( szConfigFilename, "\\" );// Add on the name of the config file.strcat ( szConfigFilename, "config.bin" );// If the caller''s buffer is big enough, return the filename.if ( strlen ( szConfigFilename ) >= nBuffSize )return false;else{strcpy ( pszName, szConfigFilename );return true;}
    }      
      这是一段很健壮的代码,然而在遇到 DBCS 字符时它将会出错。让我们来看看为什么。假设一个日本用户使用了你的程序,把它安装在 C:\youkoso.gif。下面是这个名字在内存中的存储形式:
     
    433A5C83 8883 4583 5283 5C00
       LB TB LB TB LB TB LB TB  
    C:\yo u ko so EOS

      当使用 GetConfigFileName() 检查尾部的''\\''时,它寻找安装目录名中最后的非0字节,看它是等于''\\''的,所以没有重新增加一个''\\''。结果是代码返回了错误的文件名。
      哪里出错了呢?看看上面两个被用蓝色高量显示的字节。斜杠''\\''的值是0x5c。'' ''的值是83 5c。上面的代码错误的读取了一个 trail byte,把它当作了一个字符。
      正确的后向遍历方法是使用能够识别DBCS字符的函数,使指针移动正确的字节数。下面是正确的代码。(指针移动的地方用红色标明)

    bool FixedGetConfigFileName ( char* pszName, size_t nBuffSize )
    {char szConfigFilename[MAX_PATH];// Read install dir from registry... we''ll assume it succeeds.// Add on a backslash if it wasn''t present in the registry value.// First, get a pointer to the terminating zero.char* pLastChar = _mbschr ( szConfigFilename, ''\0'' );// Now move it back one double-byte character.  pLastChar = CharPrev ( szConfigFilename, pLastChar );if ( *pLastChar != ''\\'' )_mbscat ( szConfigFilename, "\\" );// Add on the name of the config file._mbscat ( szConfigFilename, "config.bin" );// If the caller''s buffer is big enough, return the filename.if ( _mbslen ( szInstallDir ) >= nBuffSize )return false;else{_mbscpy ( pszName, szConfigFilename );return true;}
    }
    
      上面的函数使用CharPrev() API使pLastChar向后移动一个字符,这个字符可能是两个字节长。在这个版本里,if条件正常工作,因为lead byte永远不会等于0x5c。
      让我们来想象一个违背规则1的场合。例如,你可能要检测一个用户输入的文件名是否多次出现了'':''。如果,你使用++操作来遍历字符串,而不是使用CharNext(),你可能会发出不正确的错误警告如果恰巧有一个trail byte它的值的等于'':''的值。
    与规则2相关的关于字符串索引的规则:
    2a. 永远不要使用减法去得到一个字符串的索引。

    违背这条规则的代码和违背规则2的代码很相似。例如,

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

    这和向后移动一个指针是同样的效果。

    paragraph 回到关于str***()和_mbs***()的区别

      现在,我们应该很清楚为什么_mbs***()函数是必需的。Str***()函数根本不考虑DBCS字符,而_mbs***()考虑。如果,你调用strrchr("C:\\ ", ''\\''),返回结果可能是错误的,然而_mbsrchr()将会认出最后的双字节字符,返回一个指向真的''\\''的指针。
      关于字符串函数的最后一点:str***()和_mbs***()函数认为字符串的长度都是以char来计算的。所以,如果一个字符串包含3个双字节字符,_mbslen()将会返回6。Unicode函数返回的长度是按wchar_t来计算的。例如,wcslen(L"Bob")返回3。

    paragraph Win32 API中的MBCS和Unicode

    两组 APIs:
      尽管你也许从来没有注意过,Win32中的每个与字符串相关的API和message都有两个版本。一个版本接受MBCS字符串,另一个接受Unicode字符串。例如,根本没有SetWindowText()这个API,相反,有SetWindowTextA()和SetWindowTextW()。后缀A表明这是MBCS函数,后缀W表示这是Unicode版本的函数。
      当你 build 一个 Windows 程序,你可以选择是用 MBCS 或者 Unicode APIs。如果,你曾经用过VC向导并且没有改过预处理的设置,那表明你用的是MBCS版本。那么,既然没有 SetWindowText() API,我们为什么可以使用它呢?winuser.h头文件包含了一些宏,例如:

    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 APIs来build程序时,UNICODE没有被定义,所以预处理器看到:
    #define SetWindowText SetWindowTextA

      这个宏定义把所有对SetWindowText的调用都转换成真正的API函数SetWindowTextA。(当然,你可以直接调用SetWindowTextA() 或者 SetWindowTextW(),虽然你不必那么做。)
      所以,如果你想把默认使用的API函数变成Unicode版的,你可以在预处理器设置中,把_MBCS从预定义的宏列表中删除,然后添加UNICODE和_UNICODE。(你需要两个都定义,因为不同的头文件可能使用不同的宏。) 然而,如果你用char来定义你的字符串,你将会陷入一个尴尬的境地。考虑下面的代码:

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

    在预处理器把SetWindowText用SetWindowTextW来替换后,代码变成:

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

      看到问题了吗?我们把单字节字符串传给了一个以Unicode字符串做参数的函数。解决这个问题的第一个方案是使用 #ifdef 来包含字符串变量的定义:

    HWND hwnd = GetSomeWindowHandle();
    #ifdef UNICODE
    wchar_t szNewText[] = L"we love Bob!";
    #else
    char szNewText[] = "we love Bob!";
    #endif
    SetWindowText ( hwnd, szNewText );

    你可能已经感受到了这样做将会使你多么的头疼。完美的解决方案是使用TCHAR.

    paragraph 使用TCHAR

      TCHAR是一种字符串类型,它让你在以MBCS和UNNICODE来build程序时可以使用同样的代码,不需要使用繁琐的宏定义来包含你的代码。TCHAR的定义如下:

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

    所以用MBCS来build时,TCHAR是char,使用UNICODE时,TCHAR是wchar_t。还有一个宏来处理定义Unicode字符串常量时所需的L前缀。

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

      ##是一个预处理操作符,它可以把两个参数连在一起。如果你的代码中需要字符串常量,在它前面加上_T宏。如果你使用Unicode来build,它会在字符串常量前加上L前缀。

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

      像是用宏来隐藏SetWindowTextA/W的细节一样,还有很多可以供你使用的宏来实现str***()和_mbs***()等字符串函数。例如,你可以使用_tcsrchr宏来替换strrchr()、_mbsrchr()和wcsrchr()。_tcsrchr根据你预定义的宏是_MBCS还是UNICODE来扩展成正确的函数,就像SetWindowText所作的一样。
      不仅str***()函数有TCHAR宏。其他的函数如, _stprintf(代替sprinft()和swprintf()),_tfopen(代替fopen()和_wfopen())。 MSDN中"Generic-Text Routine Mappings."标题下有完整的宏列表。

    paragraph 字符串和TCHAR typedefs

      由于Win32 API文档的函数列表使用函数的常用名字(例如,"SetWindowText"),所有的字符串都是用TCHAR来定义的。(除了XP中引入的只适用于Unicode的API)。下面列出一些常用的typedefs,你可以在msdn中看到他们。

    type Meaning in MBCS builds Meaning in Unicode builds
    WCHARwchar_twchar_t
    LPSTR zero-terminated string of char (char*)zero-terminated string of char (char*)
    LPCSTR constant zero-terminated string of char (const char*)constant zero-terminated string of char (const char*)
    LPWSTRzero-terminated Unicode string (wchar_t*) zero-terminated Unicode string (wchar_t*)
    LPCWSTRconstant zero-terminated Unicode string (const wchar_t*)constant zero-terminated Unicode string (const wchar_t*)
    TCHARcharwchar_t
    LPTSTRzero-terminated string of TCHAR (TCHAR*) zero-terminated string of TCHAR (TCHAR*)
    LPCTSTR constant zero-terminated string of TCHAR (const TCHAR*)constant zero-terminated string of TCHAR (const TCHAR*)

    paragraph 何时使用 TCHAR 和 Unicode

      到现在,你可能会问,我们为什么要使用Unicode。我已经用了很多年的char。下列3种情况下,使用Unicode将会使你受益:

  • 1.你的程序只运行在Windows NT系统中。
  • 2. 你的程序需要处理超过MAX_PATH个字符长的文件名。
  • 3. 你的程序需要使用XP中引入的只有Unicode版本的API.
  •   Windows 9x 中大多数的 API 没有实现 Unicode 版本。所以,如果你的程序要在windows 9x中运行,你必须使用MBCS APIs。然而,由于NT系统内部都使用Unicode,所以使用Unicode APIs将会加快你的程序的运行速度。每次,你传递一个字符串调用MBCS API,操作系统会把这个字符串转换成Unicode字符串,然后调用对应的Unicode API。如果一个字符串被返回,操作系统还要把它转变回去。尽管这个转换过程被高度优化了,但它对速度造成的损失是无法避免的。
      只要你使用Unicode API,NT系统允许使用非常长的文件名(突破了MAX_PATH的限制,MAX_PATH=260)。使用Unicode API的另一个优点是你的程序会自动处理用户输入的各种语言。所以一个用户可以输入英文,中文或者日文,而你不需要额外编写代码去处理它们。
      最后,随着windows 9x产品的淡出,微软似乎正在抛弃MBCS APIs。例如,包含两个字符串参数的SetWindowTheme() API只有Unicode版本的。使用Unicode来build你的程序将会简化字符串的处理,你不必在MBCS和Unicdoe之间相互转换。
      即使你现在不使用Unicode来build你的程序,你也应该使用TCHAR及其相关的宏。这样做不仅可以的代码可以很好地处理DBCS,而且如果将来你想用Unicode来build你的程序,你只需要改变一下预处理器中的设置就可以实现了。

     

     

     

    paragraph 作者简介
      Michael Dunn:居住在阳光城市洛杉矶。他是如此的喜欢这里的天气以致于想一生都住在这里。他在4年级时开始编程,那时用的电脑是Apple //e。1995年,在 UCLA 获得数学学士学位,随后在Symantec 公司做 QA 工程师,在 Norton AntiVirus 组工作。他自学了 Windows 和 MFC 编程。1999-2000年,他设计并实现了 Norton AntiVirus 的新界面。 
      Michael 现在在 Napster(一个提供在线订阅音乐服务的公司)做开发工作,他还开发了UltraBar,一个IE工具栏插件,它可以使网络搜索更加容易,给了 googlebar 以沉重打击;他还开发了 CodeProject SearchBar;与人共同创建了 Zabersoft 公司,该公司在洛杉矶和丹麦的 Odense 都设有办事处。
      他喜欢玩游戏。爱玩的游戏有 pinball, bike riding,偶尔还玩 PS, Dreamcasth 和 MAME 游戏。他因忘了自己曾经学过的语言:法语、汉语、日语而感到悲哀。

    原文地址: http://www.vckbase.com/document/viewdoc/?id=1082

    转载于:https://www.cnblogs.com/Binhua-Liu/archive/2010/06/07/1753402.html

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/391945.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    网络计算机无法访问 请检查,局域网电脑无法访问,请检查来宾访问帐号是否开通...

    局域网电脑无法访问,有时候并不是由于网络故障引起的,而是因为自身电脑的一些设置问题,例如之前谈过的网络参数设置不对造成局域网电脑无法访问。今天分析另一个电脑设置的因素,它也会导致局域网电脑无法访问,那就是宾…

    雷军的金山云D轮获3亿美元!投后估值达19亿美金

    12月12日,雷军旗下金山云宣布D轮完成3亿美元融资,金额为云行业单轮融资最高。至此金山云投后估值达到19亿美元,成为国内估值最高的独立云服务商。金山集团相关公告显示,金山云在本轮融资中总计发行3.535亿股D系列优先股。骊悦投资…

    转:利用深度学习方法进行情感分析以及在海航舆情云平台的实践

    http://geek.csdn.net/news/detail/139152 本文主要为大家介绍深度学习算法在自然语言处理任务中的应用——包括算法的原理是什么,相比于其他算法它具有什么优势,以及如何使用深度学习算法进行情感分析。 原理解析 在讲算法之前,我们需要先剖…

    消费者行为分析_消费者行为分析-是否点击广告?

    消费者行为分析什么是消费者行为? (What is Consumer Behavior?) consumer behavior is the study of individuals, groups, or organizations and all the activities associated with the purchase, use, and disposal of goods and services, and how the consu…

    魅族mx5游戏模式小熊猫_您不知道的5大熊猫技巧

    魅族mx5游戏模式小熊猫重点 (Top highlight)I’ve been using pandas for years and each time I feel I am typing too much, I google it and I usually find a new pandas trick! I learned about these functions recently and I deem them essential because of ease of u…

    非常详细的Django使用Token(转)

    基于Token的身份验证 在实现登录功能的时候,正常的B/S应用都会使用cookiesession的方式来做身份验证,后台直接向cookie中写数据,但是由于移动端的存在,移动端是没有cookie机制的,所以使用token可以实现移动端和客户端的token通信。 验证流程 整个基于Token的验证流程如下: 客户…

    数据科学中的数据可视化

    数据可视化简介 (Introduction to Data Visualization) Data visualization is the process of creating interactive visuals to understand trends, variations, and derive meaningful insights from the data. Data visualization is used mainly for data checking and cl…

    手把手教你webpack3(6)css-loader详细使用说明

    CSS-LOADER配置详解 前注: 文档全文请查看 根目录的文档说明。 如果可以,请给本项目加【Star】和【Fork】持续关注。 有疑义请点击这里,发【Issues】。 1、概述 对于一般的css文件,我们需要动用三个loader(是不是觉得好…

    多重线性回归 多元线性回归_了解多元线性回归

    多重线性回归 多元线性回归Video Link影片连结 We have taken a look at Simple Linear Regression in Episode 4.1 where we had one variable x to predict y, but what if now we have multiple variables, not just x, but x1,x2, x3 … to predict y — how would we app…

    tp703n怎么做无线打印服务器,TP-Link TL-WR703N无线路由器无线AP模式怎么设置

    TP-Link TL-WR703N无线路由器配置简单,不过对于没有网络基础的用户来说,完成路由器的安装和无线AP模式的设置,仍然有一定的困难,本文学习啦小编主要介绍TP-Link TL-WR703N无线路由器无线AP模式的设置方法!TP-Link TL-WR703N无线路…

    pandas之groupby分组与pivot_table透视

    一、groupby 类似excel的数据透视表,一般是按照行进行分组,使用方法如下。 df.groupby(byNone, axis0, levelNone, as_indexTrue, sortTrue, group_keysTrue,squeezeFalse, observedFalse, **kwargs) 分组得到的直接结果是一个DataFrameGroupBy对象。 df…

    js能否打印服务器端文档,js打印远程服务器文件

    js打印远程服务器文件 内容精选换一换对于密码鉴权方式创建的Windows 2012弹性云服务器,使用初始密码以MSTSC方式登录时,登录失败,系统显示“第一次登录之前,你必须更改密码。请更新密码,或者与系统管理员或技术支持联…

    如何使用Python处理丢失的数据

    The complete notebook and required datasets can be found in the git repo here完整的笔记本和所需的数据集可以在git repo中找到 Real-world data often has missing values.实际数据通常缺少值 。 Data can have missing values for a number of reasons such as observ…

    为什么印度盛产码农_印度农产品价格的时间序列分析

    为什么印度盛产码农Agriculture is at the center of Indian economy and any major change in the sector leads to a multiplier effect on the entire economy. With around 17% contribution to the Gross Domestic Product (GDP), it provides employment to more than 50…

    pandas处理excel文件和csv文件

    一、csv文件 csv以纯文本形式存储表格数据 pd.read_csv(文件名),可添加参数enginepython,encodinggbk 一般来说,windows系统的默认编码为gbk,可在cmd窗口通过chcp查看活动页代码,936即代表gb2312。 例如我的电脑默认编码时gb2312&…

    tukey检测_回到数据分析的未来:Tukey真空度的整洁实现

    tukey检测One of John Tukey’s landmark papers, “The Future of Data Analysis”, contains a set of analytical techniques that have gone largely unnoticed, as if they’re hiding in plain sight.John Tukey的标志性论文之一,“ 数据分析的未来 ”&#x…

    spring— Spring与Web环境集成

    ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件) 方式获取的,但是每次从容器中获 得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件) ,这样的弊端是配置文件加载多次…

    Elasticsearch集群知识笔记

    Elasticsearch集群知识笔记 Elasticsearch内部提供了一个rest接口用于查看集群内部的健康状况: curl -XGET http://localhost:9200/_cluster/healthresponse结果: {"cluster_name": "format-es","status": "green&qu…

    matplotlib图表介绍

    Matplotlib 是一个python 的绘图库,主要用于生成2D图表。 常用到的是matplotlib中的pyplot,导入方式import matplotlib.pyplot as plt 一、显示图表的模式 1.plt.show() 该方式每次都需要手动show()才能显示图表,由于pycharm不支持魔法函数&a…

    到2025年将保持不变的热门流行技术

    重点 (Top highlight)I spent a good amount of time interviewing SMEs, data scientists, business analysts, leads & their customers, programmers, data enthusiasts and experts from various domains across the globe to identify & put together a list that…