数组学习易错点(仅针对自己)

一、数组元素的定义与引用:

       1.数组下标超过定义范围,编译器不会报错。

int a[5];
a[5]=5;
//不会报错

        2.C90不支持变量(包括常变量)作定义数组空间的量:

const int n=5;
int a[n];
//编译错误

        3.使用a[i+j],a[i++]合法:

int a[100];
int i=0;
while(scanf("%d",&a[i++])!=EOF);
i--;
//可用于逐个输入,并得到元素个数(动态赋值)
//同时我们可以得到数组只能逐个地使用下标变量,而不能一次处理整个数组。

二、数组的初始化:

        初始化赋值的一般形式为:类型说明符 数 组名[常量表达式]={值,值,……,值};

        p.s.可以只给部分元素赋初值,其余的值自动附0。

              只能给元素逐个赋值,不能给数组整 体赋值。

static int a[10]={0,1,2,3,4,5,6,7,8,9};
//相当于a[0]=0;a[1]=1,...,a[9]=9;

static int a[5]={1,2,3,4,5};
//可写为:
static int a[]={1,2,3,4,5};

         1.如果初始化值超过数组的长度,则导致编译 错误:

int a[5]={1,2,3,4,5,6}; 
//编译错

         2.错误点集合

int a[3]={}; //错!不能为空!
int a[]; //错!无初始化不行!
int a[4]={1,,3,4};
//错!前面和中间的初始值不能省略!
int a[]={,1,3,4}; //也是错的

        3、全局数组的声明:

#include <stdio.h>
int x[3]={1,2,3}; //全局数组定义
int main() {
extern int x[]; //全局数组声明
//此时是声明,不必写出数组的大小
printf("%d\n",x[1]);
}
//一直都要小心定义和声明的区别

三、排序:

        simplest strategy:

#include <stdio.h>
int main() {
    int i,j,max,t,a[10]; //数组定义
    printf("\nInput 10 numbers:\n");
    for (i=0;i<10;i++) scanf("%d",&a[i]); //输入
    for (i=0;i<10;i++) {
        for (max=i,j=i+1;j<10;j++)//求最大值(下标)
            if (a[max]<a[j]) max=j;
        if (i!=max) //数组元素位置交换!
            {t=a[i];
             a[i]=a[max];
             a[max]=t;
            }
        printf("%6d",a[i]); //数组输出
    }
}

四、二维数组:

        易错点:

                1.二维数组实际 的硬件存储器是连续编址的,也就是说存储器单元是按一维线性排列。

                2.在C中,二/多维数 组是按行排列的。

1.初始化:

        可按行分段赋值,也可按行连续赋值。如:
        对数组int a[5][3];按行分段赋值可写为:

static int a[5][3]= { {80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85} };
static int a[5][3]= {80,75,92,61,65,71,59,63,70,85,87,90,76, 77,85};

        这两种初始化结果是完全相同的。但后面的这种初始化受到较多的限制,一般只能用于全部元素初始化或前面部分元素的初始化。

        特殊的:

static int a[3][3]= {{1},{2},{3}};
//是对每一行的第一列元素赋值,未赋值的元素取0值。

static int a[3][3]= {1,2,3,4,5,6,7,8,9}; 
//可以写为:
static int a[][3]= {1,2,3,4,5,6,7,8,9};

2.经典例题:求鞍点

五、数组与函数:

//个人认为的最重要的一块知识点。

易错点:

1.虽然不能对数组进行整体的赋值和处理等,可以将整个数组作为参数传递给函数,不 过C不允许函数返回整个数组!

2.C采用传递数组的第1个元素(a[0]) 的地址(值)的方式,这样函数就可以找到整个数组,也就可以访问和处理这个数组。

        p.s.

                1.缺点很明显:函数知道数组的首地 址但不知道数组有多少元素(即:数组长度)

                2.这种处理方式下,实际上主函数和被调用的函数使用的其实是同一个数组,很容易导致被调函数错误修 改这个数组从而影响到主函数        

        解决问题的方法:

                1.主函数和被调 函数使用相同的数组下标最大值;主 函数传数组首地址的同时传给被调函 数该数组元素的个数。

                2.如果不允许被 调函数修改该数组,可以在参数前加 上const修饰符。如果允许修改就不加 const修饰符。

3.当被调函数接受整个数组作为参数传递时要求:

        1.形参和相对应的实参都必须是类型相同的数组

        2.在整个数组作函数参数时所进行的传送只是 数组首地址的传送,也就是把实参数组的首 地址赋予形参数组名

        形参数组名取得该首地址之后,也就等于有了实在的数组。实际 上是形参数组和实参数组为同一数组,共同 拥有一段内存空间

        3.单向性(即无需return):当形参数组发生变化时,实参数组也随之变化。

        4.被调数组在函数的声明形式:

//被调函数的函数声明应该形如:
double average(const int a[N]);
//或者(正常情况下应该使用该格式):
double average(const int a[],int n);
//实际上还可以是(也应该是指针):
double average(const int *a,int n);

        //再次提请注意函数声明、定义和调用之间的区别:调用必须用实在的数组(首)地址

        e.g.

#include<stdio.h>
#define N 3 //数组元素的个数
double average(const int a[N]);
//函数声明:参数为int数组,有N个元素
//功能:计算这N个元素的平均值
int main() {
    int x[N]={1,2,3}; //定义数组
    double ave=average(&x[0]);//调用,此处不用加const
//注意此处有一个取地址符,即让形参获得的是数组的第一个值的地址
    printf("%f\n",ave)
}

                p.s.形参数组和实参数组的长度可以不相 同,因为在调用时,只传送首地址而 不检查形参数组的长度。当形参数组 的长度与实参数组不一致时,虽然不 会出现语法错误(编译能通过)

        5.调用格式:

double ave=average(x);//对
double ave=average(x[N]);
double ave=average(x[N-1]);
double ave=average(x[0,N-1]);
double ave=average(x[0]);
double ave=average(x[]);
double ave=average(&x[0]);//对&x
double ave=average(&x);//对&x==&x[0]

        6.计算数组长度:

int lence=sizeof(x)/sizeof(x[0])

        7.二维数组的传递(极少使用,一般用指针替代):

                合法声明:

int func(int a[3][10]) 
int func(int a[][10])

六、字符与字符串:

字符串:以'\0'结尾的字符数组。

        C语言没有字符串类型,不直接支持字 符串变量的定义和使用。必须使用字 符数组来存放和处理字符串

        用来存放字符的数组称为字符数组。 而字符串是以'\0'结尾的字符数组。 单纯的字符数组一般很少使用。字符 数组一般都是用来存放字符串

        有了'\0'标 志后,就不必再用字符数组的长度来判断字符串的长度

字符数组 

        字符数组也可以是二维或多维数组, 例如:char str[5][10]; 即为二维字符数组(很常用)。str可以 存放5个字符串,每个字符串的长度不 超过9(个字符)

初始化:

初始化比较

//字符数组也允许在类型说明时作初始化赋值。例如:
char c[10]={'C',' ','p','r','o','g','r','a','m','\0'};
//当对全体元素赋初值时也可省去长度说明。例如:
static char c[]={'C',' ','p','r','o','g','r','a','m'}; 
//这时C数组的长度自动定为9
//这2个数组长度不同,只有第1个是字符串

二维字符数组的初始化

char a[][5]={{'B','A','S','I','C',},{'d','B','A','S','E'}};
char a[][5]={"BASIC","dBASE"};
//二者效果相同

初始化的各种方式:

下列三者等价:

char s[]={'C',' ','p','r','o','g','r','a','m','\0'};
char s[]={"C program"};
char s[]="C program";//最常用
//三者等价,后两者系统自动补上'\0'

注意:

这个不是字符串,若以字符串形式输出则出现错误(无标志停止的符号,将继续输出不属于它的范围的内容

#include<stdio.h>
int main() {
char s[]={'P','r','o','g','r','a','m'};
printf("[%s]\n",s);
} 
//输出形如:[Program虉 ]

而特殊情况有

#include <stdio.h>
int main() {
char s1[4]={'a','b','c'};
printf("\"%s\"\t",s1); 
char s2[3]={'a','b','c'};
printf("\"%s\"\n",s2);
}

输出形如下述:

"abc" "abc蘟bc"

s1是字符串,s2不是(原因在于自动赋零机制)

常用的字符串函数:

*应包含<string.h>

字符串输出函数 puts

Ø 格式:puts (字符数组名)

Ø 功能:把字符数组中的字符串输出到 显示器。 即在屏幕上显示该字符串。

Ø puts(s);等价于printf("%s\n",s);

Ø 当需要按一定格式输出时,通常使用 printf函数。

字符串输入函数gets

Ø 格式:gets(字符数组名)

Ø 功能:从标准输入设备键盘上输入一 个字符串。gets函数以作为输 入结束,读入并丢弃,并且自 动在串尾加上'\0',这是与scanf函数 不同的。函数返回字符串的首地址或 NULL。经常被早期的病毒攻击。

字符串连接函数strcat

格式: strcat(字符数组名1,字符数组名2)

Ø 功能:把字符数组2中的字符串连接到 字符数组1中字符串的后面,并删去字 符串1后的串标志“\0”。本函数返回值 是字符数组1的首地址。

Ø 注意:字符数组1必须有足够的长度, 否则结果不可预料。

字符串拷贝函数strcpy

格式: strcpy(字符数组名1,字符数组名2)

Ø 功能:把字符数组2中的字符串拷贝到 字符数组1中(应保证足够长)。串结束 标志“\0”也一同拷贝。字符数组名2也 可以是一个字符串常量。这时相当于 把一个字符串赋予一个字符数组。

Ø C不允许对字符数组直接进行赋值! 

字符串比较函数strcmp,格式: strcmp(字符数组名1,字符数组名2)

Ø 功能:按照ASCII码顺序比较两个数组中的 字符串,并由函数返回值返回比较结果。 字符串1=字符串2,返回值=0; 字符串2>字符串2,返回值>0; 字符串1<字符串2,返回值<0。 具体返回非0值是多少C标准没有规定。

Ø 本函数也可用于比较两个字符串常量,或比 较数组和字符串常量。字符可直接比较!

字符串长度函数strlen(区别sizeof

Ø格式:strlen(字符数组名)

Ø功能:获得字符串的实际长度(不 含字符串结束标志'\0')并作为函 数返回值

Ø注意strlen和sizeof返回值的不同。 前者得到字符串的程度,后者得到 的是数组的长度

#include <stdio.h>
#include <string.h>
int main(){
static char str[]="C language";
unsigned int s,x;
s=sizeof(str);//值为11
x=strlen(str);//值为10
printf("The lenth of the string is %d\n",x);
printf("The size of the string is %d\n",s);
}

字符串大小写转换函数strupr/strlwr

Ø 格式:strupr(字符数组名) strlwr(字符数组名)

Ø 功能:将字符串转换为大(小)写形式

Ø 说明:只转换字符串中出现的小(大) 写字母,不改变其它字符。返回指向 字符串的指针

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值