最最最详细的C语言教程笔记零起步(9)进阶必备 同笔者一起学习

最最最详细的C语言教程笔记零起步(9)进阶必备 同笔者一起学习,第1张

最最最详细的C语言教程笔记零起步(9)进阶必备 同笔者一起学习

C语言教程笔记
  • 十九. 初识数组
    • 1. 什么是数组?
    • 2. 如何声明数组
    • 3. 数组内容的初始化
      • 3.1 初始化与赋值的区别
      • 3.2 数组的初始化
      • 3.3 初始化列表
        • 3.3.1 初始化列表短于数组长度
        • 3.3.2 初始化列表长于数组长度
        • 3.3.3 让初始化列表决定数组长度
    • 4. 访问数组的元素
      • 4.1 访问数组元素的公式
      • 4.2 使用循环遍历数组元素
      • 4.3 修改数组元素的值
      • 4.4 小心数组越界
      • 4.5 如果不初始化会怎样
    • 5. 数组所占用的空间大小
    • 6. 数组能整体赋值吗
      • 6.1 使用循环,单个为元素赋值
      • 6.2 内存复制
  • 二十. 多维数组
    • 1. 数组作为数组的元素
    • 2. 二维数组
      • 2.1 二维数组初始化
      • 2.2 访问或修改二维数组元素
        • 2.2.1 访问二维数组元素
        • 2.2.2 修改二维数组元素
    • 3. 更高维度的数组
  • 二十一. 字符串与字符数组
    • 1. 字符串常量
    • 2. 用字符数组存储字符串
      • 2.1 初始化字符数组
      • 2.2 省略数组大小
      • 2.3 打印字符数组
    • 3. 字符串结尾标记''
      • 3.1 初始化列表长度小于数组长度
      • 3.2 初始化列表长度等于数组长度
      • 3.3 初始化列表长度大于数组长度
      • 3.4 省略数组大小的情况
    • 4. 字符数组的大小及长度
      • 4.1 使用循环测量字符串长度
      • 4.2 使用strlen测量字符串长度
      • 4.3 strlen与sizeof的区别
    • 5. 字符数组可以被修改
    • 6. 从键盘输入一串字符串到字符数组
    • 7. putchar与getchar函数

十九. 初识数组 1. 什么是数组?

数组由一系列类型相同的数据对象依次排列组成。 组成数组的数据对象被称作数组的元素

数组的两个重要注意点:

  1. 依次排列:每个数组元素都是相邻的,从第一个数组元素到最后一个数组元素依次摆放。
  2. 类型相同:数组的元素都是类型相同的数据对象,不同的数据对象不能组成数组。
2. 如何声明数组

我们可以用如下的代码,声明各种类型的单个变量。

char c; 
int n; 
long l; 
float f; 
double df;

既然数组是由一系列类型相同的数据对象依次排列组成。那么声明数组至少要提供三类参数。

  1. 数组名。
  2. 数组元素的类型。
  3. 数组元素的数量。

数组声明的公式:

数组的声明由数组名、元素类型、元素数量组成,例如:

char c[5]; 
int n[10]; 
long l[3]; 
float f[2]; 
double df[1];
3. 数组内容的初始化 3.1 初始化与赋值的区别

在变量声明的时候,我们讨论过初始化和赋值的区别。

int n = 100;    //  初始化为100 
n = 100;        //  赋值为100

第一行代码为声明int类型的变量n,并初始化为100。第二行代码为n赋值为100。

初始化与赋值的区别在于:
初始化时,等号的左边为变量的声明,等号的右边为值。
赋值时,等号的左边为变量,等号的右边为值。

初始化中的等号并不是赋值运算符,只是写作等号而已。

不能对一个变量多次初始化,会被认为变量被重复定义。

int n =100; 
int n = 123;    //  错误,会引发变量重定义

对一个变量重复赋值却没有问题。

int n; 
n = 123; 
n = 456;

对于基础类型,似乎赋值与初始化都是将一个值装入变量,没有特别明显的差异。而对于我们接下来要讨论的数组,却有一些差异。

3.2 数组的初始化


