AKTU 1er año Sem 1 Documento resuelto 2017-18 | COMP. SISTEMA Y PROGRAMACION C | Sec C

Enlace de descarga de papel : Papel | Sem 1 | 2017-18

Tecnología B.
(SEM-I) EXAMEN TEÓRICO 2017-18
SISTEMA INFORMÁTICO Y PROGRAMACIÓN EN C

Tiempo: 3 horas
Marcas totales : 100

Nota :-

  • Hay tres secciones. La Sección A lleva 20 puntos, la Sección B lleva 30 puntos y la Sección C lleva 50 puntos.
  • Intenta todas las preguntas. Las marcas se indica frente a cada pregunta.
  • Asumir datos adecuados siempre que sea necesario.

Sección – C

3. Intente dos de los siguientes: (2*5 = 10)

  1. ¿Qué se entiende por clases de almacenamiento de una variable? Defina todos los tipos de clases de almacenamiento con un ejemplo.
    Las clases de almacenamiento se utilizan para describir las características de una variable/función. Estas características incluyen básicamente el alcance, la visibilidad y el tiempo de vida que nos ayudan a rastrear la existencia de una variable en particular durante el tiempo de ejecución de un programa.

    El lenguaje C utiliza 4 clases de almacenamiento , a saber:

    1. auto : esta es la clase de almacenamiento predeterminada para todas las variables declaradas dentro de una función o un bloque. Por lo tanto, la palabra clave auto rara vez se usa al escribir programas en lenguaje C. Solo se puede acceder a las variables automáticas dentro del bloque/función en el que se han declarado y no fuera de ellas (lo que define su alcance). Por supuesto, se puede acceder a estos dentro de bloques anidados dentro del bloque/función principal en el que se declaró la variable automática. Sin embargo, también se puede acceder a ellos fuera de su alcance utilizando el concepto de punteros dado aquí apuntando a la ubicación de memoria exacta donde residen las variables. Se les asigna un valor basura por defecto cada vez que se declaran.
    2. externo: la clase de almacenamiento externo simplemente nos dice que la variable está definida en otro lugar y no dentro del mismo bloque donde se usa. Básicamente, el valor se le asigna en un bloque diferente y esto también se puede sobrescribir/cambiar en un bloque diferente. Entonces, una variable externa no es más que una variable global inicializada con un valor legal donde se declara para usarse en otro lugar. Se puede acceder desde cualquier función/bloque. Además, una variable global normal también se puede convertir en externa colocando la palabra clave ‘externa’ antes de su declaración/definición en cualquier función/bloque. Básicamente, esto significa que no estamos inicializando una nueva variable, sino que estamos usando/accediendo solo a la variable global. El objetivo principal de usar variables externas es que se puede acceder a ellas entre dos archivos diferentes que forman parte de un programa grande.enlace _
    3. static : esta clase de almacenamiento se usa para declarar variables estáticas que se usan popularmente al escribir programas en lenguaje C. ¡Las variables estáticas tienen la propiedad de preservar su valor incluso después de que estén fuera de su alcance! Por lo tanto, las variables estáticas conservan el valor de su último uso en su alcance. Entonces podemos decir que se inicializan solo una vez y existen hasta la finalización del programa. Por lo tanto, no se asigna memoria nueva porque no se vuelven a declarar. Su alcance es local a la función para la que fueron definidos. Se puede acceder a las variables estáticas globales desde cualquier parte del programa. Por defecto, el compilador les asigna el valor 0.
    4. registro : esta clase de almacenamiento declara variables de registro que tienen la misma funcionalidad que las variables automáticas. La única diferencia es que el compilador intenta almacenar estas variables en el registro del microprocesador si se dispone de un registro libre. Esto hace que el uso de las variables de registro sea mucho más rápido que el de las variables almacenadas en la memoria durante el tiempo de ejecución del programa. Si no hay un registro libre disponible, estos se almacenan solo en la memoria. Por lo general, algunas variables a las que se accede con mucha frecuencia en un programa se declaran con la palabra clave de registro, lo que mejora el tiempo de ejecución del programa. Un punto importante e interesante a tener en cuenta aquí es que no podemos obtener la dirección de una variable de registro usando punteros.

    Para especificar la clase de almacenamiento para una variable, se debe seguir la siguiente sintaxis:

    Sintaxis:

    storage_class var_data_type var_name; 

    Las funciones siguen la misma sintaxis dada anteriormente para las variables. Eche un vistazo al siguiente ejemplo de C para obtener más aclaraciones:

    // C program to demonstrate different storage classes
    #include <stdio.h>
      
    // declaring the variable which is to be made extern
    // an intial value can also be initialized to x
    int x;
      
    void autoStorageClass()
    {
      
        printf("\nDemonstrating auto class\n\n");
      
        // declaring an auto variable (simply
        // writing "int a=32;" works as well)
        auto int a = 32;
      
        // printing the auto variable 'a'
        printf("Value of the variable 'a'"
               " declared as auto: %d\n",
               a);
      
        printf("--------------------------------");
    }
      
    void registerStorageClass()
    {
      
        printf("\nDemonstrating register class\n\n");
      
        // declaring a register variable
        register char b = 'G';
      
        // printing the register variable 'b'
        printf("Value of the variable 'b'"
               " declared as register: %d\n",
               b);
      
        printf("--------------------------------");
    }
      
    void externStorageClass()
    {
      
        printf("\nDemonstrating extern class\n\n");
      
        // telling the compiler that the variable
        // z is an extern variable and has been
        // defined elsewhere (above the main
        // function)
        extern int x;
      
        // printing the extern variables 'x'
        printf("Value of the variable 'x'"
               " declared as extern: %d\n",
               x);
      
        // value of extern variable x modified
        x = 2;
      
        // printing the modified values of
        // extern variables 'x'
        printf("Modified value of the variable 'x'"
               " declared as extern: %d\n",
               x);
      
        printf("--------------------------------");
    }
      
    void staticStorageClass()
    {
        int i = 0;
      
        printf("\nDemonstrating static class\n\n");
      
        // using a static variable 'y'
        printf("Declaring 'y' as static inside the loop.\n"
               "But this declaration will occur only"
               " once as 'y' is static.\n"
               "If not, then everytime the value of 'y' "
               "will be the declared value 5"
               " as in the case of variable 'p'\n");
      
        printf("\nLoop started:\n");
      
        for (i = 1; i < 5; i++) {
      
            // Declaring the static variable 'y'
            static int y = 5;
      
            // Declare a non-static variable 'p'
            int p = 10;
      
            // Incrementing the value of y and p by 1
            y++;
            p++;
      
            // printing value of y at each iteration
            printf("\nThe value of 'y', "
                   "declared as static, in %d "
                   "iteration is %d\n",
                   i, y);
      
            // printing value of p at each iteration
            printf("The value of non-static variable 'p', "
                   "in %d iteration is %d\n",
                   i, p);
        }
      
        printf("\nLoop ended:\n");
      
        printf("--------------------------------");
    }
      
    int main()
    {
      
        printf("A program to demonstrate"
               " Storage Classess in C\n\n");
      
        // To demonstrate auto Storage Class
        autoStorageClass();
      
        // To demonstrate register Storage Class
        registerStorageClass();
      
        // To demonstrate extern Storage Class
        externStorageClass();
      
        // To demonstrate static Storage Class
        staticStorageClass();
      
        // exiting
        printf("\n\nStorage Classess demonstrated");
      
        return 0;
    }
      
    // This code is improved by RishabhPrabhu
    Producción:

    Un programa para demostrar Storage Classes en C

    Demostración de clase automática

      Valor de la variable ‘a’ declarada como auto: 32
      ——————————–
      Clase de registro demostrativa

      Valor de la variable ‘b’ declarada como registro: 71
      ——————————–
      Demostración de clase externa

      Valor de la variable ‘x’ declarada como externa: 0
      Valor modificado de la variable ‘x’ declarada como externa: 2
      ——————————–
      Demostración de clase estática

      Declarar ‘y’ como estático dentro del ciclo.
      Pero esta declaración ocurrirá solo una vez ya que ‘y’ es estático.
      Si no, entonces cada vez que el valor de ‘y’ será el valor declarado 5 como en el caso de la variable ‘p’

      Bucle iniciado:

      El valor de ‘y’, declarado como estático, en 1 iteración es 6
      El valor de la variable no estática ‘p’, en 1 iteración es 11

      El valor de ‘y’, declarado como estático, en 2 iteraciones es 7
      El valor de la variable no estática ‘p’, en 2 iteraciones es 11

      El valor de ‘y’, declarado como estático, en 3 iteraciones es 8
      El valor de la variable no estática ‘p’, en 3 iteraciones es 11

      El valor de ‘y’, declarado como estático, en 4 iteraciones es 9
      El valor de la variable no estática ‘p’, en 4 iteraciones es 11

      Bucle terminado:
      ——————————–

      Clases de almacenamiento demostradas

  2. Escriba un programa para multiplicar dos arrays (lea el tamaño y el número de elementos de las arrays desde el teclado).

    // C program to multiply two square arrays.
      
    #include <stdio.h>
      
    const int MAX = 100;
      
    // Function to print Matrix
    void printMatrix(int M[][MAX], int rowSize, int colSize)
    {
        for (int i = 0; i < rowSize; i++) {
            for (int j = 0; j < colSize; j++)
                printf("%d ", M[i][j]);
      
            printf("\n");
        }
    }
      
    // Function to multiply two arrays A[][] and B[][]
    void multiplyMatrix(int row1, int col1, int A[][MAX],
                        int row2, int col2, int B[][MAX])
    {
        int i, j, k;
      
        // Matrix to store the result
        int C[MAX][MAX];
      
        // Check if multiplication is Possible
        if (row2 != col1) {
            printf("Not Possible\n");
            return;
        }
      
        // Multiply the two
        for (i = 0; i < row1; i++) {
            for (j = 0; j < col2; j++) {
                C[i][j] = 0;
                for (k = 0; k < row2; k++)
                    C[i][j] += A[i][k] * B[k][j];
            }
        }
      
        // Print the result
        printf("\nResultant Matrix: \n");
        printMatrix(C, row1, col2);
    }
      
    // Driven Program
    int main()
    {
        int row1, col1, row2, col2, i, j;
        int A[MAX][MAX], B[MAX][MAX];
      
        // Read size of Matrix A from user
        printf("Enter the number of rows of First Matrix: ");
        scanf("%d", &row1);
        printf("%d", row1);
        printf("\nEnter the number of columns of First Matrix: ");
        scanf("%d", &col1);
        printf("%d", col1);
      
        // Read the elements of Matrix A from user
        printf("\nEnter the elements of First Matrix: ");
        for (i = 0; i < row1; i++) {
            for (j = 0; j < col1; j++) {
                printf("\nA[%d][%d]: ", i, j);
                scanf("%d", &A[i][j]);
                printf("%d", A[i][j]);
            }
        }
      
        // Read size of Matrix B from user
        printf("\nEnter the number of rows of Second Matrix: ");
        scanf("%d", &row2);
        printf("%d", row2);
        printf("\nEnter the number of columns of Second Matrix: ");
        scanf("%d", &col2);
        printf("%d", col2);
      
        // Read the elements of Matrix B from user
        printf("\nEnter the elements of First Matrix: ");
        for (i = 0; i < row2; i++) {
            for (j = 0; j < col2; j++) {
                printf("\nB[%d][%d]: ", i, j);
                scanf("%d", &B[i][j]);
                printf("%d", B[i][j]);
            }
        }
      
        // Print the Matrix A
        printf("\n\nFirst Matrix: \n");
        printMatrix(A, row1, col1);
      
        // Print the Matrix B
        printf("\nSecond Matrix: \n");
        printMatrix(B, row2, col2);
      
        // Find the product of the 2 arrays
        multiplyMatrix(row1, col1, A, row2, col2, B);
      
        return 0;
    }
    Producción:

    Enter the number of rows of First Matrix: 2
    Enter the number of columns of First Matrix: 3
    Enter the elements of First Matrix: 
    A[0][0]: 1
    A[0][1]: 2
    A[0][2]: 3
    A[1][0]: 4
    A[1][1]: 5
    A[1][2]: 6
    
    Enter the number of rows of Second Matrix: 3
    Enter the number of columns of Second Matrix: 2
    Enter the elements of First Matrix: 
    B[0][0]: 1
    B[0][1]: 2
    B[1][0]: 3
    B[1][1]: 4
    B[2][0]: 5
    B[2][1]: 6
    
    First Matrix: 
    1 2 3 
    4 5 6 
    
    Second Matrix: 
    1 2 
    3 4 
    5 6 
    
    Resultant Matrix: 
    22 28 
    49 64 
    
  3. Discutir varios tipos de datos usados ​​en C con ejemplos adecuados.
    Cada variable en C tiene un tipo de dato asociado. Cada tipo de datos requiere diferentes cantidades de memoria y tiene algunas operaciones específicas que se pueden realizar sobre él. Vamos a describirlos brevemente uno por uno:

    Los siguientes son ejemplos de algunos tipos de datos muy comunes utilizados en C :

    • char: El tipo de datos más básico en C. Almacena un solo carácter y requiere un solo byte de memoria en casi todos los compiladores.
    • int: como sugiere el nombre, una variable int se usa para almacenar un número entero.
    • float: Se utiliza para almacenar números decimales (números con valor de punto flotante) con precisión simple.
    • double: Se utiliza para almacenar números decimales (números con valor de coma flotante) con doble precisión.

    Los diferentes tipos de datos también tienen diferentes rangos hasta los cuales pueden almacenar números. Estos rangos pueden variar de un compilador a otro. A continuación se muestra una lista de rangos junto con los requisitos de memoria y los especificadores de formato en el compilador gcc de 32 bits.

    Tipo de datos Memoria (bytes) Rango Especificador de formato
    corto 2 -32, 768 a 32, 767 %hd
    int corto sin firmar 2 0 a 65, 535 %hu
    int sin firmar 4 0 a 4, 294, 967, 295 %u
    En t 4 -2, 147, 483, 648 a 2, 147, 483, 647 %d
    largo tiempo 4 -2, 147, 483, 648 a 2, 147, 483, 647 %ld
    int largo sin firmar 4 0 a 4, 294, 967, 295 % lu
    mucho tiempo 8 -(2^63) a (2^63)-1 %lld
    int largo largo sin firmar 8 0 a 18, 446, 744, 073, 709, 551, 615 %llu
    carácter firmado 1 -128 a 127 %C
    carácter sin firmar 1 0 a 255 %C
    flotar 4 %F
    doble 8 %lf
    largo doble 12 %Lf

    Podemos usar el operador sizeof() para verificar el tamaño de una variable.

