Helps in C dynamic allocation exercise

Asked

Viewed 152 times

0

The exercise is as follows:

Brazil has just bought a new territory where the newest Brazilian state will be built. Unlike the other states, it will have all its infrastructure planned and, for this, asked for their help.

The new state is divided into N cities and, at first, there is no road connecting any of them. Your job will be to register new built roads or inform if there is a road connecting two specific cities.

For this you will receive two integer values: N(N <= 1000, representing the number of cities) and Q(number of operations you should perform). These are Q lines where each of them will contain one char C and two integers X and Y. Char can be 'c' or 'v' which indicate registration or verification operations, respectively. (beware of reading the char not to read the n by mistake). The integers X and Y correspond to the cities in question (the cities are numbered 0 to N-1).

WARNING: it is mandatory to use dynamic allocation to solve this exercise. Do not forget to correctly release all allocated memory.

Note that all roads built will be double-handed, so adding a road between X and Y implies adding between Y and X.

In the case of a check, you should write a line "There is a road between [X] and [Y]." if it exists or "There is no road between [X] and [Y]." otherwise. There is still a chance that the reported cities do not exist. In such cases, print a line "There are no cities [X] and [Y]." if the two cities do not exist or "There is no city [X/Y]." if one of the two cities does not exist;

(The variables between [] should be replaced by their respective values, check the output example for better understanding)

Examples of input and output:

Entree:

2 3
c 2 3
c 4 3
c 5 3

Exit:

Nao existem as cidades 2 e 3.
Nao existem as cidades 4 e 3.
Nao existem as cidades 5 e 3.

My code went like this:

#include <stdio.h>
#include <stdlib.h>

char *alocar_vetor_char (int q) {
    char* ptrc;
    ptrc = malloc (q * sizeof(char));
    return ptrc; 
}

int **alocar_matriz_int (int q) {
    int** ptri;
    ptri = malloc (q * sizeof(int*));
    for (int i = 0; i < q; i++) {
        ptri[i] = malloc (2 * sizeof(int));
    }
    return ptri;
}

void liberar_memoria (char *vet, int **mat, int q) {
    free(vet);
    for (int i = 0; i < q; i++) {
        free(mat[i]);
    }
    free(mat);
}

int main (void) {

    int n, q;
    char* ptrc; // ponteiro para o vetor de char
    int** ptri; // ponteiro para a matriz de int

    scanf("%d %d", &n, &q);

    ptrc = alocar_vetor_char(q);
    ptri = alocar_matriz_int(q);

    for (int i = 0; i < q; i++) {
        scanf("%c ", &ptrc[i]);
        for (int j = 0; j < 2; j++) {
            scanf("%d ", &ptri[i][j]);
        }
    }

    char cadastro[n][n] // matriz que verifica se as cidades i e j possuem estrada entre si, no qual 1 é sim e 0 é não

    for (int k = 0; k < q; k++) {
        switch (ptrc[k]) {
            case 'c':
                if (ptri[k][0] < n && ptri[k][0] >= 0) { // verificacao se o primeiro valor de entrada e valido
                    if (ptri[k][1] < n && ptri[k][1] >= 0) {
                        cadastro[ptri[k][0]][ptri[k][1]] = 1; // adiciona 1 a cadastro[i][j]
                        cadastro[ptri[k][1]][ptri[k][0]] = 1; // adiciona 1 a cadastro[j][i]
                    } else {
                        printf("Nao existe a cidade %d.\n", ptri[k][1]);
                    }
                } else {
                    if (ptri[k][1] >= n || ptri[k][1] < 0) { // verificacao se o segundo valor de entrada e valido
                        printf("Nao existem as cidades %d e %d.\n", ptri[k][0], ptri[k][1]);
                    } else {
                        printf("Nao existe a cidade %d.\n", ptri[k][0]);
                    }                    
                }
            break;
            case 'v':
                if (ptri[k][0] < n && ptri[k][0] >= 0) { // verificacao se o primeiro valor de entrada e valido
                    if (ptri[k][1] < n && ptri[k][1] >= 0) { // verificacao se o segundo valor de entrada e valido
                        if (cadastro[ptri[k][0]][ptri[k][1]] == 1 && cadastro[ptri[k][1]][ptri[k][0]] == 1) { // condicao que verifica se cadastro[i][j] e cadastro [j][i] possui valor 1
                            printf("Existe uma estrada entre %d e %d.\n", ptri[k][0], ptri[k][1]);
                        } else {
                            printf("Nao existe uma estrada entre %d e %d.\n", ptri[k][0], ptri[k][1]);
                        }                         
                    } else {
                        printf("Nao existe a cidade %d.\n", ptri[k][1]);
                    }
                } else {
                    if (ptri[k][1] >= n || ptri[k][1] < 0) { // verificacao se o segundo valor de entrada e valido
                        printf("Nao existem as cidades %d e %d.\n", ptri[k][0], ptri[k][1]);
                    } else {
                        printf("Nao existe a cidade %d.\n", ptri[k][0]);
                    }                    
                }
            break;
            default:
            break;
        }
    }    

    liberar_memoria(ptrc, ptri, q);

    return 0;
}

My problem is that the last line of output is never printed on the screen, getting something like:

2 3
c 2 3
c 4 3
c 5 3
Nao existem as cidades 2 e 3.
Nao existem as cidades 4 e 3.

Instead of:

