第六章 数组


前言

自己身为计算机小白,刚入大一才接触程序设计,我相信有很多和我一样想学好c语言却不知怎么努力的同学,所以我想在大一期末前系统的复习整个学年的c语言知识,并且分享给大家,共同学习和进步。以下内容有的是自己所见所学,也有从别处借鉴,有误之处还请广大网友指正。

这里分享我自学的网站:c.biancheng 这个网站真的是简单易懂,受益匪浅,很适合我这种菜鸟小白自学。


目录

第六章 数组

前言

一、基础知识点

6.1 什么是数组

      数组的概念和定义

6.2 C语言二维数组

      二维数组的初始化(赋值)

6.3 判断数组中是否包含某个元素

6.4 字符数组和字符串

      字符串的输入和输出

      字符串处理函数

6.5 排序问题

二、典型例题

一维数组

二维数组

 字符串数组

总结


一、基础知识点


6.1什么是数组

举了一个例子,是输出一个 4×4 的整数矩阵,代码如下:

  1. #include
  2. #include
  3. int main()
  4. {
  5. int a1=20, a2=345, a3=700, a4=22;
  6. int b1=56720, b2=9999, b3=20098, b4=2;
  7. int c1=233, c2=205, c3=1, c4=6666;
  8. int d1=34, d2=0, d3=23, d4=23006783;
  9. printf("%-9d %-9d %-9d %-9d\n", a1, a2, a3, a4);
  10. printf("%-9d %-9d %-9d %-9d\n", b1, b2, b3, b4);
  11. printf("%-9d %-9d %-9d %-9d\n", c1, c2, c3, c4);
  12. printf("%-9d %-9d %-9d %-9d\n", d1, d2, d3, d4);
  13. system("pause");
  14. return 0;
  15. }

 运行结果:

20        345       700       22
56720     9999      20098     2
233       205       1         6666
34        0         23        23006783  

 为了减少变量的数量,让开发更有效率,使用数组(Array)为多个数据定义一个变量。 

#include<stdio.h>
int main()
{
    int i;
    int a[4]={20,345,700,22},
        b[4]={56720,9999,20098,2},
        c[4]={233,205,1,6666},
        d[4]={34,0,23,23006783};
    for(i=0;i<4;i++)
    {
        printf("  %-9d",a[i]);
    }
    printf("\n");
    for(i=0;i<4;i++)
    {
        printf("  %-9d",b[i]);
    }
      printf("\n");
    for(i=0;i<4;i++)
    {
        printf("  %-9d",c[i]);
    }
      printf("\n");
    for(i=0;i<4;i++)
    {
        printf("  %-9d",d[i]);
    }
    return 0;
}


我们借助数组来输出一个 4×4 的矩阵:
#include <stdio.h>
int main()
{
int a[4] = {20, 345, 700, 22};
int b[4] = {56720, 9999, 20098, 2};
int c[4] = {233, 205, 1, 6666};
int d[4] = {34, 0, 23, 23006783};

printf("%-9d %-9d %-9d %-9d\n", a[0], a[1], a[2], a[3]);
printf("%-9d %-9d %-9d %-9d\n", b[0], b[1], b[2], b[3]);
printf("%-9d %-9d %-9d %-9d\n", c[0], c[1], c[2], c[3]);
printf("%-9d %-9d %-9d %-9d\n", d[0], d[1], d[2], d[3]);

return 0;
}


 数组的概念和定义

要想把数据放入内存,必须先要分配内存空间 

放入4个整数,就得分配4个int类型的内存空间:

在定义数组的同时赋值    int a[4]={1,2,3,4};            注意定义时{ , , ,}

这样,就在内存中分配了4个int类型的内存空间,共 4×4=16 个字节,并为它们起了一个名字,叫a

我们把这样的一组数据的集合称为数组(Array),它所包含的每一个数据叫做数组元素(Element),所包含的数据的个数称为数组长度(Length),例如int a[4];就定义了一个长度为4的整型数组,名字是a

数组中的每个元素都有一个序号,这个序号从0开始,而不是从我们熟悉的1开始,称为下标(Index)。
 

arrayName 为数组名称,index 为下标。例如,a[0] 表示第0个元素,a[3] 表示第3个元素。

a[0]=20;
a[1]=345;
a[2]=700;
a[3]=22;

 我们来总结一下数组的定义方式:

  1. float m[12]; //定义一个长度为 12 的浮点型数组
  2. char ch[9]; //定义一个长度为 9 的字符型数组
  3. int a[4];//定义一个长度为4的整数型数组

 对于数组的初始化需要注意以下几点: 

1) 可以只给部分元素赋值。当{ }中值的个数少于元素个数时,只给前面部分元素赋值。例如:

 int a[10]={12, 19, 22 , 993, 344};

表示只给 a[0]~a[4] 5个元素赋值,而后面 5 个元素自动初始化为 0。

当赋值的元素少于数组总体元素的时候,剩余的元素自动初始化为 0:

  • 对于short、int、long,就是整数 0;
  • 对于char,就是字符 '\0';
  • 对于float、double,就是小数 0.0。

