嵌入式学习(第二周)

2023-11-19

目录

二、C语言基础

2、 运算符和表达式

2.1 运算分类

2.2 算数运算符

2.3 关系运算符

2.4 逻辑运算符

2.5 条件运算符

2.6 位运算符

2.7 运算符的运用实例

3、程序结构和过程控制

3.1 C语言程序结构

3.2 if-else结构

3.3 switch结构(多分支结构)

3.4 循环结构

3.5 其他控制语句

4、数组

4.1 一维数组

4.2 二维数组

4.3 字符串与字符数组


二、C语言基础

2、 运算符和表达式

2.1 运算分类

[1] 根据结合数的数目分类

单目运算符:即操作数只有1个的运算符

双目运算符:即操作数有2个的运算符

三目运算符:即操作数有3个的运算符,只有一个( ?: )

[2]根据运算符的用途分类:

赋值运算符:如=及其扩展运算符

逻辑运算符:如&&(与)、||(或)、!(非)

算数运算符:如+ - * / %等

关系运算符:如> < >= <= == !=等

位运算符:如<< >>等

条件运算符:只有一个 ?:

逗号运算符:只有一个 , 用于分隔

[3] 运算结合方向

运算符有两种结合顺序:自左至右、自右至左

自左至右(左结合性):表示运算符的操作数是从左向右(先左再右)与运算符结合的,如加法+

例:3 + 5,即3加上5,先取3,再取+,再取5

自右至左(右结合性):表示运算符的操作数是从右向左(先右再左)与运算符结合的,如赋值=例:a = 3,即先取数3,再给a赋值

2.2 算数运算符

练习 

i=9,j=9,k=11 
m=10,n=11,p=111

2.3 关系运算符

符号及含义:>(大于) <(小于) >=(大于等于) <=(小于等于) ==(判等) !=(不等)

1*)关系运算符的操作数可以是变量、常量和表达式

2*)关系表达式的的值是一个逻辑值:关系成立,即为真,结果为1;关系不成立,即为假,结果为0

3*)注意区分判断两个表达式相等的运算符是==,与=(赋值运算符)

练习

先判断4>2为真,即为1,接下来1>2为假,即为0。

error!

2.4 逻辑运算符

[1] 符号及含义:&& (逻辑与) ||(逻辑或) !(逻辑非)

1*)逻辑与:当且仅当两个表达式都为真时,则计算结果为真。否则为假

2*)逻辑或:当且仅当两个表达式都为假时,则计算结果为假。否则为真

3*)逻辑非:当原表达式为真时,计算结果为假;当原表达式为假时,计算结果为真

4*)使用逻辑运算符的表达式结果为真或假;

[2] 逻辑运算符短路现象

1*)逻辑与(&&)运算符短路

表达式1 && 表达式2 && 表达式3

当表达式1是真时,才会去判断表达式2的真/假。否则,如果表达式1是假,则之后的都不会进行运算。

当表达式2是真时,才会去判断表达式3的真/假。否则,如果表达式2是假,则之后的都不会进行运算。

分析: 首先会计算a++,计算a++会首先取出a的值,此时a的值是0 ,因为此时a的值是0,表达式1(a++)的位置是假,发生短路,后面的表达式2(b--)和表达式3 (++c)都不会进行运算,此时返回假(0),赋值给d ,执行a++(a的值加1)

2*)逻辑或(||)运算符短路

表达式1 || 表达式2 || 表达式3

当表达式1是真时,跳过判断表达式2和表达式3,直接返回真;

当表达式1是假时,才去判断表达式2的真/假

当表达式2是真时,跳过判断表达式3,直接返回真;

当表达式2是假时,才去判断表达式3的真/假

分析:

① 首先会计算a++,计算a++会首先取出a的值,此时a的值是0

② 因为此时a的值是0,表达式1(a++)的位置是假,需要判断表达式2(b--)的值

③ 计算b--,首先取出b的值,此时b的值是1

④ 因为此时b的值是1,表达式2(b--)的位置是真,发生短路,无需判断表达式3(++c)的真/假,此时返回真(1),赋值给d

⑤ 执行a++(a的值加1)和b--(b的值减1)

2.5 条件运算符

符号及含义: ?: (判断?前表达式是否成立,若成立取:前表达式,否则取:后表达式)

练习:

2.6 位运算符

[1]按位与&:

&的运算规则:如果两个相应的二进制位都为1,则该位的结果值为1;否则为0。

[2]按位或 |:

| 的运算规则:两个相应的二进制位中只要有一个为1,该位的结果值为1

[3]按位异或 ^(相异位1,相同为0)

^ 的运算规则:若参加运算的两个二进制位同号则结果为0(假)异号则结果为1(真)

示例:10 ^ 15 结果1010 ^ 1111 = 0101 = 5

[4]按位取反(~)

~ 的运算规则:1-->0 0-->1(若是1则变成0,若是0则变成1)

示例:~10 结果~1010 = 0101 = 5

[5]移位运算符

1*)左移运算符(<<)

左移运算符是用来将一个数的各二进制位全部左移若干位。 高位左移后溢出舍弃,右边低位补0。

2*)右移运算符(>>)

右移运算符是将一个数的各二进制位全部右移若干位,移到右端的低位被舍弃,对无符号数,高位补 0。

2.7 运算符的运用实例

实例1:

0x12345678,将该数的第5-8位设置为0x7,其他位保持不变
0001 0010 0011 0100 0101 0110 0111 1000        // 原码
​
0000 0000 0000 0000 0000 0001 1110 0000        // 0xF << 5
​
1111 1111 1111 1111 1111 1110 0001 1111        // 取反
​
0001 0010 0011 0100 0101 0110 0001 1000        // 清零  GPX2CON = GPX2CON & ~(0xF << 5)
​
0000 0000 0000 0000 0000 0000 1110 0000        // 0x7 << 5
​
0001 0010 0011 0100 0101 0110 1111 1000        // 置位:将0x7移到相应位置
​
GPX2CON = GPX2CON & ~(0xF << 5) | (0x7 << 5);

实例2:

0x12345678,将该数的第10-13位设置为0x8,22-25设置为0x9,其他位保持不变
GPX2CON = GPX2CON & ~(0xF << 10) | (0x8 << 10);
​
GPX2CON = GPX2CON & ~(0xF << 22) | (0x9 << 22);
​
​
​
GPX2CON = GPX2CON & ~(0xF << 10 | 0xF << 22)  | (0x8 << 10 | 0x9 << 22);

3、程序结构和过程控制

3.1 C语言程序结构

  *顺序结构:*就是指按照语句在程序中的先后次序一条一条的顺次执行,且每个语句都会被执行到。先执行A模块,再执行B模块。

  *选择结构:*选择语句又称为*分支语句*,它通过对给定的条件进行判断,从而决定执行两个或多个分支中的哪一支。 当条件P的值为真时执行A模块,否则执行B模块。

  *循环结构:*是在某些条件的控制下重复执行一段代码语句,让程序“杀个回马枪”,当满足循环条件时执行循环语句,否则不执行循环语句。

3.2 if-else结构

3.2.1 双重分支结构

如果 if 表达式的值为true(非0),将执行 if 语句(一个或一组)后的语句块。如果 if 表达式值为false(0),那么控制权将交给else 表达式后面的语句。else语句是可选的。 仅当 if 表达式的值为false时,才会执行else后的语句或语句序列。

// 仅当 表达式1 的值为true才会执行语句1,如果表达式的值为false,则执行else中的语句2
if(表达式1){       
    语句1;
}
else{
    语句2;
}

3.2.2 多重分支结构

首先判断条件1是否为真,若为真,则执行语句1并跳出,若为假则继续判断条件2是否为真,若条件2为真则执行语句2并跳出,否则继续判断条件3。以此类推。

if(表达式1){
    语句-1;
}
else if(表达式2){
    语句-2;
}
else if(表达式3){
    语句-3;
}
else{
    语句-4;
}

示例:

程序输入成绩,为0~100之间的整数。之后输出成绩代表的分数段:

90~100为优,80~89为良,70~79为中,60~69为及格,0~59为不及格,其他则输出错误信息.

int main(){
    int nScore;
    while(1){
        printf("请输入学生成绩: ");
        scanf("%d", &nScore);   
​
        if(nScore >= 90 && nScore <= 100){
            printf("优秀!\n");
        }
        else if(nScore < 90 && nScore >= 80){
            printf("良好!\n");
        }
        else if(nScore < 80 && nScore >= 70){
            printf("中等!\n");
        }
        else if(nScore < 70 && nScore >= 60){
            printf("及格!\n");
        }
        else if(nScore < 60 && nScore >= 0){
            printf("不及格!\n");
        }
        else{
            printf("输入错误,请重新输入!\n");
        }
    }
​
    return 0;
}

3.2.3 if语句嵌套使用

在if语句中又包含一个或多个if语句称为if语句嵌套,其形式一般如下:

需要注意的是if和else的配对问题,一个匹配原则:在嵌套if语句中,else总与它上面最近的if配对

示例:

输入一个整数,判断这个整数是正整数、0还是负整数

int main(){
    printf("请输入一个整数: ");
    int n;
    while(1){
        scanf("%d", &n);
        // if(n>0){
        //     printf("正数!\n");
        // }
        // else if(n<0){
        //     printf("负数!\n");
        // }
        // else{
        //     printf("%d\n", n);
        // }
        if(n>0){
            printf("正数!\n");
        }
        else{
            if(n<0){
                printf("负数!\n");
            }
            else{
                printf("%d\n", n);
            }
        }
    }
​
    return 0;
}

练习1:输入一个年份(正整数),判断这年是否是闰年

闰年判断标准:年份能被4整除;如若遇到100的倍数,则需判断年份能否被400整除。(逢4一闰,逢百不闰,逢400又闰)如1900年是不是闰年,1904年是闰年,2000年是闰年

#include <stdio.h>
​
int main(){
    int year;
    printf("请输入年份: ");
​
//     while(1){
//         scanf("%d", &year);
//         if(year<0){
//             printf("输入错误,请重新输入!\n");        
//             continue;       
//         }
//         else if(year % 4 != 0){     // 不能被4整除
//             printf("不是闰年!\n");
//         }
//         else if(year % 100 != 0){   // 能被4整除,但不能被100整除
//             printf("是闰年!\n");
//         }
//         else if(year % 400 == 0){   // 能被400整除
//             printf("是闰年!\n");
//         }
//         else{   // 能被4和100整除,但是不能被400整除
//             printf("不是闰年!\n");
//         }
//     }
​
    while(1){
        scanf("%d", &year);
        if(year<0){
            printf("输入错误,请重新输入!\n");
            continue;       
        }
        else{       // YEAR>0的情况
            if(year % 4 != 0){     // 不能被4整除
                printf("不是闰年!\n");
            }
            else {  // 能被4整除
                if(year % 100 != 0){   // 能被4整除,但不能被100整除
                    printf("是闰年!\n");
                }            
                else {  // 能被4整除且能被100整除
                    if(year % 400 == 0){   // 能被400整除
                        printf("是闰年!\n");
                    }
                    else{   // 能被4和100整除,但是不能被400整除
                        printf("不是闰年!\n");
                    }
                }
            }    
        }
    }
​
    return 0;
}

3.3 switch结构(多分支结构)

if-else语句只能判断2个分支,若要判断多个分支则需要if-else的多次使用或嵌套使用,程序会变得很复杂,可读性差。switch是多分支选择语句。通过switch()的多分支判断可以简便地实现多分支选择结构

switch()语句的一般形式如下:

switch(表达式){
case 常量表达式1:
    语句-1;
    break;      // 如果break不写,会顺序执行,每个case都会执行一次
case 常量表达式2:
    语句-2;
    break;
case 常量表达式3:
    语句-3;
    break;
case 常量表达式4:
    语句-4;
    break;
default:
    语句-5;
    break;  // 可写可不写
}

说明:

[1] switch(表达式)表达式的值应是一个整数(包括字符数据)

[2] switch()下的{}是一段语句块,这段语句包含若干个以case开头的语句块和至多一个以default开头的语句块

[3] case后需要一个常量(或常量表达式)。

首先判断switch(表达式)的表达式的值,之后与各个case之后的值进行比对,如果某个case后的值与表达式的值相同,则跳转到此case语句;如果所有的case都不匹配,则跳转到default后的语句。

[4] 可以没有default语句。若没有default语句,则如果没有匹配的case,则程序不执行任何语句

[5] 每个case语句后的常量值必须各不相同,否则会发生互相矛盾现象

示例:程序输入成绩,为0~100之间的整数。之后输出成绩代表的分数段(用switch语句完成):

90~100为优,80~89为良,70~79为中,60~69为及格,0~59为不及格,其他则输出错误信息

3.4 循环结构

什么是循环?

循环是程序中重复执行,直到满足指定条件才停止的一段代码;

C语言中,控制循环执行的条件在编码时用到了关系和逻辑运算符;

如果一直循环,无法退出则成为了死循环。

3.4.1 while循环

while循环在执行循环前检查条件,条件表达式一般为关系表达式或者逻辑表达式。只要表达式为真循环就会迭代,否则退出循环。循环体可以是空语句、一个简单的语句或语句块,如果while循环中包含一组语句,必须用{}括起来

// 如果表达式的值为真,则执行语句1,否则就不执行语句
while(表达式){
    语句1;        // 
}
​
while(表达式){}    // 空循环
while(表达式);     // 空循环
​
// 如果while循环中只有一句语句,则不需要加大括号(不推荐)
while(表达式)
    语句2;
​
// 如果while循环中有一个语句块(不止一个语句),则必须要加大括号将语句块括起来
while(表达式){
    语句3;
    语句4;
    ...
}

3.4.2 do-while循环

先执行一次指定的循环体语句,然后判别表达式,当表达式的值为非零(“真”) 时,返回重新执行循环体语句,如此反复,直到表达式的值等于0为止,此时循环结束;while后面的分号不能省略:do

{} while();

do{
    循环体;
}while(表达式);
 

示例:求1+2+3+……+100=?

int main(){
    int sum = 0, i = 0;
    do{
        sum += i;
        i++;
    }while(i<=100);
    printf("sum = %d\n", sum);
​
    return 0;
}

3.4.3 for循环

for(表达式1; 表达式2; 表达式3){
    循环体;    // 如果循环体只有一句话,则大括号可以省略(不推荐),否则大括号必须存在
}