4. Intente dos de los siguientes: (2*5 = 10)

  1. ¿Qué es la recursividad? Escriba un programa recursivo para encontrar el factorial de un número.

    Recursión : El proceso en el que una función se llama a sí misma directa o indirectamente se llama recursión y la función correspondiente se llama función recursiva. Usando el algoritmo recursivo, ciertos problemas se pueden resolver con bastante facilidad. Ejemplos de tales problemas son Towers of Hanoi (TOH) , Inorder/Preorder/Postorder Tree Traversals , DFS of Graph , etc.

    Condición base en recursión : en el programa recursivo, se proporciona la solución al caso base y la solución del problema más grande se expresa en términos de problemas más pequeños.

    Programa para hallar el factorial de un número:

    // C program to find factorial of given number
    #include <stdio.h>
      
    // 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;
    }

    Producción:

    Enter the number: 5
    Factorial of 5 is 120
  2. Explique la diferencia entre el mecanismo de paso de parámetros llamada por valor y llamada por referencia. ¿Cuál es más eficiente y por qué?
    Hay diferentes formas en las que los datos de los parámetros se pueden pasar dentro y fuera de los métodos y funciones. Supongamos que se llama a una función B() desde otra función A() . En este caso, A se denomina «función de llamador» y B se denomina «función de llamado o función de llamado» . Además, los argumentos que A envía a B se denominan argumentos reales y los parámetros de B se denominan argumentos formales ..

    Terminología

    • Parámetro Formal: Una variable y su tipo tal como aparecen en el prototipo de la función o método.
    • Parámetro real: la variable o expresión correspondiente a un parámetro formal que aparece en la llamada de función o método en el entorno de llamada.
    • Modos:
      • IN: pasa información de la persona que llama a la persona que llama.
      • SALIDA: El destinatario escribe valores en el llamante.
      • ENTRADA/SALIDA: La persona que llama le dice al destinatario el valor de la variable, que puede ser actualizado por el destinatario.

    Métodos importantes de paso de parámetros

    1. Pasar por valor: este método utiliza la semántica en modo . Los cambios realizados en el parámetro formal no se transmiten de vuelta a la persona que llama. Cualquier modificación a la variable de parámetro formal dentro de la función o método llamado afecta solo a la ubicación de almacenamiento separada y no se reflejará en el parámetro real en el entorno de llamada. Este método también se llama llamada por valor .

      // C program to illustrate
      // call by value
      #include <stdio.h>
        
      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;
      }

      Producción:

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

      Los lenguajes como C, C++, Java admiten este tipo de paso de parámetros. Java, de hecho, es estrictamente llamada por valor.
      Deficiencias:

      • Ineficiencia en la asignación de almacenamiento
      • Para objetos y arrays, la semántica de copia es costosa
    2. Pasar por referencia (aliasing): esta técnica utiliza semántica de modo de entrada/salida . Los cambios realizados en el parámetro formal se transmiten de vuelta a la persona que llama a través del paso de parámetros. Cualquier cambio en el parámetro formal se refleja en el parámetro real en el entorno de llamada, ya que el parámetro formal recibe una referencia (o puntero) a los datos reales. Este método también se llama < em>llamada por referencia . Este método es eficiente tanto en el tiempo como en el espacio.

      // C program to illustrate
      // call by reference
      #include <stdio.h>
        
      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;
      }

      Producción:

      a is 20 and b is 10
      

      C y C++ admiten llamadas por valor y llamadas por referencia, mientras que Java no admite llamadas por referencia.
      Deficiencias:

      • Muchos escenarios potenciales pueden ocurrir
      • Los programas son difíciles de entender a veces
  3. Escriba un programa para comprobar si un número es primo o no.

    Programa para comprobar si un número es primo o no:

    // C program to check if a number is prime
      
    #include <stdio.h>
      
    // function check whether a number
    // is prime or not
    int isPrime(int n)
    {
        // Corner case
        if (n <= 1)
            return 0;
      
        // Check from 2 to n-1
        for (int i = 2; i < n; i++)
            if (n % i == 0)
                return 0;
      
        return 1;
    }
      
    // Driver Program
    int main()
    {
      
        int num;
      
        // Ge the number of which
        // is to be checked
        scanf("%d", &num);
        printf("Enter the number: %d", num);
      
        // Check the number
        // and print the result
        printf("\nIs %d prime: ", num);
      
        if (isPrime(num) == 1) {
            printf("Yes");
        }
        else {
            printf("No");
        }
      
        return 0;
    }

    Producción:

    Enter the number: 5
    Is 5 prime: Yes