数组初始化如同基础数据类型初始化一样,也是在变量声明时加上等号,在等号右边写需要为数组初始化的值。
例如:

int arr[10] = {1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 0};

上面的代码能声明一个由 10 个 int 数据对象组成的数组,并且将它们分别初始化为1,2,3,4,5, 6,7,8,9,0。

3.3 初始化列表


数组初始化时,等号右边被称作初始化列表。 初始化列表写明数组的元素分别需要被初始化为何值,用逗号隔开,最后用花括号包括起来。

int arr[10] = {1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 0};

上面这样将10个元素分别初始化为1,2,3,4,5,6,7,8,9,0。

3.3.1 初始化列表短于数组长度
int arr[10] = {1, 2 ,3 ,4 ,5};

现在数组有10个元素,而初始化列表只指定了5个元素的值。那么剩下的元素将被填0。

int arr[10] = {};

初始化列表什么都没有,所有数组元素将被填0。

3.3.2 初始化列表长于数组长度
int arr[10] = {1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 10, 11};

初始化列表长于数组长度,剩下的11将不知道初始化给哪个元素,代码将无法编译通过。

3.3.3 让初始化列表决定数组长度
int arr[] = {1726, 838, 938, 138, 58, 82, 83, 343, 456, 534, 645, 8938, 9382, 83, 343};

如果你有多个数值需要初始化给数组,但是你懒得数清楚到底有多少个。可以在数组声明的方括号里什么都不填,这样将会让初始化列表决定数组的长度。

4. 访问数组的元素 4.1 访问数组元素的公式

数组被初始化好了,现在我们想访问这个数组的各个元素了。
访问数组指定元素的公式如下:

使用 数组名[下标] 的形式可以访问数组内的元素。
请特别注意,下标从0开始。
0为下标,访问到的是数组的第一个元素。目前请先把下标从0开始看做一个规则。

#include 
 int main()
{
    int arr[10] = { 1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 0 };
    printf("%dn", arr[0]); //  第1个元素 
    printf("%dn", arr[1]); //  第2个元素 
    printf("%dn", arr[2]); //  第3个元素 
    printf("%dn", arr[3]); //  第4个元素 
    printf("%dn", arr[4]); //  第5个元素 
    printf("%dn", arr[5]); //  第6个元素 
    printf("%dn", arr[6]); //  第7个元素 
    printf("%dn", arr[7]); //  第8个元素 
    printf("%dn", arr[8]); //  第9个元素 
    printf("%dn", arr[9]); //  第10个元素
    return 0;
}

4.2 使用循环遍历数组元素

由于数组下标是递增的,使用 for 循环将更加便利地访问每一个元素。

for(int i = 0; i < 10; i++) 
{ 
    printf("%dn", arr[i]); //  访问下标为i的元素 
}

在for循环中, i 将从0递增到9。使用 arr[i] ,即可访问下标从0到9的元素。

当然,while循环也同样能做到,不过for循环代码将更加紧凑一些。

int i = 0; 
while(i < 10) 
{ 
     printf("%dn", arr[i++]); //  访问下标为i的元素 
}

这里特别将 i++ 放入了函数调用当中。表达式 i++ 的结果为 i 当前的值,所以第一次求 i++ 的结果为 0。而后缀自增表达式会在稍后为 i 加1。这样写也能达到访问下标0到9的元素的效果。

如果你想, i++ 写在单独的一行也没问题的。

int i = 0; 
while(i < 10) 
{  
     printf("%dn", arr[i]); //  访问下标为i的元素     
     i++; 
}
4.3 修改数组元素的值

怎样修改数组元素呢?

int arr[10] = {};       //  所有元素均初始化为0 
printf("%dn", arr[5]); //  打印第6个元素的值 
arr[5] = 123;           //  将第6个元素赋值为123 
printf("%dn", arr[5]); //  打印第6个元素的值

使用赋值表达式:
数组名[下标] = 表达式;
可以为数组元素赋值为一个新值。

4.4 小心数组越界

如果数组只有10个元素,我们访问或修改了这10个元素以外的元素,那么结果是未定义的。这意味着程序看上去可以运行,但是运行的结果很怪,或异常终止。

警告:千万不要越界访问或修改数组元素。

C语言编译器不会检查数组是否越界了,所以在编译时无法发现这样的问题。

int arr[10] = {}; //  所有元素均初始化为0 
printf("%dn", arr[10]);    //  下标为0到9,访问下标10的元素属于越界访问。

如果使用循环来遍历数组,请特别注意循环条件。

for(int i = 0; i <= 10; i++) 
{     
    printf("%dn", arr[i]); //  访问下标为i的元素 
}

循环条件为 i <= 10 ,这意味着 i 可以为10。这样也将导致数组越界访问。

4.5 如果不初始化会怎样
#include  
 int main() 
 {  
     int arr[10];     
     for(int i = 0; i < 10; i++)     
     {    
          printf("%dn", arr[i]);     
     }     
 return 0; 
 }

程序打印的结果均是一些奇怪的值,未初始化的数组里面都是一些无意义的数值。

数组不一定要初始化,就像不初始化变量一样。如果不初始化变量,我们往往会在其后为其赋值。数组也是一样的,其后为其元素赋值,避免使用到无意义的数值。

#include 
 int main() 
 {  
     int arr[10];     
     int n = 0;     
     for(int i = 0; i < 10; i++)     
     {  
         arr[i] = n;         
         n = n + 2;     
     }
     for(int i = 0; i < 10; i++)     
     {    
         printf("%d ", arr[i]);     
     }     
 return 0; 
 }

5. 数组所占用的空间大小
char arr1[10]; 
short arr2[10]; 
int arr3[10]; 
long long arr4[10]; 
float arr5[10]; 
double arr6[10]; 
printf("%dn", sizeof(arr1)); 
printf("%dn", sizeof(arr2)); 
printf("%dn", sizeof(arr3)); 
printf("%dn", sizeof(arr4)); 
printf("%dn", sizeof(arr5)); 
printf("%dn", sizeof(arr6));

数组所占的空间 = 单个元素所占空间大小 * 数组元素个数

sizeof(arr1) = sizeof(char) * 10 = 10 
sizeof(arr2) = sizeof(short) * 10 = 20 
sizeof(arr3) = sizeof(int) * 10 = 40 
sizeof(arr4) = sizeof(long long) * 10 = 80 
sizeof(arr5) = sizeof(float) * 10 = 40 
sizeof(arr6) = sizeof(double) * 10 = 80
6. 数组能整体赋值吗
int arr1[5] = {}; 
int arr2[5] = {1, 2, 3, 4, 5}; 
arr1 = arr2;

第一个数组元素全部初始化为0,第二数组元素初始化为1,2,3,4,5。 我们可以使用赋值运算符让arr1赋值为arr2吗?
答案是不行的,这种写法无法通过编译。
那么重新初始化呢?
arr1 = {1, 2, 3, 4, 5};
这样也是不行的,初始化列表只能存在于初始化中。
这里也是赋值与初始化区别的一个体现,在数组初始化中可以使用初始化列表,而赋值不行。

6.1 使用循环,单个为元素赋值

虽然无法整体为数组赋值,但是使用循环,单个为元素赋值确是可以的。

int arr1[5] = {}; 
int arr2[5] = {1, 2, 3, 4, 5}; 
for (int i = 0; i < 5; i++) 
{ 
    arr1[i] = arr2[i]; 
 }
6.2 内存复制
#include  
#include  
int main() 
{  
    int arr1[5] = {};     
    int arr2[5] = {1, 2, 3, 4, 5};     
    memcpy(arr1, arr2, sizeof(arr1));     
    for (int i = 0; i < 5; i++)         
    printf("%d ", arr1[i]);     
    return 0; 
}

另外,我们还可以借助 memcpy函数 (memory copy的简写),将arr2数组的数据复制到arr1数组。
memcpy的第一个参数是目标数组名。
memcpy的第二个参数是原始数组名。
memcpy的第三个参数指明需要复制多少字节数据。
memcpy函数将会把arr2数组的数据复制到arr1数组,复制多少字节数据取决于第三个参数。

