文字と文字列


ソースコード

源文件
  1|/* char01.c */
  2|
  3|#include <stdio.h>
  4|
  5|int main(void)
  6|{
  7|  char a1, a2, a3;
  8|
  9|  a1 = 'a';
 10|  a2 = 'b';
 11|  a3 = 'c';
 12|  printf("%c%c%c\n", a1, a2, a3);
 13|
 14|  return 0;                                                                           
 15|}

実行結果

abc


ソースコード

源文件
  1|/* char02.c */
  2|
  3|#include <stdio.h>
  4|
  5|int main(void)
  6|{
  7|  char a1, a2, a3;
  8|
  9|  a1 = 'a';
 10|  a2 = 'b';
 11|  a3 = 'c';
 12|  printf("%d, %d, %d\n", a1, a2, a3);                                                 
 13|
 14|  return 0;
 15|}

実行結果

97, 98, 99

実は'a'とか'b'の文字は、その文字の ASCII コードを表しているのです。


ソースコード

源文件
  1|/* char03.c */                                                                        
  2|
  3|#include <stdio.h>
  4|
  5|int main(void)
  6|{
  7|  char i;
  8|
  9|  for(i = '!'; i <= '~'; i++){
 10|    printf("%3d(0x%2X) -- %c ", i, i, i);
 11|    if((i - '!' + 1) % 4 == 0){
 12|      printf("\n");
 13|    }
 14|  }
 15|  printf("\n");
 16|  return 0;
 17|}

