C语言数组的应用

一. 一维数组的定义:

数组是由一组同类型变量组成的集合, 一般格式为:

[存储类型]数据类型符 数组变量名[常数表达式];

例如: int arrayInt[10] = {0} ; long arrayLong[10] = {0} ;

注意:

1. 数组成元素大小必须是整型常量表达式, 不能是变量或变量表达式, 因为数组是静态分配内存的, 在编译时就确定了值.

2. int a[4] = {0};

   printf( “%d\n”, sizeof(a ) ) ;   //结果为16.

   ※sizeof的值取决于数组整个的长度.

3. ①#define SIZE 10 ;

     int a[SIZI] = {0} ;     // 编译正确.

   ②const int SIZE 10;

     int a[SIZE] = {0} ;    // 编译正确.

   ③int a = 10 ;

     const int SIZE =a ;   // 到这一步正确.

     int b = [SIZE] ;       // 到这一步错误!!

     原因: SIZE的值是由a来确定的, a是变量, 如果中间有任何代码改变a的值, SIZE就不变得不能确定了.

4. 下标:

   访问数组中的特定元素是通过访问下标来实现的, 如:

    int a[n] = {0} ;

        下标为0到( n-1 ). 图例:

        int a[3 ] ={ 10, 20, 30 } ;

       a[0] = 10 ;

       b[1] = 20 ;

       c[2] = 30 ;

        下标为:

10

20

30

             0      1    2

     5. 访问越界:

         在访问数组元素时, 要保证下标值在指订的范围内, 如果超出范围, 编译器不会报错, 但运行的结果不可预知(特别要注意), 例:

      int array[3] = {0} ;

      a[3] =10 ;    //越界, 下标范围为0到2.

※ 第一个数组元素的地址是数组所占内存块的首地址.

 

二. 数组的初始化:

定义数组时, 可以提供一组用逗号隔开的初始值, 用大括号括起来:

int array[3] = { 1,2, 3 } ;

注意:

①. 初始值的个数不能多于数组个数.

          int array[4] = { 1, 2, 3, 4, 5 }     //  错误.

      ②. 中间的数组元素值不能被省略:

          int array[4] = { 1, 2, , 4 } ;      // 错误.

          int array[4] = { 1, 2, 0, 4 } ;     //  正确.

      ③. 当初始化数组个数少于数组元素个数时, 剩余的元素自动为0:

           int array[4] = { 1 } ;

          相当于

int array[4] = { 1,0, 0, 0 } ;

           ④. 如果写int array[] = { 1,2, 3 } , 编译时默认数组a范围为3

              int a[] = { 0} ;            //  报错.

                因为之后不能赋值  a[1] = 10 ;

⑤. 比较  int a[1] = { 0 } ; 和  int a = 0 ;

    1. 赋值:   a[0] = 10 ;         a = 10 ;

    2. 内存都是4字节.

三. 数组的赋值:

    数组间不能直接赋值, 只能一个个赋值, 如:

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

    int b[3] = { 0 } ;

    b = a ;          // 错误!!

    for( i = 0 ; i < 3 ; ++i )

    {

      b[i] =a[i] ;

    }             // 正确!!

    如果要对一组长度较长的有规律的数组赋值, 每一个数组元素都列出来的话太麻烦, 例如要对int a[10]赋值, 赋成

 inta[10]={10, 20, 30, 40, 50, 60, 70, 80, 90, 100};

10个数都列出来赋值的话就太多了. 可以用条件表达式:

    int a[10] = {0} ;

    int i = 0 ;

    for( i = 0 ; i < 10 ; ++i )

    {

      a[i] =10 * ( i + 1 ) ;

    }

四. 二维数组:

1. 定义: 有两个下标的数组称为二维数组, 第一个下标表示该数据所在的行, 第二个下标表示所在列, 一般形式为:

int a[m][n] ;  

它表示定义一个有m行n列, 称为m*n的数组, 有数据m*n个.

2. 二维数组的初始化:

   有两种方式:

   ①. int a[3][2] = { 10, 20, 30, 40, 50, 60 } ;

   ②. int a[3][2] = { { 10, 20 },

                     { 30, 40 },

                     { 50, 60 } } ;                  

   ※ 无论用的是哪种初始化方式, 访问数组元素时的方式都通用.

举例:

int a[3][2] = { 10,20, 30, 40, 50, 60 } ;

①. 逻辑结构:

10

20

30

40

50

60

②. 存储结构:

10

20

30

40

50

60

如果要访问40: ①的方式为: a[1][1].

               ②的方式为: a[0][3].

※ 在逻辑结构中, 某些越界的下标方法也是正确可行的, 例:

如果要访问50: a[2][0].(正常方式)

              a[0][4].(越界方式: 由于int a只有2列, 从0行开始算起的话, 10的下标就为0, 20为1, 这列结束后自动转到下列,30为2, 40为3, 50为4)

                      a[1][2].(同理从1行开始算起, 30为0, 40为1, 转到下一列, 50为2)

      3. 字符串二维数组: char sz[3][10] = { "123”, “12" };      // 意义为: 3行字符串, 每行能存10个字符, 包括’\0’.

                            访问方式: sz[0] ;     // 打印的结果为: 123

                                         sz[1] ;     //打印结果为: 12

五. 杂项:

   1. 公式: 从2开始依次往后排列{2,4,6…n}

for( i = 0 ; i <n – 1 ; ++i )

                  {

                    array[i] = i*2 + 2 ;  

                  }

   2. 访问下标后可以直接参与数学运算.

   3. 面试题:

 (1).输出结果是什么?

char str1[] ="abc" ;

char str2[] ="abc" ;

const char str3[] = "abc" ;

const char str4[] = "abc" ;

const char *str5 = "abc" ;

const char *str6 = "abc" ;

char *str7 ="abc" ;

char *str8 ="abc" ;

cout << ( str1 == str2 ) << endl ;    // 输出为0, 因为比的是数组名, 要比值只能用strcmp来比较.

cout << ( str3 == str4 ) << endl ;    // 输出为0. 同上.

cout << ( str5 == str6 ) << endl ;    // 输出为1. 比的是地址.

cout << ( str7 == str8 ) << endl ;    // 输出为1. 同上.

str1, str2,str3, str4是数组变量,它们有各自的内存空间.

而str5, str6,str7, str8是指针,它们指向相同的常量区域。

(2). char* s = "AAA" ;

printf( "%s",s ) ;

s[0] = 'B' ;

printf( "%s",s ) ;

有什么错?

答:"AAA"是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。

const char* s="AAA";

然后又因为是常量,所以对是s[0]的赋值操作是不合法的.

字符串数组

一. 字符串数组的定义及初始化:

   1. 定义: 字符串是存储在内存中的一系列连续的字符, 可以是以在char数组中的形式中出现, 每个字符就是一个字符数组的元素, 例:

char  szName[10] = ”” ;  或  char  szName[10] = {0} ;

这个字符数组占据了10个字节, 但只能存储(n-1)个字符, 因为数组的最后一个要存储’\0’, 用以结束一个字符数组.

   2. 初始化: 字符数组的初始化方式和一维数组的一样, 但每个字符要加单引号或整体加双引号, 例:

char  szName[4] = { ‘A’, ’B’, ’C’ } ;

char  szName[4] = ”ABC” ;          //这种常用.

※ 注意以下几种方式:

①.char  szName[] = ”ABC” ;         //正确!!

②.char  szName[] = ”” ;             //错误!! 因为无法确定数组的大小.

③.char  szName[5] = ”ABCDE” ;     // 错误!!(范围超出, 无地方存储’\0’)

 

二. 字符串的输出:

    1. printf: 和一维数组一样.

2. puts: puts( szName ) ;

   ※ 比较puts 和printf :

      puts(szName ) ;  <==>  printf( “%s\n”,szName ) ;

      总结: puts会自动加回车, 而且puts不限制输出的类型.

3. putchar: 只输出单个字符, 如果想输出字符串的话, 就用循环做, 例:

   char  szName[100] = ”ABCDE” ;

   for( i = 0 ; i < 6 ; ++i )

   {

         putchar(szName[i]);

   }

三. 字符串的输入:

   1.scanf:

      一般格式: scanf( “%s”,szName ) ;

      ①. scanf输入字符串的时候不要加’&’号.

      ②. scanf( “%ns”, szName ) ;

          其中的n表示规定接收字符的数量, 如:

        scanf( “%4s”, szName ) ;     // 只接收输入的前4个字符, 后面再输入其他的也无效.

   2. gets:

      一般格式为: gets( szName) ;  它能接收任何字符或字符串.

   3. getchar:只能输入单个字符, 用法类似putchar,例:

           

   4. getch:只能输入单个字符, 限制输入个数. 一般用于用户名和密码的输入.

      用法: for(i = 0 ; i < 6 ; ++i )

             {

                     nInput[i]= getch() ;   // 回显的结果为*号, 密码只能输入6位.

                    printf( “*” ) ;

}

   ※ 对比scanf, gets, getchar 和getch:

     

格式

scanf

gets

getchar

getch

回显

回显输入

回显输入

回显输入

不回显输入

限制

可不限制也可根据要求限制个数

不限制输入个数

不限制输入个数, 只显示规定长度的元素

限制输入的个数

ESC

不能接收ESC

能接收ESC

不能接收ESC

能接收ESC

回车

能接收回车

能接收回车

能接收回车

能接收回车

空格

不能接收空格

能接收空格

能接收空格

能接收回车

 

四. 字符串处理函数:

字符串标准函数的头文件为:

#include<string.h>

1.   内存赋值函数: memset

