肉とビールとパンケーキ by @sotarok

少し大人になった「肉とご飯と甘いもの」

PHPのC言語による実装「function ucwords」

てかこんな便利な関数あったの今日知ったんだけどな。


バージョン:PHP 5.2.3

ソース

ext/standard/string.c @line 2463

/* {{{ proto string ucwords(string str)
   Uppercase the first character of every word in a string */
PHP_FUNCTION(ucwords)
{
	zval **str;
	register char *r, *r_end;
	
	if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
		WRONG_PARAM_COUNT;
	}
	convert_to_string_ex(str);

	if (!Z_STRLEN_PP(str)) {
		RETURN_EMPTY_STRING();
	}

	ZVAL_STRINGL(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
	r = Z_STRVAL_P(return_value);

	*r = toupper((unsigned char) *r);
	for (r_end = r + Z_STRLEN_P(return_value) - 1; r < r_end; ) {
		if (isspace((int) *(unsigned char *)r++)) {
			*r = toupper((unsigned char) *r);
		}
	}
}
/* }}} */

処理の流れ

とりあえず、ZVALとかその辺の、なんかいつも使ってるんだろうな?というあたりは無視して、ucwordsの処理のクリティカルな部分だけ追うことにする。その上は今度調べるとしよう、そうしよう。

なので、追うところは、

	*r = toupper((unsigned char) *r);
	for (r_end = r + Z_STRLEN_P(return_value) - 1; r < r_end; ) {
		if (isspace((int) *(unsigned char *)r++)) {
			*r = toupper((unsigned char) *r);
		}
	}

これだ。

  1. 最初の文字を大文字にする。(toupper)
  2. r_end (文字列の最後)まで繰り返す
    1. もし空白なら、次の文字は大文字にする。


意外と処理内容は普通。forでまわしてるのか。
って、ここまで読みながら書きながら考えながらでしたが、重大なことに気づいた。

(int) *(unsigned char *)r++

これなにやってるかよくわからん。(ぉ なんでintにキャストしてるの?


...調べ中...*1


あ。isspace(int c) か。isspaceの引数ってintなんだ。たしかC言語て、charをintにすると文字コードになるんだったかな?ふーん、それで。

まとめ

  • 要するに、C言語の勉強になる。*2
  • 私はC言語の文字列に関する処理が苦手


時間のあるときでやる気が出たときにこのシリーズやろ。笑

*1:調べてから書けよとか。

*2:なんだこれ。笑