📌  相关文章
📜  AKTU第一学年第二学期解题纸2015-16 | COMP。系统和C编程| B段

📅  最后修改于: 2021-05-20 08:18:26             🧑  作者: Mango

论文下载链接:论文|第二学期| 2015-16

时间: 3小时
总分数:100

注意:-

  • 共分为三个部分。 A节为20分, B节为50分, C节为30分。
  • 尝试所有问题。每个问题都带有标记。
  • 必要时假定合适的数据。

B节

2.尝试任意五个部分:(10 * 5 = 50)

  1. 空指针有什么特别之处?空指针是没有任何关联数据类型的指针。空指针可以保存任何类型的地址,并且可以将其类型转换为任何类型。
    int a = 10;
    char b = 'x';
      
    void* p = &a; // void pointer holds address of int 'a'
    p = &b; // void pointer holds address of char 'b'
    

    void指针的优点:
    1) malloc()和calloc()返回void *类型,这允许这些函数用于分配任何数据类型的内存(仅由于void *)

    int main(void)
    {
        // Note that malloc() returns void * which can be
        // typecasted to any type like int *, char *, ..
        int* x = malloc(sizeof(int) * n);
    }
    

    请注意,上面的程序在C中编译,但在C++中不编译。在C++中,我们必须将malloc的返回值显式地转换为(int *)。

    2) C中的void指针用于在C中实现泛型函数。例如qsort()中使用的compare函数。

    一些有趣的事实:
    1)无效指针不能被取消引用。例如,以下程序无法编译。

    #include 
    int main()
    {
        int a = 10;
        void* ptr = &a;
        printf("%d", *ptr);
        return 0;
    }
    

    输出:

    Compiler Error: 'void*' is not a pointer-to-object type 

    以下程序可以编译并正常运行。

    #include 
    int main()
    {
        int a = 10;
        void* ptr = &a;
        printf("%d", *(int*)ptr);
        return 0;
    }
    

    输出:

    10

    2) C标准不允许使用带空指针的指针算术。但是,在GNU C中,考虑到void的大小为1是允许的。例如,以下程序在gcc中编译并运行良好。

    #include 
    int main()
    {
        int a[2] = { 1, 2 };
        void* ptr = &a;
        ptr = ptr + sizeof(int);
        printf("%d", *(int*)ptr);
        return 0;
    }
    

    输出:

    2

    请注意,以上程序可能无法在其他编译器中运行。

  2. 参数传递机制是什么意思?参数数据可以通过不同的方法传入和传出方法和函数。让我们假设从另一个函数A()调用了函数B () 。在这种情况下, A被称为“呼叫者函数”,B被称为“被呼叫函数或被调用者函数” 。同样, A发送给B的参数称为实际参数,而B的参数称为形式参数

    参数传递的重要方法

    1. 按值传递:此方法使用模式内语义。对形式参数所做的更改不会传输回调用方。对被调用函数或方法内部的形式参数变量的任何修改仅影响单独的存储位置,并且不会反映在调用环境中的实际参数中。此方法也称为按值调用

      // C program to illustrate
      // call by value
      #include 
        
      void func(int a, int b)
      {
          a += b;
          printf("In func, a = %d b = %d\n", a, b);
      }
      int main(void)
      {
          int x = 5, y = 7;
        
          // Passing parameters
          func(x, y);
          printf("In main, x = %d y = %d\n", x, y);
          return 0;
      }
      

      输出:

      In func, a = 12 b = 7
      In main, x = 5 y = 7
      

      诸如C,C++, Java之类的语言都支持这种类型的参数传递。实际上, Java严格按值调用。
      缺点:

      • 存储分配效率低下
      • 对于对象和数组,复制语义是昂贵的
    2. 通过引用传递(别名):此技术使用输入/输出模式语义。对形式参数所做的更改确实会通过参数传递回传给调用者。形式参数的任何更改都会反映在调用环境中的实际参数中,因为形式参数会收到对实际数据的引用(或指针)。此方法也称为通过引用调用< em> 。该方法在时间和空间上都是有效的。

      // C program to illustrate
      // call by reference
      #include 
        
      void swapnum(int* i, int* j)
      {
          int temp = *i;
          *i = *j;
          *j = temp;
      }
        
      int main(void)
      {
          int a = 10, b = 20;
        
          // passing parameters
          swapnum(&a, &b);
        
          printf("a is %d and b is %d\n", a, b);
          return 0;
      }
      

      输出:

      a is 20 and b is 10
      
  3. 用C编写程序以打印以下模式:
    ABCDEFGFEDCBA
    ABCDEF FEDCBA
    ABCDE   EDCBA
    ABCD     DCBA
    ABC       CBA
    AB         BA
    A           A
    #include 
      
    int main()
    {
      
        char ch = 'A', ch1;
        int i, j, n = 7;
      
        for (int i = 0; i < n; i++) {
            for (int j = 'A'; j < 'A' + (2 * n) - 1; j++) {
                if (j >= ('A' + n - 1) + i)
                    printf("%c",
                           (char)(('A' + n - 1)
                                  - (j % ('A' + n - 1))));
                else if (j <= ('A' + n - 1) - i)
                    printf("%c", (char)j);
                else
                    printf(" ");
            }
            printf("\n");
        }
      
        return 0;
    }
    

    输出:

    ABCDEF FEDCBA
    ABCDE   EDCBA
    ABCD     DCBA
    ABC       CBA
    AB         BA
    A           A
    
  4. 编写程序以检查给定字符是大写,小写还是非字母字符。
    #include 
      
    // Driver Code
    int main()
    {
        char ch;
        int ascii;
      
        // Get the character
        scanf("%c", &ch);
      
        // Get ASCII value of the character
        ascii = ch;
      
        if (ascii >= 65 && ascii <= 91)
            printf("%c is an UpperCase character", ch);
      
        else if (ascii >= 97 && ascii <= 122)
            printf("%c is an LowerCase character", ch);
      
        else
            printf("%c is not an aplhabetic character", ch);
      
        return 0;
    }
    

    输出:

    A is an UpperCase character
    a is an LowerCase character
    0 is not an aplhabetic character
    
  5. if-else-if阶梯有什么缺点? if-else-if梯子

    在这里,用户可以在多个选项中进行选择。 if语句从上至下执行。一旦控制if的条件之一为true,则与if关联的语句将被执行,而梯形图的其余部分将被绕过。如果所有条件都不成立,则将执行最终的else语句。

    语法

    if (condition)
        statement;
    else if (condition)
        statement;
    .
    .
    else
        statement;
    

    如果其他如果梯子

    范例

    // C++ program to illustrate if-else-if ladder
      
    #include 
    using namespace std;
      
    int main()
    {
        int i = 20;
      
        if (i == 10)
            cout << "i is 10";
        else if (i == 15)
            cout << "i is 15";
        else if (i == 20)
            cout << "i is 20";
        else
            cout << "i is not present";
    }
    

    输出:

    i is 20
    

    坏处:

    • if-else-if阶梯很难理解和修改。
    • 随着if-else-if梯形图的长度增加,程序的可读性降低。
    • 在涉及一系列决策的情况下,每个决策或条件可能涉及导致整数值的表达式。在这些情况下,不建议使用if-else-if阶梯。代替该语句,我们使用switch语句。
  6. 递归的原理是什么?详细解释。函数直接或间接调用自身的过程称为递归,而相应的函数称为递归函数。使用递归算法,可以很容易地解决某些问题。此类问题的示例包括河内塔(TOH),有序/预购/后继树遍历,图的DFS等。

    递归的基本条件是什么?
    在递归程序中,提供了基本情况的解决方案,并且以较小的问题表示较大的问题。

    int fact(int n)
    {
        if (n < = 1) // base case
            return 1;
        else    
            return n*fact(n-1);    
    }
    

    在上面的示例中,定义了n <= 1的基本情况,并且可以通过转换为较小的1直到达到基本情况来解决较大的数值。

    如何使用递归解决特定问题?
    这个想法用一个或多个较小的问题表示一个问题,并添加了一个或多个停止递归的基本条件。例如,如果我们知道(n-1)的阶乘,就可以计算阶乘n。阶乘的基本情况为n =0。当n = 0时,我们返回1。

    查找数字阶乘的程序:

    // C program to find factorial of given number
    #include 
      
    // function to find factorial of given number
    unsigned int factorial(unsigned int n)
    {
      
        // Base case
        if (n == 0)
            return 1;
      
        // Recursively call factorial function
        return n * factorial(n - 1);
    }
      
    int main()
    {
      
        int num;
      
        // Ge the number of which
        // factorial is to be calculated
        scanf("%d", &num);
        printf("Enter the number: %d", num);
      
        // Find the factorial
        // and print the result
        printf("\nFactorial of %d is %d",
               num, factorial(num));
      
        return 0;
    }
    

    输出:

    Enter the number: 5
    Factorial of 5 is 120
  7. 描述结构和指针之间的关系自引用结构是具有一个或多个指针的结构,这些指针指向其成员属于同一类型的结构。

    换句话说,指向相同类型结构的结构本质上是自引用的。

    例子:

    struct node {
        int data1;
        char data2;
        struct node* link;
    };
      
    int main()
    {
        struct node ob;
        return 0;
    }
    

    在上面的示例中,“链接”是指向“节点”类型的结构的指针。因此,结构“节点”是一个以“链接”作为引用指针的自引用结构。
    需要考虑的重要一点是,指针应在访问之前正确初始化,因为默认情况下它包含垃圾值。

    自我参照结构的类型

    1. 单链接的自引用结构
    2. 具有多个链接的自引用结构

    具有单链接的自引用结构:这些结构只能具有一个自指针作为其成员。下面的示例将向我们展示如何使用单个链接连接自引用结构的对象并访问相应的数据成员。下图显示了形成的连接。

    #include 
      
    struct node {
        int data1;
        char data2;
        struct node* link;
    };
      
    int main()
    {
        struct node ob1; // Node1
      
        // Intialization
        ob1.link = NULL;
        ob1.data1 = 10;
        ob1.data2 = 20;
      
        struct node ob2; // Node2
      
        // Initialization
        ob2.link = NULL;
        ob2.data1 = 30;
        ob2.data2 = 40;
      
        // Linking ob1 and ob2
        ob1.link = &ob2;
      
        // Accessing data members of  ob2 using ob1
        printf("%d", ob1.link->data1);
        printf("\n%d", ob1.link->data2);
        return 0;
    }
    
    输出:
    30
    40
    


    具有多个链接的
    自引用结构:具有多个链接的自引用结构可以具有多个自指针。使用这些结构可以轻松构造许多复杂的数据结构。这样的结构可以轻松地一次连接到多个节点。以下示例显示了一种这样的结构,其中包含多个链接。

    可以使用下图了解以上示例中的连接。

    #include 
      
    struct node {
        int data;
        struct node* prev_link;
        struct node* next_link;
    };
      
    int main()
    {
        struct node ob1; // Node1
      
        // Intialization
        ob1.prev_link = NULL;
        ob1.next_link = NULL;
        ob1.data = 10;
      
        struct node ob2; // Node2
      
        // Intialization
        ob2.prev_link = NULL;
        ob2.next_link = NULL;
        ob2.data = 20;
      
        struct node ob3; // Node3
      
        // Intialization
        ob3.prev_link = NULL;
        ob3.next_link = NULL;
        ob3.data = 30;
      
        // Forward links
        ob1.next_link = &ob2;
        ob2.next_link = &ob3;
      
        // Backward links
        ob2.prev_link = &ob1;
        ob3.prev_link = &ob2;
      
        // Accessing  data of ob1, ob2 and ob3 by ob1
        printf("%d\t", ob1.data);
        printf("%d\t", ob1.next_link->data);
        printf("%d\n", ob1.next_link->next_link->data);
      
        // Accessing data of ob1, ob2 and ob3 by ob2
        printf("%d\t", ob2.prev_link->data);
        printf("%d\t", ob2.data);
        printf("%d\n", ob2.next_link->data);
      
        // Accessing data of ob1, ob2 and ob3 by ob3
        printf("%d\t", ob3.prev_link->prev_link->data);
        printf("%d\t", ob3.prev_link->data);
        printf("%d", ob3.data);
        return 0;
    }
    
    输出:
    10    20    30
    10    20    30
    10    20    30
    

    在上面的示例中,我们可以看到“ ob1”,“ ob2”和“ ob3”是自引用结构“节点”的三个对象。而且,通过它们的链接将它们连接起来,这样它们中的任何一个都可以轻松访问彼此的数据。这就是自我参照结构的美。可以根据程序员的要求来操纵连接。

    应用范围:
    自我参照结构在创建其他复杂数据结构中非常有用,例如:

    • 链表
    • 堆栈
    • Queue列
    • 树木
    • 图等
  8. 枚举数据类型是什么?详细解释。枚举数据类型:枚举(或枚举)是C语言中用户定义的数据类型。它主要用于将名称分配给整数常量,这些名称使程序易于阅读和维护。

    enum State {Working = 1, Failed = 0}; 

    关键字“ enum”用于在C和C++中声明新的枚举类型。

    以下是枚举声明的示例。

    // The name of enumeration is "flag" and the constant
    // are the values of the flag. By default, the values
    // of the constants are as follows:
    // constant1 = 0, constant2 = 1, constant3 = 2 and 
    // so on.
    enum flag{constant1, constant2, constant3, ....... };
    

    还可以定义enum类型的变量。可以通过两种方式定义它们:

    // In both of the below cases, "day" is 
    // defined as the variable of type week. 
    
    enum week{Mon, Tue, Wed};
    enum week day;
    
    // Or
    
    enum week{Mon, Tue, Wed}day;
    
    // An example program to demonstrate working
    // of enum in C
    #include 
      
    enum week { Mon,
                Tue,
                Wed,
                Thur,
                Fri,
                Sat,
                Sun };
      
    int main()
    {
        enum week day;
        day = Wed;
        printf("%d", day);
        return 0;
    }
    

    输出:

    2
    

    在上面的示例中,我们声明了“ day”作为变量,并且“ Wed”的值分配给了day,即2。因此,结果是打印了2。

    枚举的另一个示例是:

    // Another example program to demonstrate working
    // of enum in C
    #include 
      
    enum year { Jan,
                Feb,
                Mar,
                Apr,
                May,
                Jun,
                Jul,
                Aug,
                Sep,
                Oct,
                Nov,
                Dec };
      
    int main()
    {
        int i;
        for (i = Jan; i <= Dec; i++)
            printf("%d ", i);
      
        return 0;
    }
    

    输出:

    0 1 2 3 4 5 6 7 8 9 10 11
    

    在此示例中,for循环将从i = 0运行到i = 11,因为最初i的值是Jan,即Jan,它是0,Dec的值是11。