5. Intente dos de los siguientes: (2*5 = 10)

  1. ¿Qué es Macros? ¿Cómo se sustituye? Escriba la definición de macro con argumentos para el cálculo del área y el perímetro de un círculo y un rectángulo. Guarde estas definiciones de macros en un archivo llamado «areaperi.h». Incluya este archivo en su programa y llame a la definición de macro para calcular el área y el perímetro del círculo.
    1. Creando areaperi.h: Escriba el siguiente código y luego guarde el archivo como areaperi.h . La extensión debe ser .h, lo que indica que es un archivo de encabezado.

      #define AREA_OF_CIRCLE(r) (3.14 * r * r)
      #define PERIMETER_OF_CIRCLE(r) (3.14 * 2 * r)
      #define AREA_OF_RECTANGLE(l, b) (l * b)
      #define AREA_OF_RECTANGLE(l, b) (2 * (l * b))
    2. Incluir el archivo areaperi.h en otro programa: Ahora, necesitamos incluir stdio.h como #include para usar la función printf(). También necesitaremos incluir el archivo de encabezado anterior areaperi.h como #include”areaperi.h” . Los ” ” aquí se utilizan para indicar al preprocesador que busque en la carpeta actual y en la carpeta estándar de todos los archivos de encabezado si no se encuentra en la carpeta actual. Por lo tanto, si desea utilizar corchetes angulares en lugar de «» para incluir su archivo de encabezado, puede guardarlo en la carpeta estándar de archivos de encabezado. Si está utilizando » «, debe asegurarse de que el archivo de encabezado que creó se guarde en la misma carpeta en la que guardará el archivo C usando este archivo de encabezado.
    3. Usando el archivo de encabezado creado:

      // C program to find area and perimeter
      // of circle and rectangle
        
      #include "areaperi.h"
      #include <stdio.h>
        
      int main()
      {
        
          float radius, length, breadth;
        
          // Get the radius of the circle;
          scanf("%f", &radius);
          printf("Enter the radius of the circle: %f", radius);
        
          // This calls AREA_OF_CIRCLE macro
          // written in areaperi.h and
          // therefore no compilation error.
          printf("\nThe area of circle: %f",
                 AREA_OF_CIRCLE(radius));
        
          // This calls PERIMETER_OF_CIRCLE macro
          // written in areaperi.h and
          // therefore no compilation error.
          printf("\nThe perimeter of circle: %f",
                 PERIMETER_OF_CIRCLE(radius));
        
          // Get the length of the Rectangle
          scanf("%f", &length);
          printf("\nEnter the length of the Rectangle: %f", length);
        
          // Get the breadth of the Rectangle
          scanf("%f", &breadth);
          printf("\nEnter the breadth of the Rectangle: %f", breadth);
        
          // This calls AREA_OF_RECTANGLE macro
          // written in areaperi.h and
          // therefore no compilation error.
          printf("\nThe area of Rectangle: %f",
                 AREA_OF_RECTANGLE(length, breadth));
        
          // This calls PERIMETER_OF_CIRCLE macro
          // written in areaperi.h and
          // therefore no compilation error.
          printf("\nThe perimeter of Rectangle: %f",
                 PERIMETER_OF_CIRCLE(length, breadth));
      }

      Producción:

  2. ¿Cuáles son los diferentes modos de apertura de archivos en C? ¿ Escribir un programa para copiar el contenido de un archivo en otro archivo ?
    Modos de apertura de archivos en C:
    • “r” – Archivo de búsquedas. Si el archivo se abre con éxito, fopen() lo carga en la memoria y establece un puntero que apunta al primer carácter que contiene. Si el archivo no se puede abrir, fopen( ) devuelve NULL.
    • “w” – Archivo de búsquedas. Si el archivo existe, su contenido se sobrescribe. Si el archivo no existe, se crea un nuevo archivo. Devuelve NULL, si no puede abrir el archivo.
    • “a” – Archivo de búsquedas. Si el archivo se abre con éxito, fopen() lo carga en la memoria y configura un puntero que apunta al último carácter que contiene. Si el archivo no existe, se crea un nuevo archivo. Devuelve NULL, si no puede abrir el archivo.
    • “r+” – Busca archivo. Si se abre con éxito, fopen() lo carga en la memoria y configura un puntero que apunta al primer carácter que contiene. Devuelve NULL, si no puede abrir el archivo.
    • “w+” – Busca archivos. Si el archivo existe, su contenido se sobrescribe. Si el archivo no existe, se crea un nuevo archivo. Devuelve NULL, si no puede abrir el archivo.
    • “a+” – Busca archivos. Si el archivo se abre con éxito, fopen() lo carga en la memoria y configura un puntero que apunta al último carácter que contiene. Si el archivo no existe, se crea un nuevo archivo. Devuelve NULL, si no puede abrir el archivo.

    Programa en C para copiar el contenido de un archivo a otro archivo:

    #include <stdio.h>
    #include <stdlib.h> // For exit()
      
    int main()
    {
        FILE *fptr1, *fptr2;
        char filename[100], c;
      
        printf("Enter the filename to open for reading \n");
        scanf("%s", filename);
      
        // Open one file for reading
        fptr1 = fopen(filename, "r");
        if (fptr1 == NULL) {
            printf("Cannot open file %s \n", filename);
            exit(0);
        }
      
        printf("Enter the filename to open for writing \n");
        scanf("%s", filename);
      
        // Open another file for writing
        fptr2 = fopen(filename, "w");
        if (fptr2 == NULL) {
            printf("Cannot open file %s \n", filename);
            exit(0);
        }
      
        // Read contents from file
        c = fgetc(fptr1);
        while (c != EOF) {
            fputc(c, fptr2);
            c = fgetc(fptr1);
        }
      
        printf("\nContents copied to %s", filename);
      
        fclose(fptr1);
        fclose(fptr2);
        return 0;
    }

    Producción:

    Enter the filename to open for reading
    a.txt
    Enter the filename to open for writing
    b.txt
    Contents copied to b.txt 
    
  3. Definir estructura con sintaxis . También escriba un programa que compare dos fechas dadas. Para almacenar la estructura de uso de fecha, digamos fecha que contiene tres miembros, a saber, fecha, mes y año. Si las fechas son iguales, muestra el mensaje como «Igual», de lo contrario, «Desigual».

    Una estructura es un tipo de datos definido por el usuario en C/C++. Una estructura crea un tipo de datos que se puede usar para agrupar elementos de tipos posiblemente diferentes en un solo tipo.

    ¿Cómo crear una estructura?
    La palabra clave ‘struct’ se utiliza para crear una estructura. El siguiente es un ejemplo.

    struct address {
        char name[50];
        char street[100];
        char city[50];
        char state[20];
        int pin;
    };

     
    ¿Cómo declarar variables de estructura?
    Una variable de estructura puede declararse con una declaración de estructura o como una declaración separada como los tipos básicos.

    // A variable declaration with structure declaration.
    struct Point {
        int x, y;
    } p1; // The variable p1 is declared with 'Point'
      
    // A variable declaration like basic data types
    struct Point {
        int x, y;
    };
      
    int main()
    {
        struct Point p1; // The variable p1 is declared like a normal variable
    }

    Nota: En C++, la palabra clave struct es opcional antes de la declaración de una variable. En C, es obligatorio.

    Programa que compara dos fechas dadas:

    #include <stdio.h>
      
    // Declaring the structure of Date
    struct Date {
        int date;
        int month;
        int year;
    };
      
    // Driver code
    int main()
    {
        int date1, date2, month1,
            month2, year1, year2;
      
        // Get the first date
        scanf("%d", &date1);
        printf("Enter the first date: %d", date1);
        scanf("%d", &month1);
        printf("\nEnter the first month: %d", month1);
        scanf("%d", &year1);
        printf("\nEnter the first year: %d", year1);
      
        // Initialise the structure with first date
        struct Date Date1 = { date1, month1, year1 };
      
        // Get the second date
        scanf("%d", &date2);
        printf("\nEnter the second date: %d", date2);
        scanf("%d", &month2);
        printf("\nEnter the second month: %d", month2);
        scanf("%d", &year2);
        printf("\nEnter the second year: %d", year2);
      
        // Initialise the structure with first date
        struct Date Date2 = { date2, month2, year2 };
      
        printf("\nThe given dates are: ");
      
        // Comparing the Dates
        if (Date1.date == Date2.date
            && Date1.month == Date2.month
            && Date1.year == Date2.year) {
            printf("Equal");
        }
        else {
            printf("Unequal");
        }
      
        return 0;
    }

    Producción:

    Enter the first date: 10
    Enter the first month: 11
    Enter the first year: 2018
    Enter the second date: 10
    Enter the second month: 11
    Enter the second year: 2018
    The given dates are: Equal
    

