• 【实验5】数组和指针



    实验任务一

    实验源代码:

     1 #include <stdio.h> 
     2 
     3 const int N=3;
     4 int main() {
     5     int a[N] = {1, 2, 3};  
     6     int i;
     7     
     8     printf("通过数组名及下标直接访问数组元素:
    ");
     9     for(i=0; i<N; i++)
    10         printf("%d: %d
    ", &a[i], a[i]);
    11         
    12     printf("通过地址间接访问数组元素:
    ");
    13     for(i=0; i<N; i++)
    14         printf("%d: %d
    ", a+i, *(a+i));
    15 
    16     return 0;
    17 } 

    运行结果:

    有关问题:

    1. 数组元素在内存中是否是连续存放的?

      答:是的,并且在整型数组中间隔四个字节。

    2. 对于数组元素及其地址的访问,以下访问方式是否是等价的?

       a+i和&a[i]都表示数组元素a[i]的地址

      *(a+i)和a[i]都表示数组元素a[i]

      答:是的。


    实验任务二:

    程序源代码:

     1 #include <stdio.h>
     2 const int LINE = 2;
     3 const int COL = 3;
     4 
     5 int main() {
     6     int a[LINE][COL] = {1,2,3,4,5,6};  
     7     int i,j;
     8     
     9     printf("通过数组名及下标直接访问数组元素:
    ");
    10     for(i=0; i<LINE; i++)
    11         for(j=0; j<COL; j++)
    12             printf("%d: %d
    ", &a[i][j], a[i][j]);
    13         
    14     printf("通过地址间接访问数组元素:
    ");
    15     for(i=0; i<LINE; i++)
    16         for(j=0; j<COL; j++)
    17             printf("%d: %d
    ", a[i]+j, *(a[i]+j));
    18     
    19     printf("二维地址中a+i表示的地址:
    ");
    20     for(i=0; i<LINE; i++) 
    21         printf("a + %d: %d
    ", i, a+i);
    22     
    23     return 0;
    24 } 

    运行结果:

    回答问题:

    1. c语言中,二维数组在内存中是否是按行存放的?

      答:是的,并且行的顺序优先于列。

    2. 对于二维数组元素及其地址的访问,以下方式是否是等价的?

      a[i]+j和&a[i][j]都表示二维数组元素a[i][j]的地址

      *(a[i]+j)和a[i][j]都表示二维数组元素a[i][j]

      答:是的。

    3. 对于二维数组a[2][3],以下方式是否是等价的?

      a和&a[0]都表示二维数组第0行的地址

      a+1和&a[1]都表示二维数组第1行的地址

      答:是的。


    实验任务三:

    程序源代码:

     1 // 使用指针变量间接访问一维数组 
     2 #include <stdio.h> 
     3 #include <stdlib.h> 
     4 
     5 const int N=3;
     6 
     7 int main() {
     8     int a[N];
     9     int *p,i;
    10     
    11     // 通过指针变量p,完成数组元素输入
    12     for(p=a; p<a+N; p++)
    13         scanf("%d", p);
    14     
    15     // 过指针变量p,完成数组元素输出
    16     for(p=a; p<a+N; p++)
    17         printf("%d ", *p);
    18     printf("
    ");
    19     
    20     p = a;
    21     //通过指针变量p,完成数组元素输入
    22     for(i=0; i<N; i++)
    23         scanf("%d", p+i); 
    24         
    25     // 通过指针变量p,完成数组元素输出
    26     for(i=0; i<N; i++)
    27         printf("%d ", *(p+i));
    28     printf("
    "); 
    29 
    30     return 0;
    31 }  

    运行结果:

    回答问题:

    1. 程序中,指针变量p在使用时是否指向确定的地址?

      答:是的。在使用时都指向了数组a中的元素的地址。

    2. 程序源码中,line12-line13执行完后,指针变量p指向哪里?line16-line17执行完后,指针变量p 指向哪里?

      答:a[3]; a[3]。

    3. 程序源码中,line22-line27执行完后,指针变量p指向哪里?line26-line27执行完后,指针变量p 指向哪里?

      答:a[3]; a[3]。

    4. 对比line16-line17和line26-line27,体会它们通过指针变量间接访问一维数组时的差异和灵活性。

      答:一个是直接改变指针变量p的指向(l16-l17),另一个是不改变指针变量p的指向的情况下,在输出时改变要输出变量的地址(l26-l27)。


    实验任务四:

    程序源代码:

     1 // 使用指针变量间接访问二维数组 
     2 #include <stdio.h> 
     3 
     4 int main() {
     5     int a[2][3] = {1,2,3,4,5,6};
     6     int i,j;
     7     int *p;  // p是指针变量,存放int型数据的地址 
     8     int (*q)[3]; // q是指针变量,存放包含有3个元素的一维数组的地址
     9     
    10     // 通过指针变量p间接访问,输出二维数组a的元素值
    11     for(p=a[0]; p<a[0]+6; p++)
    12         printf("%d ", *p);
    13     printf("
    ");
    14     
    15     // 通过行指针变量q间接访问,输出二维数组a的元素值 
    16     for(q=a; q<a+2; q++)
    17         for(j=0; j<3; j++)
    18             printf("%d ", *(*q+j));
    19     printf("
    ");
    20     
    21 
    22     return 0;
    23 }  

    运行结果:

    回答问题:

    1. 程序源码中,line11改成如下形式是否可以?

    11  for(p=&a[0][0]; p<&a[0][0] + 6; p++)

      答:可以,都是访问了二维数组a0行中列元素的地址。

    2. 程序源码中,line18中,*q+j和*(*q+j)分别表示什么?

      答:*q+j代表指针q指向的整型数组变量a[0]的地址后整型变量j的值个单元的地址。

        *(*q+j)代表上述地址所存放的整型变量。

    3. 结合line11-line12和line16-line18,理解和体会二维数组中,指向数组元素的指针变量p和指向一维数组的指针变量q的不同。

      答:指针p所指向的变量是二维整型数组a中的列元素,并逐个输出。

        指针q所指向的变量是二维整型数组a中的行元素,再在输出时将指针指向的行元素中的列元素逐个输出。

    4. 基于对这个实验的理解,回答以下问题。

    1 int a[2][3];
    2 int (*q)[3];
    3 int *p;
    4 
    5 p = a[0];
    6 q = a;

    则,以下能够正确表示数组元素a[1][2]地址的有?

    A. &a[1][2]

    B. a[0] + 5

    C. p + 5

    D. *q + 5

    E. *(q+1) + 2

    F. &a[0][0] + 1*3 + 2

    G. a[0] + 1*3 + 2  

      答:A||B||C||D||E||F||G


    实验任务五:

    Q1:

    补足后的程序源代码:

     1 // 练习:使用二分查找,在一组有序元素中查找数据项
     2 //  形参是数组,实参是数组名 
     3 #include  <stdio.h>
     4 
     5 const int N=5;
     6 
     7 int binarySearch(int x[], int n, int item); // 函数声明 
     8 
     9 int main() {
    10     int a[N]={2,7,19,45,66};
    11     int i,index, key;
    12     
    13     printf("数组a中的数据:
    ");
    14     for(i=0;i<N;i++)
    15        printf("%d ",a[i]);
    16     printf("
    ");
    17     
    18     printf("输入待查找的数据项: ");
    19     scanf("%d", &key);
    20     
    21     // 调用函数binarySearch()在数组a中查找指定数据项key,并返回查找结果给index
    22     index=binarySearch(a,N,key);// 补足代码① 
    23     // ×××
    24     
    25     if(index>=0) 
    26         printf("%d在数组中,下标为%d
    ", key, index);
    27     else
    28         printf("%d不在数组中
    ", key); 
    29    
    30    return 0;
    31 }
    32 
    33 //函数功能描述:
    34 //使用二分查找算法在数组x中查找特定值item,数组x大小为n 
    35 // 如果找到,返回其下标 
    36 // 如果没找到,返回-1 
    37 int binarySearch(int x[], int n, int item) {
    38     int low, high, mid;
    39     
    40     low = 0;
    41     high = n-1;
    42     
    43     while(low <= high) {
    44         mid = (low+high)/2;
    45         
    46         if (x[mid]==item/*补足代码②*/)
    47             return mid;
    48         else if(x[mid]>item/*补足代码③*/)
    49             high = mid - 1;
    50         else
    51             low = mid + 1;
    52     }
    53     
    54     return -1;
    55 }

    运行结果:

    Q2:

    补足后的程序源代码:

     1 // 练习:使用二分查找,在一组有序元素中查找数据项
     2 //  形参是指针变量,实参是数组名 
     3 #include  <stdio.h>
     4 
     5 const int N=5;
     6 
     7 int binarySearch(int *x, int n, int item); // 函数声明 
     8 
     9 int main() {
    10     int a[N]={2,7,19,45,66};
    11     int i,index, key;
    12     
    13     printf("数组a中的数据:
    ");
    14     for(i=0;i<N;i++)
    15        printf("%d ",a[i]);
    16     printf("
    ");
    17     
    18     printf("输入待查找的数据项: ");
    19     scanf("%d", &key);
    20     
    21     // 调用函数binarySearch()在数组a中查找指定数据项key,并返回查找结果给index
    22     index=binarySearch(a,N,key); // 补足代码① 
    23     // ×××
    24     
    25     if(index>=0) 
    26         printf("%d在数组中,下标为%d
    ", key, index);
    27     else
    28         printf("%d不在数组中
    ", key); 
    29    
    30    return 0;
    31 }
    32 
    33 //函数功能描述:
    34 //使用二分查找算法在从x中查找特定值item,数组x大小为n 
    35 // 如果找到,返回其下标 
    36 // 如果没找到,返回-1 
    37 int binarySearch(int *x, int n, int item) {
    38     int low, high, mid;
    39     
    40     low = 0;
    41     high = n-1;
    42     
    43     while(low <= high) {
    44         mid = (low+high)/2;
    45         
    46         if ( item == *(x+mid) )
    47             /*补足代码②*/
    48             return mid; 
    49         else if(item < *(x+mid))
    50             /*补足代码③*/
    51             high = mid-1; 
    52         else
    53             /*补足代码③*/
    54             low = mid+1; 
    55     }
    56     
    57     return -1;
    58 }

    运行结果:


    实验任务六:

    补充后的程序源代码:

    
    
     1 // 练习:使用选择法对字符串按字典序排序
     2 #include <stdio.h>
     3 #include<string.h>
     4 const int N = 5;
     5 
     6 void selectSort(char str[][20], int n ); // 函数声明,形参str是二维数组名 
     7 int main() {
     8     char name[][20] = {"Bob", "Bill", "Joseph", "Taylor", "George"};
     9     int i;
    10     
    11     printf("输出初始名单:
    ");
    12     for(i=0; i<N; i++)
    13         printf("%s
    ", name[i]);
    14         
    15     selectSort(name, N);  // 调用选择法对name数组中的字符串排序
    16     
    17     printf("按字典序输出名单:
    ");
    18     for(i=0; i<N; i++)
    19         printf("%s
    ", name[i]);
    20     
    21     return 0;
    22 } 
    23 
    24 // 函数定义
    25 // 函数功能描述:使用选择法对二维数组str中的n个字符串按字典序排序 
    26 void selectSort(char str[][20], int n) {
    27     int i,j,t,k;
    28     char temp[20];
    29     for(i=0; i<n; i++){
    30         k = i;
    31         for(j=i+1; j<n; j++){ 
    32             for(t=0; t<20; t++){
    33                 if(str[j][t]==str[k][t])
    34                     continue;
    35                 if(str[j][t]<str[k][t])
    36                     k = j;
    37                 else
    38                     break;
    39             }
    40         }
    41         if(str[k] != str[i]){
    42             strcpy(temp,str[i]);
    43             strcpy(str[i],str[k]);
    44             strcpy(str[k],temp);
    45         }
    46     }
    47     // 补足代码
    48     // ××× 
    49 }
    
    
    
     

    运行结果:



    实验总结:

    1.第一次充分地实践了新学的指针,它成为了我的新助手,我必须要惯用它。

      但我最重要的发现是在实验里没有体现的:指针可以把实参形参建立起联系。例如在互换两个整型变量的值的void函数中,形参为int是无法直接交换二者并且返回的。这就需要指针,或者叫地址。

      我习惯把指针认为是地址,所以我这么说。在调用时不是以整型变量为实参,而是以其地址为实参,再通过函数交换二者的地址,就做到了交换。原来完全无法解决的函数问题通过指针的方法,我解决了。

    2.目前初学指针,虽没有体会但我明白其有着强大的功能。是有待我日后去发现的。

      曾有言指针是初学者的地狱,是黑客的天堂。它可以访问内存中不能直接访问的内容,而又是相当危险的(这也应证了C语言相比其他语言而言是一门危险的编程语言)。

    3.不懂的地方需要立刻实践,生硬的地方就得多打。这是初学程序员的准则,私以为。


    Thanks for reading.

  • 相关阅读:
    Oracle性能调整ASH,AWR,ADDM
    子网掩码、子网划分详解
    10046事件sql_trace跟踪
    find详解
    date详解
    touch详解
    [转]lsof详解
    iftop、ifstat详解
    iotop详解
    关于Unity的入门游戏飞机大战的开发(上)
  • 原文地址:https://www.cnblogs.com/yinjx/p/14111577.html
Copyright © 2020-2023  润新知