【win32】day02-字符与编码

本文详细介绍了字符编码的历史与发展,包括ASCII、扩展ASCII、DBCS及Unicode编码,并探讨了这些编码在C语言中的应用及如何在Win32程序中处理字符编码问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

字符编码

2.1 编码的历史

  2.1.1 ASCII  0-127    7位表示

  2.1.2 ASCII扩展码 0-255   8位表示

   代码页:通过代码页来切换对应的字符

  2.1.3 双字节字符集 DBCS

    使用一个或两个字节表示字符.       

       "AB"

          12 1 2

          A: 0x41 :0x8051

          B: 0x42 :0x8253

          

            1    2    3    4    5     6

          0x41  0x80 0x51  0x42  0x82  0x53   

          A      中      B      

  2.1.4 Unicode

     全部使用2个字节表示字符

"A B"

           2  2 2 2

          A: 0x0041 :0x8051

          B: 0x0042 :0x8253

------------内存当中,小字节在前,高字节在后------------

          1  2  3   4    5   6   7   8

         41  00  51  80   42  00  53  82

       带来的问题:??

       内存/硬盘等资源占用变大.

       对编程支持度.c语言输出字符串,遇到\0结束。

C语言和编码

2.2.1 单字节的字符和字符串

      char cText = 'A';

      char * pszText = "ABCD";

      

    2.2.2 宽字节的字符

      wchar_t cText = 'A'

      wchar_t * pszText = L"ABCD";

      

    2.2.3 相关函数

单字字符的函数,对应有多.宽字节的函数.

       strlen wcslen mbslen

       printf wprintf

       

    2.2.4 TCHAR

      为了程序中可以方便的支持的Unicode和多字节字符等,所以使用TCHAR来定义字符和字符串.

      根据_UNICODE宏开关,会将TCHAR编译成不同字符类型.

         #ifndef _UNICODE

    typedef char TCHAR

     #define __T(x) x

   #else

typedef wchar_t TCHAR

  #define __T(x)  L##x

 #endif

使用时,要增加TCHAR.H头文件支持,使用_UNICODE宏开关进行编译    

   CL window.c  /D_UNICODE

 或者在程序中

 #define _UNICODE

 #include "tchar.h"

 

定义方式:

   TCAHR * pszText = __T("ABCDEF");

   

代码使用:使用UNICODE宏开关,通知编译器选择编译的代码.

#ifndef _UNICODE

int nLen = strlen( pszText );

#else

int nLen = wcslen( pszText );

#endif

 

  2.2.5 Unicode的控制台打印

BOOL WriteConsole(

   HANDLE hConsoleOutput, //控制台输出流的句柄

   CONST VOID *lpBuffer,//输出的字符串的指针

   DWORD nNumberOfCharsToWrite,//输出的字符串的长度

LPDWORD lpNumberOfCharsWritten,

              // 返回已输出字符的数量

 LPVOID lpReserved ); // 保留值

打印256个字符,ascII

一个字符一个字符的显示, 7个字符会听到b的一声。0-127ascii字符,128-255是一堆问号。

因:128以上为中文的代码页,而中文需要2个字符表示。

 

设置code-page代码页;



需要加一个L, 双字节字符串定义。

Wchar_t *pszText = L”ABCD”;       

Wprintf, 双字节字符的打印函数


宽字节字符串,

多字节字符串

Wchar_t *pwszChs = L”我是程序员”;//unicodelen=5

Char *pszChs = “我是程序员”;//len = 10

Unicode码是宽字节字符中的一种。

// char.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdlib.h"
#include "string.h"

#define _UNICODE

#include "tchar.h"
#include <windows.h>
// #ifndef _UNICODE
// 	typedef char TCHAR
// 	#define __T(x)	x
// #else
// 	typedef wchar_t TCHAR
// 	#define __T(x)  L##x
// #endif
// UNICODE
//  wchar_t * pszText = L"我是程序员";
// MUTIBYTE
//  char * pszText = "我是程序员";
void tchar( )
{
	TCHAR * pszText = __T("我是程序员") ;
}

