c言語文字列の詳細

1.文字列リテラル。

「キャンディーは\ nダンディです\ nしかしリキュールは\ n速いです。」

これは、C ++では文字列リテラルと呼ばれます。「\ n」などの転送シーケンスを文字列内に埋め込むことができます。

文字列に8進数と16進数の転送シーケンスを埋め込むように注意してください。8進数の転送シーケンスは/で始まり、16進数の転送シーケンスは/ xで始まり(xは小文字である必要があります)、8進数の転送シーケンスは3桁です( 0〜7の範囲)後で終了するか、最初の8進数以外の数値で終了します(数値は8以上で終了します)。

16進数の/ xの後に制限はなく、最初の非16進数(fより大きい)で終わります。16進数は大文字にできることに注意してください(コンパイラーの結果から取得)。たとえば、次のコードを見てください。

#include <stdio.h>
int main()
{
if(('\xAA') ==  ('\xaa'))
        printf("equal");
else 
        printf("not equal.");
    return 0;
}

操作の結果は次のとおりです。

equal

2.文字列リテラルを続行します。

(1)方法1:\を使用する

たとえば、「私は学生です\

   そしてあなたは教師です。「」

特徴:最初の行は\(含まれていません)で終わり、2番目の行は行の先頭から始まります。

(2)方法2:2つ以上の文字列が隣接している場合、C言語は自動的に文字列をマージします。このルールを使用して、このように記述します

"私は学生です "

「そしてあなたは先生です。」

最後に、コンパイラは文字列自体をマージします。「私は学生で、あなたは教師です。」

3.文字列リテラルの保存。C言語は、文字列リテラルを文字配列として格納します。c言語が長さnの文字列を検出すると、文字列リテラルに長さn + 1のメモリ空間を割り当て、末尾に「\ 0」を追加します。注:ここで「\ 0」、「0」、および「」を混同しないでください。ヌル文字のコード値は0、「0」(ASCII)のコード値は48、スペースのコード値は'' ASCllは32です。覚えておいて、文字配列がデフォルトで初期化されている場合、それは「\ 0」になります。

文字配列がデフォルトで初期化されると、各文字にもスペースバーの代わりに「\ 0」の値が割り当てられ、算術型配列の各桁は0に初期化されます。

空の文字列は ""で、空の文字列は単一の空の文字 '\ 0'として格納されます。

文字列は文字通り配列として格納されるため、文字列は文字通りポインタとして扱われます(配列名はポインタとして扱われます)。たとえば、printf( "abcde");の場合、文字列 "abcde"が渡されます。 printf関数へアドレス(つまり、文字aのメモリユニットへのポインタ)。

4.文字列リテラルはポインタとして扱われます。

例:「abc」

printf( "abc");ここで、 "abc"は、文字aのメモリユニットへのポインタと見なされます。

printfとscanfはどちらも、最初のパラメーターとしてchar * typeを受け入れます。

5.文字列リテラルの操作。

(1)文字列リテラル値は変更できません。次のコードを見てください。

#include <stdio.h>
int main()
{
char *str = "abcde";
*str = 'a';
printf("%s",str);
   return 0;
}                                                                         
                

実行結果でランタイムエラーが発生しました:

r@r:~/coml_/c/13/2$ gcc 3.c -o 123
r@r:~/coml_/c/13/2$ ./123
Segmentation fault (core dumped)
r@r:~/coml_/c/13/2$ 

結論:文字列リテラルの内容は変更できません。ただし、char *オブジェクトが別の文字列を指すようにすることはできます。

