Comment résoudre le problème des caractères tronqués php

藏色散人
Libérer: 2023-03-08 12:52:01
original
2614 Les gens l'ont consulté

php trim tronqué le code est dû au fait que lors de l'exécution de rtrim, 0x81 sera supprimé, ce qui entraînera un code tronqué. La solution consiste à utiliser la méthode "mb_rtrim($tag, ", ",$encoding)" pour résoudre le problème. code brouillé.

Comment résoudre le problème des caractères tronqués php

L'environnement d'exploitation de cet article : système Windows7, version PHP7.1, ordinateur DELL G3

Exécutez d'abord le code suivant :

$tag = "互联网产品、";
$text = rtrim($tag, "、");
print_r($text);
Copier après la connexion

Nous pouvons penser que le résultat que nous obtiendrons est un produit Internet, mais le résultat réel est un produit Internet. Pourquoi cela se produit-il ?

Science populaire

Le préfixe mb_ en PHP est constitué de toutes les fonctions multi-octets http://php.net/manual/zh/ref....

Par exemple

$str = "abcd";
print_r(strlen($str).""); // 4
print_r(mb_strlen($str).""); // 4
$str = "周梦康";
print_r(strlen($str).""); // 9
print_r(mb_strlen($str).""); // 3
Copier après la connexion

Les fonctions de la série mb_ fonctionnent sur la base de la granularité de "un caractère composé de plusieurs octets". Sans mb_, elles fonctionnent sur la base du nombre réel d'octets.

Principe

documentation de la fonction trim

string trim ( string $str [, string $character_mask = " " ] )
Copier après la connexion

Cette fonction n'est pas une fonction multi-octets, c'est-à-dire que les caractères multi-octets comme les caractères chinois auront leur tête ou tail Utilisez un seul octet pour faire correspondre le tableau de caractères correspondant au $character_mask suivant. S'il se trouve dans le tableau suivant, supprimez-le et continuez la correspondance. Par exemple :

echo ltrim("bcdf","abc"); // df
Copier après la connexion

est affiché dans la fonction string_print_char dans la démo ci-dessous :

se compose de trois octets 0xe3 0x80 0x81, et

se compose de trois octets 0xe5 0x93 0x81 composition .

Ainsi, lors de l'exécution de rtrim, 0x81 sera supprimé via une comparaison d'octets, ce qui entraînera des caractères tronqués à la fin.

[Apprentissage recommandé : "Tutoriel vidéo PHP"]

Exploration du code source

Afficher le code source de PHP7, puis j'ai extrait la petite démo suivante pour permettre à tout le monde d'apprendre ensemble. En fait, apprendre le code source PHP n'est pas difficile, et vous pouvez faire un peu de progrès chaque jour.

//
// main.c
// trim
//
// Created by 周梦康 on 2017/10/18.
// Copyright © 2017年 周梦康. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void string_print_char(char *str);
void php_charmask(unsigned char *input, size_t len, char *mask);
char *ltrim(char *str,char *character_mask);
char *rtrim(char *str,char *character_mask);
int main(int argc, char const *argv[])
{
printf("%s",ltrim("bcdf","abc"));
string_print_char("品"); // e5 93 81
string_print_char("、"); // e3 80 81
printf("%s",rtrim("互联网产品、","、"));
return 0;
}
char *ltrim(char *str,char *character_mask)
{
char *res;
char mask[256];
register size_t i;
int trimmed = 0;
size_t len = strlen(str);
php_charmask((unsigned char*)character_mask, strlen(character_mask), mask);
for (i = 0; i < len; i++) {
if (mask[(unsigned char)str[i]]) {
trimmed++;
} else {
break;
}
}
len -= trimmed;
str += trimmed;
res = (char *) malloc(sizeof(char) * (len+1));
memcpy(res,str,len);
return res;
}
char *rtrim(char *str,char *character_mask)
{
char *res;
char mask[256];
register size_t i;
size_t len = strlen(str);
php_charmask((unsigned char*)character_mask, strlen(character_mask), mask);
if (len > 0) {
i = len - 1;
do {
if (mask[(unsigned char)str[i]]) {
len--;
} else {
break;
}
} while (i-- != 0);
}
res = (char *) malloc(sizeof(char) * (len+1));
memcpy(res,str,len);
return res;
}
void string_print_char(char *str)
{
unsigned long l = strlen(str);
for (int i=0; i < l; i++) {
printf("%02hhx ",str[i]);
}
printf("");
}
void php_charmask(unsigned char *input, size_t len, char *mask)
{
unsigned char *end;
unsigned char c;
memset(mask, 0, 256);
for (end = input+len; input < end; input++) {
c = *input;
mask[c]= 1;
}
}
Copier après la connexion

Si vous pensez que la démo n'est pas assez claire, copiez-la et exécutez-la vous-même~

Les étudiants ayant de mauvaises bases en langage C n'ont pas à s'inquiéter, j'écrirai un tutoriel PHP spécial pour les débutants plus tard Une série de courts articles d'introduction au langage C.

Solution

Ensuite, suivons le même modèle et utilisons les propres fonctions multi-octets de PHP pour l'implémenter :

function mb_rtrim($string, $trim, $encoding)
{
$mask = [];
$trimLength = mb_strlen($trim, $encoding);
for ($i = 0; $i < $trimLength; $i++) {
$item = mb_substr($trim, $i, 1, $encoding);
$mask[] = $item;
}
$len = mb_strlen($string, $encoding);
if ($len > 0) {
$i = $len - 1;
do {
$item = mb_substr($string, $i, 1, $encoding);
if (in_array($item, $mask)) {
$len--;
} else {
break;
}
} while ($i-- != 0);
}
return mb_substr($string, 0, $len, $encoding);
}
mb_internal_encoding("UTF-8");
$tag = "互联网产品、";
$encoding = mb_internal_encoding();
print_r(mb_rtrim($tag, "、",$encoding));
Copier après la connexion

Bien sûr, vous pouvez également utilisez des expressions régulières. Grâce à l'apprentissage des fonctions ci-dessus, avez-vous appris les fonctions mono-octet et les fonctions multi-octets ?

Code source lié à PHP7

PHP_FUNCTION(trim)
{
php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
}
PHP_FUNCTION(rtrim)
{
php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
}
PHP_FUNCTION(ltrim)
{
php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
static void php_do_trim(INTERNAL_FUNCTION_PARAMETERS, int mode)
{
zend_string *str;
zend_string *what = NULL;
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR(str)
Z_PARAM_OPTIONAL
Z_PARAM_STR(what)
ZEND_PARSE_PARAMETERS_END();
ZVAL_STR(return_value, php_trim(str, (what ? ZSTR_VAL(what) : NULL), (what ? ZSTR_LEN(what) : 0), mode));
}
PHPAPI zend_string *php_trim(zend_string *str, char *what, size_t what_len, int mode)
{
const char *c = ZSTR_VAL(str);
size_t len = ZSTR_LEN(str);
register size_t i;
size_t trimmed = 0;
char mask[256];
if (what) {
if (what_len == 1) {
char p = *what;
if (mode & 1) {
for (i = 0; i < len; i++) {
if (c[i] == p) {
trimmed++;
} else {
break;
}
}
len -= trimmed;
c += trimmed;
}
if (mode & 2) {
if (len > 0) {
i = len - 1;
do {
if (c[i] == p) {
len--;
} else {
break;
}
} while (i-- != 0);
}
}
} else {
php_charmask((unsigned char*)what, what_len, mask);
if (mode & 1) {
for (i = 0; i < len; i++) {
if (mask[(unsigned char)c[i]]) {
trimmed++;
} else {
break;
}
}
len -= trimmed;
c += trimmed;
}
if (mode & 2) {
if (len > 0) {
i = len - 1;
do {
if (mask[(unsigned char)c[i]]) {
len--;
} else {
break;
}
} while (i-- != 0);
}
}
}
} else {
if (mode & 1) {
for (i = 0; i < len; i++) {
if ((unsigned char)c[i] <= &#39; &#39; &&
(c[i] == &#39; &#39; || c[i] == &#39;&#39; || c[i] == &#39;&#39; || c[i] == &#39; &#39; || c[i] == &#39;&#39; || c[i] == &#39;&#39;)) {
trimmed++;
} else {
break;
}
}
len -= trimmed;
c += trimmed;
}
if (mode & 2) {
if (len > 0) {
i = len - 1;
do {
if ((unsigned char)c[i] <= &#39; &#39; &&
(c[i] == &#39; &#39; || c[i] == &#39;&#39; || c[i] == &#39;&#39; || c[i] == &#39; &#39; || c[i] == &#39;&#39; || c[i] == &#39;&#39;)) {
len--;
} else {
break;
}
} while (i-- != 0);
}
}
}
if (ZSTR_LEN(str) == len) {
return zend_string_copy(str);
} else {
return zend_string_init(c, len, 0);
}
}
/* {{{ php_charmask
* Fills a 256-byte bytemask with input. You can specify a range like &#39;a..z&#39;,
* it needs to be incrementing.
* Returns: FAILURE/SUCCESS whether the input was correct (i.e. no range errors)
*/
static inline int php_charmask(unsigned char *input, size_t len, char *mask)
{
unsigned char *end;
unsigned char c;
int result = SUCCESS;
memset(mask, 0, 256);
for (end = input+len; input < end; input++) {
c=*input;
if ((input+3 < end) && input[1] == &#39;.&#39; && input[2] == &#39;.&#39;
&& input[3] >= c) {
memset(mask+c, 1, input[3] - c + 1);
input+=3;
} else if ((input+1 < end) && input[0] == &#39;.&#39; && input[1] == &#39;.&#39;) {
/* Error, try to be as helpful as possible:
(a range ending/starting with &#39;.&#39; won&#39;t be captured here) */
if (end-len >= input) { /* there was no &#39;left&#39; char */
php_error_docref(NULL, E_WARNING, "Invalid &#39;..&#39;-range, no character to the left of &#39;..&#39;");
result = FAILURE;
continue;
}
if (input+2 >= end) { /* there is no &#39;right&#39; char */
php_error_docref(NULL, E_WARNING, "Invalid &#39;..&#39;-range, no character to the right of &#39;..&#39;");
result = FAILURE;
continue;
}
if (input[-1] > input[2]) { /* wrong order */
php_error_docref(NULL, E_WARNING, "Invalid &#39;..&#39;-range, &#39;..&#39;-range needs to be incrementing");
result = FAILURE;
continue;
}
/* FIXME: better error (a..b..c is the only left possibility?) */
php_error_docref(NULL, E_WARNING, "Invalid &#39;..&#39;-range");
result = FAILURE;
continue;
} else {
mask[c]=1;
}
}
return result;
}
/* }}} */
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
php
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal