数组和字符串

数组和字符串

数组是相同数据类型的有序集合,例如:int arr[10] = {1, 2, 3, 44, 55};

数组的特点:

  • 同一个数组的所有成员都是相同的数据类型
  • 各个元素的内存地址连续 (%p)

一维数组

数组地址

  • 数组名为地址,是数组首元素的地址 (arr &arr[0])
  • 数组首元素地址 (arr[0])

大小

int arr[5] = {1, 2, 3, 4, 5};
sizeof(arr)                         // 数组大小
sizeof(arr[0])                    // 数组每个元素的大小
sizeof(arr)/sizeof(arr[0])  // 数组元素的个数

数组初始化

// 1.全部元素初始化
int arr[5] = {1, 2, 3, 4, 5};

// 2.部分元素初始化,剩余未初始化的元素默认0值
int arr[5] = {1, 2, 3};

// 3.初始化一个全为0的数组
int arr[5] = {0};

// 4.不指定数组大小,编译器会自动求元素个数
int arr[] = {1, 2, 3, 4, 5};
int arr[] = {0};  // 只有一个元素,值为0

// 5.部分元素初始化,其余未被初始化的元素,默认是随机数
int arr[10];
arr[0] = 1;
arr[1] = 2;

示例

  • 数组逆序:三杯水变量交换法
    #define _CRT_SECURE_NO_WARNINGS
    #include 
    #include 
    
    int main(void)
    {
        int arr[6] = {1, 2, 3, 4, 5, 6};  // 倒序为 {6, 5, 4, 3, 2, 1}
        int num = sizeof(arr) / sizeof(arr[0]);  // 此数组的元素个数
    
        int temp = 0;
        for (size_t i = 0; i<num/2; i++)  // size_t == int
        {
            // 三杯水法
            temp = arr[i];
            arr[i] = arr[num - 1 - i];
            arr[num - 1 - i] = temp;
        }
    
        for (size_t k=0; k<num; k++)
        {
            printf("%d ", arr[k]);
        }
        putchar('\n');
    
        system("pause");
        return 0;
    }
    
  • 冒泡排序
    #define _CRT_SECURE_NO_WARNINGS
    #include 
    #include 
    
    int main(void)
    {
        int arr[6] = { 1, 2, 6, 3, 5, 4 };
        int num = sizeof(arr) / sizeof(arr[0]);  // 元素个数
        int temp = 0;
        for (size_t k = 0; k < num; k++)  // 打印原本的数组
        {
            printf("%d ", arr[k]);
        }
        putchar('\n');
    
        for (size_t i = 0; i<num; i++)  // 分成的行数
        {
            for (size_t j = 0; j arr[j+1])
                {
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j + 1] = temp;
                }   
            }
        }
    
        for (size_t k = 0; k < num; k++)  // 打印排序后的数组
        {
            printf("%d ", arr[k]);
        }
        putchar('\n');
    
        system("pause");
        return 0;
    }
    
    //1 2 6 3 5 4
    //1 2 3 4 5 6
    

二维数组

格式

// int arr[行数][列数] = {};
int arr[2][6] = {
{1, 2, 3, 4, 5, 6},
{3, 4, 5, 6, 7, 8}
}

打印二维数组

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main(void)
{
    int arr[2][3] = {
        {1, 2, 3},
        {5, 6, 7}
    };

    int row = sizeof(arr)/sizeof(arr[0]);  // 行数
    int col = sizeof(arr[0]) / sizeof(arr[0][0]);  // 列数

    printf("行数是 %d,列数是 %d\n", row, col);

    for (size_t i = 0; i < row; i++)
    {
        for(size_t j = 0; j < col; j++)
        { 
            printf("%d ", arr[i][j]);
        }
        putchar('\n');
    }

    // 打印数组地址
    printf("%p\n", arr);
    printf("%p\n", &arr[0]);
    printf("%p\n", &arr[0][0]);

    system("pause");
    return 0;
}

//行数是 2,列数是 3
//1 2 3
//5 6 7
//008FFDC8
//008FFDC8
//008FFDC8

地址合一

  • 数组的首地址 数组首元素地址 数组的首行地址
    arr == &arr[0] == &arr[0][0]
    

大小

sizeof(arr)          // 数组大小
sizeof(arr[0])           // 一行大小,二维数组的一行就是一个一维数组
sizeof(arr[0][0])     // 一个元素的大小
sizeof(arr)/sizeof(arr[0])                 // 行数
sizeof(arr[0])/sizeof(arr[0][0])    // 列数

二维数组初始化

// 1.常规初始化
int arr[2][3] = {{1, 2, 4}, {3, 4, 6}};

// 2.不完全初始化
int arr[2][4] = {{1, 2}, {3, 4, 6}};  // 未被初始化的数值为0
int arr[2][4] = {0};              // 初始化一个初值全为0的二维数组
int arr[2][3] = {1, 2, 4, 5, 6};  // 系统自动分配行列 (少见)

// 3.不完全指定行列初始化
int arr[][] = {1, 2, 4, 5, 6};   // error! 二维数组必须指定列值
int arr[][3] = {1, 2, 4, 5, 6};  // 可以不指定行值

示例:求 3 名学生 2 门功课的总成绩

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

int main(void)
{
    // 学生成绩如下
    // 姓名 语文 数学
    // a     60   90
    // b     70   80
    // c     90   80

    int score[3][2] = {
        {60, 90},
        {70, 80},
        {90, 80}
    };

    int n_ren = sizeof(score) / sizeof(score[0]);       // 人数
    int n_ke = sizeof(score[0]) / sizeof(score[0][0]);  // 课程数

    //printf("人数:%d\t,课程数:%d\n", n_ren, n_ke);

    // 每个人的总成绩
    for (size_t i = 0; i < n_ren; i++)
    {
        int sum1 = 0;  // 每个人的总成绩

        for (size_t j = 0; j < n_ke; j++)
        {
            sum1 += score[i][j];
        }

        //putchar('\n');
        printf("每个人的总成绩分别为:%d\n", sum1);
    }

    // 每门功课的总成绩
    for (size_t j = 0; j < n_ke; j++)
    {
        int sum2 = 0;  // 每门功课的总成绩

        for (size_t i = 0; i < n_ren; i++)
        {
            sum2 += score[i][j];
        }

        //putchar('\n');
        printf("每门功课的总成绩分别为:%d\n", sum2);
    }

    system("pause");
    return 0;
}

多维数组

以三维数组举例。四维数组、五维数组 … N 维数组,与三维数组语法相似。

格式

// int arr[层][行][列] = {};
int arr[2][3][4] = {
    {{1, 2, 3, 4},
     {9, 1, 3, 4},
     {3, 4, 5, 6}
    },
    {{2, 5, 8, 9},
     {0, 4, 3, 4},
     {2, 4, 7, 1}
    }
}

打印三维数组

字符数组和字符串

字符数组和字符串的区别

  • 结尾字符不同,字符串的最后一个字符一般是 ‘\0’

  • 示例

    • 打印字符串和字符数组
      #define _CRT_SECURE_NO_WARNINGS
      #include 
      #include 
      #include 
      
      int main(void)
      {
          char str1[6] = { 'h', 'e', 'l', 'l', 'o', '\0' };  // 字符串
          char str2[6] = "abcde";  // 字符串
          char str3[5] = { 'h', 'e', 'l', 'l', 'o' };  // 字符数组
      
          printf("str1[6] %s\n", str1);
          printf("str2[6] %s\n", str2);
          printf("str3[6] %s\n", str3);  // 将数组按字符串打印,会出现乱码
      
          // 正确打印数组的方法
          for (size_t i = 0; i < 5; i++)
          {
              printf("%c ", str3[i]);
          }
          putchar('\n');
      
          system("pause");
          return 0;
      }
      
      //str1[6] hello
      //str2[6] abcde
      //str3[6] hello烫烫烫烫烫蘟bcde
      
    • 键盘输入字符串,存至 str[] 中,统计每个字母出现的次数
      #define _CRT_SECURE_NO_WARNINGS
      #include 
      #include 
      #include 
      
      int main(void)
      {
          //char str[6] = "hello";  // 输入的字符串
          char str[6];
          char letter[26] = { 0 };  // 借助26个字母
          //char a = 97;
      
          scanf("%s", str);  // 键盘输出一个6位字符串
          //printf("%s", str);
      
          for (size_t i = 0; i < 6; i++)
          {
              int index = str[i] - 'a';  // 求在 letter 中的下标
              //printf("%d", index);
      
              letter[index]++;  // i 从 0 开始,会有一个 letter[-97] 警告,可以忽略
          }
      
          for (size_t j = 0; j  0)
              {
                  printf("%c 出现了 %d 次\n", 'a' + j, letter[j]);
              }
          }
      
          system("pause");
          return 0;
      }
      

常用函数

  • scanf 函数
    #define _CRT_SECURE_NO_WARNINGS
    #include 
    #include 
    #include 
    
    int main(void)
    {
        char str[5];
        //scanf("%s", str);    // 遇到空格和 \n 终止
        scanf("%[^\n]", str);  // 借助正则表达式获取带有空格的字符串
        printf("%s\n", str);
    
        system("pause");
        return 0;
    }
    
    • 函数描述
      • 获取字符串
    • 注意事项
      • 用于存储字符串的空间必须足够大,防止溢出
      • 获取字符串 %s,遇到空格和换行 \n 终止
    • 借助正则表达式获取带有空格的字符串
      scanf("%[^\n]", str);  // ^:表示除 xxx 之外
      
  • gets/fgets 函数
    • 函数描述
      • get string 的缩写,获取一个字符串,返回字符串的首地址
    • 函数原型
      char *gets(char *s)
      char *fgets(char *s, int size, FILE *stream)
      
      • 参数
        • s
          • 字符串首地址
        • size
          • 空间大小
        • stream
          • 文件描述符 (可以是标准输入 stdin)
      • 返回值
        • 成功,返回读入的字符串;失败,返回 NULL
    • gets(str) 与 scanf(“%s”, str) 的区别
      • gets(str) 允许输入的字符串含有空格
      • scanf(“%s”, str) 不允许含有空格
    • gets 和 fgets 的区别
      • gets 不安全,fgets 安全
        • gets 必须遇到换行符或读到文件结尾才终止接收,所以和 scanf 一样,都是不安全的
      • fgets 会预留 \0 的存储空间
        • 如果空间足够,会读 \n
        • 如果空间不够,不会读 \n,且在 \0 之前
    • 示例
      #define _CRT_SECURE_NO_WARNINGS
      #include 
      #include 
      
      int main(void)
      {
          char str[5];
          printf("%s\n", gets(str));  // 输入的字符串可以包含空格
          printf("%s", fgets(str, 5, stdin));  // 安全,输入的字符串不包含空格
      
          system("pause");
          return 0;
      }
      
  • puts/fputs 函数

    将一个字符串输出到屏幕,输出字符串后会自动添加 \n。

    • 函数描述
      • 字符串输出
      • 输出字符串后,不自动添加 \n
    • 函数原型
      int puts(const char *s)
      int fputs(const char *str, FILE * stream)
      
      • 参数
        • s/str
          • 字符串首地址
        • stream
          • 文件描述符 (可以是标准输入 stdin)
      • 返回值
        • 成功,返回 0;失败,返回 -1
    • 示例:puts() 和 fputs() 的对比
      #define _CRT_SECURE_NO_WARNINGS
      #include 
      #include 
      #include 
      
      int main(void)
      {
          //char str[5];
          //printf("%s\n", gets(str));  // 不安全,输入的字符串可以包含空格
          //printf("%s", fgets(str, 5, stdin));  // 安全,输入的字符串不包含空格
      
          char str2[] = "hello world";
      
          puts(str2);           // 自动添加了 \n
          fputs(str2, stdout);  // 没有自动添加 \n
      
          system("pause");
          return 0;
      }
      
  • strlen 函数

    获取字符串的有效长度,这个长度不包含 \0,碰到 \0 结束。

    • 函数描述
      • 获取字符串长度
    • 函数原型
      size_t strlen(const char *s)
      
      • 参数
        • s
          • 字符串首地址
      • 返回值
        • 字符串 s 的长度,size_t 可以看成 unsigned int
    • 示例:对比 sizeof() 和 strlen()

      “`c++

      <h1>define _CRT_SECURE_NO_WARNINGS</h1>

      <h1>include</h1>

      <h1>include</h1>

      <h1>include</h1>

      <h1>include</h1>

      <h1>include</h1>

      <h1>include</h1>

      //#include

      int main(void)
      {
      //char str[5];

      <pre><code>//printf("%s\n", gets(str)); // 不安全,输入的字符串可以包含空格
      //printf("%s", fgets(str, 5, stdin)); // 安全,输入的字符串不包含空格

      char str2[] = "hello world";

      //puts(str2); // 自动添加了 \n
      //fputs(str2, stdout); // 没有自动添加 \n

      printf("sizeof() = %d\n", sizeof(str2)); // 结果为 12,表示总长度
      printf("strlen() = %d\n", strlen(str2)); // 结果为 11,表示有效长度

      system("pause");
      return 0;
      </code></pre>

      <p>}

      “`

示例:字符串追加

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    char str1[6] = "hello";
    char str2[6] = "world";
    char str3[100] = { 0 };

    char temp;
    int i = 0;
    for (i = 0; i < 6 - 1; i++)
    {
        str3[i] = str1[i];
    }
    printf("%s\n", str3);  // -> i = 5

    int j = 0;
    while (str2[j])  // (str2[j] != '\0')
    {
        str3[i+j] = str2[j];
        j++;
    }  // -> j = 5

    //str3[i + j] = '\0';  // 因为在定义 str3[100] 时指定了 0,所以不需要手动添加 \0
    printf("%s\n", str3);

    system("pause");
    return 0;
}
英仔
版权声明:本站原创文章,由 英仔 2022-08-08发表,共计6289字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)