可以用于数组的初试化和清理内存, 例:

(1). memset( szName,‘\0’, 100 ) ;    // 表示把数组szName前100位的元素清0.

(2). memset( szName,‘A’, 5 ) ;       // 表示把前数组前5位的元素都替换成A.

(3). memset( szName+5, ‘A’, 5 ) ;    // 表示从数组下标为5的元素开始往后5个元素都替换成A.

(4). int szStr[10]= { 1,2,3 } ;

    memset(szStr, 0, sizeof( szStr ) ) ;  // 表示把str全部元素清0.

2.   字符串拷贝: srtcpy

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

       strcpy(字符数组名, 字符常量);

 ※ 只有上面这两种格式, 整型数组等不可用.

        strncpy( szTemp+x, “ABC” ) ;      // 表示把数组下标为x的元素开始往后按顺序替换成A,B,C.

       注: (1). 被copy者的长度一定要够长, 不然崩溃.

          (2). 对于这样的情况:

A

B

C

D

\0

\0

\0

\0

strcpy(szBuffer, “12” ) ;

替换后打印为12, 因为默认”12”后会跟”\0”(字符串以”\0”结尾), strcpy遇到后打印就会结束, D不会打印出来, 如果用

printf( “%c\n”,szBuffer[3] ) ;

就可以把D打印出来.

             (3). strncpy( str, “12345”,2 ) ;    // 意义: 只复制”12345”的前两个字符给str字符串.

              (4). strncpy(strA+x, strB+y, z ) ; // 意义: 把strB的下标为y之后的z个字符, 复制给strA以下标为x的字符后面去.(包括x.y的元素)

   3. 统计字符串长度: strlen

      格式: strlen(字符串常量);

           strlen(字符数组名);

           返回值为无符号整型.

      工作方式: 检查’\0’, 没遇到就+1, 遇到就结束(返回值不含’\0’).

      strlen( strA+x ) ;  // 意义: 统计strA下标为x开始之后的长度.

   4. 字符串比较: strcmp

      格式: strcmp(字符串1, 字符串2);

      本质: 比较相同位置上的ASCII码值的大小(常用于比较字符串是否相等).

      注: (1). strncmp(“12345”, “123”, 3);    // 意义: 只比较前3个字符是否相等.(千万别漏n)

          想要输出比较结果的话, 要先建一个int然后把strcmp赋值给它, 如:

          int a = 0 ;

          a= strncmp(字符串1, 字符串2);

          printf( “%d\n”, a ) ;

         (2). strncmp( szA+x, szB+y, z ) ;   // 意义: 从数组szA下标为x的元素开始, 和数组szB下标为y的元素开始往后比较, 只比较z个数.(比较的元素包括x,y)

   5. 字符串拼接: strcat

      描述: 将字符串2拷贝到字符串1的尾部.

      格式: strcat(数组, 常量);

           strcat(数组1, 数组2);

           strcat(字符串1, 字符串2);

  ※ strncat(strA, strB+y,z);    // 意义: 把数组strB下标为y的元素开始往后的前z个元素与数组strA拼接(不包括y元素)(strA+x 无效).

   6. 找子串: strstr

        格式: char*findIndex = strstr(字符串1, 字符串2) ; //在字符串1中找到字符串2, 把包括字符串2及之后的元素保留下来.

        例: char* pFindSub = strstr( “ABCDE”, “BC” ) ;

             printf( “%s\n”, pFindSub ) ;   // 结果为: BCDE

五. 杂项:

1. gets和puts的s都是指的字符串, 和%s意义一样.

2. 倒序输出的代码格式:

      char szInput[10] = ”” ;

      int i = 0 ;

      for( i < 9 ; i >= 0 ; --i )

      {

         if( ‘\0’ == szInput[i] )

        {

continue ;         // 红字部分意义为: 如果输出的是结果为\0, 则跳过, 不输出.

}

        putchar( szInput[i] );

       }

        printf( “\n” ) ;

      注: for条件中的”i<9”, 在某些情况下无法使用, 需换成”i=9-1”的形式.  

3. if( 0 == i %5 )

  {

     printf(“\n” ) ;      // 表示每行排5个元素.

   }

 4. 冒泡排序:

void pailie( int array[], int length )

{

    int i = 0;

    int k = 0;

    int temp= 0 ;

    for( k = 0 ; k < length ; ++k )

    {

          for( i = 0 ; i < length-k ; ++i )

          {

               if( array[i] > array[i+1] )

               {

                     temp= array[i+1] ;

                     array[i+1]= array[i] ;

                     array[i]= temp ;

               }

          }

    }

}

5面试题:

           (1).找错:

      voidtest (char* str1) 

{

   char string[10];

         if( strlen( str1 ) <= 10 )     // 不能等于10. strlen运算不包括’\0’

         {

             strcpy(string, str1 );

    }

}


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值