注意事项:设第三个参数,需要复制的字节数为N。

  1. sizeof(arr2)不能小于N,否则复制完arr2的数据后,将复制到无意义内容。
  2. sizeof(arr1)不能小于N,否则将没有足够空间存放数据。
  3. 要使用memcpy函数,需要包含头文件 memory.h 。
#include  
#include  
int main() 
{  
    int arr1[3] = {};     
    int arr2[5] = {1, 2, 3, 4, 5};     
    memcpy(arr1, arr2, sizeof(int) * 2);     
    for (int i = 0; i < 3; i++)         
    printf("%d ", arr1[i]);     
    return 0; 
}

上面的代码没有问题,将仅复制arr2中的sizeof(int) * 2字节数据到arr1。 也就是说,仅会将arr2中前2个int元素的数据复制到arr1。 而arr1可以容纳3个int,有足够的空间存放数据。

二十. 多维数组 1. 数组作为数组的元素

有一个数组A,它的元素为 int 类型,元素数量为10个。 另外有一个数组B,它的元素类型为包含10个int元素的数组,元素数量为5个。


数组A已经在上一节中充分讨论过了, int A[10] 可以声明一个这种类型的数组。 但是,怎样声明数组B这种类型的数组呢?

让我们再回顾一下数组声明的公式:
数组的声明由数组名、元素类型、元素数量组成。 下面我们来尝试写一个数组B的声明。

  1. 数组名:B
  2. 元素类型:int[10]
  3. 元素数量: 5 组合这3个要素,写出如下声明
int[10] B[5];

数组名左边的方括号都移到最右边来。

int B[5][10];

这样就是B数组的声明了。B数组含有5个元素,而每个元素都是含有10个int元素的数组。

2. 二维数组

访问数组指定元素的公式如下:

使用 数组名[下标] 的形式可以访问数组内的元素。

例如: B[0] ,而数组B的每一个元素都是一个 int[10] 类型的数组。

再进一步访问,访问数组元素中的int元素。 例如: B[0][0] ,访问了第一个元素中的第一个元素。


可以发现,数组构成了一个二维的矩阵。并且,可以通过下标轻松地访问到它的每一个元素。

2.1 二维数组初始化

我们这样初始化一个一维数组

int A[10] = {0, 1, 2, 3, 4, 5 ,6 ,7 ,8 ,9};

而对于一个二维数组,它的每一个元素都是一个数组。

int B[5][10] = {  
                 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},     
                 {10, 11, 12, 13, 14, 15, 16, 17, 18, 19},     
                 {20, 21, 22, 23, 24, 25, 26, 27, 28, 29},     
                 {30, 31, 32, 33, 34, 35, 36, 37, 38, 39},     
                 {40, 41, 42, 43, 44, 45, 46, 47, 48, 49} 
               }

类似于一维数组,初始化列表中的常量个数少于元素个数,将使用0初始化元素。

int B[5][10] = {  
                  {0, 1, 2, 3, 4, 5},     
                  {10, 11, 12, 13, 14, 15},     
                  {20, 21, 22},     
                  {30},     
                  {} 
               }

另外,也可以省略里面的花括号。

int B[5][10] = { 
                  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,     
                  10, 11, 12, 13, 14, 15, 16, 17, 18, 19,     
                  20, 21, 22, 23, 24, 25, 26, 27, 28, 29,    
                  30, 31, 32, 33, 34, 35, 36, 37, 38, 39,     
                  40, 41, 42, 43, 44, 45, 46, 47, 48, 49 
               }

省略内层花括号时,如果元素的个数不足。那么后续的将元素将使用0初始化。

int B[5][10] = {  
                     0, 1, 2, 3, 4, 5, 6, 7, 8, 9,     
                     10, 11, 12, 13, 14, 15, 16, 17, 18, 19 
                }

对于一维数组代码:

#include int main()
{
int B[5][10] = {
                  {0},{1},{2},{3},{4}
                };
for(int i = 0; i<5; i++)
  {
     for(int j = 0; j<10;j++)
     {
          printf( "%d ",B[i][j]);
      }
     printf( "n");
   }
return 0;
}