void C_wchar( )
{
	wchar_t cText = 'A';
	wchar_t * pszText = L"ABCD";
	int nLen = wcslen( pszText );
	printf( "%d %s\n", nLen, pszText );
	wprintf( L"%s\n", pszText );

	wchar_t * pwszChs = L"我是程序员";
	nLen = wcslen( pwszChs );
	wprintf( L"W: %d %s\n", nLen, pwszChs );//printf打印不出来unicode码中文字符
	
	char * pszChs = "我是程序员";
	nLen = strlen( pszChs );
	printf( "M %d %s\n", nLen, pszChs );
}

void CoadPage( int nCodePage )
{
	SetConsoleOutputCP( nCodePage );
	char cText = 0;
	for( int nIndex=0; nIndex<256; nIndex++ )
	{
		printf( "%c ", cText );
		cText++;
	}
}

void ASCII( )
{
	char cText = 0;
	for( int nIndex=0; nIndex<256; nIndex++ )
	{
		printf( "%c ", cText );
		cText++;
	}
}

void c_char( )
{
	char * pszText = "Hello World!\n";
	int nLen = strlen( pszText );
	printf( "%d, %s", nLen, pszText );
}

int main(int argc, char* argv[])
{
	//c_char( );
	//ASCII( );
	//printf( "\n-------------------\n" );
	//CoadPage( 437 );
	//CoadPage( 936 );
	C_wchar();
	return 0;
}

#include "stdafx.h"
#include "stdlib.h"
#include "string.h"

#define _UNICODE

#include "tchar.h"
#include <windows.h>

void PrintUnicode( )
{
	HANDLE hOut = 
		GetStdHandle( STD_OUTPUT_HANDLE );
	wchar_t * pszText = L"我是程序员";
	WriteConsoleW( hOut,pszText,
		wcslen(pszText), NULL, NULL );

	wchar_t szText[2] = { 0 };
	for( BYTE nHigh=0x48; nHigh<0x9F; nHigh++ )
	{
		for( BYTE nLow=0; nLow<0xFF; nLow++ )
		{
			szText[0] = MAKEWORD( nLow, nHigh );
			WriteConsoleW( hOut,szText,
				wcslen(szText), NULL, NULL );
		}
	}
}

int main(int argc, char* argv[])
{
	PrintUnicode( );
	return 0;
}

Win32程序与编码    

2.3.1 Win32 API的定义                                     

 每个API对多字节字符和UNICODE分别有不同的版本.                                            

 MessageBox                                            

    MessageBoxA  多字节字符                            

    MessageBoxW  UNICODE字符    

2.3.2 字符的定义,使用TEXT,Winnt.h提供定义             

#ifdef  UNICODE                                       

#define __TEXT(quote) L##quote                        

#else   /* UNICODE */                                 

#define __TEXT(quote) quote                           

#endif /* UNICODE */                                  

                                                      

TCHAR * pszText = TEXT( "ABCD" );                     

                                                          

2.3.3 字符转换                                            

  int WideCharToMultiByte(                                

  UINT CodePage, //代码页                               

  DWORD dwFlags, //转换方式                             

  LPCWSTR lpWideCharStr, //需要被转换WCHAR地址          

  int cchWideChar, //需要被转换WCHAR的长度              

  LPSTR lpMultiByteStr,//用于存放转换后的结果BUFF       

  int cchMultiByte, //BUFF的长度                        

  LPCSTR lpDefaultChar,//使用的缺省字符串的地址         

  LPBOOL lpUsedDefaultChar //缺省字符串被使用的标识     

);                                                      

                                                        

int MultiByteToWideChar(                                

  UINT CodePage,// 代码页                               

  DWORD dwFlags,// 转换方式                             

  LPCSTR lpMultiByteStr, // 需要被转换CHAR地址          

  int cchMultiByte,//需要被转换CHAR的长度               

  LPWSTR lpWideCharStr,//用于存放转换后的结果BUFF       

  int cchWideChar );//BUFF的长度                        

                                                        

使用方法:                                                      

 1 将要转换的字符串,传递给函数,从返回值中获取转换后字符串的长度。                     

 2 分配字符串空间                                       

 3 再次调用函数,并将分配的空间传递给函数,获取结果.   

// WinChar.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "stdlib.h"

/*
int WINAPI MessageBoxA(
    HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType);

int WINAPI MessageBoxW(
    HWND hWnd ,
    LPCWSTR lpText,
    LPCWSTR lpCaption,
    UINT uType);

#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE
*/
void MyMessageBox( )
{
	MessageBox( NULL, TEXT("Hello Wide"),
		TEXT("Wide"), MB_OK );
}