2 3
c 2 3
c 4 3
c 5 3
Nao existem as cidades 2 e 3.
Nao existem as cidades 4 e 3.
Nao existem as cidades 5 e 3.

And I don’t know what the problem is.

  • Shouldn’t you make the dynamic allocation of registry[n][n]? At compile time the value of variable n is not known.

  • "last line of output is never printed on the screen": and how the last line should be ?

  • @anonymo Actually, it doesn’t matter. I did not make dynamic allocation to use less memory and fewer lines of code, since registration will always be a square matrix of order n (n is the number of cities, whose value is given by the user). So it makes no difference whether I dynamically allocate or not the matrix.

  • @zentrunix I edited the question to show how the last line should be.

  • And why do you think the compiler will allocate the correct memory space if only during the run you will read the value of variable n?

  • @anonimo: C99 allows dynamic arrays...

Show 1 more comment

1 answer

0


You had problems with scanf. Below goes the corrected font. I also put some printf to debug (oddly it seems that teachers do not teach this).

PS. Whenever the scanf function is used it is advisable to test the return.
Thus:

n = scanf("%d%d", &i, &j);
if (n != 2)
{
  // ocorreu algum erro na digitacao
  // ....
}

I did not want to change your code to put this consistency, but it is fatal, who does not these tests catch with scanf.

Now your program fixed.

#include <stdio.h>
#include <stdlib.h>

char *alocar_vetor_char (int q)
{
  char* ptrc;
  ptrc = malloc (q * sizeof(char));
  return ptrc; 
}

int **alocar_matriz_int (int q)
{
  int** ptri;
  ptri = malloc (q * sizeof(int*));
  for (int i = 0; i < q; i++)
  {
    ptri[i] = malloc (2 * sizeof(int));
  }
  return ptri;
}

void liberar_memoria (char *vet, int **mat, int q)
{
  free(vet);
  for (int i = 0; i < q; i++) {
    free(mat[i]);
  }
  free(mat);
}

int main (void)
{

  int n, q;
  char* ptrc; // ponteiro para o vetor de char
  int** ptri; // ponteiro para a matriz de int

  printf("* digite 'n' e 'q': ");
  scanf("%d %d", &n, &q);

  ptrc = alocar_vetor_char(q);
  ptri = alocar_matriz_int(q);

  for (int i = 0; i < q; i++) {
    printf("* digite linha %d: ", i);
    scanf(" %c", &ptrc[i]);              // <---------------------------
    for (int j = 0; j < 2; j++) {
      scanf("%d", &ptri[i][j]);          // <---------------------------
    }
    printf("* linha %d: c=%c\n", i, ptrc[i]);
  }

  char cadastro[n][n]; // matriz que verifica se as cidades i e j possuem estrada entre si, no qual 1 é sim e 0 é não

  for (int k = 0; k < q; k++)
  {
    switch (ptrc[k])
    {
      case 'c':
        printf("* case c: k=%d\n", k); /// <------------- para debug
        if (ptri[k][0] < n && ptri[k][0] >= 0) { // verificacao se o primeiro valor de entrada e valido
          if (ptri[k][1] < n && ptri[k][1] >= 0) {
            cadastro[ptri[k][0]][ptri[k][1]] = 1; // adiciona 1 a cadastro[i][j]
            cadastro[ptri[k][1]][ptri[k][0]] = 1; // adiciona 1 a cadastro[j][i]
          } else {
            printf("Nao existe a cidade %d.\n", ptri[k][1]);
          }
        } else {
          if (ptri[k][1] >= n || ptri[k][1] < 0) { // verificacao se o segundo valor de entrada e valido
            printf("Nao existem as cidades %d e %d.\n", ptri[k][0], ptri[k][1]);
          } else {
            printf("Nao existe a cidade %d.\n", ptri[k][0]);
          }
        }
        break;

      case 'v':
        printf("* case v: k=%d\n", k); // <------------------------ para debug
        if (ptri[k][0] < n && ptri[k][0] >= 0) { // verificacao se o primeiro valor de entrada e valido
          if (ptri[k][1] < n && ptri[k][1] >= 0) { // verificacao se o segundo valor de entrada e valido
            if (cadastro[ptri[k][0]][ptri[k][1]] == 1 && cadastro[ptri[k][1]][ptri[k][0]] == 1) { // condicao que verifica se cadastro[i][j] e cadastro [j][i] possui valor 1
              printf("Existe uma estrada entre %d e %d.\n", ptri[k][0], ptri[k][1]);
            } else {
              printf("Nao existe uma estrada entre %d e %d.\n", ptri[k][0], ptri[k][1]);
            }
          } else {
            printf("Nao existe a cidade %d.\n", ptri[k][1]);
          }
        } else {
          if (ptri[k][1] >= n || ptri[k][1] < 0) { // verificacao se o segundo valor de entrada e valido
            printf("Nao existem as cidades %d e %d.\n", ptri[k][0], ptri[k][1]);
          } else {
            printf("Nao existe a cidade %d.\n", ptri[k][0]);
          }
        }
        break;

      default:
        printf("* case default: k=%d (ptrc[%d]=%c)\n", k, k, ptrc[k]); // para debug
        break;
    }
  }

  liberar_memoria(ptrc, ptri, q);

  return 0;
}

Explanation: whenever the "%c" format is used, a space should be placed before, thus: "%c" to consume spaces and end of line before reading the next character.

The other format problem was "%d " (with space after %d)...apparently this additional space did not match the end of line after typing the second number (e.g.: c 2 4ENTER).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.