php比較関数
12002 ワード
最近PHP言語のソースコード-比較関数をブラウズしました
実は私が言った比較関数は文字列比較ではなく、PHPの配列でソートするときに比較関数が必要です.
1、なぜ比較関数を使うのか
まず比較関数を使うメリットはコードの抽象で、実は比較関数の規則を満たすだけで、あなた自身の方法でソートすることができて、降順と昇順のこれらの簡単な規則ではありません!ルールを満たす{-1,0,1}-1:より小さい、0は等しい、1はサイズを表す
2.比較関数で
3.まとめ
実は一般の人は比較関数が簡単だと思っています:-1,0,1を返して比較してもいいですか、どうしてそんなに長く書いていますか.第一に、phpは弱いタイプの言語で、私達は2つの数がどんなタイプなのかを比較することができなくて、例えば数字、数字はまた型を分けて、浮動小数点型、長い型、文字列、空は長いPHPの2つのPHPのタイプの個数=2^(PHPのタイプの個数)に等しいです
これは一つの言語で、人気のある言語で、考慮の方面は比較的に多くて、全面性、
一つの言語の存在時間が長ければ長いほど、パッチが多くなります.これは実践の中で検証されています.なぜかと聞くと、知らないかもしれませんが、どうせこのような問題は避けることができます.環境のために、あなたはきっと#if HAVEを見たことがあります.STRCOLL#endifなどは、関数のバグを避けることもできるし、コードの抽象的な違いを避けることもできる.例えばアプリケーション層:php言語でwebページを書くことができます.下位層はc言語でtcp/ipの書き込みプロトコルを書くだけです.
実は私が言った比較関数は文字列比較ではなく、PHPの配列でソートするときに比較関数が必要です.
1、なぜ比較関数を使うのか
まず比較関数を使うメリットはコードの抽象で、実は比較関数の規則を満たすだけで、あなた自身の方法でソートすることができて、降順と昇順のこれらの簡単な規則ではありません!ルールを満たす{-1,0,1}-1:より小さい、0は等しい、1はサイズを表す
2.比較関数で
ZEND_API int compare_function(zval *result, zval *op1, zval *op2) /* {{{ */
{
int ret;
int converted = 0;
zval op1_copy, op2_copy;
zval *op_free, tmp_free;
while (1) {
switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
case TYPE_PAIR(IS_LONG, IS_LONG):
ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));
return SUCCESS;
case TYPE_PAIR(IS_DOUBLE, IS_LONG):
Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
return SUCCESS;
case TYPE_PAIR(IS_LONG, IS_DOUBLE):
Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
return SUCCESS;
case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {
ZVAL_LONG(result, 0);
} else {
Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);
ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));
}
return SUCCESS;
case TYPE_PAIR(IS_ARRAY, IS_ARRAY):
ZVAL_LONG(result, zend_compare_arrays(op1, op2));
return SUCCESS;
case TYPE_PAIR(IS_NULL, IS_NULL):
case TYPE_PAIR(IS_NULL, IS_FALSE):
case TYPE_PAIR(IS_FALSE, IS_NULL):
case TYPE_PAIR(IS_FALSE, IS_FALSE):
case TYPE_PAIR(IS_TRUE, IS_TRUE):
ZVAL_LONG(result, 0);
return SUCCESS;
case TYPE_PAIR(IS_NULL, IS_TRUE):
ZVAL_LONG(result, -1);
return SUCCESS;
case TYPE_PAIR(IS_TRUE, IS_NULL):
ZVAL_LONG(result, 1);
return SUCCESS;
case TYPE_PAIR(IS_STRING, IS_STRING):
if (Z_STR_P(op1) == Z_STR_P(op2)) {
ZVAL_LONG(result, 0);
return SUCCESS;
}
ZVAL_LONG(result, zendi_smart_strcmp(op1, op2));
return SUCCESS;
case TYPE_PAIR(IS_NULL, IS_STRING):
ZVAL_LONG(result, Z_STRLEN_P(op2) == 0 ? 0 : -1);
return SUCCESS;
case TYPE_PAIR(IS_NULL, IS_STRING):
ZVAL_LONG(result, Z_STRLEN_P(op2) == 0 ? 0 : -1);
return SUCCESS;
case TYPE_PAIR(IS_STRING, IS_NULL):
ZVAL_LONG(result, Z_STRLEN_P(op1) == 0 ? 0 : 1);
return SUCCESS;
case TYPE_PAIR(IS_OBJECT, IS_NULL):
ZVAL_LONG(result, 1);
return SUCCESS;
case TYPE_PAIR(IS_NULL, IS_OBJECT):
ZVAL_LONG(result, -1);
return SUCCESS;
default:
if (Z_ISREF_P(op1)) {
op1 = Z_REFVAL_P(op1);
continue;
} else if (Z_ISREF_P(op2)) {
op2 = Z_REFVAL_P(op2);
continue;
}
if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HANDLER_P(op1, compare)) {
return Z_OBJ_HANDLER_P(op1, compare)(result, op1, op2);
} else if (Z_TYPE_P(op2) == IS_OBJECT && Z_OBJ_HANDLER_P(op2, compare)) {
return Z_OBJ_HANDLER_P(op2, compare)(result, op1, op2);
}
if (Z_TYPE_P(op1) == IS_OBJECT && Z_TYPE_P(op2) == IS_OBJECT) {
if (Z_OBJ_P(op1) == Z_OBJ_P(op2)) {
/* object handles are identical, apparently this is the same object */
ZVAL_LONG(result, 0);
return SUCCESS;
}
if (Z_OBJ_HANDLER_P(op1, compare_objects) == Z_OBJ_HANDLER_P(op2, compare_objects)) {
ZVAL_LONG(result, Z_OBJ_HANDLER_P(op1, compare_objects)(op1, op2));
return SUCCESS;
}
}
if (Z_TYPE_P(op1) == IS_OBJECT) {
if (Z_OBJ_HT_P(op1)->get) {
zval rv;
op_free = Z_OBJ_HT_P(op1)->get(op1, &rv);
ret = compare_function(result, op_free, op2);
zend_free_obj_get_result(op_free);
return ret;
} else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {
ZVAL_UNDEF(&tmp_free);
if (Z_OBJ_HT_P(op1)->cast_object(op1, &tmp_free, ((Z_TYPE_P(op2) == IS_FALSE || Z_TYPE_P(op2) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op2))) == FAILURE) {
ZVAL_LONG(result, 1);
zend_free_obj_get_result(&tmp_free);
return SUCCESS;
}
ret = compare_function(result, &tmp_free, op2);
zend_free_obj_get_result(&tmp_free);
return ret;
}
}
if (Z_TYPE_P(op2) == IS_OBJECT) {
if (Z_OBJ_HT_P(op2)->get) {
zval rv;
op_free = Z_OBJ_HT_P(op2)->get(op2, &rv);
ret = compare_function(result, op1, op_free);
zend_free_obj_get_result(op_free);
return ret;
} else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {
ZVAL_UNDEF(&tmp_free);
if (Z_OBJ_HT_P(op2)->cast_object(op2, &tmp_free, ((Z_TYPE_P(op1) == IS_FALSE || Z_TYPE_P(op1) == IS_TRUE) ? _IS_BOOL : Z_TYPE_P(op1))) == FAILURE) {
ZVAL_LONG(result, -1);
zend_free_obj_get_result(&tmp_free);
return SUCCESS;
}
ret = compare_function(result, op1, &tmp_free);
zend_free_obj_get_result(&tmp_free);
return ret;
} else if (Z_TYPE_P(op1) == IS_OBJECT) {
ZVAL_LONG(result, 1);
return SUCCESS;
}
}
if (!converted) {
if (Z_TYPE_P(op1) == IS_NULL || Z_TYPE_P(op1) == IS_FALSE) {
ZVAL_LONG(result, zval_is_true(op2) ? -1 : 0);
return SUCCESS;
} else if (Z_TYPE_P(op2) == IS_NULL || Z_TYPE_P(op2) == IS_FALSE) {
ZVAL_LONG(result, zval_is_true(op1) ? 1 : 0);
return SUCCESS;
} else if (Z_TYPE_P(op1) == IS_TRUE) {
ZVAL_LONG(result, zval_is_true(op2) ? 0 : 1);
return SUCCESS;
} else if (Z_TYPE_P(op2) == IS_TRUE) {
ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1);
return SUCCESS;
} else {
zendi_convert_scalar_to_number(op1, op1_copy, result);
zendi_convert_scalar_to_number(op2, op2_copy, result);
converted = 1;
}
} else if (Z_TYPE_P(op1)==IS_ARRAY) {
ZVAL_LONG(result, 1);
return SUCCESS;
} else if (Z_TYPE_P(op2)==IS_ARRAY) {
ZVAL_LONG(result, -1);
return SUCCESS;
} else if (Z_TYPE_P(op1)==IS_OBJECT) {
ZVAL_LONG(result, 1);
return SUCCESS;
} else if (Z_TYPE_P(op2)==IS_OBJECT) {
ZVAL_LONG(result, -1);
return SUCCESS;
} else {
ZVAL_LONG(result, 0);
return FAILURE;
}
}
}
}
3.まとめ
実は一般の人は比較関数が簡単だと思っています:-1,0,1を返して比較してもいいですか、どうしてそんなに長く書いていますか.第一に、phpは弱いタイプの言語で、私達は2つの数がどんなタイプなのかを比較することができなくて、例えば数字、数字はまた型を分けて、浮動小数点型、長い型、文字列、空は長いPHPの2つのPHPのタイプの個数=2^(PHPのタイプの個数)に等しいです
これは一つの言語で、人気のある言語で、考慮の方面は比較的に多くて、全面性、
一つの言語の存在時間が長ければ長いほど、パッチが多くなります.これは実践の中で検証されています.なぜかと聞くと、知らないかもしれませんが、どうせこのような問題は避けることができます.環境のために、あなたはきっと#if HAVEを見たことがあります.STRCOLL#endifなどは、関数のバグを避けることもできるし、コードの抽象的な違いを避けることもできる.例えばアプリケーション層:php言語でwebページを書くことができます.下位層はc言語でtcp/ipの書き込みプロトコルを書くだけです.