为什么不能将全角字符中的所有字符更改为半宽字符?

时间:2015-04-09 12:46:11

标签: php

我想将全角字符中的所有字符更改为半角字符,编写以下代码来完成工作。 例如,要更改

中的所有全角字符
 Codebit.cn - 聚合小段精华代码 

成半角字符,进入

 codebit.cn - 聚合小段精华代码

实现目标有两种方法,但都失败了 所有的php文件都保存为utf-8格式。

方法1:

<?php
    function fulltohalf($str){
    $arr=Array( 
    '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4',  
    '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', 
    'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E',  
    'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 
    'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O',  
    'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 
    'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y',  
    'Z' => 'Z', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 
    'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i',  
    'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 
    'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's',  
    't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 
    'y' => 'y', 'z' => 'z', '-' => '-' 
    ); 

    $new = '';            
    foreach ($str as $char){
        if (isset ($arr[$char]))  
            $new .= $arr[$char];    
        else
            $new .= $arr;    
        }
    return $new;
    }

$str="Codebit.cn - 聚合小段精华代码";
echo fulltohalf($str);
?>

错误讯息:

enter image description here

方法2:

<?php
function fulltohalf($Str) { 
    $Queue = Array( 
    '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4',  
    '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', 
    'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E',  
    'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 
    'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O',  
    'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 
    'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y',  
    'Z' => 'Z', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 
    'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i',  
    'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 
    'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's',  
    't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 
    'y' => 'y', 'z' => 'z', '-' => '-' 
); 

return preg_replace("/([\xA3][\xB0-\xB9\xC1-\xDA\xE1-\xFA])/e","\$Queue[\\1]", $Str); 

}

$str = "Codebit.cn - 聚合小段精华代码"; 
echo $str; 
echo "<br />"; 
echo fulltohalf($str); 
?>

错误讯息:

enter image description here

如何修复其中两个?

我解决了方法1问题,固定代码如下。

<?php
function fulltohalf($str){
$arr=Array( 
'0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4',  
'5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', 
'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E',  
'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 
'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O',  
'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 
'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y',  
'Z' => 'Z', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 
'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i',  
'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 
'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's',  
't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 
'y' => 'y', 'z' => 'z', '-' => '-' 
); 

$new = '';
preg_match_all('/./u', $str, $results);
$str=$results[0];            
foreach ($str as $char){
    if (isset ($arr[$char]))  
        $new .= $arr[$char];    
    else
        $new .= $char;   
    }
return $new;
}

echo fulltohalf("Codebit.cn - 聚合小段精华代码");
?>

6 个答案:

答案 0 :(得分:8)

一行代码:

$str="Codebit.cn - 聚合小段精华代码";
$str = mb_convert_kana($str, "rnaskhc", 'UTF-8');
echo $str;

Codebit.cn - 聚合小段精华代码

变为

Codebit.cn - 聚合小段精华代码

你可以将这些字母作为奖励。

参考:http://php.net/mb_convert_kana

答案 1 :(得分:1)

strstr()在另一个字符串中搜索字符串的出现次数。

您使用字符串和数组调用它。

为什么不直接返回键的相应值?

function fulltohalf($str){

    $arr = array('0' => '0', '1' => '1', '2' => '2', '3' => '3', 
                 '4' => '4','5' => '5', '6' => '6', '7' => '7',
                 '8' => '8', '9' => '9','A' => 'A',
                 ....
                );
    $new = '';            //initialise output
    $old = str_split($str); // convert string to array of characters
    foreach ($old as $char){
        if (isset $arr[$char]) //check if the input is a key in the array
            $new .= $arr[$char];   //add to output
        else
            $new .= '_';   //put something to indicate missing/undefined
    }
    return $new;
}

在每个函数调用上构造数组可能效率低。

你可能想在你的main函数中定义它,然后将它传递给你的fulltohalf()函数,或者根本不打扰函数。

在这些情况下,我会补充一点,你应该避免使用mysql来支持mysqli(改进)。

<强> 附加

如果从一个字符集转换为另一个字符集,我会使用php函数,而不是重新发明轮子。

请参阅mb_convert_encodingsupported encodings

我无法确定您要使用哪种编码,但以下内容可能会起作用:

mb_convert_encoding($str, "UTF-8","UCS-2")

答案 2 :(得分:1)

一个简单的解决方案是将str_replace()与字符串数组一起使用,有效地进行多字节替换。例如:

$str = 'Fooooo';
echo str_replace(array('F', 'o'), array('F', 'o'), $str);

可能更强大的解决方案是使用mb_convert_kana(),如下所示:

$str = 'Fooooo';
echo mb_convert_kana($str, 'a', 'UTF-8'); // change UTF-8 to fit your input charset

两种解决方案都将输出:

Fooooo

答案 3 :(得分:1)

我认为在这种情况下最好使用preg_replace而不是str_replace。我们将在字符串中搜索队列数组的键,并用相应的值替换它们。这也是一个非常易读且易于解决的问题。

function fulltohalf($str)
{ 
    $queue = [ 
        '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4',  
        '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', 
        'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E',  
        'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 
        'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O',  
        'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 
        'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y',  
        'Z' => 'Z', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 
        'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i',  
        'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 
        'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's',  
        't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 
        'y' => 'y', 'z' => 'z', '-' => '-' 
    ]; 

    return str_replace(array_keys($queue),array_values($queue),$str);
}

请注意,我通过声明:

使页面处于UTF-8模式
<meta charset="UTF-8">

这是我的测试:

$str = "Codebit.cn - 聚合小段精华代码";
echo $str;
echo "<br>";
echo fulltohalf($str);

以下是我的结果:

  

Codebit.cn - 聚合小段精华代码
  Codebit.cn - 聚合小段精华代码

答案 4 :(得分:0)

方法2:

我已将preg_replace更改为preg_replace_callback并使用匿名函数来消除警告。你的正则表达错了,我已经改变了。在匿名函数中有简单的查找。

<?php
function fulltohalf($Str) { 
    $Queue = Array( 
        '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4',  
        '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', 
        'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E',  
        'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 
        'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O',  
        'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 
        'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y',  
        'Z' => 'Z', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 
        'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i',  
        'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 
        'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's',  
        't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 
        'y' => 'y', 'z' => 'z', '-' => '-' 
    ); 

    return preg_replace_callback(
        "/([\xEF][\x80-\xBF]+)/",
        function($m) use($Queue) {
            if (array_key_exists($m[0], $Queue)) {
                return $Queue[$m[0]];
            } else {
                return $m[0];
            }
        },
        $Str);
}

$str = "Codebit.cn - 聚合小段精华代码"; 
echo $str; 
echo "<br />"; 
echo fulltohalf($str);

答案 5 :(得分:0)

我只是修复你的错误。

<?php
function fulltohalf($str){
    $arr=Array(
        '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4',
        '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9',
        'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E',
        'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J',
        'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O',
        'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T',
        'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y',
        'Z' => 'Z', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd',
        'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i',
        'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n',
        'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's',
        't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x',
        'y' => 'y', 'z' => 'z', '-' => '-'
    );

    $new = '';
    for($i = 0; $i < strlen($str); $i++){
        $char = $str[$i];
        $new .= (isset($arr[$char]))?  $arr[$char]: $char;
    }
    return $new;
}

$str="Codebit.cn - 聚合小段精华代码";
echo fulltohalf($str);
?>

首先,你的代码使用了foreach,我改为for($ i = ...),因为string不支持foreach语法(迭代)。 其次,你的if / else短语与逻辑不兼容。

if()$arr[$char]; else $arr; // <- else array!?

我修好了,

if() $converted_char; else $original_char;

另外,您可以使用其他方法

每个人都说,mb_convert_kana()。是的,这是一个很好的解决方案。