2.2 访问或修改二维数组元素 2.2.1 访问二维数组元素

对于二维数组代码:

因为有两个下标,所以使用嵌套循环来遍历二维数组

#include 
int main()
{
int B[5][10] = {
                 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
                 {10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
                 {20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
                 {30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
                 {40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
};
for (int i = 0; i < 5; i++)           //遍历二维数组 查看所有元素
{
    for (int j = 0; j < 10; j++)
    {
        printf("%d ", B[i][j]);
    }
    printf("n");
}
return 0;
}

2.2.2 修改二维数组元素

可以使用赋值运算符修改二维数组元素

B[i][j] = B[i][j] * 2;  //  修改二维数组值

下面的代码将二维数组每个元素都设置为原来的2倍。

#include  
int main() 
{ 
 int B[5][10] = {     
                    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},     
                    {10, 11, 12, 13, 14, 15, 16, 17, 18, 19},     
                    {20, 21, 22, 23, 24, 25, 26, 27, 28, 29},     
                    {30, 31, 32, 33, 34, 35, 36, 37, 38, 39},     
                    {40, 41, 42, 43, 44, 45, 46, 47, 48, 49}   
                };
  for(int i = 0; i < 5; i++)   
  { 
      for(int j = 0; j < 10; j++)     
      {   
          B[i][j] = B[i][j] * 2;  //  修改二维数组值     
      }   
  }
  for(int i = 0; i < 5; i++)   
   {
      for(int j = 0; j < 10; j++)     
     {   
         printf("%d ", B[i][j]);     
     }     
      printf("n");   
    }   
return 0; 
}

3. 更高维度的数组

如果将二维数组作为数组的元素,那么可以实现三位数组。依次类推,可以实现更高维度的数组。

int C[2][5][10];
数组C,有两个元素,每个元素是一个int[5][10]类型的二维数组。 对于三维数组,我们会使用三重循环来访问或修改元素值。

#include  
int main() 
{ 
    int B[2][5][10] = {     
                         {       
                            {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},       
                            {10, 11, 12, 13, 14, 15, 16, 17, 18, 19},       
                            {20, 21, 22, 23, 24, 25, 26, 27, 28, 29},       
                            {30, 31, 32, 33, 34, 35, 36, 37, 38, 39},       
                            {40, 41, 42, 43, 44, 45, 46, 47, 48, 49}     
                          },     
                        
                        {    
                            {-0, -1, -2, 3, -4, -5, -6, -7, -8, -9},       
                            {-10, -11, -12, -13, -14, -15, -16, -17, -18, -19},       
                            {-20, -21, -22, -23, -24, -25, -26, -27, -28, -29},       
                            {-30, -31, -32, -33, -34, -35, -36, -37, -38, -39},       
                            {-40, -41, -42, -43, -44, -45, -46, -47, -48, -49}     
                         }   
                       };
for(int i = 0; i < 2; i++)   
{ 
  for(int j = 0; j < 5; j++)     
     {   
         for(int k = 0; k < 10; k++)       
            {     
                printf("%d ", B[i][j][k]);       
             }  
       printf("n");     
       }  
   printf("n");   
  }   
return 0; 
}

二十一. 字符串与字符数组

在探究字符数组之前,来复习一下字符串相关的知识点吧。

1. 字符串常量
#include 
 int main() 
 {  
     printf("sizeof HelloWorld = %dn", 
     sizeof("HelloWorld"));     
     return 0; 
  }

字符串常量 “HelloWorld” 占用11个字节。

字符串常量在内存中,由每个字符的ASCII码按照顺序排列构成,每个字符仅占一个字节,并且末尾会附上一个数值0,指示字符串结尾。

字符’0’对应的ASCII码为十进制48。而标记字符串结尾的数值0,为了不与字符’0’冲突,使用转义序列’’表示。

字符常量

2. 用字符数组存储字符串

既然字符串满足数组的类型相同且顺序排列的特点。那么元素为 char 的数组可以用于存储字符串。

2.1 初始化字符数组

我们声明一个数组,且把它初始化为"HelloWorld"

char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};

由于数组有20个元素,而初始化列表中仅有10个元素。数组大小大于初始化列表长度,数组后10个将会被初始化为0。也就相当于已经帮我们标记了字符串结尾了。

还有一种更加便捷的字符数组初始化方式。将初始化列表直接写成一个字符串常量,可以用于初始化字符数组。

char str[20] = "HelloWorld";

由于字符串常量末尾会自动添加’’为字符串结尾标识,所以当用字符串常量初始化字符数组时,代码等价于:

char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', ''};
2.2 省略数组大小

有时候我们希望一个数组被初始化为某个字符串,但是又不想数清楚到底有多少个字符。我们可以在数组声明时,省略数组大小,初始化列表中的元素个数即为数组的大小。

char str1[] = "HelloWorld"; 
char str2[] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', ''};

上面两种写法是等价的,数组的大小为初始化列表中元素的个数,即11。

2.3 打印字符数组

接下来,我们想让这串字符串被打印在控制台上。 printf的第一个参数可以接收一串字符串。所以我们可以直接把数组作为printf的第一个参数。

printf("HelloWorld"); //使用数组 printf(str);

另外,转换规范 %s ,可以作为字符串的占位符。

printf("%s", str);

将字符数组打印在控制台:

#include 
 int main() 
 { 
     char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};     
     printf(str);     
     printf("n");     
     printf("%s", str);     
     printf("n");     
     return 0; 
}

3. 字符串结尾标记’’

在使用字符串常量时,系统会自动为我们在字符串末尾添加 ‘’ 标记字符串结束。 而在使用字符数组时,有些情况不能保证字符串末尾有 ‘’,需要格外注意。

3.1 初始化列表长度小于数组长度
char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};

