PHP5上級試験/準上級試験の上級合格に挑戦(6)　4章文字列後編

# 4章文字列

ここでは関数を中心に挙げる
使いこなせるようにドリルも用意した。

文字列操作関数/エンティティ置換関数・エンコード処理関数・エスケープ処理関数/文字列比較関数/文字列分解・結合関数/文字列検索関数/

## 文字列操作

### 不要なものを除去する
+ 対象が両端か、それとも右端、左端かによって３つある（trim,ltrim,rtrim)
+ 引数は３つとも、取り除く文字。設定しない場合は、<br>空白・タブ・キャリッジリターン・NULLバイト・垂直タブを除去
+ マクロでも同様のものはあるが、PHPのように除去したい文字を自由に指定することはできないのでPHPは便利

コードは後ほど

### 大文字⇔小文字変換
+　大文字⇔小文字、小文字⇔大文字、文字列の先頭の文字だけを大文字にする、各単語の先頭の文字を大文字にするの４種類。
+　それぞれ、strtolower(),strtoupper(),ucfirst(),ucwords()がある。引数はもちろん変更対象。
+　問題としては、strtolower/strtoupper/ucfirstを絡めて出力結果がどうなるかを問う問題が多い傾向。
+　正誤問題としては、ucfirst()とucwords()の違いが問われそう。
+　ちなみに問題集にはないが、文字列の先頭の文字だけ小文字にする[lcfirst\(\)](https://www.php.net/manual/ja/function.lcfirst.php)もある。
   先頭を大文字にするのは英語の特徴なので、lcfirstはあまり使わない。
+　ucwords()の動作が分かりづらいので実際にコードを書いて確かめる。コードは下記。

```index.php
//(1)trim
$MyStr = "Hello,World";
echo "<br>";
echo trim($MyStr,"Hdle");
echo "<br>";
echo ltrim($MyStr,"Hdle");
echo "<br>";
echo rtrim($MyStr,"Hdle");

//(2)大文字⇔小文字変換
$MyStr = "HELLO,WORLD!";
echo ucfirst(strtolower($MyStr));
echo "<br>";
$MyStr2 = "Thank|you!";
echo ucwords($MyStr2);
echo "<br>";
echo ucwords($MyStr2,"|");

```

(1)出力は
o,Wor
o,World
Hello,Wor

(2)出力は
Hello,world!
Thank|you!
Thank|You!

(1)Hdleというのは、リストで、H,d,l,eがあればトリムするということ。
trimの場合は両端、
ltrim/rtrimの場合、それぞれ左端・右端から数えて空白やコンマのところまで。（検証済）
実際に使うときは　たとえば、/words/　があって、両端ではなくて右端のだけ削除したいとかで役に立つだろう。

（２）　これはucfirstとstrtolowerのあわせ技。結構出ると思う。
そしてもう一つ、ucwordsの使い方。　他のデータから持ってきてプログラム上で使いたい、などのときに役に立つ。

## 文字数取得
+ strlenとmb_strlenがある。
+ 英語はstrlenで調べ,mb_strlenは日本語（マルチバイト）の文字数を調べる。

コードは後ほど

## 文字列検索(substr系）
### substr(string $string,int $start [, int $length])
+ 文字列の中から、該当する位置から指定した文字数分<b>コピー</b>したものを返す。
+ startは開始位置だが、実際に返すのは開始位置＋１から。結構間違えるので注意。
+ startが正の場合は、前から数えるが、負の場合は、後ろから数えることになる
+ lengthは文字数を表すが、これが負の場合、後ろから数えることになる
+ [参考|PHPマニュアル](https://www.php.net/manual/ja/function.substr.php)

### substr_count(string $target,string $search_word,int $offset = 0 , int|null $length = null ) : int)
+ 特定のキーワードが何回登場するかを返す。
+ ＄targetは検索する文字列。
+ $search_wordは検索する文字列
+ ＄offset,$lengthは検索開始位置と検索する長さ。
+ [参考|PHPマニュアル](https://www.php.net/manual/ja/function.substr-count)

### substr_replace(array|string $target , array|string $replace_word , array|int $offset , array|int|null $length = null ) : string|array

+ 文字列の一部を検索して置換する
+ \$targetは置換対象、\$replace_wordは置き換えるワード。\$offsetと$lengthで置き換える位置とその長さを指定する
+ ちなみに見ての通り、配列へも置換できる
+ [参考|PHPマニュアル](https://www.php.net/manual/ja/function.substr-replace)

## その他

### strrev ( string $string ) : string
文字列を逆読みにして返す
わかりやすいのでマニュアルへのリンクはなし

### str_repeat ( string $string , int $times ) : string
\$stringを$times分繰り返す
わかりやすいのでマニュアルへのリンクはなし

### str_pad ( string $string1 , int $length , string $pad_string2 = " " , int $pad_type = STR_PAD_RIGHT ) : string

+ ある文字列＄string1に指定した＄lengthの長さになるまで、\$pad_string2を継ぎ足していく。
+ \$pad_typeは継ぎ足す方向。上記の場合は右端（デフォルト）。　他にも`STR_PAD_LEFT`(左端）, `STR_PAD_BOTH`（両端）がある。
+ [参考|PHPマニュアル](https://www.php.net/manual/ja/function.str_pad)

```index.php

$MyStr = "HELLO,WORLD!";
$MyStr2 = "ごきげんだね、きみは";

echo strlen($MyStr);
echo "<br>";
echo mb_strlen($MyStr2);
echo "<br>";
echo "<br>";
//文字列検索
echo substr($MyStr,4,2);
echo "<br>";
echo substr($MyStr,-7);
echo "<br>";
echo substr($MyStr,-7,-5);
echo "<br>";
echo substr_count($MyStr,'L');
echo "<br>";
echo substr_count($MyStr,'L',7,5);
echo "<br>";
echo substr_replace($MyStr,'Atsu',6,5);
echo "<br>";
//その他
echo strrev($MyStr);
echo "<br>";
echo str_repeat('^=',10);
echo "<br>";
echo str_pad($MyStr,20,'^=',STR_PAD_BOTH);


```
出力は
12
10

O,
,WORLD!
,W
3
1
HELLO,Atsu!
!DLROW,OLLEH
^=^=^=^=^=^=^=^=^=^=
^=^=HELLO,WORLD!^=^=

となる。

substr_replaceは、日本語変換すると文字化けするので、英語に。
str_repeatやstr_padをつかって面白いやり方をしてみた。これ色々な意味で使えそう

## エンティティ（HTMLエンティティ） 系関数
+ HTMLで特別な意味を持つタグをHTMLとしないでエスケープさせてそのまま出力させるもの
+ たとえば、HTMLの、\<p\>新しい地図\</p\>　は、
\&lt;p\&gt;新しい地図\&lt;/p\&gt; 
 と変換される。
+ たとえばフォームなどでいたずらでHTMLタグをそのまま記入すると、バグを引き起こす要因になるので、フォーム側でこのエンティティ処理が必要。つまりはセキュリティ上必要な処理。
+ そのようなエンティティ処理をする関数にはhtmlentities()とhtmlspecialchars()がある。
+ htmlspecialchars()は 「&」、「"」、「'」、「<」、「>」 の５つの記号をエンコードするが、htmlentitiesはエンコード可能なものはすべて根こそぎエンコードするということろに違いがある。（ただし、両方ともオプションによって変わる）

### htmlentities ( string $string , int $flags = ENT_COMPAT , string|null $encoding = null , bool $double_encode = true ) : string

+ stringはエンコード対象となる文字列 
+ flagsは置き換えオプション。
+ デフォルトは`ENT_COMPAT`で、「ダブルクォートのみエンコード」、`ENT_QUOTES`で「シングルクォートもエンコード」、`ENT_NOQUOTES`で「クォートはエンコードしない」という意味
+ encordingはエンコーディング。基本はいじらなくてOK　UTF-8などに変える必要があればこちらで。
+ double_encodeはオフにするとPHP は既存の html エンティティをエンコードしなくなる
+ アクセント記号（発音記号みたいな）やウムラウト記号（ドイツ語みたいな上に２つの点がついてるもの）もエンコード。(htmlspecialchars（）はしない）
+ [参考|PHPマニュアル](https://www.php.net/manual/ja/function.htmlentities)

### htmlspecialchars ( string $string , int $flags = ENT_COMPAT , string|null $encoding = null , bool $double_encode = true ) : string

+ 引数はhtmlentitiesと共通
+ アクセント記号（発音記号みたいな）やウムラウト記号（ドイツ語みたいな上に２つの点がついてるもの）もエンコードしない
+ [参考|PHPマニュアル](https://www.php.net/manual/ja/function.htmlspecialchars)

## URLエンコード
### urlencode ( string $string ) : string
+ 文字通り文字列をURLエンコードする
+ -_. を除くすべての非英数文字が % 記号 (%)に続く二桁の16進数で置換、 空白は +にエンコード
+ ~（チルダ）は`&7E`とエンコード
+ デコードはurldecode() 。


### rawurlencode ( string $string ) : string
+ RFC 3986 に基づき URL エンコードを行う
+ -_.~ を除くすべての非アルファベット文字をパーセント 記号 (%)に続いて 2 つの 16 進数がある表現形式に置換した文字列を返す
+ 空白は%20にエンコード。
+ デコードはrawurldecode() 。

※RFC 3986とは、RFC（Request for Comments）、すなわち、インターネットで用いられるさまざまな技術の標準化や運用に関する事項など幅広い情報共有を行うために公開される文書シリーズの３９８６番目？のファイルのこと
ちなみに[Wikipedia](https://ja.wikipedia.org/wiki/Request_for_Comments)を見ると他のRFCへのリンクが貼ってある

※このファイルでは、エンコード、すなわち予約文字(Reserved Character)と非予約文字(Unreserved Character)が定められており、これに従ってエンコードされるということ。

※ [参考 | URLエンコードについておさらいしてみた@sisisin](https://qiita.com/sisisin/items/3efeb9420cf77a48135d)　

### addslashes() ※非推奨
+ addslashes()は対象の文字列にある「'」「"」「\」「NULLバイト」に「\」をつける
+ Database上ではこのエスケープは不適切で、使用するDBシステムに合わせて専用のエスケープを使用することが推奨されている

### stripslashes()
+ クォートされた文字列のクォート部分を取り除く

## その他

### strip_tags( string $string [, string $allowable_tags ) : string

+ 文字列からHTMLタグなどを取り除く
+ $alloable_tagsは取り除かないタグ。省略可。
+ [参考|PHPマニュアル](https://www.php.net/manual/ja/function.htmlspecialchars)

### get_meta_tags(string $filename , bool $use_include_path = false ) : array|false) 

+ HTMLファイルのMETAタグを読み取って連想配列にする
+ $filenameとあるが、ファイル名以外にURLも指定できる
+ $use_include_pathはTrueの場合はインクルードパスに従ってファイルを探す
+ [参考|PHPマニュアル](https://www.php.net/manual/ja/function.get-meta-tags.php)

##文字列比較（数値比較ではない）

+ 演算子を用いる方法と関数を用いる方法の２つがある
+ 演算子`==`と`===`とで比較する場合、<b>どちらも大文字小文字を区別する</b>。ただし、`==`は思わぬ結果が帰るので使わないほうがいい。
+ `<`と`<=`は、辞書順での比較になる。　たとえば、　aa < ab と、後になる方が大きくなる。
+ ちなみに、数値という文字列とアルファベットとでは、数値よりアルファベットのほうが大きくなる。
+ ただし、文字列と文字列でない数値の比較になると、文字列が数値に変換されてから比較されるので、数値のほうが大きくなる。

関数ドリル

（１）大文字小文字を区別せず、２つの文字列を辞書順で比べ、正負の数、０のどれかをリターンするのは？
（２）大文字小文字を区別し、２つの文字列を辞書順で比べるのは？
（３）大文字小文字を区別し、最初の数文字だけを比較するのは？
（４）大文字小文字を区別せず最初の数文字だけを比較するのは？
（５）大文字小文字を区別せず、２つの文字列を自然順で比べ、正負の数、０のどれかをリターンするのは？
（６）大文字小文字を区別し、２つの文字列を自然順で比べ、正負の数、０のどれかをリターンするのは？

（１） strcmp(string \$str1, string $str2) 読み：すとらきゃんぷ

（2） strcasecmp(string \$str1, string $str2) 読み：すとらけーすきゃんぷ

（３） strncmp((string \$str1, string $str2, int\ $$len) 読み：すとらんきゃんぷ

（４） strncasecmp((string \$str1, string $str2, int\ $$len) 読み：すとらんけーすきゃんぷ

（５） strnatecmp((string \$str1, string $str2, int\ $$len) 読み：すとらねいときゃんぷ

（6） strnatecasecmp((string \$str1, string $str2, int\ $$len) 読み：すとらねいとけーすきゃんぷ



## 文字列の分解・結合処理関数

関数ドリル
（１）区切り文字で分解して配列を返すのは？
（２）区切り文字列を間に入れ、配列にある文字列を結合するのは？
（3）（2）のエイリアスは？
（4）文字列をトークンに分割するのは？
（５）URLをスキーム、ホスト、パスなどの構成要素に分解し、連想配列として返すのは？
（６）printfと同じ「書式文字列」に沿ってかかれた文字列を分解して、配列にして返すのは？

（１） explode(string \$delimiter, string $string)

（２） implode(string \$glue, array $pieces)

（３） join((string \$glue, array $pieces)

（４）strtok(string \$str, string \$token) →２回目以降　strtok(string \$token)

（５）parse_url(string $url)

（６） sscanf(string \$string string $format) 読み方：えすすきゃんえふ


## 文字列検索関数

関数ドリル
（１）文字列から、左端を０とし、KWが<b>最初</b>に現れる位置を返すのは？　見つからない時は何を返す？
（２）文字列から、左端を０とし、KWが<b>最後</b>に現れる位置を返すのは？　見つからない時は何を返す？
(3)文字列から、左端を０とし、KWが<b>最初</b>に現れた位置から末尾までの文字を返すのは？
（４）（３）のエイリアスは？
（５）文字列から、大文字小文字を無視し、左端を０とし、KWが<b>最初</b>に現れた位置から末尾までの文字を返すのは？
（６）文字列から、左端を０とし、KWが<b>最後</b>に現れた位置から末尾までの文字を返すのは？
（７）文字列から「検索文字列」に含まれる文字のみで構成される部分が何文字あるかを返すのは？
（８）文字列から「検索文字列」に含まれない文字のみで構成される部分が何文字あるかを返すのは？

（１） strpos(string \$target, mixed $keyword)  読み方；すとらぽす

（２） strrpos(string \$target, mixed $keyword)  読み方；すとらりぽす　※リバースの頭がリなので

（３） strstr(string \$target, mixed $keyword)   読み方；すとらすとら 

（４） strchr(string \$target, mixed $keyword)   読み方；すとらちゃー 

（５） stristr(string \$target, mixed $keyword)   読み方；すとりすとら

（６） strrchr(string \$target, mixed $keyword)   読み方；すとらりちゃー

（７） strspn(string \$target, mixed $keyword)   読み方；すとらすぱん

（８） strcspn(string \$target, mixed $keyword)   読み方；すとらしーすぱん


文字列検索関数は、関数名からしてややこしく、関数名からどのような機能かを正誤問題で出題しそう。
（７）・（８）は文字列であって、数値は検索しないことに注意。