表达式1:循环的初始条件,只执行一次。可以为0个、1个或多个变量设置初值

表达式2:判断循环结束的条件。在每次执行循环体前判断此表达式,若表达式为真则进入循环,否则不执行循环

表达式3:作为循环的调整(即改变循环状态),在执行完循环体之后执行

注意:

[1] for()括号内的3个表达式的分隔符是分号 ";" 不是逗号 " , "

[2] for()括号内的3个表达式都可以同时省略,但是不能省略分号 ";",当省略表达式2时,程序将陷入死循环。

示例:求1+2+3+……+100=?

int main(){
    int sum = 0;
    // C99/C11支持这么写
    // i=1,设置这个循环的初始值(注意:这个部分只执行一次)
    // i<=100, 设置这个循环的结束条件(循环体执行之前需要先判断)
    // i++,改变整个循环的状态(等到循环体结束之后,再执行该语句)
    for(int i = 1; i <= 100; i++){
        sum += i;
    }
    printf("sum = %d\n", sum);
​
    return 0;
}

示例: 用for循环求奇数和,偶数和

#include <stdio.h>
​
int main(){
    int sum = 0;
    int sum2 = 0;
    for(int i=0; i<=100; i++){
        if(i%2==0){ // 偶数
            sum = sum + i;
        }
        else{
            sum2 = sum2 + i;
        }
    }
    printf("偶数和:sum = %d\n", sum);
    printf("奇数和:sum2 = %d\n", sum2);
​
    return 0;
}

死循环:

while(1){}

while(1);

do{}while(1);

for循环的死循环:for(;;);

3.5 其他控制语句

3.5.1 break

break语句的用途:

用于在 switch 语句中终止case。

用来从循环体内跳出循环体,即提前结束循环,接着执行循环下面的语句。

注意:

break语句不能用于循环语句和switch语句之外的任何其他语句中。

多层循环中,break只向外跳一层

示例:从r=1开始,输出所有半径是正整数的圆的面积,直至出现面积大于100为止

3.5.2 continue

continue语句的作用:

结束本次循环,即跳过循环体中下面尚未执行的语句,接着进行下一次是否执行循环的判定.

注意:

在while循环和do…while循环中,程序控制权传递给条件测试语句;

在for循环中,continue影响循环的增量部分,然后执行条件测试;

/**
 *  输出100-200以内所有不能被3整除的整数 
 */
int main(){
    // for(int i=0; i<=30; i++){
    //     if(i%3){
    //         printf("%d  ", i);
    //     }    
    // }
    for(int i=100; i<=200; i++){
        if(i%3 == 0){
            continue;
        }  
        printf("%d  ", i);  
    }
    printf("\n");
    return 0;
}

3.5.3 return

return语句说明:

结束当前函数,并将返回值返回给函数调用的位置。

return语句的用法:

return 返回值;

其中返回值由函数类型决定。如main()函数是int类型,则需要返回一个整数。如果函数是void类型则无需写返回值。

注意:

表达式是可选的。一个函数中可以使用多个return语句,但是遇到第一个return语句时返回

3.5.4 goto

goto语句说明:

goto语句为无条件转向语句;

goto语句的用法:

goto 标签;

当执行到goto语句时,程序会跳转到同一函数内goto语句所指向的标号处,例如下图,goto语句执行后,程序会自动跳转到label_1标签处。标签的命名规则与C语言标识符的命名规则相同。

int main(){
    int sum;
label:
    // ...注意:在同一个函数内
    goto label;
    return 0;
}

实例:

用goto语句实现1+2+3....+100?

注意:

用不用goto一直是一个著名的争议话题,滥用goto语句会使程序无规律、可读性差。goto语句违背了C语言的模块化编程的基本思想,因此goto语句不推荐使用。

Linux内核源代码中对goto的应用非常广泛,但是一般只限于错误处理中。

4、数组

4.1 一维数组

4.1.1 一维数组的定义

数组定义的语法:

存储类型 数据类型 数组名[数组长度] ;

说明:

l 存储类型:auto,register,static,extern。若省略,相当于auto

l 数据类型:可以是任何一种基本数据类型或构造数据类型

l 数组名:每个数组都有一个名字,我们称之为数组名数组名代表数组的起始地址。数组名应当符合标识符的命名规则,即以字母、数字、下划线组成,但不能以数字开头。

l 数组长度:所包含的数据的个数称为数组长度(Length)

数组长度一般只能是常量和常量表达式(但在C99新增了变长数组VLA)

示例:一个拥有10个元素的int型数组a

int a[10];

注意:数组必须先定义后使用

4.1.2 一维数组元素的引用

C语言规定数组必须逐个元素引用,不能整体引用。

数组元素由索引下标(Index)标识,索引或下标从0开始。

数组元素的表示方法:

数组名[下标]

例如:int a[10];

其元素是a[0]、a[1]、a[2]、a[3]、a[4]、a[5]、a[6]、a[7]、a[8]、a[9]

注意:C语言对数组不作越界检查,使用时要注意

4.1.3 一维数组内存分配

数组在定义后,就在内存中划分了一块连续的空间用于存储数组。以int a[n]为例(n大于0):这块空间的大小是sizeof(int)*n,划分成n块来顺序存储a[0]~a[n-1]。数组名代表这块空间的首地址(也就是a[0]的地址)

 

练习1:输入数字n,使用数组存储斐波那契数列前n项,并输出

练习2:从键盘输入10个学生的成绩,如果遇到大于100或者小于0的成绩需要提示输入错误重新输入。之后计算10个学生的总成绩和平均成绩。

#include <stdio.h>
​
int main(){
    int score[10];
    for(int i=0; i<10; i++){
        scanf("%d", &score[i]);
        if(score[i] < 0 || score[i] > 100){
            printf("分数输入错误,请重新输入!\n");
            i--;
            continue;
        }
    }
​
    int totalScore = 0;   // stack -- 随机值
    for(int i=0; i < 10; i++){
        totalScore += score[i];
    }
    printf("学生总分为: %d\n", totalScore);
    printf("平均成绩为: %f\n", (float)totalScore/10);
​
    return 0;
}

4.1.4 变长数组

C99新增了变长数组(variable-length array, VLA),允许使用变量表示数组的长度。

例如:

int lenth = 5; 
int array[lenth];

注意:变长数组不能改变大小

变长数组中的”变”不是指可以修饰已创建数组的大小,一旦创建了变长数组,它的大小则保持不变。这里的”变”指的仅仅是:在创建数组时,可以使用变量指定数组的长度。

4.1.5 一维数组使用实例

冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

算法描述:

①  比较相邻的元素。如果第一个比第二个大(小),就交换它们两个;

②  对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大(小)的数;

③  针对所有的元素重复以上的步骤,除了最后一个;

④  重复步骤1~3,直到排序完成。

示例:从键盘输入10个各不相同的整数,存储在数组中,使用冒泡排序法将数组排序并输出

#include <stdio.h>
#define Max 10
​
int main(){
    int arr[Max], tmp;
    printf("请输入10个数:\n  ");
    for(int i=0; i<Max; i++){
        scanf("%d", &arr[i]);
    }
​
    // 1. 从数组中找出最大的元素(设置第一个元素为最大的元素)
    for(int i=0; i<Max-1; i++){
        for(int j=0; j<Max-1-i; j++){
            if(arr[j] > arr[j+1]){
                tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
        }
    }
​
    printf("排序完成: ");
    for(int i=0; i<Max; i++){
        printf("%d  ", arr[i]);
    }
    printf("\n");
​
    return 0;
}

4.2 二维数组

4.2.1 二维数组的定义

二维数组的声明方式:

数据类型 数组名常量表达式

示例:

int a[2] [3]; //定义一个2*3的二维int型数组

float f[3] [4]; //定义一个3*4的二维float型数组

4.2.2 二维数组的存储方式

二维数组常常被称为矩阵(matrix)。把矩阵想成行(row)和列(column)的排列方式,更有助于形象化地理解二维数组地逻辑结构。

虽然二维数组在概念上可以理解是二维的,其下标在两个方向上变化,有行和列的说法。但是内存却是连续编址的,按一维线性排列的。如何在一维的存储器中存放二维数组?

存储形式:二维数组在内存中是按行的顺序存放的,即先存放第一行的元素,再存放第二行的元素,……。

4.2.3 深入理解多维数组(二维数组)

在C语言中我们可以将二维数组视为一种特殊的一维数组,它的元素又是一个一维数组。例如,上图的二维数组 int a[3] [4]。可以理解成由三个元素a[0],a[1],a[2]组成的数组,每个元素a[i]是包含四个元素的一维数组:

因此在C语言中的多维数组其实就是元素为数组的数组。n 维数组的元素是 n-1 维数组。例如,二维数组的每个元素都是一维数组,一维数组的元素当然就不是数组了。

示例:char screen[10] [40] [80]; // 一个三维数组

数组 screen 包含 10 个元素,从 screen[0] 到 screen[9]。每个元素又是一个二维数组,它有 40 个元素,这 40 个元素均是一维数组,然后每个一维数组内都有 80 个字符。整体来说,screen 数组有 32000(10×40×80)个 char 类型元素。

4.2.4 二维数组元素的引用及初始化

[1] 二维数组元素的引用

数组名[行下标] [列下标]

例如:ary[1] [3] = 12;

[2] 分行初始化

分行给二维数组赋值。例如:

int a[3] [4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

每行的元素使用花括号分隔开,中间用逗号分隔开,如果有未写的则默认为0。

[3] 线性初始化

把所有的元素都写在一个花括号内,这样会按照数组在内存中的存储顺序给二维数组赋值。例如:

int a[3] [4]={1,2,3,4,5,6,7,8,9,10,11,12};

类似于一维数组,如果有未写的则默认为0。

[4] 全部元素初始化

可以提供全部元素的初值,这样常量表达式1(即第一个下标)可以缺省不写,系统会根据输入的多少来计算行数。但常量表达式2(即第二个下标)不可缺省。例如:

int a[] [4]={1,2,3,4,5,6,7,8,9,10,11,12};

则系统自动计算出这个二维数组是a[3] [4]。

注意:第一维的长度可以省略,但是第二维长度不能省,例如:

int a[3] []={1,2,3,4,5,6,7,8,9,10,11,12};

编译程序时,会有语法错误

4.2.5 二维数组程序实例

示例:自定义一个3*4的矩阵,输出矩阵中值最大的元素,并输出其数组下标

#include <stdio.h>
#define row 3
#define col 4
​
int main(){
    int arr[row][col] = {1,4,7,2,5,8,3,6,9,11,10,0};
    int nMax = arr[0][0];
    int x, y;
    for(int i=0; i<row;i++){
        for(int j=0; j<col; j++){
            if(nMax <= arr[i][j]){
                nMax = arr[i][j];
                x = i;
                y = j;
            }
        }
    }
    printf("最大值为: arr[%d][%d] = %d\n", x, y, nMax);
​
    return 0;
}

练习:打印杨辉三角型前10行

杨辉三角型:杨辉三角型是形如以下矩阵的三角形:

4.3 字符串与字符数组

4.3.1字符串

字符串常量是由一对双引号括起来的,以’\0’为结束标志的一组字符序列。例如字符串“hello”在内存中按照如下方式存储:

4.3.2 字符数组的定义

在C语言中没有专门的字符串变量,通常用一个字符数组来存储一个字符串。因此当一个字符串存入一个数组时,也把结束符’\0’存入数组,并以此作为该字符串是否结束的标志。 字符数组是元素的数据类型为字符类型的数组,可以是一维的,也可以是多维的,它既具有普通数组的一般性质,又具有某些特殊性质。字符数组的定义形式如下: char c[10], ch[3] [4];

4.3.3 字符数组初始化

[1] 逐个元素初始化 和普通数组相同,逐个为数组元素赋值。

示例1:char ch[6]={‘H’,’e’,’l’,’l’,’o’,’\0’};

[2] 使用字符串常量为数组元素赋值

示例1:char ch[6]={“abcde”};

4.3.4 字符串的输入输出

输出字符串不必使用for()循环遍历整个数组,直接使用%s格式控制符即可。

printf("%s",c);

例如:

当然,我们也可以使用%s在scanf()函数中直接输入一个字符串:

scanf("%s",c);

不过,使用%s输入整个字符串需要注意以下几点:

① 因为C语言不检查数组下标越界问题,因此如果直接键入字符串给字符数组,需要将字符数组设置的足够大,这样才不会丢失数据。

② 输入字符串给字符数组,注意scanf()的第二个参数不要带&(取地址符)。因为数组名就代表了数组的地址。

示例:

③ 用scanf输入地字符串里面可能有空格、制表符等空白字符,空白字符后面地字符不能被存入到数组中。这种情况可以通过下面方式处理

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式学习(第二周) 的相关文章

  • nslookup 报告“无法解析 '(null)': 名称无法解析”,尽管它成功解析了 DNS 名称

    我在 ubuntu 上 并且正在运行 docker 默认桥接网络 我有 Zookeeper kafka 的容器化版本 以及我编写的与 kafka 对话的应用程序 I do a docker exec it
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 两种情况或 if 哪个更快? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我必须制作一个 非常 轻的脚本 它将接受用户的选项并调用脚本中的函数来执行一些任务 现在我可以使用 IF 和 CASE 选项 但我想知道两
  • 如何在Linux内核源代码中打印IP地址或MAC地址

    我必须通过修改 Linux 内核源代码来稍微改变 TCP 拥塞控制算法 但为了检查结果是否正确 我需要记录 MAC 或 IP 地址信息 我使用 PRINTK 函数来打印内核消息 但我感觉很难打印出主机的MAC IP地址 printk pM
  • 将 PDF 转换为 600dpi 的 TIFF 和 jpg 96 dpi

    我想使用 ImageMagick 从 Python 脚本将 pdf 转换为 600 dpi 的 tiff 和 96 dpi 的 jpg 我使用 imagemagick 命令行完成了这项任务 但我想使用python中的Imagemagick将
  • Linux:在文件保存时触发 Shell 命令

    我想在修改文件时自动触发 shell 命令 我认为这可以通过注册 inotify 挂钩并调用来在代码中完成system 但是是否有更高级别的 bash 命令可以完成此任务 尝试 inotify 工具 我在复制链接时遇到问题 抱歉 但 Git
  • 安装J语言的JQt IDE,出现错误

    我一直按照这里的说明进行操作 http code jsoftware com wiki System Installation Linux http code jsoftware com wiki System Installation L
  • jpegtran 优化而不更改文件名

    我需要优化一些图像 但不更改它们的名称 jpegtran copy none optimize image jpg gt image jpg 但是 这似乎创建了 0 的文件大小 当我对不同的文件名执行此操作时 大小仍然完全相同 怎么样 jp
  • SSE:跨页边界的未对齐加载和存储

    我在页面边界旁边执行未对齐加载或存储之前读过某处 例如使用 mm loadu si128 mm storeu si128内在函数 代码应首先检查整个向量 在本例中为 16 个字节 是否属于同一页 如果不属于同一页 则切换到非向量指令 我知道
  • 在脚本内使用不带密码的 sudo

    由于某种原因 我需要作为用户在没有 sudo 的情况下运行脚本 script sh 该脚本需要 root 权限才能工作 我认为将 sudo 放入 script sh 中是唯一的解决方案 让我们举个例子 script sh bin sh su
  • 如何更改 Apache 服务器的根目录? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何更改 Apache 服务器的文档根目录 我基本上想要localhost从 来 users spencer projects目录而不是
  • 如何在 Bash 中给定超时后终止子进程?

    我有一个 bash 脚本 它启动一个子进程 该进程时不时地崩溃 实际上是挂起 而且没有明显的原因 闭源 所以我对此无能为力 因此 我希望能够在给定的时间内启动此进程 如果在给定的时间内没有成功返回 则将其终止 有没有simple and r
  • Linux 上的用户空间能否实现本机代码的抢占式多任务处理?

    我想知道是否可以在 Linux 用户空间的单个进程中实现本机代码的抢占式多任务处理 也就是说 从外部暂停一些正在运行的本机代码 保存上下文 交换到不同的上下文 然后恢复执行 所有这些都由用户空间精心安排 但使用可能进入内核的调用 我认为这可
  • MySQL 中的创建/写入权限

    我的设备遇到一些权限问题SELECT INTO OUTFILE陈述 当我登录数据库并执行简单的导出命令时 例如 mysql gt select from XYZ into outfile home mropa Photos Desktop
  • 按进程名称过滤并记录 CPU 使用情况

    Linux 下有选项吗顶部命令 https www man7 org linux man pages man1 top 1 html我可以在哪里按名称过滤进程并将每秒该进程的 CPU 使用情况写入日志文件 top pgrep 过滤输出top
  • Linux - 从第二个选项卡获取文本

    假设我们有这样的文件 一些文本11 一些文本12 一些文本13 一些文本21 一些文本22 一些文本23 文本由制表符分隔 我们知道第 1 列中的一些文本 但希望从第 2 列中获取文本 我知道我可以通过以下方式获取线路 grep somet
  • 如何在c linux中收听特定接口上的广播?

    我目前可以通过执行以下操作来收听我编写的简单广播服务器 仅广播 hello int fd socket PF INET SOCK DGRAM 0 struct sockaddr in addr memset addr 0 sizeof ad
  • Urwid:使光标不可见

    我正在使用 urwid 它是一个用于在 ncurses 中设计终端用户界面的 Python 框架 但有一件事我在 urwid 中无法做到 而这在 Curses 中很容易做到 使光标不可见 现在 选择按钮时光标是可见的 而且看起来很丑 有办法
  • Fortran gfortran linux 中的“分段错误(核心转储)”错误

    我正在创建一个程序 该程序将分析目录中的文件 fits 然后它将在另一个目录中创建另一个文件 txt 它只是一个转换器 当我尝试执行该程序 编译正常 时 它给了我一条错误消息 程序收到信号 SIGSEGV 分段错误 无效的内存引用 此错误的
  • PyQt5 - 无法使用 QVideoWidget 播放视频

    from PyQt5 QtWidgets import from PyQt5 QtMultimedia import from PyQt5 QtMultimediaWidgets import from PyQt5 QtCore impor

随机推荐

  • 计算员工工资

    请编写一个程序 可以读取一名员工的员工编号 本月工作总时长 小时 以及时薪 并输出他的工资条 工资条中包括员工编号和员工月收入 输入格式 输入包含两个整数和一个浮点数 分别代表员工编号 工作时长以及时薪 每个数占一行 输出格式 输出共两行
  • Unreal Engine4蓝图编程学习(一)

    学习内容主要介绍了蓝图进行对象交互 升级玩家技能 升级AI敌人 跟踪游戏状态完成游戏体验等内容 内容来源于 Unreal Engine4蓝图可视化编程 书籍为2017年 与现在版本有一定区别 一 制作移动标靶 1 1 首先 我们想先创建一个
  • mysql database uri,未设置SQLALCHEMY_DATABASE_URI

    I tried to work with CURD operation using Flask and SQLAlchemy But getting Error while connecting to database Here is th
  • springboot+vue教室图书馆预约管理系统、

    下载地址 https download csdn net download ouyangxiaobai123 22176771 项目介绍 springboot vue教室图书馆预约管理系统 系统说明 聪慧物联网教室预定系统 后台系统 项目简
  • 多维数组变成一维数组

    这个问题来源于一个朋友曾经问过我的问题 当时是一个二维数组变成一维数组 后面我想整理一下 整理一个多维 并且是不定维的数组 一 二维数组变成一维数组 1 遍历数组 将元素一个个放入新数组 结果 如果元素不是数组 将会报错 下面是改良版 这样
  • 信号量和自旋锁

    信号量和自旋锁 为了避免并发 防止竞争 内核提供了一组同步方法来提供对共享数据的保护 我们的重点不是介绍这些方法的详细用法 而是强调为什么使用这些方法和它们之间的差别 Linux 使用的同步机制可以说从2 0到2 6以来不断发展完善 从最初
  • python编程实验,模拟聪明版的尼姆游戏设计原理

    实验原理与内容 本实验完成一个模拟聪明版的尼姆游戏功能 尼姆游戏是个著名的游戏 有很多变种玩法 两个玩家轮流从一堆物品中拿走一部分 在每一步中 玩家可以自由选择拿走多少物品 但是必须至少拿走一个并且最多只能拿走一半物品 然后轮到下一个玩家
  • Python SQLAlchemy ( ORM )、dictalchemy、Flask-SQLAlchemy、Flask-migrate、flask-script、flask-upload

    From Python中强大的通用ORM框架 SQLAlchemy https zhuanlan zhihu com p 444930067 Python ORM之SQLAlchemy全面指南 https zhuanlan zhihu co
  • ubuntu 18.04安装wireshark及网卡接口权限问题

    1 安装 sudo apt fast install wireshark 第一次安装过程中可能会提示Should non superusers be able to capture packets 选是即可 默认是否 2 待安装成功后 你会
  • MFC 菜单栏的使用

    MFC 菜单栏的使用 主要介绍两种比较简单和常用的创建方法 一 在资源视图中添加菜单资源 通过鼠标点击添加菜单项 菜单栏设计好 以后就是添加了 介绍两种方法 1 很简单 鼠标右击想显示菜单栏的对话框属性 可以看到有一个menu的属性 点击就
  • Linux 宝塔面板的安装

    Ptw cwl 登录宝塔官网 查看宝塔的详情 www bt cn 安装 linux服务器图形化界面管理器 安装 宝塔面板 在xshell当中执行宝塔面板的安装命令 yum install y wget wget O install sh h
  • python批量处理

    python opencv图像二值化批量处理 from skimage import data dir io transform color filters import numpy as np import cv2 def convert
  • 红帽Redhat—Linux网卡聚合

    文章目录 一 实验环境设置 二 网卡聚合nmcli 配置步骤 1 创建聚合接口 2 配置网络属性 3 添加物理接口 4 激活端口 5 查看聚合接口状态 一 实验环境设置 在已经安装好的RHEL8 3添加两个新网卡 1 点击虚拟机 gt 设置
  • 机器学习笔记----Fuzzy c-means(FCM)模糊聚类详解及matlab实现

    前言 这几天一直都在研究模糊聚类 感觉网上的文档都没有一个详细而具体的讲解 正好今天有时间 就来聊一聊模糊聚类 一 模糊数学 我们大家都知道计算机其实只认识两个数字0 1 我们平时写程序其实也是这样if 1 then do 永远这种模式 在
  • C++实现String类

    C 实现String类 还没有完成 待继续 有以下注意的点 1 赋值操作符返回的是一个MyString 而重载的 返回的是一个MyString 其中的原因参看 effective c 主要是返回引用的时候 必须返回必须在此函数之前存在的引用
  • Android Studio安装教程+打包APK

    前言 这是一篇给新人的教程 如果你觉得简单啰嗦请保持冷静 同时如果本篇能给予到你帮助 是我的荣幸 Android Studio安装教程 点击链接下载Android Studio Android Studio官网下载 下载完成后双击 exe文
  • [实验三]LZW 编解码算法实现与分析

    目录 一 LZW算法 1 1 编码步骤 1 2 解码步骤 1 3 关于有可能出现当前码字CW不在词典中的情况说明 二 代码实现 2 1 程序说明 2 2 数据结构 2 3 bitio h 2 4 bitio c 2 5 lzw c 三 实验
  • VC++ FTP文件上传(断点续传)

    include
  • vue项目设置ip访问

    1 只用ip访问 打开config gt index 文件 host 172 16 1 95 新增host 改成IP地址 最后重新运行项目 2 既可以IP访问 由可以localhost访问 将config gt index 中host 该为
  • 嵌入式学习(第二周)

    目录 二 C语言基础 2 运算符和表达式 2 1 运算分类 2 2 算数运算符 2 3 关系运算符 2 4 逻辑运算符 2 5 条件运算符 2 6 位运算符 2 7 运算符的运用实例 3 程序结构和过程控制 3 1 C语言程序结构 3 2