初始化列表长度小于数组长度,数组前10个元素被初始化为HelloWorld,后10个元素和普通数组一样后,被填充为0。
既然第11个元素为0,因此字符数组中的字符串正常结尾。

3.2 初始化列表长度等于数组长度
char str[10] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};

初始化列表长度小于数组长度,数组前10个元素被初始化为HelloWorld。第11个元素在数组外,也不能预知这个元素的值。字符数组中的字符串无法结尾。

程序运行后,正常打印出了数组中的10个元素HelloWorld。但是,由于数组中的字符串缺少结尾标 记 ‘’。因此,printf将继续打印数组外的元素,这样将导致数组越界访问。直到遇到一个 ‘’ ,才停止打印。

3.3 初始化列表长度大于数组长度
char str[5] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};

初始化列表长度大于数组长度将无法通过编译。

3.4 省略数组大小的情况
char str[] = "HelloWorld";

使用字符串常量初始化数组,由于系统会为字符串常量结尾添加’’。所以字符串常量大小为11。 使用该字符串初始化数组,数组大小为11,且最后一个字符为’’。字符数组中的字符串正常结尾。

char str[] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', ''};

使用初始化列表初始化数组,初始化列表中有11个字符常量,且最后一个字符常量为’’。 使用该初始化列表初始化数组,数组大小为11,且最后一个字符为’’。字符数组中的字符串正常结尾。

char str[] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};

使用初始化列表初始化数组,初始化列表中有10个字符常量,最后一个字符常量为’d’。 使用该初始化列表初始化数组,数组大小为10,且最后一个字符为’d’。字符数组中的字符串无法结尾。

4. 字符数组的大小及长度
char str[20] = "HelloWorld";

我们声明了一个长度为20的字符数组str,并将它使用字符串常量"HelloWorld"进行初始化。 这样,字符数组的前10个元素为HelloWorld,第11个元素为’’。

我们使用sizeof关键词,测试一下str的大小。
结果为20个字节,和我们声明的大小一致。

4.1 使用循环测量字符串长度

那么怎样知道这个字符数组中存储的字符串的长度呢。
事实上,一个字符串用 ‘’ 来标记结尾,只要知道在 ‘’ 之前,有多少个字符,就能知道字符数组中的字符串的长度了。

#include 
 int main() 
 {  
     char str[20] = "HelloWorld";     
     int len = 0;     
     while(str[len] != '')     
     {    
          len++;     
      }     
 printf("%d", len);     
 return 0; 
}


声明一个len变量,用于统计字符串长度。 while循环从第一个元素开始,检查元素是否为 ‘’ ,如果不是长度len加一,直到元素为 ‘’ 为止。 循环结束时, len 的值即为字符串的长度。

4.2 使用strlen测量字符串长度

另外,还可以使用 strlen 函数来计算字符串长度。 strlen为 string(字符串)与 length(长度)的合成词。 strlen 的使用范式:

  1. strlen可以接受一个字符串作为参数。
  2. strlen返回值为这个字符串的长度。
  3. 使用strlen函数,需包含头文件string.h。
#include  
#include 
 int main() 
 { 
     char str[20] = "HelloWorld";     
     int len1;     
     len1 = strlen(str);     
     printf("len1 = %dn", len1);
     int len2;     
     len2 = strlen("HelloWorld");     
     printf("len2 = %dn", len2);
     
     printf("sizeof str %dn", sizeof(str));     
     printf("sizeof helloworld %dn", sizeof("HelloWorld"));     
     return 0; 
}


len1为strlen函数测量字符数组 str 内字符串的长度。
len2为strlen函数测量字符串常量 “HelloWorld” 的长度。
后续,再用sizeof分别测量字符数组str和字符串常量"HelloWorld"所占空间大小。

HelloWorld有10个字符,所以字符串长度为10,len1、len2均为10。
而字符数组有20个元素,所以占用20字节空间。
字符串常量为字符串长度加结尾标记,所以占用11字节空间。

4.3 strlen与sizeof的区别

strlen(str)测量从第一个元素开始直到元素值为’’的字符串长度。 sizeof(str)测量数组本身占用空间的大小。

5. 字符数组可以被修改

字符串常量不能被修改,但是字符数组却是可以被修改的。 下面的代码中,数组被初始化为"abcde",我们让小写字符变为大写。小写字母ASCII码减32即为对应的大写字母。

#include 
#include  
int main() 
{ 
    char str[20] = "abcde";
    //  修改前     
    printf(str);     
    printf("n");
    //  每个元素减32     
    for(int i = 0; i < strlen(str); i++)     
    {    
        str[i] = str[i] - 32;     
     }
    //  修改后     
    printf(str);     
    return 0; 
}

6. 从键盘输入一串字符串到字符数组

对应于printf,scanf中字符串的占位符为"%s"。使用scanf配合"%s"占位符,可以将键盘输入的一串字符串存储到字符数组。

char str[20]; scanf("%s", str);   //  将键盘输入的一串字符串存储到字符数组str

下面的代码使用scanf将一串字符串存储到字符数组,其后将小写字母转为大写字母再输出。

#include  
#include 
 int main() 
 {     
     char str[20];
     //  输入一串字符到str     
     scanf("%s", str);
     //  修改前     
     printf(str);     
     printf("n");
     //  每个元素减32     
     for(int i = 0; i < strlen(str); i++)     
     {     
         str[i] = str[i] - 32;     
      }
      //  修改后     
 printf(str);    
 return 0; 
 }

scanf会帮我们在输入的字符串后加上’’,输入的字符串可以正常结尾。

7. putchar与getchar函数

putchar 与 getchar 函数可以单独输出或输入一个字符。 putchar 输出单个字符:

putchar('A');

getchar输入单个字符:

char c; c = getchar();

我们使用getchar与putchar,输入一个小写字符,将它转换为大写再输出。 小写字母ASCII码减32即为对应的大写字母。

#include 
 int main() 
 {  
     char c;     
     c = getchar();     
     c = c - 32;     
     putchar(c);     
     return 0; 
}

使用getchar函数输入小写字符’a’,将它转换为大写后,使用putchar函数输出。

结合上循环,使用putchar输出一串字符串。

#include 
 int main() 
 {  
     char str[] = "HelloWorld";     
     int i = 0;    
     while(str[i] != '')     
     {   
          putchar(str[i++]);     
      }    
 return 0; 
}


点个赞吧 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5651006.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存