#include <stdio.h>
int main()
{
char *str = "abcde";
printf("%s\n",str);
//str 重新指向另一个字符串字面量
str = "efghikasdfasd fasdf asdf asdf asf";
printf("%s",str);
return 0;

結果は次のとおりです。

abcde
efghikasdfasd fasdf asdf asdf asfr

予期しない場所:元の文字列の長さを超える可能性があります。

(2)半分の場合、char *が必要な場所ならどこでも文字列リテラルを使用できます。

たとえば、char * p;

p = "abc";この操作は、文字列をコピーするのではなく、文字aのアドレスをpに割り当てることです。つまり、文字列の割り当てプロセス全体ではなく、ポインタ変数pの割り当てプロセスです。

(3)ポインタには添え字演算があり、文字列リテラルにも

「abc」[1]は文字bを指します

次の関数は、整数を16進文字に変換します。

char number_to_hex(int n)
{
return "0123456789ABCDEF"
}                                                                         
  

(4)ここで、16進数と8進、および転送シーケンスは同じではないことに注意してください

          (a)16進数の定義\ x00(xは大文字と小文字の両方、数値部分には長さの要件はありません)、8進数の定義\ 012(数値0の先頭は8進数、および数値\ 0の後の長さの制限はありません

         (b)16進エスケープシーケンスは\ xで始まる必要がありxは小文字で、次の桁は0からffまで最大2桁である必要があります)、8進転送シーケンス\始まり、次の桁は最も3桁の数字。次の図を参照してください。レビューを

6.文字列リテラルと文字定数は交換できません。次のコードを参照してください。

#include <stdio.h>
int main()
{
printf("\n");
printf('\n');  //这里引发错误
    return 0;
}        

gccコンパイラのコンパイル結果は次のとおりです。

r@r:~/coml_/c/13/2$ gcc 4.c -o 123
4.c: In function ‘main’:
4.c:5:8: warning: passing argument 1 of ‘printf’ makes pointer from integer without a cast [-Wint-conversion]
    5 | printf('\n');
      |        ^~~~
      |        |
      |        int
In file included from 4.c:1:
/usr/include/stdio.h:332:43: note: expected ‘const char * restrict’ but argument is of type ‘int’
  332 | extern int printf (const char *__restrict __format, ...);
      |                    ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
4.c:5:1: warning: format not a string literal and no format arguments [-Wformat-security]
    5 | printf('\n');

7.文字列変数。「\ 0」で終了する必要があることに注意してください。そうでない場合、ライブラリ関数が呼び出すときに未定義の動作が発生します。

#include <stdio.h>
#define STR_LEN 20
int main()
{
//方法1:直接定义成字符数组+初始化
char str[STR_LEN + 1] = "you are welcome.";
//方法2:直接定义为char * + 初始化
char * str1 = "you are welcome.";
//方法3:先定义一个字符数组,和一个char *,把char *对象指向一个char 数组
char str2[STR_LEN + 1],*str3;
str3 = str2;
//方法4:先定义一个char *,后来可以指向一个字符串字面值
char *ptr;
ptr = "you are welcome";
puts(ptr);
  return 0;
}

ただし、scanfを使用してchar *を読み取る場合は、最初に十分なスペースを開く必要があります。つまり、最初に型をchar [STR_LEN + 1]として宣言する必要がありますが、型char *としては宣言しないでください。

char * p; //ポインタpがポインタスペースを格納するのに十分なだけです。文字列にスペースを割り当てることはできません。pを使用して読み込むと、エラーが発生します。

#include <stdio.h>
int main()
{
char *p;
scanf("%s",p);
printf("%s",p);
  return 0;
}

操作の結果は次のとおりです。必要に応じてaresdfを入力した後、出力は実際にnullになります。

you arasdf
(null)

8.文字列変数を初期化します

c言語が配列初期化式を処理する場合、配列初期化式が配列自体によって短縮されると、残りの配列要素は0に初期化され(要素はint、float、double)、char配列は同じ規則に従います。 。 '\ 0'が追加されました。

char *またはchar [](値のタイプは文字列リテラル)に値を割り当てても、末尾に「\ 0」が自動的に追加されます。

#include <stdio.h>
int main()
{
double d[12] = {0.0};
int i;
for(i = 0; i!= 12; ++i)
{
printf("%f\n",d[i]);
}
   return 0;
}
~   

結果は次のとおりです。

0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000
0.000000

9.文字配列と文字ポインタ

類似点:文字配列または文字ポインターが受け入れられる場合は常に、両方を実際のパラメーターとして使用できます。

差:

(1)文字配列は文字の値を変更できますが、文字ポインタは文字列リテラル値を変更できません。

(2)文字配列の名前は配列名であり、文字ポインタは変数であり、実行中に他の文字列を指すことができます。

たとえば、char * pです。ここで、pはcharオブジェクトを指すポインタ変数です。pの値は変更できます(pが指すオブジェクトは変更できません。* p = ...(違法)とp = ...(合法)を区別してください)

char * p;

p = "abcde"; //リーガル、変更されたpの値は次のとおりです。pは変数ですが、もちろん変更することもできます。

* p = "efghi"; //不正です。pが指す文字列リテラルを変更する場合は、エラーが報告されます。

 

10.文字列の読み取りと書き込み

(1)読む

scanfまたはfget();を使用します。

機能:最初以降のすべての空白は無視されます。たとえば、bc defを入力すると、最初の空白は無視され、最後にaが読み取られ、後者の一部がメモリにキャッシュされて待機します。後続の読み取り用。

(2)書く

                 printf( "")は、最初の「\ 0」に遭遇するまで、厳密に1つずつ出力します。文字列の最後に「\ 0」がない場合は、最初の「\ 0」まで書き続けます。メモリが検出されました。0 '。

                puts()は、行の最後に直接「\ n」を追加します(自動折り返し)

(3)文字列読み取り関数を記述して解決すべき問題は次のとおりです。

   (a)いつ読み取りを開始するか(最初の空白文字を無視するかどうか)(b)「\ n」を終了する方法、スペースはまだ特定の文字であり、終了文字を文字列に書き込む必要があるかどうか(c)読み取り文字列が長すぎる場合、余分な文字は直接無視されるか、次の入力操作のために残されます。

たとえば、改行文字が無視されない場合、最初の改行文字は終了し、改行文字は文字列に存在しません。次に、次のように記述します。関数read()をコードに記述します。

#include <stdio.h>
#define LEN 20
int read(char str[],int n);
void print(char str[],int n);
int main()
{
char array[LEN + 1] = {' '};
read(array,LEN);
print(array,LEN+1);
    return 0;
}
int read(char str[],int n)
{
char ch;
char *p = str;
int i = 0;
while((ch = getchar()) != '\n')
{
 if(i < n)
 { *p ++ = ch;
     i++;
  }
}
*p = '\0';
return i;

}
void print(char str[],int n)
{
int i = 0;
for(i = 0; i!= n; ++i)
  {
    printf("%c",str[i]);
  }
}

                   関数read()は、次のように簡単に記述することもできます。

int read(char str[],int n)
{int i = 0;
char ch;
  while((ch = getchar()) != '\n')
  {
  if(i < n)
      str[i ++] = ch;
  }
  str[i] = '\0';  //terminates string
  return i;       //number of characters stored
}

scanf関数とgets関数は、最後に自動的にヌル文字を追加します。ただし、関数を自分で作成する場合は、自分でヌル文字を追加する必要があります。

 

 

 

 

 

おすすめ

転載: blog.csdn.net/digitalkee/article/details/112757288