Qt中实现获取中文首字母(GB2312 和 unicode以及调用Unihan实现全汉字拼音转换,支持多音字和生僻字等)和中英文数字排序功能

Qt5中可以通过qSort接口,结合QLocale类和QCollator类,可以对中文,英文,数字进行排序,但默认排序顺序为数字、英文、中文,但如果需要中英文混合排序的话,需要另外封装方法实现。
这种方法就是先获取中文的首字母,然后在进行排序。

获取中文首字母

获取中文首字母需要用到编解码规则,下面有一份代码是我在网上找到的资料,能获取中文的首字母(GB2312)。

使用接口的时候切记不要忘记头文件哦

#include <QTextCodec>

接口(代码)部分:

static bool In(wchar_t start, wchar_t end, wchar_t code)
{
	return (code >= start && code <= end) ? true : false;
}

static char convert(wchar_t n)
{
	if (In(0xB0A1, 0xB0C4, n)) return 'a';
	if (In(0XB0C5, 0XB2C0, n)) return 'b';
	if (In(0xB2C1, 0xB4ED, n)) return 'c';
	if (In(0xB4EE, 0xB6E9, n)) return 'd';
	if (In(0xB6EA, 0xB7A1, n)) return 'e';
	if (In(0xB7A2, 0xB8c0, n)) return 'f';
	if (In(0xB8C1, 0xB9FD, n)) return 'g';
	if (In(0xB9FE, 0xBBF6, n)) return 'h';
	if (In(0xBBF7, 0xBFA5, n)) return 'j';
	if (In(0xBFA6, 0xC0AB, n)) return 'k';
	if (In(0xC0AC, 0xC2E7, n)) return 'l';
	if (In(0xC2E8, 0xC4C2, n)) return 'm';
	if (In(0xC4C3, 0xC5B5, n)) return 'n';
	if (In(0xC5B6, 0xC5BD, n)) return 'o';
	if (In(0xC5BE, 0xC6D9, n)) return 'p';
	if (In(0xC6DA, 0xC8BA, n)) return 'q';
	if (In(0xC8BB, 0xC8F5, n)) return 'r';
	if (In(0xC8F6, 0xCBF0, n)) return 's';
	if (In(0xCBFA, 0xCDD9, n)) return 't';
	if (In(0xCDDA, 0xCEF3, n)) return 'w';
	if (In(0xCEF4, 0xD188, n)) return 'x';
	if (In(0xD1B9, 0xD4D0, n)) return 'y';
	if (In(0xD4D1, 0xD7F9, n)) return 'z';
	return '\0';
}

接口(代码)使用:

	QTextCodec *codec4gbk = QTextCodec::codecForName("GBK");    //获取qt提供的gbk的解码器
	QByteArray buf = codec4gbk->fromUnicode(str);             //qt用的unicode,专程gbk        
	quint16 *array = new quint16[buf.size() + 1];
	QString FirstWord;
//	for (int i = 0, j = 0; i < buf1.size(); i++, j++) //循环多次查找,此处只需获取首字母
//	{
		if ((quint8)buf1[0] < 0x80)
		{
			FirstWord = str;
			//continue;
		}//gbk的第一个字节都大于0x81,所以小于0x80的都是符号,字母,数字etc
		else
		{
			array[0] = (((quint8)buf[0]) << 8) + (quint8)buf[1];    //计算gbk编码
			//i++;
			FirstWord.append(convert(array[0]));            //相当于查表,用gbk编码得到首拼音字母
		}	
//	}

上面方法代码量有点过于复杂,我重新封装了一个接口,方便直接使用。

头文件

#include <QByteArray>

封装接口代码(GB2312):

static char getFirstWord(const QString &str)
{
	QByteArray bArr = str.toLocal8Bit();
	const char *p = bArr.data();
	uint8_t firstByte = *p;
	if (firstByte < 128)
	{
		return firstByte;
	}

	uint8_t secondByte = *(p + 1);
	uint16_t word = 0;
	word = firstByte << 8;
	word |= secondByte;

	if (word >= 0xB0A1 && word < 0xB0C4) return 'A';
	if (word >= 0XB0C5 && word < 0XB2C0) return 'B';
	if (word >= 0xB2C1 && word < 0xB4ED) return 'C';
	if (word >= 0xB4EE && word < 0xB6E9) return 'D';
	if (word >= 0xB6EA && word < 0xB7A1) return 'E';
	if (word >= 0xB7A2 && word < 0xB8c0) return 'F';
	if (word >= 0xB8C1 && word < 0xB9FD) return 'G';
	if (word >= 0xB9FE && word < 0xBBF6) return 'H';
	if (word >= 0xBBF7 && word < 0xBFA5) return 'J';
	if (word >= 0xBFA6 && word < 0xC0AB) return 'K';
	if (word >= 0xC0AC && word < 0xC2E7) return 'L';
	if (word >= 0xC2E8 && word < 0xC4C2) return 'M';
	if (word >= 0xC4C3 && word < 0xC5B5) return 'N';
	if (word >= 0xC5B6 && word < 0xC5BD) return 'O';
	if (word >= 0xC5BE && word < 0xC6D9) return 'P';
	if (word >= 0xC6DA && word < 0xC8BA) return 'Q';
	if (word >= 0xC8BB && word < 0xC8F5) return 'R';
	if (word >= 0xC8F6 && word < 0xCBF0) return 'S';
	if (word >= 0xCBFA && word < 0xCDD9) return 'T';
	if (word >= 0xCDDA && word < 0xCEF3) return 'W';
	if (word >= 0xCEF4 && word < 0xD188) return 'X';
	if (word >= 0xD1B9 && word < 0xD4D0) return 'Y';
	if (word >= 0xD4D1 && word < 0xD7F9) return 'Z';
	return '#';
}

封装接口代码(unicode):

static char FirstLetter(const QString &str)
{
	int ucHigh, ucLow;
	int nCode;
	QByteArray bArr = str.toLocal8Bit();
	const char *p = bArr.data();
	uint8_t firstByte = *p;
	ucHigh = (int)(p[0] & 0xFF);
	ucLow = (int)(p[1] & 0xFF);
	if (ucHigh < 0xa1 || ucLow < 0xa1)
	{
		return firstByte;
	}
	nCode = (ucHigh - 0xa0) * 100 + ucLow - 0xa0;

	if (nCode >= 1601 && nCode < 1637) return 'A';
	if (nCode >= 1637 && nCode < 1833) return 'B';
	if (nCode >= 1833 && nCode < 2078) return 'C';
	if (nCode >= 2078 && nCode < 2274) return 'D';
	if (nCode >= 2274 && nCode < 2302) return 'E';
	if (nCode >= 2302 && nCode < 2433) return 'F';
	if (nCode >= 2433 && nCode < 2594) return 'G';
	if (nCode >= 2594 && nCode < 2787) return 'H';
	if (nCode >= 2787 && nCode < 3106) return 'J';
	if (nCode >= 3106 && nCode < 3212) return 'K';
	if (nCode >= 3212 && nCode < 3472) return 'L';
	if (nCode >= 3472 && nCode < 3635) return 'M';
	if (nCode >= 3635 && nCode < 3722) return 'N';
	if (nCode >= 3722 && nCode < 3730) return 'O';
	if (nCode >= 3730 && nCode < 3858) return 'P';
	if (nCode >= 3858 && nCode < 4027) return 'Q';
	if (nCode >= 4027 && nCode < 4086) return 'R';
	if (nCode >= 4086 && nCode < 4390) return 'S';
	if (nCode >= 4390 && nCode < 4558) return 'T';
	if (nCode >= 4558 && nCode < 4684) return 'W';
	if (nCode >= 4684 && nCode < 4925) return 'X';
	if (nCode >= 4925 && nCode < 5249) return 'Y';
	if (nCode >= 5249 && nCode < 5590) return 'Z';
	return '#';
}

至于通过Unihan字实现中文转换字母,由于代码量比较大,已上传到资源下载:
https://download.csdn.net/download/qq_36651243/11257140

排序部分(qSort)

QCollator类:能根据本地化的排序规则算法比较字符串
QLocale类:能在不同语言的数字及其字符串表示形式之间进行转换

使用的时候,记得加上头文件

#include <QLocale>
#include <QCollator>

排序代码部分:

qSort(m_listUserInfo.begin(), m_listUserInfo.end(), [=](auto p2, auto p1) {
	QLocale loc(QLocale::Chinese, QLocale::China);  //此处由于已经改成了英文比较(字母),因此语言和地区都可以选择英文/美国
	QCollator qcol(loc); 
	int nResult = 0;
	QString str1 = getFirstWord(p1->getNickName()); //获取首字母
	QString str2 = getFirstWord(p2->getNickName());
	nResult = qcol.compare(str1, str2);
	return nResult > 0 ? true : false;
});

想更深了解QCollator类?
https://doc.qt.io/qt-5.9/qcollator.html

想更深了解QLocale类?
https://doc.qt.io/qt-5.9/qlocale.html

猜你喜欢

转载自blog.csdn.net/qq_36651243/article/details/92651963