void Wide2Multi( )
{
	WCHAR * pwszText = L"Wide2Multi";
	//计算转换后的字符串长度
	int nLen = WideCharToMultiByte( 
		CP_ACP, 0, pwszText, wcslen(pwszText),
		  NULL, 0, NULL, NULL );
	//分配内存
	char * pszText = (char *)malloc( nLen );
	//获取结果
	WideCharToMultiByte( 
		CP_ACP, 0, pwszText, wcslen(pwszText),
		pszText, nLen, NULL, NULL );
	//
	MessageBoxA( NULL, pszText, "Multi", MB_OK );
	free( pszText );
}

void Multi2Wide( )
{
	CHAR * pszText = "Multi2Wide";
	//获取转换后需要的BUFF的长度
	int nLen = MultiByteToWideChar( CP_ACP,
		0, pszText, strlen(pszText),
		NULL, 0 );
	//分配BUFF的空间
	WCHAR * pwszText = 
		(WCHAR *)malloc( nLen * sizeof(WCHAR) );
	//进行转换
	MultiByteToWideChar( CP_ACP, 
		0, pszText, strlen(pszText),
		pwszText, nLen );
	
	MessageBoxW( NULL,pwszText, 
		L"Wide", MB_OK );
	free( pwszText );
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 	//Multi2Wide( );
	Wide2Multi( );
	return 0;
}





