php에서 잘못된 코드를 자르는 것은 rtrim을 실행할 때 0x81이 제거되어 잘못된 코드가 발생하기 때문입니다. 해결책은 "mb_rtrim($tag, ",",$encoding)" 메서드를 사용하여 잘못된 코드를 해결하는 것입니다.
이 기사의 운영 환경: Windows 7 시스템, PHP 버전 7.1, DELL G3 컴퓨터
먼저 다음 코드를 실행합니다:
$tag = "互联网产品、"; $text = rtrim($tag, "、"); print_r($text);
우리가 얻게 될 결과는 인터넷 제품이라고 생각할 수도 있지만, 실제 결과는 인터넷 제품입니다. 왜 이런 일이 발생합니까?
대중 과학
PHP의 mb_ 접두사는 모두 멀티바이트 함수입니다. http://php.net/manual/zh/ref....
예를 들어,
$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
mb_ 일련의 함수는 " 다중 "바이트로 구성된 문자"는 세분성으로 작동되며 mb_가 없으면 실제 바이트 수를 기반으로 작동됩니다.
Principle
trim 함수 문서
string trim ( string $str [, string $character_mask = " " ] )
이 함수는 멀티바이트 함수가 아닙니다. 즉, 한자와 같은 멀티바이트 문자의 경우 머리 또는 꼬리의 단일 바이트가 일치하는 데 사용됩니다. 후속 $character_mask 배열에 해당하는 char이 일치하는 경우 다음 배열에 있으면 삭제하고 일치를 계속합니다. 예:
echo ltrim("bcdf","abc"); // df
아래 데모의 string_print_char 함수에 표시된 대로:
는 3바이트 0xe3 0x80 0x81로 구성되고
는 3바이트 0xe5 0x93 0x81로 구성됩니다.
그래서 rtrim을 실행하면 바이트 비교를 통해 0x81이 제거되어 결국 문자가 깨집니다.
[추천 학습: "PHP 비디오 튜토리얼"]
소스 코드 탐색
PHP7의 소스 코드를 확인한 후 다음과 같은 작은 데모를 추출하여 모두가 함께 학습할 수 있도록 하세요. 소스 코드는 매일 조금씩 발전해 보세요.
// // main.c // trim // // Created by 周梦康 on 2017/10/18. // Copyright © 2017年 周梦康. All rights reserved. // #include#include #include 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; } }
데모가 명확하지 않다고 생각하시면 복사해서 직접 실행해보세요~
C 언어 기초가 부족한 학생도 걱정하지 마세요. PHP 초보자가 C 언어를 배울 수 있도록 일련의 소개 기사를 쓸 예정입니다. 나중에.
Solution
그런 다음 동일한 패턴을 따르고 PHP 자체 멀티바이트 함수를 사용하여 구현해 보겠습니다.
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));
물론 정규식을 사용하여 구현할 수도 있습니다. 위의 함수 학습을 통해 싱글바이트 함수와 멀티바이트 함수를 학습하셨나요?
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] <= ' ' && (c[i] == ' ' || c[i] == '' || c[i] == '' || c[i] == ' ' || c[i] == '' || c[i] == '')) { trimmed++; } else { break; } } len -= trimmed; c += trimmed; } if (mode & 2) { if (len > 0) { i = len - 1; do { if ((unsigned char)c[i] <= ' ' && (c[i] == ' ' || c[i] == '' || c[i] == '' || c[i] == ' ' || c[i] == '' || c[i] == '')) { 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 'a..z', * 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] == '.' && input[2] == '.' && input[3] >= c) { memset(mask+c, 1, input[3] - c + 1); input+=3; } else if ((input+1 < end) && input[0] == '.' && input[1] == '.') { /* Error, try to be as helpful as possible: (a range ending/starting with '.' won't be captured here) */ if (end-len >= input) { /* there was no 'left' char */ php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the left of '..'"); result = FAILURE; continue; } if (input+2 >= end) { /* there is no 'right' char */ php_error_docref(NULL, E_WARNING, "Invalid '..'-range, no character to the right of '..'"); result = FAILURE; continue; } if (input[-1] > input[2]) { /* wrong order */ php_error_docref(NULL, E_WARNING, "Invalid '..'-range, '..'-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 '..'-range"); result = FAILURE; continue; } else { mask[c]=1; } } return result; } /* }}} */
위 내용은 PHP 트림 문자 왜곡 문제를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!