首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 微博風格字符統計:UTF-8/GBK 雙編碼支援,中文 2 分、英文 1 分、全半角精準計算

     編輯:PHP 相關知識

微博字數規則:中文 2 分、英文 1 分、全角標點 2 分、半角標點 1 分。PHP strlen 計位元組(UTF-8 中文 3 字節),mb_strlen 計字符(中文 1 個),均不符合。本文提供精準實現 strlen_weibo(),支援 UTF-8 與 GBK 雙編碼。

核心函數:strlen_weibo()

/**
 * 微博風格字符長度計算
 * @param string $string 輸入字符串
 * @param string $charset 編碼:'utf-8' 或 'gbk'
 * @return int 計算長度
 */
function strlen_weibo(string $string, string $charset = 'utf-8'): int {
    $n = $count = 0;
    $length = strlen($string);
    $charset = strtolower($charset);

    if ($charset === 'utf-8') {
        while ($n < $length) {
            $byte = ord($string[$n]);

            // ASCII 控制字符、可打印字符(含半角標點、數字、字母)
            if ($byte === 9 || $byte === 10 || (32 <= $byte && $byte <= 126)) {
                $n++; $count++;
            }
            // 2 字節 UTF-8 字符(擴展拉丁、希臘、西里爾等)→ 視為 2 分
            elseif (194 <= $byte && $byte <= 223) {
                $n += 2; $count += 2;
            }
            // 3 字節 UTF-8(中日韓統一表意文字、常用漢字)→ 2 分
            elseif (224 <= $byte && $byte <= 239) {
                $n += 3; $count += 2;
            }
            // 4 字節 UTF-8(Emoji、生僻字)→ 2 分
            elseif (240 <= $byte && $byte <= 247) {
                $n += 4; $count += 2;
            }
            // 5/6 字節(極罕見,保守按 2 分)
            elseif (248 <= $byte && $byte <= 251) {
                $n += 5; $count += 2;
            }
            elseif ($byte === 252 || $byte === 253) {
                $n += 6; $count += 2;
            }
            // 非法字節,按 1 字節跳過計 1 分
            else {
                $n++; $count++;
            }

            if ($count >= $length) break; // 安全閾值
        }
        return $count;
    }

    // GBK/GB2312:雙字節字符高位 ≥ 0x81
    for ($i = 0; $i < $length; $i++) {
        if (ord($string[$i]) > 127) {
            $i++; // 跳過低位字節
            $count++; // 雙字節字符計 1 個「中文單位」→ 2 分
        }
        $count++; // ASCII 或已計數的雙字節字符各計 1 分
    }
    return $count;
}

測試驗證

<?php
$str = "s@@你好"; // s(半角) @(全角) @(半角) 你(中) 好(中)
var_dump(strlen_weibo($str, 'utf-8')); // int(8)
// 解析:s=1, @=2, @=1, 你=2, 好=2 → 總計 8

編碼判斷邏輯圖解 (UTF-8)

首字節範圍字節數字符集範例微博計分
0x00-0x7F (0-127)1ASCII 控制/可打印1
0xC2-0xDF (194-223)2拉丁擴展、希臘、西里爾2
0xE0-0xEF (224-239)3中日韓統一表意文字 (CJK)2
0xF0-0xF7 (240-247)4Emoji、CJK 擴展 A/B2
0xF8-0xFB (248-251)5極罕見2
0xFC-0xFD (252-253)6理論最大2

GBK 邏輯簡析

  • GBK 中文字符佔 2 字節,首字節範圍 0x81-0xFE(即 > 127)。
  • 遇到首字節 > 127 時,跳過次字節,長度 +1(代表一個中文單位 → 2 分)。
  • ASCII 字符(≤127)長度 +1(1 分)。

工程化封裝建議

class WeiboLength {
    public static function calc(string $str, string $charset = 'utf-8'): int {
        return strlen_weibo($str, $charset);
    }

    // 截取至指定微博長度(返回截取後字符串)
    public static function substr(string $str, int $maxLen, string $charset = 'utf-8', string $suffix = '...'): string {
        // 此處需配合字符級截取(如 mb_substr 或自定義),略
    }
}

避坑指南

  • 編碼不匹配:傳入 UTF-8 字符串卻指定 gbk 會產生錯誤計數,務必確保編碼一致。
  • Emoji 組合字符:如 👨‍👩‍👧‍👦 (家庭) 由多個代碼點組成,本函數按字節級處理會計為多個 2 分單位,實際顯示為 1 個字形。需用 grapheme_strlen (intl 擴展) 處理字形簇。
  • 性能:逐字節循環,超長文本(>100KB)建議改用 C 擴展或預計算字節類型表。

精準掌握字符寬度計算,是構建輸入限制、顯示截斷、排版引擎的基石,微博風格只是其中一種業務規則映射。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved