C语言:数组(补充)

二维数组

定义:

二维数组本质是一个行列式的组合,也就是说二维数组是由行和列两部分组成。二维数组数据是通过行列进行解读。

二维数组可被视为一个特殊的一维数组,相当于二维数组又是一个一维数组,只不过它的元素是一维数组。(也就是说数组的元素可以是数组类型)

{3,4,5}
{{1,2,3},{4,5,6}}
语法:
类型 数组名[行数][列数]

举例:

int arr1[3][3] = {{11,12,13},{21,22,23},{31,32,33}};// 等价于下面写法
int arr2[3][3] = {{11,12,13},{21,22,23},{31,32,33}};// 柔性数组

inte arr3[3][3] = {{11,12},{21,22,23},{31}};// 等价于下面写法(柔性数组,根据最大列的元素个数分配)
int arr[3][3] = {{11,12,0},{21,22,23},{31,0,0}};

注意:在C语言中,二维数组在计算机的存储顺序是按行进行的,即第一维的下标变法慢慢,第二位下标变化快。

应用场合

主要应用于数据有行列要求的情况。比如说我们现在要存储粤嵌目前在读班级的学生的成绩。

特殊写法
  • 下标可以是整型表达式。如:a[2-1][2*2-1]

  • 下标可以是已经有值的变量或数组元素,如a[2*x-1][b][3][1]

  • 数组元素可以出现在表达式中,如b[1][2] = a [2][3]/2

注意:使用数组元素的下标应在已定义数组的大小范围内:应注意区别定义组大小和引用数组元素的区别

初始化
  • 分行给二维数组赋初值
int arr[3][4] = {{11,12,13,14}{21,22,23,24},{31,32,33,34}};
  • 可将所有数据写入在一个花括号内,按照排列顺序对元素赋值
int arr[3][4] = {11,12,13,14,15,16,17,18};
  • 可对部分元素赋初值,其余未赋值部分自动填充整型默认值-0 | 字符型默认值-\0 | 浮点型默认值-0.0..
int arr[3][4] = {{11},{21,22},{31}};
  • 若对全部元素赋初值,自定义数组时可以省略第1维数组的长度,第2维数组的长度必须指明。
int a[][4] = {11,12,13,14,15,16,17,18};
  • 在分行赋初值时,也可以省略第1维的长度。
int arr[][4] = {{11,12,13},{0},{0,10}};
案例1:
#include <stdio.h>
/**
 * 需求:二维数组的遍历
 */

int arr_test1()
{
    // 创建一个二维数组,经过论证:二维数组我们必须指定列的大小,行的大小可以省略
    int arr[][3] = {{11},{21,22},{31,32,33}};
    
    // 获取二维数组的大小,其实就是行数
    int len = sizeof(arr) / sizeof(arr[0]);
    
    // 遍历二维数组,因为二维数组是行列式,所以要使用到双重for循环
    // 外层循环遍历外层数组,获取行
    for(int row = 0;row < len;row++)
    {
        // 获取列元素的总大小
        int len2 = sizeof(arr[row]) / sizeof(int);
        // 内层循环遍历内层数组,获取列(数据元素)
        for(int col = 0;col < len2;col++)
        {
            // 获取元素
            printf("%-3d",arr[row][col]);// 获取数组arr第row行,第col列
        }
    }
}

int main(int argc,char *argv[])
{
    int arr_test1();
    return 0;
}
案例2:
/**
 * 需求:二维数组案例-矩阵的转置(就是将一个2行3列的数组转换为3行2列的数组)
 */

int arr_test2()
{
    // 准备2个数组,存放转置前后的数列
    int arr_before[2][3] = {11,12,13,14,15,16};// {{11,12,13},{14,15,16}}
    int arr_after[3][2] = {0};// {{11,14},{12,15},{13,16}}
    
    // 计算arr_before中行的个数
    int r_len = sizeof(arr_before) / sizeof(arr_before[0]);
    
    // 遍历arr_before
    for(int i = 0;i < r_len;r++)
    {
        // 计算arr_before中的列数
        int c_len = sizeof(arr_before[i]) / sizeof(int);
        
        for(int j = 0;j < c_len;j++)
        {
            printf("%-4d,arr_before][j][i]");
            // 转置
            arr_after[j][i] = arr_before[i][j];// arr_before[1][0]--arr_after[0][1]   
        }
        printf("\n");
    }
    printf("\n");
    
    // 遍历arr_after
    for(int i = 0;i < sizeof(arr_after)/sizeof(arr_after[0]);r++)
    {
        // 计算arr_after中的列数
        int c_len = sizeof(arr_after[i]) / sizeof(int);
        
        for(int j = 0;j < c_len;j++)
        {
            printf("%-4d,arr_after[i][j]");
}

int main(int argc,char *argc[])
{
    return 0;
}
案例3:
/**
 * 需求:二维数组案例-准备一个int类型二维数组,求该数组中最大的值,以及对应的行号和列号
 */
#include <stdio.h>

int arr_test3()
{
    // 准备一个二维数组
    int arr[][3] = {{1,2,3},{9,8,7},{-10,10,-5}};
    // 创建变量:最大值、行号、列号
    int max = arr[0][0], row = 0, col = 0;
    
    // 遍历集合
    for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
    {
        for(int j = 0; j < sizeof(arr[i])/sizeof(int); j++)
        {
            // 判断最大值
            if(arr[i][j] > max)
            {
                max = arr[i][j];
                row = i;
                col = j;
            }
        }
    }
    printf("max=%d, row=%d, col=%d\n", max, row, col);
}
 

int main(int argc,char *argv[])
{
    arr_test3();
    return 0;
}

字符数组

概念

元素类型为char字符型的数组,字符数组往往是用来存储字符串数据的。需要注意的一点是:我们C语言中的字符是字节字符。

字节字符:也就是1个字符占1个字节,在C语言中,我们使用char表示字节。

测试题:

char a = 'A'; // 正确
char a = '1'; // 正确
char c = 65;  // 正确,ASCII码
char d = "A"; // 错误,这是字符串的写法,也是我们char数组的写法,char d[1] = "A";
char e = '司'// 错误,中文一个字符超过一个字节
语法:
char 数组名[容量]// 一维
char 数组名[行容量][列容量]; // 二维    

字符数组的语法就是前面所学的一维数组和二维数组的语法,只不过数据类型是char而已。

注意:

  • 如果我们的char数组初始化的时候,没有完全赋完值的时候,空出来的地方使用\0进行填充。

  • 比如:char c[8] = {'h','e','l','l','o'}等价于char c [8] = {'h','e','l','l','o','\0','\0','\0'}

字符案例
#include <stdio.h>
/**
 * 需求:输出一个字符串(I LOVE YOU!)
 */
int char_test1()
{
    char arr[11] = {'I','\0','L','O','V','E','\0','Y','O','U','!'};
    
    // 通过一个for循环进行遍历输出
    for(int i = 0;i < sizeof(arr)/sizeof(char);i++)
    {
        printf("%c",arr[i]);
    }
    printf("\n");
}
int main(int argc,char *argv[])
{
    int char_test1();
    
    return 0;
}

注意:

① 如果定义时不初始化,元素值不确定。

char arr1[2];  // 此时处于未初始化,元素值是不确定的(随机的)
char arr2[5] = {'a','b','c'};  // 此时处于未完全初始化,未初始化的元素使用\0进行填充

② 如果提供的字符个数大于数组长度,则按语法错误处理;如果字符个数小于数组长度,后面的元素自动为空字符(\0)。

③ 如果提供的字符个数与数组长度相同时,可省略数组长度,系统会自动确定元素个数,适合字符个数较多时。

字符串和字符串结束标志
说明
  • C语言规定,字符串以字符\0作为结束标志。
  • 编译系统对字符串常量自动加一个\0作为结束标志。
  • 程序中往往通过判断\0来检测字符串是否结束。
  • \0的ASCII码为0,不是一个可显示的字符,是“空操作符”,它什么都不做,不会增加有效字符,仅是一个供判断 的标志。
字符数组的多样表示

我们的char数组可以以数组的方式一个个输出每个字符;我们的char数组也可以以字符串的方式整体进行输出所有字符。

/**
 * 需求:字符数组→字符串
 */
#include <stdio.h>

int main()
{
    // 字符串的第1中表示:
    char s1[] = {'h','e','l','l','o',' ','w','o','r','l','d'};
    // 字符串的第2中表示:
    char s2[] = {"hello world"};
    // 字符串的第3中表示
    char s3[] = "hello world";
    
    // 输出字符串
    printf("%s,%s,%s\n,s1,s2,s3");
}

注意:

  • 字符串的长度与字符数组的长度不一定相同。

  • 利用字符串常量可以对字符数组进行初始化,但不能用字符串常量为字符数组赋值。

    // 正确演示,利用字符串常量可以对字符数组进行初始化
    char arr1[6] = "hello";
    
    // 错误演示,字符串常量可以对字符数组进行赋值
    char arr2[6];
    arr2 = "hello";
    
字符串的基础操作

在用格式说明符%S进行输入输出时,其输入输出项均为数组名。但在输入时,相邻两个字符串之间要用空格分割,系统将自动的在字符串最后加结束符“\0”。在输出时,遇到结束符’\0’作为输出结束标志。

对于字符串的操作,我们需要使用到一些系统提供的函数。

字符串的输入

语法:

scanf("%s",数组名)

案例:

/**
 * 需求:字符串的输入
 * 语法:scanf("%s",数组名);
 */
#include <stdio.h>
int test1()
{
    // 创建一个char数组,用来存放人的名字
    char name[20];
    printf("请输入您的姓名\n");
    scanf("%S",name); // 如果时字符串,这里不是变量地址,是变量名,数组本身不占内存空间,数组默认指向第一个元素的首地址
    printf("您的名字是:%s\n",name);
}

int main(int argc,char *argv[])
{
    test1();
    
    return 0;
}

注意:采用scanf()进行字符串输入,要求字符串不能存在空格,否则字符串遇到空格会结束。

  • fgets(数组名,数组容量,stdin);
    • 功能:
      • 从键盘录入一个字符串到字符数组,返回字符数组的地址。
    • 说明:
      • 采用fgets进行字符串输入,可获取所有输入的字符串,包含\n,在实际的字符串处理时,我们可能需要处理\n
/**
 * 字符串的输入
 * 语法:fgets(数组名,数组容量,stdin);
 */
#include <stdio.h>
int test2()
{
  // 创建一个char数组,用来存放人的名字
  char name[20];

  printf("请输入您的姓名:\n");
  fgets(name,sizeof(name)/sizeof(char),stdin);

  printf("您的名字是:%s\n",name);
}

int main(int argc,char *argv[])
{
    test2();
    return 0;
}

注意:

① 如果输入的字符串不包括空格换行,可以使用scanf() | fgets();

② 如果输入的字符串需要包含空格换行,只能使用fgets

字符串的输出
  • printf(“%s”,数组名);

案例:

#include <stdio.h>

int test3()
{
    // 创建一个char数组,用来存放人的名字
    char name[20];
    
    printf("请输入您的姓名:\n");
    
    scanf("%s",name);// 如果时字符串,这里不是变量地址,是变量名,数组本身不占内存空间,数组默认指向第一个元素的首地址
    
    printf("您的姓名是:%s\n",name);
}

int main(int argc,char *argv[])
{
    test3();
    return 0;
}
  • puts(数组名)
    • 功能:
      • 输出一个字符串
    • 说明:
      • 字符串可以包含转义字符
    • 案例:
#include <stdio.h>
/**
 * 字符串的输入
 * 语法:puts(数组名);
 */
int test4()
{
    // 创建一个char数组,用来存放人的名字
    char name[20];
    
    printf("请输入您的名字:\n");
    // fgets和scanf只能二选一
    fgets(name,sizeof(name)/sizeof(char),stdin);
    
    puts(name);// 无法进行拼接,只能输出
    // printf("您的名字是:%s\n",name);
}

int main(int argc,char *argv[])
{
    test4();
    
    return 0;
}
字符串拼接
  • strcat(数组名(字符串1),“需要拼接的字符串(字符串2)”);

    • 引用:
    #include <string.h>
    
    • 案例:
    #include <stdio.h>
    #include <string.h>
    /**
     * 字符串的输入
     * 语法:strcat(数组名,"需要拼接的字符串");
     */
    int test5()
    {
        // 创建一个char数组,用来存放人的名字
        char name[20];
        
        printf("请输入您的名字:\n");
        // fgets和scanf只能二选一
        fgets(name,sizeof(name)/sizeof(char),stdin);
        
        puts(strcat(name," 快跑!"));
        // printf("您的名字是:%s\n",name);
    }
    
    int main(int argc,char *argv[])
    {
        test5();
        
        return 0;
    }
    

注意:

① 字符数组1的长度必须足够大,以便于能容纳被连接的字符串。

② 连接后系统将自动取消字符串1(字符数组1)

,后面的结束符’\0’;

字符串可以是字符数组名,也可以是字符串常量,如:strcat(s1,“def”);

字符串拷贝
  • strcpy(数组名,字符串);

  • 引入:

include (string,h);
  • 说明:
    • 这个函数适合给字符串赋值用
char str[16] = "司高超"// 正确,初始化
char[16] str[16]= "司高超"; //错误
char str[16]; strcpy(str,"司高超")// 正确
  • 案例:
/**
 * 字符串的拷贝
 * 语法:strcpy(数组名,"字符串");
 */
#include <stdio.h>
#include <string.h>
int test6()
{
    // 创建一个char数组,用来存放人的名字
    chara name[20];
    
    printf("请输入您的名字:\n");
    // fgets和scanf只能二选一
    fgets(name,sizeof(name)/sizeof(char),stdin);
    
    strcty(name,"司高超")printf("您的名字是:%s\n",name);
}

int main(int argc,char *argv[])
{
    test6();
    
    return 0;
}
字符串的比较
  • strcmp:(字符串1,字符串2);

    • 引入:
    #include <string.h>
    
    • 功能:

    比较两个字符串对应位置字符ASCII的大小(字典顺序比较)

    • 返回值:

    字符串1等于字符串2返回0

    字符串1大于字符串2返回正数

    字符串1小于字符串2返回负数

    • 说明:

    ① 执行这个函数时,自左到右逐个比较对应字符的ASCII的值,直到发现了不同字符或字符串结束符’\0’为止。

    ② 对字符串不能用数值型比价符。

    ③ 字符串1与字符串2可以是字符数组名,也可以是字符串常量。

int test7()
{
    // 创建一个char数组,用来存放账户和密码
    char username[20],password[8];
    printf("请输入您的账户:\n");
    scanf("%s",username);
    printf("请输入您的密码:\n");
    scanf("%s",password);
    
    if(!strcmp(username,"admin") && !strcmp(password,"123456"))
    {
        printf("登陆成功!\n");
    }
    else
    {
        printf("账户或密码错误!\n");
    }
}

int main(int argc,char *aargv[])
{
    test7;
    return 0;
}
获取字符串长度
  • strlen(字符串)

引用:

#include <string.h>

注意:

返回字符串中包含的字符的实际个数,不含\0

案例:

/**
 * 字符串的长度
 * 语法:strlen(字符串 | 字符数组)
 */
#include <stdio.h>
#include <string.h>
int test8()
{
    // 创建一个char数组,用来存放账户和密码
    char username[20];
    printf("请输入您的账户:\n");
    scanf("%s",username);

    // 获取字符串的长度
    unsigned long len = strlen(username);
    if(!strcmp(username,"admin") )
    {
        printf("账户输入正确!%lu\n",len);
    }
    else
    {
        printf("账户输入错误!%lu\n",len);
    }
}

int main(int argc,char *aargv[])
{
    test8();
    return 0;
}

是字符串常量。

int test7()
{
    // 创建一个char数组,用来存放账户和密码
    char username[20],password[8];
    printf("请输入您的账户:\n");
    scanf("%s",username);
    printf("请输入您的密码:\n");
    scanf("%s",password);
    
    if(!strcmp(username,"admin") && !strcmp(password,"123456"))
    {
        printf("登陆成功!\n");
    }
    else
    {
        printf("账户或密码错误!\n");
    }
}

int main(int argc,char *aargv[])
{
    test7;
    return 0;
}
获取字符串长度
  • strlen(字符串)

引用:

#include <string.h>

注意:

返回字符串中包含的字符的实际个数,不含\0

案例:

/**
 * 字符串的长度
 * 语法:strlen(字符串 | 字符数组)
 */
#include <stdio.h>
#include <string.h>
int test8()
{
    // 创建一个char数组,用来存放账户和密码
    char username[20];
    printf("请输入您的账户:\n");
    scanf("%s",username);

    // 获取字符串的长度
    unsigned long len = strlen(username);
    if(!strcmp(username,"admin") )
    {
        printf("账户输入正确!%lu\n",len);
    }
    else
    {
        printf("账户输入错误!%lu\n",len);
    }
}

int main(int argc,char *aargv[])
{
    test8();
    return 0;
}
内容概要:本文介绍了MATLAB实现基于模拟温度浴优化(MTBO)和卷积神经网络(CNN)的多输入分类预测系统。文章首先回顾了项目的背景和发展现状,强调在大数据背景下,针对多输入特征的高效处理与分类需求的重要性。接着阐述了结合两种先进技术的具体方式以及所带来的优势——不仅能提升数据分类精度、增加模型稳定性,还能大幅度削减手工调整所需时间和精力。详细解析了模型构建流程包括数据加载、预处理、构建网络层结构到超参数的智能调节。此外展示了训练效果及误差分析图示,通过可视化的形式让使用者直观感受其效能。最后展望了该方案在未来的发展趋势和技术延伸的可能性,如加入遗传算法(GA)或粒子群优化(PSO),并且提出了一系列改进建议。 适合人群:具备中级以上编程技能的研究人员或者工程师,特别是那些关注于数据挖掘、深度学习、医学影像、自然语言处理等领域内的专业工作者。 使用场景及目标:此资源主要用于解决制造业、医疗保健、金融服务等行业内复杂的多模态数据分析任务。比如智能工厂里的机械故障侦测或是临床医学里疾病的筛查等工作流环节,借助这套强大的工具,企业可以在不影响业务连续性的前提下完成精准决策,助力业务转型。 其他说明:随附的代码片段可以帮助初学者逐步建立起完整的理解和实践经验,从基本的数据输入直到最终输出。同时提供的文献参考也为深入探究提供了丰富的资料依据。文中亦提及到了有关计算性能优化、预防过度拟合、多线程加速等方面的注意点,有助于读者避免常见误区。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值