我们可以通过下面的形式将数组的所有元素初始化为 0:

int nums[10] = {0};
char str[10] = {0};
float scores[10] = {0.0};    

由于剩余的元素会自动初始化为 0,所以只需要给第 0 个元素赋值为 0 即可。

 2) 只能给元素逐个赋值,不能给数组整体赋值。例如给 10 个元素全部赋值为 1,只能写作: 

 int a[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};

 而不能写作: int a[10] = 1; 

 3) 如给全部元素赋值,那么在定义数组时可以不给出数组长度。例如:

int a[ ] = {1, 2, 3, 4, 5};

 等价于

int a[5] = {1, 2, 3, 4, 5}; 


数组内存是连续的

(连续的内存为指针操作(通过指针来访问数组元素)和内存处理(整块内存的复制、写入等)提供了便利,这使得数组可以作为缓存(临时存储数据的一块内存)使用。)

数组是一个整体,它的内存是连续的;也就是说,数组元素之间是相互挨着的,彼此之间没有一点点缝隙。下图演示了int a[4];在内存中的存储情形:

这里的0、1、2、3就是数组下标,a[0]、a[1]、a[2]、a[3] 就是数组元素。

在学习过程中,我们经常会使用循环结构将数据放入数组中(也就是为数组元素逐个赋值),然后再使用循环结构输出(也就是依次读取数组元素的值)

#include <stdio.h>
int main()
    {
    int i,a[10];
                          //将1~10放入数组中
    for(i=0; i<10; i++)
    {
        n[i] = (i+1);
    }
   
                            //依次输出数组元素
    for(i=0; i<10; i++)
    {
        printf("%d ", n[i]);
    }
  
    return 0;
}

运行结果:

1 2 3 4 5 6 7 8 9 10 

 更改上面的代码,让用户输入 10 个数字并放入数组中(从控制台读取用户输入):

#include <stdio.h>
int main()
{
    int i,a[10];
   
                                    //从控制台读取用户输入
    for(i=0; i<10; i++)             //数组 a 的最大下标是 9,也就是不能超过 10
    {
        scanf("%d", &a[i]);         //注意取地址符 &,不要遗忘哦
    }
   
                                    //依次输出数组元素
    for(i=0; i<10; i++)
    {
        printf("%d ", a[i]);
    }
   
    return 0;
}

 运行结果:

22 18 928 5 4 82 30 10 666 888↙

22 18 928 5 4 82 30 10 666 888


6.2C语言二维数组

我们可以将二维数组看做一个 Excel 表格,有行有列,length1 表示行数,length2 表示列数,要在二维数组中定位某个元素,必须同时指明行和列。例如:

int a[3][4];

定义了一个 3 行 4 列的二维数组,共有 3×4=12 个元素,数组名为 a,即:

a[0][0], a[0][1], a[0][2], a[0][3]
a[1][0], a[1][1], a[1][2], a[1][3]      如果想表示第 2 行第 1 列的元素,应该写作 a[2][1]。
a[2][0], a[2][1], a[2][2], a[2][3]

二维数组的各个元素也是相互挨着的,彼此之间没有缝隙。

  • 一种是按行排列, 即放完一行之后再放入第二行;在C语言中,二维数组是按行排列的。
  • 另一种是按列排列, 即放完一列之后再放入第二列。

a[0][0], a[0][1], a[0][2], a[0][3]------a[0]行
a[1][0], a[1][1], a[1][2], a[1][3]------a[1]行   
a[2][0], a[2][1], a[2][2], a[2][3]------a[2]行

先存放完a[0],a[1],a[2]行,再存放每一行中的4个元素。此数组占用(3✖4)✖4=48字节。


 二维数组的初始化(赋值)

二维数组的初始化可以按行分段赋值,也可按行连续赋值

对于二维数组的初始化还要注意以下几点: 

1) 可以只对部分元素赋值,未赋值的元素自动取“零”值。例如: 

int a[3][3] = {{1}, {2}, {3}};     int a[3][3] = {{0,1}, {0,0,2}, {3}};

是对每一行的第一列元素赋值,未赋值的元素的值为 0。赋值后各元素的值为:

1  0  0                                                                                   0 1 0   
2  0  0                                                                                   0 0 2
3  0  0                                                                                   3 0 0

 2) 如果对全部元素赋值,那么第一维的长度可以不给出。例如:

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

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

 3) 二维数组可以看作是由一维数组嵌套而成的;如果一个数组的每个元素又是一个数组,那么它就是二维数组。当然,前提是各个元素的类型必须相同。根据这样的分析,一个二维数组也可以分解为多个一维数组,C语言允许这种分解。

a[3][4]可以分解为a[0],a[1],a[2]三个均有4个元素的一维数组,

a[0][0], a[0][1], a[0][2], a[0][3] 
a[1][0], a[1][1], a[1][2], a[1][3]
a[2][0], a[2][1], a[2][2], a[2][3]


6.3判断数组中是否包含某个元素

对无序数组的查询

所谓无序数组,就是数组元素的排列没有规律。无序数组元素查询的思路也很简单,就是用循环遍历数组中的每个元素,把要查询的值挨个比较一遍。请看下面的代码:

#include<stdio.h>
int main()
{
    int i,n,thisindex=-1;
    int a[10]={1,10,6,296,177,23,0,100,34,999};
    scanf("%d",&n);
    for(i=0;i<10;i++)
    {
        if(a[i]==n)           //if括号中要用==,且后面用大括号{}
        {
            thisindex=i;      //把i赋值给thisindex
            break;            //找到相等的数,打印下标,跳出循环
        }
    }
    if(thisindex<0) 
    {
        printf("%d isn't  in the array.\n",n);
    }
    else
    {
        printf("%d is in the array, it's index is %d.\n",n,thisindex);  
    }
}

运行结果:

100↙
100 is  in the array, it's index is 7.

28↙
28 isn't  in the array.

注意:数组下标的取值范围是非负数,当 thisindex >= 0 时,该数字在数组中,当 thisindex < 0 时,该数字不在数组中,所以在定义 thisindex 变量时,必须将其初始化为一个负数。

对有序数组的查询

查询无序数组需要遍历数组中的所有元素,而查询有序数组只需要遍历其中一部分元素。

例如有一个长度为 10 的整型数组,它所包含的元素按照从小到大的顺序(升序)排列,假设比较到第 4 个元素时发现它的值大于输入的数字,那么剩下的 5 个元素就没必要再比较了,肯定也大于输入的数字,这样就减少了循环的次数,提高了执行效率。

#include<stdio.h>
int main()
{
    int i,n,thisindex=-1;
    int a[10]={1,10,6,296,177,23,0,100,34,999};
    scanf("%d",&n);
    for(i=0;i<10;i++)
    {
        if(a[i]==n)           //if括号中要用==,且后面用大括号{}
        {
            thisindex=i;      //把i赋值给thisindex
            break;            //找到相等的数,打印下标,跳出循环
        }
        else if(a[i]>n) break;
    }
    if(thisindex<0) 
    {
        printf("%d isn't  in the array.\n",n);
    }
    else
    {
        printf("%d is in the array, it's index is %d.\n",n,thisindex);  
    }
}

6.4C语言字符数组和字符串

用来存放字符的数组称为字符数组,例如:

  1. char a[10]; //一维字符数组
  2. char b[5][10]; //二维字符数组
  3. char c[20]={'c', ' ', 'p', 'r', 'o', 'g', 'r', 'a','m'}; // 给部分数组元素赋值
  4. char d[ ]={'c', ' ', 'p', 'r', 'o', 'g', 'r', 'a', 'm' }; //对全体元素赋值时可以省去长度

字符数组实际上是一系列字符的集合,也就是字符串(String)。在C语言中,没有专门的字符串变量,没有string类型,通常就用一个字符数组来存放一个字符串。

C语言规定,可以将字符串直接赋值给字符数组,例如:

              char str[30] = {"wlacm"};

     为了方便,也可以不指定数组长度,从而写作:

     char str[] = {"wlacm"}; 

 字符数组只有在定义时才能将整个字符串一次性地赋值给它,一旦定义完了,就只能一个字符一个字符地赋值了。

数组第 0 个元素为'w',第 1 个元素为'l',第6 个元素为'.',后面的元素以此类推。


字符串结束标志(划重点)

在C语言中,字符串总是以'\0'作为结尾,所以'\0'也被称为字符串结束标志,或者字符串结束符。

C语言在处理字符串时,会从前往后逐个扫描字符,一旦遇到'\0'就认为到达了字符串的末尾,就结束处理。'\0'至关重要,没有'\0'就意味着永远也到达不了字符串的结尾。

下图演示了"C program"在内存中的存储情形:

" "包围的字符串会自动在末尾添加'\0'。例如,"C program"从表面看起来只包含了 9 个字符,其实不然,C语言会在最后隐式地添加一个'\0',这个过程是在后台默默地进行的,所以我们感受不到。

当用字符数组存储字符串时,要特别注意'\0',要为'\0'留个位置;这意味着,字符数组的长度至少要比字符串的长度大 1。请看下面的例子:

 char str[7] = "abc123";

 需要注意的是,逐个字符地给数组赋值并不会自动添加'\0',例如:

char str[] = {'a', 'b', 'c'};

数组 str 的长度为 3,而不是 4,因为最后没有'\0'

 接下来没看懂的。。。

要想避免这些问题也很容易,在字符串的最后手动添加'\0'即可。修改上面的代码,在循环结束后添加'\0'

#include <stdio.h>
int main(){
    char str[30];
    char c;
    int i;
    for(c=65,i=0; c<=90; c++,i++){
        str[i] = c;
    }
    str[i] = 0;             //此处为添加的代码,也可以写作 str[i] = '\0';
    printf("%s\n", str);
   
    return 0;
}

第 9 行为新添加的代码,它让字符串能够正常结束。根据 ASCII 码表,字符'\0'的编码值就是 0。

 但是,这样的写法貌似有点业余,或者说不够简洁,更加专业的做法是将数组的所有元素都初始化为“零”值,这样才能够从根本上避免问题。再次修改上面的代码:

#include <stdio.h>
int main(){
    char str[30] = {0};  //将所有元素都初始化为 0,或者说 '\0'
    char c;
    int i;
    for(c=65,i=0; c<=90; c++,i++){
        str[i] = c;
    }
    printf("%s\n", str);
   
    return 0;
}


字符串长度

在C语言中,我们使用string.h头文件中的 strlen() 函数来求字符串的长度

#include <stdio.h>
#include <string.h>  //记得引入该头文件
int main(){
    char str[] = "http://c.biancheng/c/";
    long len = strlen(str);
    printf("The lenth of the string is %ld.\n", len);
   
    return 0;
}

C语言字符串的输入和输出

字符串的输出

  • puts():输出字符串并自动换行,该函数只能输出字符串。
  • printf():通过格式控制符 %s输出字符串,不能自动换行
#include <stdio.h>
int main(){
    char str[] = "I.Love.You";
    printf("%s\n", str);                            //通过字符串名字输出
    printf("%s\n", "I.Love.You");       //直接输出
    puts(str);                                      //通过字符串名字输出
    puts("I.Love.You");                 //直接输出
    return 0;
}

输出字符串时只需要给出名字,不能带后边的[ ]

字符串的输入

  • scanf():通过格式控制符%s输入字符串。
  • gets():直接输入字符串,并且只能输入字符串。

scanf() 和 gets() 是有区别的:

  • scanf() 读取字符串时以空格为分隔,遇到空格就认为当前字符串结束了,所以***无法读取含有空格的字符串。***
  • gets() 认为空格也是字符串的一部分,只有遇到回车键时才认为字符串输入结束,所以,不管输入了多少个空格,只要不按下回车键,对 gets() 来说就是一个完整的字符串。换句话说,***gets() 用来读取一整行字符串。***
#include <stdio.h>
int main()
{

    char str1[30] = {0};
    char str2[30] = {0};
    
    //gets() 用法
    printf("Input a string: ");
    gets(str1);

    //scanf() 用法
    printf("Input a string: ");
    scanf("%s", str2);    //注意这行scanf()

   
    printf("str1: %s\n", str1);
    printf("str2: %s\n", str2);
   
    return 0;
}

就目前学到的知识而言,int、char、float 等类型的变量用于 scanf() 时都要在前面添加&,而数组或者字符串用于 scanf() 时不用添加&,它们本身就会转换为地址。


C语言字符串处理函数

C语言提供了丰富的字符串处理函数,可以对字符串进行输入、输出、合并、修改、比较、转换、复制、搜索等操作,使用这些现成的函数可以大大减轻我们的编程负担。

string.h是一个专门用来处理字符串的头文件


字符串连接函数 strcat()

strcat 是 string catenate 的缩写,意思是把两个字符串拼接在一起,语法格式为:

strcat(arrayName1, arrayName2);

strcat() 将把 arrayName2 连接到 arrayName1 后面,并删除原来 arrayName1 最后的结束标志'\0'这意味着,arrayName1 必须足够长,要能够同时容纳 arrayName1 和 arrayName2,否则会越界(超出范围)。

strcat() 的返回值为 arrayName1 的地址。

#include<stdio.h>
#include<string.h>
int main()
{
    char s1[100]="AC ";
    char s2[100];
    gets(s2);
    strcat(s1,s2);
    puts(s1);
    return 0;
}

输入:

is not the true happiness.

输出:

AC is not the true happiness.


字符串复制函数 strcpy()

strcpy 是 string copy 的缩写,意思是字符串复制,也即将字符串从一个地方复制到另外一个地方,语法格式为:

strcpy(arrayName1, arrayName2);

strcpy() 会把 arrayName2 中的字符串拷贝到 arrayName1 中,字符串结束标志'\0'也一同拷贝

strcpy() 要求 arrayName1 要有足够的长度,否则不能全部装入所拷贝的字符串。请看下面的例子:

#include <stdio.h>
#include <string.h>
int main(){
    char str1[50] = "AC不是真正的快乐。";
    char str2[50] = "AC is not the true happiness.";
    strcpy(str1, str2);
    printf("%s\n", str1);
    return 0;
}

***字符串比较函数 strcmp()

strcmp 是 string compare 的缩写,意思是字符串比较,语法格式为:

strcmp(arrayName1, arrayName2);

字符本身没有大小之分,strcmp() 以各个字符对应的 ASCII 码值进行比较。strcmp() 从两个字符串的第 0 个字符开始比较,如果它们相等,就继续比较下一个字符,直到遇见不同的字符,或者到字符串的末尾。

返回值:若 arrayName1 和 arrayName2 相同,则返回0;若 arrayName1 大于 arrayName2,则返回大于 0 的值;若 arrayName1 小于 arrayName2,则返回小于0 的值。

对4组字符串进行比较:

#include <stdio.h>
#include <string.h>
int main(){
    char a[] = "aBcDeF";
    char b[] = "AbCdEf";
    char c[] = "aacdef";
    char d[] = "aBcDeF";
    printf("a VS b: %d\n", strcmp(a, b));
    printf("a VS c: %d\n", strcmp(a, c));
    printf("a VS d: %d\n", strcmp(a, d));
   
    return 0;
}

运行结果:

a VS b: 32
a VS c: -31
a VS d: 0

6.5排序问题

对数组元素进行排序的方法有很多种,比如冒泡排序、归并排序、选择排序、插入排序、快速排序等,其中最经典最需要掌握的是「冒泡排序」

以从小到大排序为例,冒泡排序的整体思想是这样的:

  • 从数组头部开始,不断比较相邻的两个元素的大小,让较大的元素逐渐往后移动(交换两个元素的值),直到数组的末尾。经过第一轮的比较,就可以找到最大的元素,并将它移动到最后一个位置。
  • 第一轮结束后,继续第二轮。仍然从数组头部开始比较,让较大的元素逐渐往后移动,直到数组的倒数第二个元素为止。经过第二轮的比较,就可以找到次大的元素,并将它放到倒数第二个位置。
  • 以此类推,进行 n-1(n 为数组长度)轮“冒泡”后,就可以将所有的元素都排列好。


整个排序过程就好像气泡不断从水里冒出来,最大的先出来,次大的第二出来,最小的最后出来,所以将这种排序方式称为冒泡排序(Bubble Sort)。

经典例题:排序;

题目描述:

输入N个数据(整数,至少1个,但不多于20个),按照升序输出,数据项之间有一个空格

输入:

输入中包含多个正整数,读取数据,直到输入结束(至少1个,但不多于20个)

样例输入:

100

8 5

10 80 24

样例输出:

100

5 8

10 24 80

选择排序法 

#include<stdio.h>
int main()
{
    int i,j,t,n,a[20];
    
    for(i=0;;i++)
    {
        if(scanf("%d",&a[i])!=1) break;
    }
    n=i;                    //读取数组时要令n有范围
    
    for(i=0;i<n;i++)
    {
        for(j=i+1;j<n;j++)  //
        {
            if(a[i]>a[j])     
            {t=a[i];a[i]=a[j];a[j]=t;}
        }
        printf("%d ",a[i]);
    }
}

冒泡排序法 

    a[i]             a[j]

(10               15     )|      8           7          6          12          9

i=0,j=1,a[0]=10与a[1]=15两个相邻的数先进行比较,不用交换

                   a[i]         a[j]

10         |(  8            15  )|       7          6          12          9

i=1,j=2,a[1]=15与a[2]=8进行比较,需要引入新变量t来达到交换的目的

以此类推

完成了第一轮

10        8        7       6        12        9       15

第二轮

8 7 6 10 9 12 15

第三轮

7 6 8 9 10 12 15

第四轮

6 7 8 9 10 12 15

#include<stdio.h>
int main()
{
    int i,j,t,n,a[20];
    
    for(i=0; ;i++)
    {
        if(scanf("%d",&a[i])!=1) break;
    }
    n=i;                    //读取数组时要令n有范围
    
    for(i=1;i<n;i++)
    {
        for(j=0;j<n-i;j++)  
        {
            if(a[j]>a[j+1])     
            {t=a[j];a[j]=a[j+1];a[j+1]=t;}
		}
	}
	
	
	for(j=0;j<n;j++)
	{
			  printf("%d ",a[j]);
	}
}

二、典型例题

主要是本学年做过的一些典型题,比较有借鉴和反思的地方。


一维数组

溢出,查数,排序(主要都与循环结构搭配)

统计数据的个数

题目描述:输入一组数据(整数,至少1个,但不多于20个),按顺序输出这组数据,并在数据之前输出数据的个数

#include<stdio.h>
int main()
{
    int i,n=20,a[20];              //n=20,a[20]只是定义时随意取值,不固定;
    for(i=0;i<=n-1;i++)
    {
        
        if(scanf("%d",&a[i])!=1)   //if(scanf("%d",&n)==1)说明成功读入了n的值; 
        break;                     //用户端再输入完数组后输入字符显然不能成功读取时,                         
                                   //便会结束循环,防止数组溢出;
    }
    n=i;                           //把此时结束循环时的i值赋给n,即要求的数据个数;
    printf("%d",n);                //立刻输出而不能让n进入数组输出的循环结构中;
    for(i=0;i<=n-1;i++)
    {
        printf(" %d",a[i]);        //注意输出数组时同样需要循环;
    }
}

输入:1 2 3 4 5aaaaa 

输出:5 1 2 3 4 5 

for(i=0;i<=n-1;i++)
    {    
     if(scanf("%d",&a[i])!=1)    如果没有正确输入一个整型数给数组中的一个元素.
        break;                                                   就会结束循环。                                       
    }


逆序输出数据

输入一组数据(整数,不多于20个),逆序输出这组数据

#include<stdio.h>
int main()
{
    int i,n=20,a[20],k;
    scanf("%d",&k);
    for(i=0;i<=n-1;i++)
    {
        if(scanf("%d",&a[i])!=1) break;
    }
    n=i;                                       //这个条件不能少!!!
    for(i=n-1;i>=0;i--)
    {
        printf(" %d",a[i]);
    }
}

 个人理解:n=i 这一行读取了输入的数组的数据长度,进而影响下面倒序输出数组时循环的条件。


 成绩统计:低于平均值的人数与分数

输入一组成绩(整数,介于[0,100]之间,至少1个,但不多于20个),输出低于平均值的人数与分数

#include<stdio.h>
int main()
{
    int i,n=20,a[20],s=0;
    float average;
    for(i=0;i<=n-1;i++)
    {
        if(scanf("%d",&a[i])!=1) break;
        s=s+a[i];
    }
    n=i;
    average=(s*(1.0)/n);
    int k=0,m;
    for(i=0;i<=n-1;i++)
    {
        if(a[i]<average)
        {
            k=k+1;
        }
    }
    printf("%d",k);
}

 我的错误代码只算出了低于平均值的人数,分数没有搞定。

#include<stdio.h>
int main()
{
	int i,n,a[100],s=0,k;
	for(i=0;;i++)
	{
		if(scanf("%d",&a[i])!= 1) break;
		s=s+a[i];
	}
	n=i;
	k=0;
	for(i=0;i<=n-1;i=i+1)
	{
	    if(a[i]<1.0*s/n) k=k+1;
	}
	    printf("%d",k);
	for(i=0;i<=n-1;i=i+1)
	{
	    if(a[i]<1.0*s/n)
		 printf(" %d",a[i]);
	}
	
} 

 有被自己蠢到😂

#include<stdio.h>
int main()
{
    int i,n=20,a[20],s=0;
    float average;
    for(i=0;i<=n-1;i++)
    {
        if(scanf("%d",&a[i])!=1) break;
        s=s+a[i];
    }
    n=i;
    average=(s*(1.0)/n);
    int k=0,m;
    for(i=0;i<=n-1;i++)
    {
        if(a[i]<average)
        {
            k=k+1;
        }
    }
    printf("%d",k);
    for(i=0;i<=n-1;i++)
    {
        if(a[i]<average)
        {
         printf(" %d",a[i]);
        }
    }
}

 成绩统计:最小值、最大值、平均值与均方差

输入一组成绩(整数,介于[0,100]之间,至少1个,但不多于20个),计算并输出这组成绩的最小值、最大值、平均值(一位小数)与均方差(两位小数),数据之间空一格

注:均方差的计算公式为: 

,其中μ为数据的平均值

均方差能够体现各数据项与平均值的偏差程度

例如,一组学生的成绩:80、82、84、86,平均值为83.0
方差D=[(80-83)2+(82-83)2+(84-83)2+(86-83)2]/4=5,均方差σ=2.24(方差D的平方根)

而另一组学生的成绩:82、82、83、85,平均值也为83.0
但是方差D=[(82-83)2+(82-83)2+(83-83)2+(85-83)2]/4=1.5,均方差σ=1.22
说明这一组学生的成绩比较稳定,与平均值的偏差较小

#include<stdio.h>
#include<math.h>
int main()
{
    int i,n=20,a[20],s=0;
    float u;
    for(i=0;i<n;i++)
    {
        if(scanf("%d",&a[i])!=1) break;
         s=s+a[i];
    }
    n=i;
    
    u=s*(1.0)/n;
    printf("%d %d %0.1f",a[0],a[n-1],u);
    float o,m;
    int p=0;
    for(i=0;i<n;i++)
    {
        m=(a[i]-u)*(a[i]-u);
        p=p+m;
    }
    o=sqrt((p*1.0)/n);
    printf(" %0.2f",o);
}

小KK的环(竞赛题)

题目描述:

小KK是一个玩圆环的高手。这天,小KK买回来了3个完全相同的圆环,小KK发现这三个圆环通过任意的摆放形成的图形的面积是不同的。小KK决定通过摆出不同的形状的图形来算出图形的面积。请你编写一个程序帮助小KK计算出图形的面积。

以下是三个圆环的其中七种摆放方式,我们将其分别从1~7编号:

 输入:

给定一个T代表样例的个数,接下来T行每行给出r,n,s,分别为圆的半径,相交类型的编号(1~7)以及任意两圆相交部分的面积,6号图(三圆相交)会额外给出公共部分的面积p。

PS:请注意π请使用3.14进行计算

输出:

 对于每一组输入样例,按照样例格式输出,结果只保留整数部分,样例编号从1开始。

 样例输入:

3
2 4 12.56
6.5 6 5 2.1
3 7 2

 样例输出:

#Case1 : 25
#Case2 : 385
#Case3 : 54


二维数组

点阵字符

题目描述:

点阵字符是计算机系统中对文字(包括字母、数字、标点符号)字型信息的一种存储方式,其中每个字形都以一组二维像素信息表示,文字笔画经过的区域存储为1,否则存储为0 

 输入:

输入一个正整数N(N≤24)以及由数值0和1构成的NxN点阵。

 输出:

输出对应的字符。

样例输入:

8
0   0   1   1   1   0   0   0
0   1   1   0   1   1   0   0
1   1   0   0   0   1   1   0
1   1   0   0   0   1   1   0
1   1   1   1   1   1   1   0
1   1   0   0   0   1   1   0
1   1   0   0   0   1   1   0
0   0   0   0   0   0   0   0

 样例输出: 

    ooo  
  oo  oo 
oo      oo
oo      oo
ooooooo
oo      oo
oo      oo

 又没复盘出来

#include<stdio.h>
int main()
{
    int a[24][24],n;
    scanf("%d\n",&n);
    
    int i,j;
    scanf("%d",a[i][j]);
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            if(a[i][j]==0) printf(" ");
            if(a[i][j]==1) printf("o");
        }
    }
}

正解

#include<stdio.h>
int main()
{
	int i,j,n,a[24][24];
	scanf("%d",&n);
	for(i=0;i<=n-1;i=i+1)
	{
	  for(j=0;j<=n-1;j=j+1)
	  {
	    scanf("%d",&a[i][j]);
	  }
	}
			
	for(i=0;i<=n-1;i=i+1)
	{
	  for(j=0;j<=n-1;j=j+1)
	  {
	 if(a[i][j]==1) printf("o");
	 else printf(" ");
	 printf("\n");
	  }
	}
}


 矩阵转置

题目描述:

输入一个矩阵,共M行N列(1≤M,N≤10),矩阵中的每个元素均为整数,将其转置后输出

输入:

输入格式为:两个正整数M,N,之后共有M行N列的整数值

输出: 

矩阵转置之后的结果,共N行M列的整数值,每个整数值之前有一个空格,每行结尾有一个\n

 样例输入:

2 3
1 2 3
4 5 6

3 2
1 4
2 5
3 6

 样例输出:

 1 4
 2 5
 3 6

 1 2 3
 4 5 6

#include<stdio.h>
int main()
{
	int i,j,m,n,a[24][24];
	scanf("%d %d",&m,&n);
	for(i=0;i<=m-1;i=i+1)
	{
	  for(j=0;j<=n-1;j=j+1)
	  {
	    scanf("%d",&a[i][j]);
	  }
	}
	for(j=0;j<=n-1;j=j+1)
	{
	  for(i=0;i<=m-1;i=i+1)
	  {
        printf(" %d",a[i][j]);
	  }
	 printf("\n");
	}
}

杨辉三角

#include<stdio.h>
int main()
{
    int a[30][30],i,j,n;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        a[0][0]=1;
        a[i][i]=1;
        for(j=0;j<n;j++)
        {
          if(i>=j) a[i][j]=a[i-1][j]+a[i-1][j-1];
          else printf(" "); 
        }
    }
    
    
     for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
           printf("%d",a[i][j]);
        }
        printf("\n");
    }
}

 有错误      if(i>=j) a[i][j]=a[i-1][j]+a[i-1][j-1];   ???

#include<stdio.h>
int main()
{
	int n,i,j,a[40][40];
	scanf("%d",&n);
	for(i=0;i<=n;i=i+1)
	{
		a[i][0]=1;
		for(j=1;j<=i;j=j+1)
		{
			if(i==j) a[i][j]=1;
			else a[i][j]=a[i-1][j]+a[i-1][j-1];
		}
	}
	for(i=0;i<=n;i=i+1)
	{
		for(j=0;j<=i;j=j+1)
		printf("%d ",a[i][j]);
		printf("\n");
	}
}

这里for循环中的条件范围值得深究

#include<stdio.h>
int main()
{
    int i,j,n,a[40][40];
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        for(j=0;j<=i;j++)
        {
            if(j==0||j==i) a[i][j]=1;
            else a[i][j]=a[i-1][j]+a[i-1][j-1];
        }
    }
    
    for(i=0;i<n;i++)
    {
        for(j=0;j<=i;j++)
        {
            printf("%d",a[i][j]);
        }
        printf("\n");
    }
}

    字符串数组

判断回文、排序

字符串倒序输出

题目描述:

输入一个字符串,以换行符号作为结束(字符串长度不超过50)将输入内容倒序输出

样例输入:

flow

样例输出:

wolf

 正解

1.

#include<stdio.h>
#include<string.h>
int main()
{
	char a[100],i,n;
	gets(a);
	n = strlen(a);
	for(i=n-1;i>=0;i=i-1)
	printf("%c",a[i]);
}

 2.


#include<string.h>
#include<stdio.h>
int main()
{
 char s[100];
 int i,n,j;
 gets(s);
 for(i=0; ;i++)
 {
  if(s[i]=='\0')  break;
 }
 n=i;
 for(j=n-1;j>=0;j--)
 {
   printf("%c",s[j]);
 }
 } 

 运行错误或答案错误非正解

#include<stdio.h>
#include<string.h>
int main()
{
    char a[50];
    int n,i,j,t;
    gets(a);
    n=strlen(a);
     for(i=0,j=n-1;i<=j;i++,j--)
    {
    	t=a[i];
    	a[i]=a[j];
    	a[j]=t;
    }
    for(i=0;i<n;i++)
    {
    	 printf("%c",a[i]);
	}
}


#include<stdio.h>
#include<string.h>              //记得引入该头文件
int main()
{
	char a[100],i,n;      
	gets(a);                   // gets()
	n = strlen(a);          
	for(i=n-1;i>=0;i=i-1)
	printf("%c",a[i]);         //     %c
}

最后一行我用%s输出的是一堆数字 

【字符串】回文

题目描述:

输入一行字符串(长度不超过100),判断是否为回文。例如ABA是回文字符串,ABC不是回文字符串。

输入:

键盘输入的一行字符串(没有空格)。不包含结尾的\n

输出:

yes 或 no 表示是否为回文

正解(网上答案)  

#include<stdio.h>
#include<string.h>
int  main(void)
{
	int i,j;
	int len;         //用于记录字符串长度 
	char S1[1005];    
	char S2[1005];

	gets(S1);
	len = strlen(S1);
	for(i=len-1,j=0;i>=0;i--,j++) 
	{
		S2[j] = S1[i];               //将S1逆序赋给S2 
	}
	for(i=0,j=0;i<len;i++,j++)
	{
		if(S1[i]!=S2[i])                   //如果S1正序和逆序不同,则不是回文字符串 
		{
			printf("no");
			break;
		}
		else if(i==len-1)
		{
			printf("yes");
		}
	}
	return 0;
 } 

 答案错误25%

#include<stdio.h>
#include<string.h>
int main()
{
    char s[105];
    gets(s);
    int i,j,n,k=0;
    n=strlen(s);
    for(i=0,j=n-1;i<=j;i++,j--)
    {
        if(s[i]!=s[j]) k=k+1; break;
    }
    if(k==0) printf("yes");
    if(k==1) printf("no");
}

 答案错误25%

 

#include<stdio.h>
#include<string.h>
int main()
{
    char s[105];
    gets(s);
    int i,j,n,k=0;
    n=strlen(s);
    for(i=0,j=n-1;i<=j;i++,j--)
    {
        if(s[i]!=s[j]) k=k+1; break;
    }
    if(k) printf("no");   //啥意思
    else printf("yes");
}

运行错误 50%

#include <stdio.h>
#include <string.h>
int main()
{
char str[50];
int i,n,k=0;
gets(str);
n = strlen(str);
	for (i = 0; i <= n/2; i++ )
	{
		if (str[i] != str[n - 1 - i])
		{
			k=k+1;break;
		}
	}
	if(k==0)  printf("yes");
	if(k==1)  printf("no");
}

 运行错误 50%

#include <stdio.h>
#include <string.h>
int main()
{
    char str[50];
    int i,n;
    gets(str);
    n = strlen(str);
    for (i = 0; i <= n/2; i++ )
    {
        if (str[i] != str[n - 1 - i])
        {
	    printf("no");
        break;
        }
        else
        if (i == n / 2)
        printf("yes");
    }
}


 纠正英文语句中的大小写拼写错误

题目描述:

在书写英文语句时,语句中第一个单词的第一个字母通常需要大写的形式,如 Hello,how are you. 
但在录入英文语句时,有时会出现大小写拼写的错误。 
请编写程序,纠正录入的英文语句中出现的大小写拼写错误(暂不考虑语句中会出现的缩略词语,如IBM、ZWU)

输入:

输入英文语句,以换行符号作为结束(语句长度不超过50,并且第一个单词之前没有空格或其他符号)

输出:

输出正确的书写形式

样例输入:

hello,How are you.

样例输出:

Hello,how are you.

#include<stdio.h>
#include<string.h>
int main()
{
   char a[100];
   gets(a);
   int i,n,m;
   n=strlen(a);
   for(i=0;i<=n-1;i++)
   {
    if(a[0]>=91) a[0]=a[0]-32;
    if(a[i]==44)
    {
        if(a[i+1]<=91&&a[i+1]>=65) a[i+1]=a[i+1]+32;
    }
    printf("%c",a[i]);
   }
}

我们知道,计算机在存储字符时并不是真的要存储字符实体,而是存储该字符在字符集中的编号(也可以叫编码值)。对于 char 类型来说,它实际上存储的就是字符的 ASCII 码。

#include
int main()
{
    char s=44;
    printf("%c",s);
}


输出:

   ,    

大写英文字母:65-90

小写英文字母:97-122

总结

以上就是我所分享的内容,本文仅仅是c语言入门,我也只是计算机小白,希望自己和大家能够在接下来的学习中共同进步,加油。

更多推荐

C语言入门(大一笔记)数组篇