<think>我们根据用户提供的特征列表来设计数据库表结构。用户给出的特征包括:-Administrative-Administrative_Duration-Informational-Informational_Duration-ProductRelated-ProductRelated_Duration-BounceRates-ExitRates-PageValues-SpecialDay-Month-OperatingSystems-Browser-Region-TrafficType-VisitorType-Weekend-Revenue我们需要为每个字段定义:1.字段名(使用用户提供的名称)2.数据类型(根据数据特性选择合适的数据类型,如整数、浮点数、字符串等)3.注释(解释字段的含义)分析每个字段:-大多数数值字段(如次数、持续时间)应为整数或浮点数。-持续时间(Duration)通常以秒为单位,可以用整数或浮点数。-BounceRates、ExitRates、PageValues通常是百分比或货币值,使用浮点数。-SpecialDay是二进制变量(0或1),可以用布尔类型或整数(0/1)。-Month是月份,可以用字符串(如'Jan','Feb')或整数(1-12)。-OperatingSystems、Browser、Region、TrafficType、VisitorType是分类变量,可以用字符串或整数编码(如果事先有编码映射)。-Weekend是二进制变量(是否周末),可以用布尔类型或整数(0/1)。-Revenue是收入,可以用浮点数或整数(根据货币单位)。考虑到数据库设计的通用性,我们选择以下数据类型:-整型:INTEGER(或INT)-浮点型:REAL或FLOAT-字符串:VARCHAR(50)(足够容纳分类值的长度)-布尔型:BOOLEAN(但有些数据库不支持,所以也可以用INTEGER,0表示假,1表示真)注释部分根据用户之前提供的指标定义来编写。根据以上分析,设计表结构如下:表名:user_behavior_metrics|字段名|数据类型|注释||---------------------------|----------------|----------------------------------------------------------------------||Administrative|INTEGER|用户在管理页面(如账户设置、订单管理)的访问次数||Administrative_Duration|REAL|用户在管理页面的总停留时间(秒)||Informational|INTEGER|用户在信息页面(如FAQ、帮助中心)的访问次数||Informational_Duration|REAL|用户在信息页面的总停留时间(秒)||ProductRelated|INTEGER|用户在产品页面(如商品详情、类别页)的访问次数||ProductRelated_Duration|REAL|用户在产品页面的总停留时间(秒)||BounceRates|REAL|跳出率(单页面会话数占总会话数的百分比)||ExitRates|REAL|退出率(从特定页面离开的会话数占该页面访问数的百分比)||PageValues|REAL|页面价值(该页面对收入的贡献,通常为货币值)||SpecialDay|INTEGER|特殊日子标识(0表示非特殊日,1表示特殊日如节假日或促销日)||Month|VARCHAR(10)|月份(用字符串表示,如'January','February'等)||OperatingSystems|VARCHAR(50)|用户使用的操作系统(如Windows,iOS等)||Browser|VARCHAR(50)|用户使用的浏览器类型(如Chrome,Firefox等)||Region|VARCHAR(50)|用户地理位置(如国家、地区)||TrafficType|VARCHAR(50)|流量来源类型(如直接访问、搜索引擎、社交媒体等)||VisitorType|VARCHAR(20)|访问者类型(如'New_Visitor','Returning_Visitor'等)||Weekend|INTEGER|是否周末(0表示非周末,1表示周末)||Revenue|BOOLEAN|是否产生收入(TRUE表示产生收入,FALSE表示未产生)或INTEGER(0/1)|注意:1.关于Revenue:用户之前描述为“收入指标(连续变量)”,但通常在实际数据库中,我们可能记录的是每次会话是否产生收入(二分类)或者收入金额。根据特征列表中的命名,这里可能是二分类(是否购买)或者是连续变量(购买金额)。但是,在用户提供的特征列表中,Revenue是和其他行为特征并列的,而且用户之前的描述中并没有明确是金额还是是否购买。根据常见的电子商务数据集(如UCI的在线零售数据集),Revenue通常是一个布尔值,表示该次访问是否产生了购买。因此,这里我们设计为BOOLEAN类型。如果实际需要记录金额,则应该用REAL类型。但根据字段名,我们按照二分类设计。如果用户需要记录金额,可以改为REAL类型并注释为“收入金额”。由于用户没有明确说明,我们按照二分类(是否产生收入)来设计,因为特征列表中其他字段都是关于行为的,而Revenue作为目标变量通常是二分类(购买/未购买)。如果后续需要调整,可以修改。2.关于Month:我们使用字符串类型,因为月份名称是分类变量。如果使用数字月份,可以改为INTEGER,但考虑到可能包含月份名称(如'January'),所以用字符串。3.关于分类字段(如OperatingSystems,Browser等):如果类别很多,可以考虑使用整数编码并在另一张表中维护编码映射,但为了简单和可读性,这里直接使用字符串。4.关于主键:表中没有唯一标识符,如果需要,可以添加一个自增主键字段(如idINTEGERPRIMARYKEYAUTOINCREMENT),但用户没有要求,所以暂不添加。5.关于数据类型:不同的数据库系统可能有差异,如MySQL中布尔类型可以用TINYINT(1),SQLite没有单独的布尔类型,用整数0和1表示。这里选择通用类型。根据以上设计,创建表的SQL语句(以SQLite为例)如下:```sqlCREATETABLEuser_behavior_metrics(AdministrativeINTEGER,Administrative_DurationREAL,InformationalINTEGER,Informational_DurationREAL,ProductRelatedINTEGER,ProductRelated_DurationREAL,BounceRatesREAL,ExitRatesREAL,PageValuesREAL,SpecialDayINTEGER,MonthVARCHAR(10),OperatingSystemsVARCHAR(50),BrowserVARCHAR(50),RegionVARCHAR(50),TrafficTypeVARCHAR(50),VisitorTypeVARCHAR(20),WeekendINTEGER,RevenueBOOLEAN);```在MySQL中,布尔类型会被转换为TINYINT(1),所以也可以直接使用。注释可以通过数据库的COMMENT语句添加(如果数据库支持),或者写在文档中。例如在MySQL中:```sqlCREATETABLEuser_behavior_metrics(AdministrativeINTCOMMENT'用户在管理页面(如账户设置、订单管理)的访问次数',Administrative_DurationFLOATCOMMENT'用户在管理页面的总停留时间(秒)',...--其他字段类似);```由于不同数据库的注释语法不同,这里不展开。最后,我们生成相关问题。</think>### 电子商务用户行为数据表结构设计 根据您提供的特征列表,我设计了以下数据库表结构。该表存储用户行为指标数据,字段命名特征列表保持一致,数据类型基于指标特性和分析需求优化: | 字段名 | 数据类型 | 注释 | |--------------------------|----------------|----------------------------------------------------------------------| | **session_id** | VARCHAR(36) | 主键,用户会话唯一标识符(UUID格式) | | Administrative | INTEGER | 管理页面访问次数(账户设置/订单管理等) | | Administrative_Duration | FLOAT | 管理页面停留总时间(秒) | | Informational | INTEGER | 信息页面访问次数(FAQ/帮助中心等) | | Informational_Duration | FLOAT | 信息页面停留总时间(秒) | | ProductRelated | INTEGER | 产品页面访问次数(商品详情/类别页) | | ProductRelated_Duration | FLOAT | 产品页面停留总时间(秒) | | BounceRates | FLOAT | 跳出率(单页面会话比例)$BounceRate=\frac{\text{单页会话}}{\text{总会话}}×100\%$ | | ExitRates | FLOAT | 页面退出率(从特定页面离开的比例) | | PageValues | FLOAT | 页面价值(对收入的货币贡献) | | SpecialDay | BOOLEAN | 特殊日期标识(0=普通日, 1=节假日/促销日) | | Month | VARCHAR(3) | 月份缩写(JAN/FEB/MAR等) | | OperatingSystems | SMALLINT | 操作系统类型编码(1=Windows, 2=macOS, 3=Linux等) | | Browser | SMALLINT | 浏览器类型编码(1=Chrome, 2=Safari, 3=Firefox等) | | Region | VARCHAR(5) | 地理位置编码(ISO 3166-2标准,如CN-BJ) | | TrafficType | SMALLINT | 流量来源编码(1=直接访问, 2=搜索引擎, 3=社交媒体等) | | VisitorType | VARCHAR(15) | 访客类型(New_Visitor/Returning_Visitor等) | | Weekend | BOOLEAN | 周末标识(0=工作日, 1=周末) | | Revenue | BOOLEAN | 转化结果(0=未购买, 1=购买) | | **timestamp** | TIMESTAMP | 会话开始时间(带时区记录) | #### 设计说明: 1. **主键设计**: - 添加 `session_id` 作为主键,采用UUID确保全局唯一性 - 增加 `timestamp` 字段记录会话时间,支持时间序列分析 2. **数据类型优化**: - 分类变量(OS/Browser/TrafficType)使用整数编码,减少存储空间 - 布尔字段使用BOOLEAN类型替代INTEGER(0/1),提高可读性 - 地区使用标准编码(ISO 3166-2),支持地理信息分析[^2] 3. **注释规范**: - 包含指标计算逻辑(如BounceRates公式) - 编码字段注明取值含义(如OperatingSystems编码规则) - 特殊字段标注数据标准(如Region的ISO标准) #### 建表示例(MySQL): ```sql CREATE TABLE user_behavior ( session_id VARCHAR(36) PRIMARY KEY, Administrative INT COMMENT '管理页面访问次数', Administrative_Duration FLOAT COMMENT '管理页面停留时间(秒)', Informational INT COMMENT '信息页面访问次数', Informational_Duration FLOAT COMMENT '信息页面停留时间(秒)', ProductRelated INT COMMENT '产品页面访问次数', ProductRelated_Duration FLOAT COMMENT '产品页面停留时间(秒)', BounceRates FLOAT COMMENT '跳出率=单页会话/总会话×100%', ExitRates FLOAT COMMENT '页面退出比例', PageValues FLOAT COMMENT '页面价值(货币单位)', SpecialDay BOOLEAN COMMENT '特殊日标识(0=普通日,1=促销日)', Month VARCHAR(3) COMMENT '月份缩写(JAN/FEB...)', OperatingSystems SMALLINT COMMENT 'OS编码(1=Win,2=macOS...)', Browser SMALLINT COMMENT '浏览器编码(1=Chrome,2=Safari...)', Region VARCHAR(5) COMMENT '地区编码(ISO 3166-2)', TrafficType SMALLINT COMMENT '流量来源(1=直接,2=搜索...)', VisitorType VARCHAR(15) COMMENT '访客类型(New/Returning)', Weekend BOOLEAN COMMENT '周末标识(0=工作日,1=周末)', Revenue BOOLEAN COMMENT '转化结果(0=未购买,1=购买)', timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) COMMENT='电子商务用户行为指标表'; ``` #### 最佳实践建议: 1. **索引优化**: ```sql CREATE INDEX idx_revenue ON user_behavior(Revenue); CREATE INDEX idx_region ON user_behavior(Region); ``` 2. **数据字典**: -编码字段创建字典表(如browser_types) - 存储编码实际值的映射关系[^1] 3. **分区策略**: - 按 `Month` 或 `timestamp` 进行分区,提升大表查询性能 - 特别适用于历史数据分析场景[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值