C言語の文字数計測の基本
「文字列の文字数を数えたい」と思ったとき、まず知っておくべきことがあります。
それは、「C言語で文字列がどういう仕組みで保存されているか」ということです。
この基本を理解しておくと、文字数を数えるときに起こるエラーの原因がわかり、安全なプログラムを書けるようになります。
文字列と終端文字の概念整理
C言語の文字列には、他の言語にはない特別な仕組みがあります。
それは、文字列の最後に必ず「\0」というNULL文字(終端文字)が付くということです。このNULL文字が文字列の終わりを示す目印になっています。
文字数を数えるときは、この終端文字は含めません。
例えば「cat」という文字列は、メモリ上では「c」「a」「t」「\0」という4つの要素で構成されていますが、文字数としては3文字になります。
配列とポインタによる文字アクセス
C言語では、文字列を「配列」または「ポインタ」という2つの方法で扱います。
配列として定義すると、文字列は決まったサイズのメモリ領域に格納されます。一方、ポインタとして定義すると、文字列の先頭アドレス(場所)を指すようになります。
文字数を数える処理では、この2つの違いを理解しておくことが大切です。実は、配列名は配列の先頭要素のアドレスを表すため、実際の処理では同じようにアクセスできます。
ちなみに、配列とポインタはメモリの使い方に違いがあります。配列は固定サイズの領域を確保しますが、ポインタの場合、実体である "cat" はプログラム自体が保存されている読み取り専用のメモリ領域にあります。
ポインタはその住所を指しているだけなので、配列のように中身を直接書き換えることはできません。
最初は、難しいと思うので、「メモリの使い方が違うんだな」ということだけ押さえておいてください。
文字数計測における注意点と制限
文字数を数えるときに最も注意しなければならないのは、「終端文字がちゃんとあるか」を確認することです。
もし文字列に終端文字がない場合、プログラムは「どこで終わるのかわからない」状態になってしまいます。そうなると、メモリの範囲外まで読み続けてしまい、プログラムがクラッシュする可能性があります。
また、配列のサイズを超えて文字を書き込むと「バッファオーバーフロー」という深刻なエラーが発生します。
こういった問題を避けるため、常に配列のサイズを意識し、適切な終端処理を行うことが重要です。
最初のtigerは終端文字がないため、文字数を数えようとすると予期しない動作を引き起こす可能性があります。
2番目のlionのように、必ず最後に\0を付けることが安全なプログラムを作る第一歩です。
strlen関数による文字数計測の基礎
「文字数を数えたい」と思ったとき、C言語で最もよく使われるのがstrlenという関数です。
わざわざ自分で1文字ずつ数えるプログラムを書かなくても、この関数を使えば簡単に文字列の長さを取得できます。
ここではstrlenの仕組みから実用的な使い方、そしてよくある失敗例までくわしく見ていきましょう。
なお、以下の記事でもstrlen関数について詳しく解説しています。
【関連】C言語のstrlen関数の使い方は?初心者向けに徹底解説
strlen関数の仕組みと基本構文
strlen関数は、文字列の先頭から終端文字「\0」まで、1文字ずつ数えていきます。戻り値の型はsize_t型(通常は符号なし整数)で、終端文字は含まれません。例えば「rabbit」という6文字の文字列なら、6が返ってきます。
使う際はstring.hというヘッダーファイルをインクルードする必要があります。
インクルードとは、他のファイルに書かれている機能を自分のプログラムで使えるようにする仕組みのことです。C言語には、文字列操作や数学計算など、よく使う機能があらかじめ用意されています。この機能は「ライブラリ」と呼ばれるファイルにまとめられていて、#includeを使うことで読み込むことができます。
例えば、#include <string.h>と書くと、strlen関数やstrcpy関数など、文字列を扱うための関数が使えるようになります。
インクルードを忘れると、コンパイラが「そんな関数は知りません」というエラーを出すので、必要なヘッダーファイルは忘れずにインクルードしましょう。
出力結果
文字数: 6strlen(animal)と書くだけで、あっという間に文字数が取得できます。
ちなみに、%zuという書式指定子はsize_t型を表示するためのものです。
strlen使用時の典型的なエラーと注意点
strlenを使うときに危険なのは、終端文字のない文字列を渡してしまうことです。
この場合、関数はメモリ上を無制限に読み続けてしまい、プログラムがクラッシュする可能性があります。また、初期化されていないポインタやNULLポインタを渡すことも同じように危険です。
また、戻り値がsize_t型(符号なし)であることを忘れて負数と比較すると、思わぬ結果を招くことがあります。
コメントアウトしている行は、実際に実行すると危険な例です。
empty_ptrはNULLなので、strlenに渡すとエラーになります。no_terminatorは終端文字がないため、どこまで読み進めるかわかりません。
strlenと他関数(strcmpなど)との関連
strlenは、他の文字列を処理する関数と組み合わせて使うことが多いです。
例えば、strcmp関数で文字列を比較する前に、strlenで長さを確認することで処理効率を上げられます。
また、strcpy関数で文字列をコピーする際は、コピー先の配列サイズがstrlenの結果より大きいことを確認する必要があります。
出力結果
同じ長さ: -1この例では、まず両方の文字列が同じ長さかどうかをstrlenで確認してから、strcmpで内容を比較しています。
strcmp という関数は、2つの文字列を先頭から1文字ずつ同じかどうかを確認していく関数です。
そもそも長さが違えば、同じ文字列ではないことが明白になります。比較する必要もないので、効率的な処理になるというわけです。
while文を使った文字数カウントの自作実装
strlen関数は便利ですが、実際にどうやって文字数を数えているのでしょうか?
自分で文字数をカウントする関数を作ることで、文字列処理の仕組みをより深く理解できます。while文を使って、strlenと同じような関数を作ってみましょう。
while文を使った文字数カウントの自作実装
while文で文字数をカウントする方法は、とてもシンプルです。文字列の先頭から1文字ずつチェックして、終端文字「\0」に出会うまでカウンタを増やし続ければいいのです。
この処理には2つのやり方があります。1つは配列のインデックスを使う方法で、もう1つはポインタを使う方法です。
どちらも同じ結果が得られますが、ポインタを使う方法の方がメモリ効率が良いとされています。実装する際に大切なのは、終端の条件を正しく設定することです。
出力結果
文字数: 5この関数では、str[count]で1文字ずつチェックして、それが\0でない限りカウントを増やしています。
\0に到達したらループが終わり、その時点でのカウント数が文字数になります。
whileを用いた基本的な文字数走査処理
ポインタを活用すると、もう少し違った書き方ができます。
ポインタを直接操作しながら進んでいく方法では、ポインタをインクリメント(1つずつ進める)しながら、指している文字が終端文字になるまでループを続けます。
ポインタを活用した方法は、配列のインデックス操作よりも処理が速くなる場合があります。ポインタの操作に慣れると、より効率的な文字列処理プログラムを作れるようになります。
出力結果
文字数: 5*strは「ポインタが指している文字」を表します。str++でポインタを1つ先に進めながら、同時にカウントも増やしていきます。
配列のインデックスを使うか、ポインタを使うかは好みの問題ですが、どちらも同じように動作します。
whileループ実装における典型的なミスと対処法
自作の文字数カウント関数でよくある失敗は、NULLポインタのチェックを忘れることと、無限ループに陥ることです。
NULLポインタが渡された場合の処理を忘れると、プログラムがクラッシュしてしまいます。また、終端文字のない文字列を処理しようとすると、ループが永遠に終わらなくなってしまいます。
こういった事態を防ぐには、関数の最初にNULLチェックを行い、安全な上限値を設定することです。
この関数では、まず最初にstrがNULLかどうかをチェックしています。NULLなら-1を返してエラーを知らせます。
さらに、count < max_limitという条件を加えることで、万が一終端文字がなくても1000文字でループを抜けられるようにしています。
このような安全対策を施すことで、予期しないエラーを防ぎ、より信頼性の高いプログラムになります。
文字数計測に関連する関数・処理
文字数を数える処理は、単独で使われることはあまりありません。
実際のプログラムでは、文字列をコピーしたり、比較したり、連結したりする処理と組み合わせて使うことがほとんどです。
C言語の標準ライブラリには、文字列を効率的に扱うためのさまざまな関数が用意されており、これらを適切に使い分けることで質の高いプログラムを作ることができます。
文字列処理に必須の関数一覧
C言語で文字列を扱うとき、よく使われる関数がいくつかあります。
代表的な関数を確認しておきましょう。
- strlen:文字数を取得する
- strcpy:文字列をコピーする
- strcat:文字列を連結する
- strcmp:文字列を比較する
【関連】C言語のstrlen関数の使い方は?初心者向けに徹底解説
上記の関数は全てstring.hヘッダーに定義されており、終端文字を基準に動作します。
出力結果
長さ: 7この例では、まずstrcpyで「cat」をanimal2にコピーし、次にstrcatで「fish」を連結しています。
その結果「catfish」という7文字の文字列ができるため、strlenで長さを確認すると7文字となるというわけです。
用途別の最適な関数ガイド
文字列操作を行う際、やりたいことに応じて使う関数を選ぶことで、安全で効率的なプログラムを作れます。先ほど代表的な関数を紹介しましたが、strncpy、strncat、strncmpのようにn付きの関数もあります。
このn付きの関数は、バッファサイズを指定できるため、メモリオーバーフローを防ぐことができます。
例えば、上記のような関数は次のような形で書きます。
出力結果
最初の文字が異なりますstrncmp(dog, cat, 1)では、最初の1文字だけを比較しています。
「d」と「c」は異なるため、0以外の値が返され、「最初の文字が異なります」と表示されます。
自作関数による文字数計測の応用
標準関数だけでは対応できない特殊な要件がある場合、自作関数を作ることになります。
例えば、「特定の文字だけを数える関数」や「大文字小文字を区別しない比較機能を備えた長さを知るための関数」などです。
自作関数の利点は、自分のプログラムでしか使わない特別なルールを自由に作ることができることです。
ただし、標準関数と違って「もしデータが空だったらどうするか?」や「変なデータが入ってきたらどう防ぐか?」といった、ミスが起きないための仕組み(エラーチェック)も自分で考えて作らなければなりません。
出力結果
文字列: rabbit
'b' の数: 2この関数は、文字列の中から特定の文字が何個あるかを数えます。
例えば「rabbit」という文字列で「b」を数えたら2個という結果が返ってきます。試しに、調べたい文字列や数えたい文字は、変更することができます。実際に、他のワードに変えて実行してみてください。
このように、標準関数にはない機能が必要なときは、自分で作ることができます。
よくある質問(Q&A)
Q: 文字列の長さが0の場合の処理は?
A: 空文字列("")の場合、strlenは0を返します。これは正常な動作で、エラーではありません。ただし、NULLポインタとは区別して処理する必要があります。
出力結果
長さ: 0Q: 日本語文字の長さ測定はできる?
A: strlenはバイト単位で計算するため、マルチバイト文字(日本語など)では正確な文字数を取得できません。日本語1文字が複数バイトとして計算されます。正確な文字数にはwcslen関数などを使用します。
Q: 配列サイズと文字列長の違いは?
A: 配列サイズはメモリ上で確保された領域の大きさで、文字列長は実際に格納されている文字の数です。配列サイズの方が大きくなることが一般的です。
出力結果
配列サイズ: 10
文字列長: 5Q: strlenの戻り値が負数になることは?
A: strlenの戻り値はsize_t型(符号なし整数)のため、負数にはなりません。ただし、他の整数型と比較する際は型変換に注意が必要です。
Q: 自作関数とstrlenの性能差は?
A: 一般的にstrlenの方が最適化されており高速です。ただし、特殊な処理が必要な場合や学習目的では自作関数も有効です。処理内容に応じて適切に選択しましょう。
まとめ
文字数を数えるのは、文字列処理プログラムの基本となる技術です。
関数の使い方や安全な実装方法を理解することで、効率的で信頼性の高いプログラムを作成できます。
この記事で学んだポイントを振り返ってみましょう。
文字数計測で押さえておきたいポイント
-
終端文字の理解
文字列の最後には必ず「\0」が付き、これが文字列処理の基礎になります。 -
strlen関数の活用
標準ライブラリのstrlenは、最も効率的で安全な文字数の取得方法です。 -
while文による自作実装
自分で文字数カウント関数を作ることで、文字列処理の仕組みを深く理解できます。 -
エラー対策の重要性
NULLポインタチェックや終端文字の確認など、エラー対策は欠かせません。 -
関数の使い分け
用途に応じて適切な関数を選ぶことが、品質向上の鍵です。
初心者の方が特に注意すべき点は、終端文字の付け忘れとNULLポインタの扱いです。
文字列を扱う際は、必ず終端文字があることを確認し、NULLポインタが渡される可能性を考慮しましょう。
実際の開発では、ユーザー入力の検証、パスワードの長さチェック、データの整形など、さまざまな場面で文字数計測を使います。
この記事で学んだ基本的な知識を、実践的なプログラムに活かしていきましょう。