実行結果

 33(0x21) -- !  34(0x22) -- "  35(0x23) -- #  36(0x24) -- $ 
 37(0x25) -- %  38(0x26) -- &  39(0x27) -- '  40(0x28) -- ( 
 41(0x29) -- )  42(0x2A) -- *  43(0x2B) -- +  44(0x2C) -- , 
 45(0x2D) -- -  46(0x2E) -- .  47(0x2F) -- /  48(0x30) -- 0 
 49(0x31) -- 1  50(0x32) -- 2  51(0x33) -- 3  52(0x34) -- 4 
 53(0x35) -- 5  54(0x36) -- 6  55(0x37) -- 7  56(0x38) -- 8 
 57(0x39) -- 9  58(0x3A) -- :  59(0x3B) -- ;  60(0x3C) -- < 
 61(0x3D) -- =  62(0x3E) -- >  63(0x3F) -- ?  64(0x40) -- @ 
 65(0x41) -- A  66(0x42) -- B  67(0x43) -- C  68(0x44) -- D 
 69(0x45) -- E  70(0x46) -- F  71(0x47) -- G  72(0x48) -- H 
 73(0x49) -- I  74(0x4A) -- J  75(0x4B) -- K  76(0x4C) -- L 
 77(0x4D) -- M  78(0x4E) -- N  79(0x4F) -- O  80(0x50) -- P 
 81(0x51) -- Q  82(0x52) -- R  83(0x53) -- S  84(0x54) -- T 
 85(0x55) -- U  86(0x56) -- V  87(0x57) -- W  88(0x58) -- X 
 89(0x59) -- Y  90(0x5A) -- Z  91(0x5B) -- [  92(0x5C) -- \ 
 93(0x5D) -- ]  94(0x5E) -- ^  95(0x5F) -- _  96(0x60) -- ` 
 97(0x61) -- a  98(0x62) -- b  99(0x63) -- c 100(0x64) -- d 
101(0x65) -- e 102(0x66) -- f 103(0x67) -- g 104(0x68) -- h 
105(0x69) -- i 106(0x6A) -- j 107(0x6B) -- k 108(0x6C) -- l 
109(0x6D) -- m 110(0x6E) -- n 111(0x6F) -- o 112(0x70) -- p 
113(0x71) -- q 114(0x72) -- r 115(0x73) -- s 116(0x74) -- t 
117(0x75) -- u 118(0x76) -- v 119(0x77) -- w 120(0x78) -- x 
121(0x79) -- y 122(0x7A) -- z 123(0x7B) -- { 124(0x7C) -- | 
125(0x7D) -- } 126(0x7E) -- ~ 


次に、文字を int 型としてみます。

ソースコード

源文件
  1|/* char04.c */
  2|
  3|#include <stdio.h>
  4|
  5|int main(void)
  6|{
  7|  int c;
  8|
  9|  for(c = 'A'; c <= 'z'; c++){
 10|    if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')){
 11|      printf("%c = %3d(0x%X)  ", c, c, c);
 12|      if((c - 'A' + 1) % 4 == 0){                                                     
 13|        printf("\n");
 14|      }
 15|    }
 16|  }
 17|  return 0;
 18|}

実行結果

A =  65(0x41)  B =  66(0x42)  C =  67(0x43)  D =  68(0x44)  
E =  69(0x45)  F =  70(0x46)  G =  71(0x47)  H =  72(0x48)  
I =  73(0x49)  J =  74(0x4A)  K =  75(0x4B)  L =  76(0x4C)  
M =  77(0x4D)  N =  78(0x4E)  O =  79(0x4F)  P =  80(0x50)  
Q =  81(0x51)  R =  82(0x52)  S =  83(0x53)  T =  84(0x54)  
U =  85(0x55)  V =  86(0x56)  W =  87(0x57)  X =  88(0x58)  
Y =  89(0x59)  Z =  90(0x5A)  a =  97(0x61)  b =  98(0x62)  c =  99(0x63)  d = 100(0x64)  
e = 101(0x65)  f = 102(0x66)  g = 103(0x67)  h = 104(0x68)  
i = 105(0x69)  j = 106(0x6A)  k = 107(0x6B)  l = 108(0x6C)  
m = 109(0x6D)  n = 110(0x6E)  o = 111(0x6F)  p = 112(0x70)  
q = 113(0x71)  r = 114(0x72)  s = 115(0x73)  t = 116(0x74)  
u = 117(0x75)  v = 118(0x76)  w = 119(0x77)  x = 120(0x78)  
y = 121(0x79)  z = 122(0x7A)                       

&& と || では && のほうが優先順位が高いので、括弧を省いて

if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')


文字列の式の値は、先頭文字の置かれたアドレスである。

文字配列の最後の要素は必ず '\0' である。

ソースコード

源文件
  1|/* string01.c */
  2|
  3|#include <stdio.h>
  4|
  5|int main(void)
  6|{
  7|  char *str;
  8|  str = "ABC";
  9|
 10|  printf("*(str + 0) = '%c',"
 11|         "*(str + 1) = '%c',"
 12|         "*(str + 2) = '%c'\n",
 13|         *(str + 0), *(str + 1), *(str + 2));
 14|
 15|  printf("str[0] = '%c', str[1] = '%c', str[2] = '%c'\n ",
 16|         str[0], str[1], str[2]);                                                     
 17|
 18|  return 0;
 19|}

実行結果

*(str + 0) = 'A',*(str + 1) = 'B',*(str + 2) = 'C'
str[0] = 'A', str[1] = 'B', str[2] = 'C'


ソースコード

源文件
  1|/* string02.c */
  2|
  3|#include <stdio.h>
  4|
  5|int main(void)
  6|{
  7|  printf("%c, %c, %c\n",
  8|         *("ABC" + 0), *("ABC" + 1), *("ABC" + 2));
  9|  printf("%c, %c, %c\n", "ABC"[0], "ABC"[1], "ABC"[2]);
 10|
 11|  return 0;                                                                           
 12|}

実行結果

A, B, C
A, B, C

さて、次のような疑問がわきませんか。

char *str1, *str2;

str1 = "ABC";

str2 = "ABC";

str1とstr2には、同じアドレスが格納されているだろうか

答えは「異なるアドレスが格納されています」です。文字列は出て来るたびにそれぞれ別々のところに格納されます。string02.c では"ABC"が6箇所に出て来ています。これらは、すべて別々なことろに格納されています。

しかし、しかしです!!!「文字列としては同じなので、別々のアドレスに格納するのは、メモリの無駄遣いだ」と考えで、文字列として同じものが出て来たら、別のアドレスに格納しないコンパイラオプションもあります。

しかし、文字列の比較という意味で

if (str1 == str2){
  ...                                                                                     
 }

というようなプログラムは間違いであると考えて下さい。


strcmp関数

2つの文字列を比較します。

int strcmp(
           const char *string1,
           const char *string2
           );   

この関数を使いたときは、string.h をインクルードする必要があります。

ソースコード

源文件
  1|/* string03.c */                                                                      
  2|
  3|#include <stdio.h>
  4|#include <string.h>
  5|
  6|int main(void)
  7|{
  8|  char str1[32], str2[32];
  9|  int cmp;
 10|
 11|  printf("str1を入力してください---");
 12|  scanf("%s", str1);
 13|  printf("str2を入力してください---");
 14|  scanf("%s", str2);
 15|
 16|  cmp = strcmp(str1 ,str2);
 17|    if(cmp < 0){
 18|      printf("%sは、%sより前にあります\n", str1, str2);
 19|    } else if (cmp > 0) {
 20|      printf("%sは、%sより後ろにあります\n", str1 ,str2);
 21|    } else {
 22|      printf("%sと%sは、同じ文字列です\n", str1, str2);
 23|    }
 24|  return 0;
 25|}

実行結果

str1を入力してください---3
str2を入力してください---4
3は、4より前にあります

str1を入力してください---5
str2を入力してください---2
5は、2より後ろにあります

str1を入力してください---5
str2を入力してください---5
55は、同じ文字列です


さて、"ABC"の場合、文字列ですね。文字列の長さを調べる関数というものもあります。

size_t strlen(
              const char *string                                                          
              );

これで返される値には、ヌル文字は含まれていません。

ソースコード

源文件
  1|/* string04.c */
  2|
  3|#include <stdio.h>
  4|#include <string.h>
  5|
  6|int main(void)
  7|{
  8|  char str[32];
  9|  size_t len;
 10|
 11|  printf("文字列を入力してください---");
 12|  scanf("%s", str);
 13|
 14|  len = strlen(str);
 15|  //  printf("%sの長さ%zuです\n", str, len);                                          
 16|  printf("%sの長さ%luです\n", str, len);
 17|
 18|  return 0;
 19|}

実行結果

文字列を入力してください---sjflasdfja
sjflasdfjaの長さ10です


Chapte7 @ C言語目録 @ HomeWork List @ 昭亮's Homepage