【c/c++】关于中文字符串的复制切割

    在使用strncpy()函数进行字符串的复制时,有时候会出现这样的情况:目标字符串的最后一个字符是非法字符,导致写入数据库时报错;

    【以GBK编码为例】原因在于一个中文字符占两个字节,假如需要写入的字符串长度是30,而恰巧第30位和第31位字节存储的是汉字,这样就会将汉字编码切割开来。然后与之后的字符(例如sql中,后面会加一个单引号)进行组合,形成意料之外的中文字符。

    GBK编码采用双字节编码方案,其编码范围为:8140-FEFE,剔除xx7F码位,共23940个码位。其中中文字符范围为:[0x81-0xFE]。由于汉字是双字节编码,如果要满足该双字节是汉字的要求的话。则第一个字节范围必须在0x81-0xFE之间,而第二个字节范围可以放宽至0x40-0xFE之间。

    如果该字符串是以  '|'【0x7C】   作为分隔符的话,要满足该分隔符之前是汉字的要求,前面一个字节的编码必须在【0x81-0xA0,0xA8-0xFE】之间。因为【0xA1-0xA7】【0x7C】 该双字节并不组成汉字。具体规则可参考网址:https://www.qqxiuzi.cn/zh/hanzi-gbk-bianma.php

代码如下:

void   safe_strncpy(char   dest[], char   source[], int N)
{
	int strlen_source = strlen(source);
	int i = 0, j = 0;
	int flag = 0; /*添加一个标志,用来标志所加的中文的位数 */
	unsigned char *p;
	/*N取目标串和N的最小值*/
	if (strlen_source = 0x81 && p[i] <= 0xFE) /*中文字符[0x81-0xFE] */
		{
			if ((i + 1) == N)
			{
				/* 前面一半是中文,后面是结束符,舍弃半个汉字*/
				dest[j++] = '\0';
			}
			else
			{
				if (p[i + 1] >= 0x40 && p[i + 1] <= 0xFE)
				{
					if (p[i + 1] == 0x7C && ((p[i]<0x81 && p[i]>0xFE) || (p[i]>0xA0 && p[i]<0xA8)))
					{
						/* 如果是以|为分隔符的,要满足前面一半是中文,字节范围必须在【0X81-0XA0,0XA8-0XFE】之间。如果不在舍弃前面一个 */
						i++;
						dest[j++] = p[i];
					}
					else
					{
						/* 前面一半是中文,后面一半也是中文,说明是一个汉字*/
						dest[j++] = p[i];
						i++;
						dest[j++] = p[i];
					}
				}
				else
				{
					/* 前面一半是中文,后面一半非中文,舍弃前面一个 */
					i++;
					dest[j++] = p[i];
				}
			}
		}
		else
		{
			/* 普通的非中文字符 */
			dest[j++] = p[i];
		}
	}
	dest[j] = '\0';  /*字符串最后赋值结束符*/

	return;
}

 

你可能感兴趣的:(c/c++,c++,c语言)