6. Intente dos de los siguientes: (2*5 = 10)

  1. Supongamos que un archivo contiene los registros de los estudiantes y cada registro contiene el nombre y la edad de un estudiante. Escriba un programa en C para leer estos registros y mostrarlos ordenados por nombre.

    // C program to read Student records 
    // like id, name and age, 
    // and display them in sorted order by Name 
      
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
      
    // struct person with 3 fields 
    struct Student { 
        char* name; 
        int id; 
        char age; 
    }; 
      
    // setting up rules for comparison 
    // to sort the students based on names 
    int comparator(const void* p, const void* q) 
        return strcmp(((struct Student*)p)->name, 
                    ((struct Student*)q)->name); 
      
    // Driver program 
    int main() 
        int i = 0, n = 5; 
      
        struct Student arr[n]; 
      
        // Get the students data 
        arr[0].id = 1; 
        arr[0].name = "bd"
        arr[0].age = 12; 
      
        arr[1].id = 2; 
        arr[1].name = "ba"
        arr[1].age = 10; 
      
        arr[2].id = 3; 
        arr[2].name = "bc"
        arr[2].age = 8; 
      
        arr[3].id = 4; 
        arr[3].name = "aaz"
        arr[3].age = 9; 
      
        arr[4].id = 5; 
        arr[4].name = "az"
        arr[4].age = 10; 
      
        // Print the Unsorted Structure 
        printf("Unsorted Student Records:\n"); 
        for (i = 0; i < n; i++) { 
            printf("Id = %d, Name = %s, Age = %d \n"
                arr[i].id, arr[i].name, arr[i].age); 
        
        // Sort the structure 
        // based on the specified comparator 
        qsort(arr, n, sizeof(struct Student), comparator); 
      
        // Print the Sorted Structure 
        printf("\n\nStudent Records sorted by Name:\n"); 
        for (i = 0; i < n; i++) { 
            printf("Id = %d, Name = %s, Age = %d \n"
                arr[i].id, arr[i].name, arr[i].age); 
        
      
        return 0; 

    Producción:

    Unsorted Student Records:
    Id = 1, Name = bd, Age = 12 
    Id = 2, Name = ba, Age = 10 
    Id = 3, Name = bc, Age = 8 
    Id = 4, Name = aaz, Age = 9 
    Id = 5, Name = az, Age = 10 
    
    
    Student Records sorted by Name:
    Id = 4, Name = aaz, Age = 9 
    Id = 5, Name = az, Age = 10 
    Id = 2, Name = ba, Age = 10 
    Id = 3, Name = bc, Age = 8 
    Id = 1, Name = bd, Age = 12
    
  2. Escriba un programa para clasificar un conjunto de nombres almacenados en una array en orden alfabético .

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
      
    // Defining comparator function as per the requirement
    static int myCompare(const void* a, const void* b)
    {
      
        // setting up rules for comparison
        return strcmp(*(const char**)a, *(const char**)b);
    }
      
    // Function to sort the array
    void sort(const char* arr[], int n)
    {
        // calling qsort function to sort the array
        // with the help of Comparator
        qsort(arr, n, sizeof(const char*), myCompare);
    }
      
    int main()
    {
      
        // Get the array of names to be sorted
        const char* arr[];
        = { "GeeksforGeeks",
            "GeeksQuiz",
            "CLanguage" };
        int n = sizeof(arr) / sizeof(arr[0]);
        int i;
      
        // Print the given names
        printf("Given array of names is\n");
        for (i = 0; i < n; i++)
            printf("%d: %s \n", i, arr[i]);
      
        // Sort the given names
        sort(arr, n);
      
        // Print the sorted names
        printf("\nSorted array of names is\n");
        for (i = 0; i < n; i++)
            printf("%d: %s \n", i, arr[i]);
      
        return 0;
    }

    Producción:

    Given array of names is
    0: GeeksforGeeks 
    1: GeeksQuiz 
    2: CLanguage 
    
    Sorted array of names is
    0: CLanguage 
    1: GeeksQuiz 
    2: GeeksforGeeks 
    
  3. Escriba una función definida por el usuario para comparar dos strings en las que sean idénticas o no.

    // C program to check if
    // two strings are identical
      
    #include <stdio.h>
    #include <string.h>
      
    int main()
    {
      
        char string1[100], string2[100];
      
        // Get the strings which
        // is to be checked
        scanf("%s", string1);
        printf("Enter the first string: %s", string1);
      
        // Get the strings which
        // is to be checked
        scanf("%s", string2);
        printf("\nEnter the second string: %s", string2);
      
        // Check if both strings are equal
        printf("\nAre both strings same: ");
      
        if (strcmp(string1, string2) == 0) {
            printf("Yes");
        }
        else {
            printf("No");
        }
      
        return 0;
    }
    Producción:

    Enter the first string: GeeksForGeeks
    Enter the second string: GeeksForGeeks
    Are both strings same: Yes
    

7. Intente dos de los siguientes: (2*5 = 10)

  1. Defina el concepto de puntero> Defina también la asignación de memoria dinámica y varias funciones para la asignación de memoria dinámica, con ejemplos adecuados.

    Los punteros son representaciones simbólicas de direcciones. Permiten que los programas simulen llamadas por referencia, así como que creen y manipulen estructuras de datos dinámicas. Su declaración general en C/C++ tiene el formato:

    Sintaxis:

    datatype *var_name; 
    int *ptr;   //ptr can point to an address which holds int data
    

    ¿Cómo usar un puntero?

    • Definir una variable de puntero
    • Asignar la dirección de una variable a un puntero usando el operador unario (&) que devuelve la dirección de esa variable.
    • Acceder al valor almacenado en la dirección mediante el operador unario (*) que devuelve el valor de la variable ubicada en la dirección especificada por su operando.

    La razón por la que asociamos el tipo de datos a un puntero es que sabe en cuántos bytes se almacenan los datos . Cuando incrementamos un puntero, aumentamos el puntero por el tamaño del tipo de datos al que apunta.

    punteros en c

    Asignación de memoria dinámica en C : se puede definir como un procedimiento en el que el tamaño de una estructura de datos (como Array) se cambia durante el tiempo de ejecución.

    C proporciona algunas funciones para lograr estas tareas. Hay 4 funciones de biblioteca proporcionadas por C definidas en el archivo de encabezado <stdlib.h> para facilitar la asignación de memoria dinámica en la programación de C. Están:

    1. malloc()
    2. llamar()
    3. libre()
    4. reasignar()

    Veamos cada uno de ellos en detalle.

    1. malloc()

      El método «malloc» o «asignación de memoria» se utiliza para asignar dinámicamente un solo bloque grande de memoria con el tamaño especificado. Devuelve un puntero de tipo void que se puede convertir en un puntero de cualquier forma.

      Sintaxis:

      ptr = (cast-type*) malloc(byte-size)
      
      For Example:
      ptr = (int*) malloc(100 * sizeof(int));
      
      Since the size of int is 4 bytes, 
      this statement will allocate 400 bytes of memory. 
      And, the pointer ptr holds the address 
      of the first byte in the allocated memory.
      

      Si el espacio es insuficiente, la asignación falla y devuelve un puntero NULL.

      Ejemplo:

      #include <stdio.h>
      #include <stdlib.h>
        
      int main()
      {
        
          // This pointer will hold the
          // base address of the block created
          int* ptr;
          int n, i, sum = 0;
        
          // Get the number of elements for the array
          n = 5;
          printf("Enter number of elements: %d\n", n);
        
          // Dynamically allocate memory using malloc()
          ptr = (int*)malloc(n * sizeof(int));
        
          // Check if the memory has been successfully
          // allocated by malloc or not
          if (ptr == NULL) {
              printf("Memory not allocated.\n");
              exit(0);
          }
          else {
        
              // Memory has been successfully allocated
              printf("Memory successfully allocated using malloc.\n");
        
              // Get the elements of the array
              for (i = 0; i < n; ++i) {
                  ptr[i] = i + 1;
              }
        
              // Print the elements of the array
              printf("The elements of the array are: ");
              for (i = 0; i < n; ++i) {
                  printf("%d, ", ptr[i]);
              }
          }
        
          return 0;
      }
      Producción:

      Enter number of elements: 5
      Memory successfully allocated using malloc.
      The elements of the array are: 1, 2, 3, 4, 5,
      
    2. llamar()

      El método «calloc» o «asignación contigua» se utiliza para asignar dinámicamente el número especificado de bloques de memoria del tipo especificado. Inicializa cada bloque con un valor predeterminado ‘0’.

      Sintaxis:

      ptr = (cast-type*)calloc(n, element-size);
      
      For Example:
      ptr = (float*) calloc(25, sizeof(float));
      
      This statement allocates contiguous space in memory 
      for 25 elements each with the size of float.
      

      Si el espacio es insuficiente, la asignación falla y devuelve un puntero NULL.

      Ejemplo:

      #include <stdio.h>
      #include <stdlib.h>
        
      int main()
      {
        
          // This pointer will hold the
          // base address of the block created
          int* ptr;
          int n, i, sum = 0;
        
          // Get the number of elements for the array
          n = 5;
          printf("Enter number of elements: %d\n", n);
        
          // Dynamically allocate memory using calloc()
          ptr = (int*)calloc(n, sizeof(int));
        
          // Check if the memory has been successfully
          // allocated by malloc or not
          if (ptr == NULL) {
              printf("Memory not allocated.\n");
              exit(0);
          }
          else {
        
              // Memory has been successfully allocated
              printf("Memory successfully allocated using calloc.\n");
        
              // Get the elements of the array
              for (i = 0; i < n; ++i) {
                  ptr[i] = i + 1;
              }
        
              // Print the elements of the array
              printf("The elements of the array are: ");
              for (i = 0; i < n; ++i) {
                  printf("%d, ", ptr[i]);
              }
          }
        
          return 0;
      }
      Producción:

      Enter number of elements: 5
      Memory successfully allocated using calloc.
      The elements of the array are: 1, 2, 3, 4, 5,
      
    3. libre()

      El método «libre» se utiliza para desasignar dinámicamente la memoria. La memoria asignada mediante las funciones malloc() y calloc() no se desasigna por sí sola. Por lo tanto, se usa el método free() siempre que se lleva a cabo la asignación de memoria dinámica. Ayuda a reducir el desperdicio de memoria al liberarla.

      Sintaxis:

      free(ptr);
      

      Ejemplo:

      #include <stdio.h>
      #include <stdlib.h>
        
      int main()
      {
        
          // This pointer will hold the
          // base address of the block created
          int *ptr, *ptr1;
          int n, i, sum = 0;
        
          // Get the number of elements for the array
          n = 5;
          printf("Enter number of elements: %d\n", n);
        
          // Dynamically allocate memory using malloc()
          ptr = (int*)malloc(n * sizeof(int));
        
          // Dynamically allocate memory using calloc()
          ptr1 = (int*)calloc(n, sizeof(int));
        
          // Check if the memory has been successfully
          // allocated by malloc or not
          if (ptr == NULL || ptr1 == NULL) {
              printf("Memory not allocated.\n");
              exit(0);
          }
          else {
        
              // Memory has been successfully allocated
              printf("Memory successfully allocated using malloc.\n");
        
              // Free the memory
              free(ptr);
              printf("Malloc Memory successfully freed.\n");
        
              // Memory has been successfully allocated
              printf("\nMemory successfully allocated using calloc.\n");
        
              // Free the memory
              free(ptr1);
              printf("Calloc Memory successfully freed.\n");
          }
        
          return 0;
      }
      Producción:

      Enter number of elements: 5
      Memory successfully allocated using malloc.
      Malloc Memory successfully freed.
      
      Memory successfully allocated using calloc.
      Calloc Memory successfully freed.
      
    4. reasignar()

      El método de «reasignación» o «reasignación» se utiliza para cambiar dinámicamente la asignación de memoria de una memoria previamente asignada. En otras palabras, si la memoria previamente asignada con la ayuda de malloc o calloc es insuficiente, se puede usar realloc para reasignar memoria dinámicamente .

      Sintaxis:

      ptr = realloc(ptr, newSize);
      
      where ptr is reallocated with new size 'newSize'.
      

      Si el espacio es insuficiente, la asignación falla y devuelve un puntero NULL.

      Ejemplo:

      #include <stdio.h>
      #include <stdlib.h>
        
      int main()
      {
        
          // This pointer will hold the
          // base address of the block created
          int* ptr;
          int n, i, sum = 0;
        
          // Get the number of elements for the array
          n = 5;
          printf("Enter number of elements: %d\n", n);
        
          // Dynamically allocate memory using calloc()
          ptr = (int*)calloc(n, sizeof(int));
        
          // Check if the memory has been successfully
          // allocated by malloc or not
          if (ptr == NULL) {
              printf("Memory not allocated.\n");
              exit(0);
          }
          else {
        
              // Memory has been successfully allocated
              printf("Memory successfully allocated using calloc.\n");
        
              // Get the elements of the array
              for (i = 0; i < n; ++i) {
                  ptr[i] = i + 1;
              }
        
              // Print the elements of the array
              printf("The elements of the array are: ");
              for (i = 0; i < n; ++i) {
                  printf("%d, ", ptr[i]);
              }
        
              // Get the new size for the array
              n = 10;
              printf("\n\nEnter the new size of the array: %d\n", n);
        
              // Dynamically re-allocate memory using realloc()
              ptr = realloc(ptr, n * sizeof(int));
        
              // Memory has been successfully allocated
              printf("Memory successfully re-allocated using realloc.\n");
        
              // Get the new elements of the array
              for (i = 5; i < n; ++i) {
                  ptr[i] = i + 1;
              }
        
              // Print the elements of the array
              printf("The elements of the array are: ");
              for (i = 0; i < n; ++i) {
                  printf("%d, ", ptr[i]);
              }
        
              free(ptr);
          }
        
          return 0;
      }
      Producción:

      Enter number of elements: 5
      Memory successfully allocated using calloc.
      The elements of the array are: 1, 2, 3, 4, 5, 
      
      Enter the new size of the array: 10
      Memory successfully re-allocated using realloc.
      The elements of the array are: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
      
  2. ¿Qué es una cuerda? También explique diferentes funciones de strings con ejemplos.

    Strings en C : las strings se definen como una array de caracteres. La diferencia entre una array de caracteres y una string es que la string termina con un carácter especial ‘\0’.

    Algunas de las funciones de string más utilizadas son:

  3. strcat : la función strcat() agregará una copia de la string de origen al final de la string de destino. La función strcat() toma dos argumentos:
    1) dest
    2) src
    Agregará una copia de la string de origen en la string de destino. El carácter de terminación al final de dest se reemplaza por el primer carácter de src.
    Valor devuelto: la función strcat() devuelve dest, el puntero a la string de destino.
  4. strchr : en C/C++, strrchr() es una función predefinida que se utiliza para el manejo de strings. cstring es el archivo de encabezado requerido para las funciones de string.

    Esta función Devuelve un puntero a la última aparición de un carácter en una string.
    El carácter cuya última aparición queremos encontrar se pasa como segundo argumento de la función y la string en la que tenemos que encontrar el carácter se pasa como primer argumento de la función.
    Sintaxis

    char *strrchr(const char *str, int c) 
    

    Aquí, str es la string y c es el carácter a localizar. Se pasa como su promoción int, pero se vuelve a convertir internamente en char.

  5. strcmp : strcmp() es una función de biblioteca incorporada y se declara en el archivo de encabezado <string.h> . Esta función toma dos strings como argumentos y compara estas dos strings lexicográficamente.

    Sintaxis: :

    int strcmp(const char *leftStr, const char *rightStr );
    

    En el prototipo anterior, la función srtcmp toma dos strings como parámetros y devuelve un valor entero basado en la comparación de strings.

    • strcmp() compara las dos strings lexicográficamente , lo que significa que comienza la comparación carácter por carácter a partir del primer carácter hasta que los caracteres de ambas strings sean iguales o se encuentre un carácter NULO.
    • Si el primer carácter en ambas strings es igual, esta función verificará el segundo carácter, si también es igual, verificará el tercero y así sucesivamente.
    • Este proceso continuará hasta que un carácter en cualquiera de las strings sea NULL o los caracteres sean desiguales.
  6. strcpy : strcpy() es una función de biblioteca estándar en C/C++ y se usa para copiar una string a otra. En C está presente en el archivo de encabezado string.h y en C++ está presente en el archivo de encabezado cstring .

    Sintaxis:

    char* strcpy(char* dest, const char* src);
    

    Parámetros: Este método acepta los siguientes parámetros:

    • dest : Puntero a la array de destino donde se copiará el contenido.
    • src: string que se copiará.

    Valor devuelto: después de copiar la string de origen a la string de destino, la función strcpy() devuelve un puntero a la string de destino.

  7. strlen : La función strlen() calcula la longitud de una string determinada . La función strlen() se define en el archivo de encabezado string.h . No cuenta el carácter nulo ‘\0’.

    Sintaxis:

    int strlen(const char *str);
    

    Parámetro:

    • str: Representa la variable de string cuya longitud debemos encontrar.

    Retorno: esta función devuelve la longitud de la string pasada.

  8. strncat : en C/C++, strncat() es una función predefinida que se utiliza para el manejo de strings. string.h es el archivo de encabezado requerido para las funciones de string.

    Esta función agrega no más de n caracteres de la string a la que apunta src al final de la string a la que apunta dest más un carácter Nulo de terminación. El carácter inicial de string(src) sobrescribe el carácter nulo presente al final de string(dest). Por lo tanto, la longitud de la string (dest) se convierte en strlen (dest) + n. Pero, si la longitud de string(src) es menor que n , solo se copia el contenido hasta el carácter nulo final y la longitud de string(dest) se convierte en strlen(src) + strlen(dest).

    El comportamiento es indefinido si

    • las cuerdas se superponen.
    • la array dest no es lo suficientemente grande para agregar el contenido de src.

    Sintaxis:

    char *strncat(char *dest, const char *src, size_t n)
    

    Parámetros: Este método acepta los siguientes parámetros:

    • dest : la string donde queremos agregar.
    • src : la string de la que se agregarán los caracteres ‘n’.
    • n : representa el número máximo de caracteres que se agregarán. size_t es un tipo integral sin signo.

    Valor de retorno: la función strncat() devolverá el puntero a la string (destino).

  9. La función strncmp : std::strncmp() compara lexicográficamente no más que contar caracteres de las dos strings terminadas en nulo y devuelve un número entero basado en el resultado.
    • Esta función toma dos strings y un número num como argumentos y compara como máximo los primeros num bytes de ambas strings.
    • num debe ser como máximo igual a la longitud de la string más larga. Si num se define mayor que la longitud de la string, la comparación se realiza hasta el carácter nulo (‘\ 0’) de cualquiera de las strings.
    • Esta función compara lexicográficamente las dos strings. Comienza la comparación desde el primer carácter de cada string. Si son iguales entre sí, continúa y compara el siguiente carácter de cada string y así sucesivamente.
    • Este proceso de comparación se detiene hasta que se alcanza un carácter nulo de terminación de cualquiera de las strings o el número de caracteres de ambas strings coincide.

    Sintaxis:

    int strncmp(const char *str1, const char *str2, size_t count);
    
    Parameters:
    str1 and str2: C string to be compared.
    count: Maximum number of characters to compare.
     size_t is an unsigned integral type.
    
    Return Value: 
    Value                               Meaning
    Less than zero                      str1 is less than str2.
    Zero                                str1 is equal to str2.
    Greater than zero                   str1 is greater than str2.
    
  10. strncpy : la función strncpy() es similar a la función strcpy(), excepto que se copian como máximo n bytes de src. Si no hay ningún carácter NULL entre los primeros n caracteres de src, la string colocada en dest no terminará en NULL. Si la longitud de src es menor que n, strncpy() escribe caracteres NULL adicionales en dest para garantizar que se escriba un total de n caracteres.

    Sintaxis:

    char *strncpy( char *dest, const char *src, size_t n )

    Parámetros: esta función acepta dos parámetros, como se mencionó anteriormente y se describe a continuación:

    • src: La string que se copiará.
    • dest: Puntero a la array de destino donde se copiará el contenido.
    • n: el primer carácter n copiado de src a dest.

    Valor devuelto: Devuelve un puntero a la string de destino.

  11. strrchr : la función strrchr() en C/C++ localiza la última aparición de un carácter en una string. Devuelve un puntero a la última aparición en la string. El carácter nulo de terminación se considera parte de la string C. Por lo tanto, también se puede ubicar para recuperar un puntero al final de una string. Se define en el archivo de encabezado cstring .
    Sintaxis:
    const char* strrchr( const char* str, int ch )
                or
    char* strrchr( char* str, int ch )
    

    Parámetro: La función toma dos parámetros obligatorios que se describen a continuación:

    • str : especifica el puntero a la string terminada en nulo que se buscará.
    • ch: especifica el caracter a buscar.

    Valor devuelto: la función devuelve un puntero a la última ubicación de ch en la string, si se encuentra el ch . Si no se encuentra, devuelve un puntero nulo.

  12. Escriba una breve nota sobre lo siguiente (cualquiera de los dos):
    • (i) Stack con operación push y pop : Stack es una estructura de datos lineal que sigue un orden particular en el que se realizan las operaciones. El orden puede ser LIFO (Last In First Out) o FILO (First In Last Out).

      Principalmente, las tres operaciones básicas siguientes se realizan en la pila:

      • Empujar: agrega un elemento a la pila. Si la pila está llena, se dice que hay una condición de desbordamiento.
      • Pop: elimina un elemento de la pila. Los elementos se abren en el orden inverso al que se empujaron. Si la pila está vacía, se dice que es una condición de subdesbordamiento.
      • Peek o Top: Devuelve el elemento superior de la pila.
      • isEmpty: Devuelve verdadero si la pila está vacía, de lo contrario, devuelve falso.

      pila

      ¿Cómo entender una pila de forma práctica?
      Hay muchos ejemplos de la vida real de stack. Considere el ejemplo simple de los platos apilados unos sobre otros en la cantina. La placa que está en la parte superior es la primera que se retira, es decir, la placa que se ha colocado en la posición más baja permanece en la pila durante el mayor período de tiempo. Por lo tanto, se puede ver simplemente que sigue el orden LIFO/FILO.

      Tiempo Complejidades de las operaciones en la pila:

      push(), pop(), isEmpty() y peek() toman tiempo O(1). No ejecutamos ningún bucle en ninguna de estas operaciones.

      Aplicaciones de pila:

      Implementación:
      hay dos formas de implementar una pila:

      • Usando array
      • Usar lista enlazada

      Implementando Stack usando Arrays

      // C program for array implementation of stack
      #include <limits.h>
      #include <stdio.h>
      #include <stdlib.h>
        
      // A structure to represent a stack
      struct Stack {
          int top;
          unsigned capacity;
          int* array;
      };
        
      // function to create a stack of given capacity. It initializes size of
      // stack as 0
      struct Stack* createStack(unsigned capacity)
      {
          struct Stack* stack = (struct Stack*)malloc(sizeof(struct Stack));
          stack->capacity = capacity;
          stack->top = -1;
          stack->array = (int*)malloc(stack->capacity * sizeof(int));
          return stack;
      }
        
      // Stack is full when top is equal to the last index
      int isFull(struct Stack* stack)
      {
          return stack->top == stack->capacity - 1;
      }
        
      // Stack is empty when top is equal to -1
      int isEmpty(struct Stack* stack)
      {
          return stack->top == -1;
      }
        
      // Function to add an item to stack.  It increases top by 1
      void push(struct Stack* stack, int item)
      {
          if (isFull(stack))
              return;
          stack->array[++stack->top] = item;
          printf("%d pushed to stack\n", item);
      }
        
      // Function to remove an item from stack.  It decreases top by 1
      int pop(struct Stack* stack)
      {
          if (isEmpty(stack))
              return INT_MIN;
          return stack->array[stack->top--];
      }
      // Driver program to test above functions
      int main()
      {
          struct Stack* stack = createStack(100);
        
          push(stack, 10);
          push(stack, 20);
          push(stack, 30);
        
          printf("%d popped from stack\n", pop(stack));
        
          return 0;
      }
    • Lista enlazada : Al igual que las arrays, la Lista enlazada es una estructura de datos lineal. A diferencia de las arrays, los elementos de la lista enlazada no se almacenan en ubicaciones contiguas; los elementos se vinculan mediante punteros.

      lista enlazada

      ¿Por qué lista enlazada?
      Los arreglos se pueden usar para almacenar datos lineales de tipos similares, pero los arreglos tienen las siguientes limitaciones.
      1) El tamaño de las arrays es fijo: por lo que debemos conocer el límite superior en el número de elementos de antemano. Además, generalmente, la memoria asignada es igual al límite superior independientemente del uso.
      2) Insertar un nuevo elemento en una array de elementos es costoso, porque se debe crear espacio para los nuevos elementos y, para crear espacio, los elementos existentes deben cambiarse.

      Por ejemplo, en un sistema si mantenemos una lista ordenada de ID en una array id[].

      id[] = [1000, 1010, 1050, 2000, 2040].

      Y si queremos insertar un nuevo ID 1005, entonces para mantener el orden ordenado, tenemos que mover todos los elementos después de 1000 (excluyendo 1000).
      La eliminación también es costosa con arrays hasta que se utilicen algunas técnicas especiales. Por ejemplo, para eliminar 1010 en id[], todo lo que esté después de 1010 debe moverse.

      Ventajas sobre las arrays
      1) Tamaño dinámico
      2) Facilidad de inserción/eliminación

      Inconvenientes:
      1) No se permite el acceso aleatorio. Tenemos que acceder a los elementos de forma secuencial a partir del primer Node. Por lo tanto, no podemos realizar búsquedas binarias con listas enlazadas de manera eficiente con su implementación predeterminada. Lea sobre esto aquí .
      2) Se requiere espacio de memoria adicional para un puntero con cada elemento de la lista.
      3) No compatible con caché. Dado que los elementos de la array son ubicaciones contiguas, existe una localidad de referencia que no existe en el caso de las listas vinculadas.

      Representación:
      una lista enlazada se representa mediante un puntero al primer Node de la lista enlazada. El primer Node se llama cabeza. Si la lista enlazada está vacía, el valor de head es NULL.
      Cada Node en una lista consta de al menos dos partes:
      1) datos
      2) Puntero (o referencia) al siguiente Node
      En C, podemos representar un Node usando estructuras. A continuación se muestra un ejemplo de un Node de lista vinculada con datos enteros.

      // A linked list node
      struct Node {
          int data;
          struct Node* next;
      };
    • Argumento de la línea de comandos : la función más importante de C/C++ es la función main(). Se define principalmente con un tipo de retorno de int y sin parámetros:
      int main() { /* ... */ } 
      

      También podemos dar argumentos de línea de comandos en C y C++. Los argumentos de la línea de comandos se dan después del nombre del programa en el shell de línea de comandos de los sistemas operativos.
      Para pasar argumentos de la línea de comandos, normalmente definimos main() con dos argumentos: el primer argumento es el número de argumentos de la línea de comandos y el segundo es la lista de argumentos de la línea de comandos.

      int main(int argc, char *argv[]) { /* ... */ }
      

      o

      int main(int argc, char **argv) { /* ... */ }
      
      • argc (ARGument Count) es de tipo int y almacena el número de argumentos de la línea de comandos pasados ​​por el usuario, incluido el nombre del programa. Entonces, si le pasamos un valor a un programa, el valor de argc sería 2 (uno para el argumento y otro para el nombre del programa)
      • El valor de argc no debe ser negativo.
      • argv(ARGument Vector) es una array de punteros de caracteres que enumeran todos los argumentos.
      • Si argc es mayor que cero, los elementos de la array de argv[0] a argv[argc-1] contendrán punteros a strings.
      • Argv[0] es el nombre del programa, después de eso hasta argv[argc-1] cada elemento son argumentos de línea de comandos.

Publicación traducida automáticamente

Artículo escrito por RishabhPrabhu y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *