C言語
前回、C言語での文字列の分割(strtok関数)を勉強してみました。
これが前回の出てきた文字列の分割のプログラムです。
#include <stdio.h>
#include <string.h>
int main(void)
{
char strs[] = "str1,str2,str3,str4,str5";
char *token = strtok(strs, ",");
while(token != NULL) {
printf("%s\n", token);
token = strtok(NULL, ",");
}
}
実行結果
str1
str2
str3
str4
str5
「char *token = strtok(strs, “,”);」で新しい文字列tokenを定義しているのですが、その文字列名の前に「*(アスタリスク)」が付けられています。
今回はこの「*」を使った文字列の定義を勉強していきます。
文字列の定義の方法:おさらい
まずはC言語での文字列の定義の方法をおさらいしますが、詳しくは前の記事をご覧ください。
これまでに学んだ文字列の定義の仕方はこんな感じです。
#include <stdio.h>
int main(void)
{
char str1[5] = "str1";
char str2[] = "str2";
printf("%s\n", str1);
printf("%s\n", str2);
}
実行結果
str1
str2
「char 文字列名[文字の長さ]」で空の文字列を、もしくは「char 文字列名[文字列の長さ] = “文字列”」を定義することができます。
また最初から文字列を定義している場合は「文字列の長さ」は省略することも可能です。
ポインタ
今回、新しく勉強するのは「char *文字列名 = “文字列”」という書き方です。
#include <stdio.h>
int main(void)
{
char *str3 = "str3";
printf("%s\n", str3);
}
実行結果
str3
確かにこの書き方でも問題なく、文字列の定義と表示を行うことができました。
この書き方での文字列の定義は、先ほどおさらいした書き方とはコンピュータ内での扱いが違うようで、「ポインタ」と呼ばれるものだそうです。
またおさらいした書き方は本当は「文字配列」と呼ぶようです。
正直、これらの違いがどのような違いなのか、正確に解説できる自信はありません。
ということで、そこら辺はGoogleで「C言語 文字列 ポインタ」とでも検索していただいて、内部で何が起こっているのかを調べてみてください。
今回はそう言った難しいところはとりあえずは飛ばして、何ができて何ができないのかを明確にしたいと思います。
ポインタを使うメリット:書き換えが可能
ポインタを使った文字列の定義でできることの一つ目は文字列の書き換えが直接できることです。
つまりこのように文字列を書き換えることができます。
#include <stdio.h>
int main(void)
{
char *str3 = "str3";
str3 = "str4";
printf("%s\n", str3);
}
実行結果
str4
このような書き換え方法は、文字列の長さを指定する文字配列の書き方ではできません。
#include <stdio.h>
int main(void)
{
char str3[] = "str3";
str3 = "str4";
printf("%s\n", str3);
}
実行結果
str_pointer12.c:7:10: error: array type 'char [5]' is not assignable
str3 = "str4";
~~~~ ^
1 error generated.
また先ほどの例では書き換え前後で文字列の長さは同じなのですが、ポインタを使った文字列の定義の方法で書き換える文字列の長さが、元々の文字列の長さよりも長くなってしまっても大丈夫です。
#include <stdio.h>
int main(void)
{
char *str3 = "str3";
str3 = "str1str2str3str4str5";
printf("%s\n", str3);
}
実行結果
str1str2str3str4str5
また別に定義した文字列を代入することも可能です。
#include <stdio.h>
int main(void)
{
char *str3;
char *str4 = "str4";
str3 = str4;
printf("%s\n", str3);
}
実行結果
str4
文字列ポインタで定義した文字列だけでなく、文字配列で定義した文字列でも代入可能です。
#include <stdio.h>
int main(void)
{
char *str3;
char str5[] = "str5";
str3 = str5;
printf("%s\n", str3);
}
実行結果
str5
ポインタを使うデメリット:特定の文字の書き換えは不可能
先ほどはポインタを使った際にできることを紹介しましたが、逆にできないこともあります。
それは文字列の中の特定の文字を書き換えることです。
文字配列の場合はこのようにして文字列中の特定の文字を書き換えることができました。
#include <stdio.h>
int main(void)
{
char str5[] = "str5";
str5[0] = 'S';
printf("%s\n", str5);
}
実行結果
Str5
しかし文字列のポインタでは特定の文字を書き換えることはできません。
#include <stdio.h>
int main(void)
{
char *str6 = "str6";
str6[0] = 'S';
printf("%s\n", str6);
}
実行結果
/bin/sh: line 1: 79892 Bus error: 10 "/path to program/"str_pointer9
ただこれは文字列中の特定の文字にアクセスできない訳ではありません。
その証拠に特定の文字を指定して、表示してやることは可能です。
#include <stdio.h>
int main(void)
{
char *str6 = "str6";
printf("%c\n", str6[1]);
}
実行結果
t
あくまでも「文字列中の特定の文字書き換えができない」のです。
Pythonでは文字列一つ定義するのに、ここまでいくつもの方法があったわけではないので、正直どう使い分けしていったらいいのか理解しきれていません。
個人的にはポインタを使う方が文字列そのものを書き換えられるので便利じゃないかなと思っているくらいです。
いろんな解説サイトも見ていますが、同じことをやるのに文字配列で文字列を定義しているところもあれば、ポインタを使って文字列を定義しているところもあり、多分個人個人で考え、もしくは好みで定義しているのが多いのではないかなと感じました。
ということでとりあえず勉強していって、自分に合った方を使っていこうと思います。
次回はC言語のリストに関して勉強していきましょう。
ではでは今回はこんな感じで。
コメント