Print array of names in C++

Asked

Viewed 222 times

0

I’m having trouble printing an array that has as elements a char 'Name' saved. When I print these elements, only the last letter of the char leaves, in this case, the letter 'and', and not the whole name, which in this case is the word 'Name'.

#include <stdlib.h>
#include <iostream>

using namespace std;

char** Alocar_matriz_real(int m, int n)
{
    char** v;  /* ponteiro para a matriz */
    int   i;    /* variavel auxiliar      */
    if (m < 1 || n < 1) { /* verifica parametros recebidos */
        printf("** Erro: Parametro invalido **\n");
        return (NULL);
    }
    /* aloca as linhas da matriz */
    v = (char**)calloc(n, sizeof(char*)); // Um vetor de m ponteiros para char* /
        if (v == NULL) {
            printf("** Erro: Memoria Insuficiente **");
            return (NULL);
        }
    /* aloca as colunas da matriz */
    for (i = 0; i < m; i++) {
        v[i] = (char*)calloc(m, sizeof(char));  /* m vetores de n floats */
        if (v[i] == NULL) {
            printf("** Erro: Memoria Insuficiente **");
            return (NULL);
        }
    }
    return (v); /* retorna o ponteiro para a matriz */
}

char** Liberar_matriz_real(int m, int n, char** v)
{
    int  i;  /* variavel auxiliar */
    if (v == NULL) return (NULL);
    if (m < 1 || n < 1) {  /* verifica parametros recebidos */
        printf("** Erro: Parametro invalido **\n");
        return (v);
    }
    for (i = 0; i < m; i++) free(v[i]); /* libera as linhas da matriz */
    free(v);      /* libera a matriz (vetor de ponteiros) */
    return (NULL); /* retorna um ponteiro nulo */
}

void main(void)
{
    char** mat;  /* matriz a ser alocada */
    int   l, c;   /* numero de linhas e colunas da matriz */
    int i, j;
    //...           /* outros comandos, inclusive inicializacao para l e c */
    cin >> l;
    cin >> c;
        mat = Alocar_matriz_real(l, c);

    for (i = 0; i < l; i++)
        for (j = 0; j < c; j++)
            mat[i][j] = 'Nome';
    for (i = 0; i < l; i++)
        for (j = 0; j < c; j++)
            printf("%c ", mat[i][j]);
        printf("\n");
    //...           /* outros comandos utilizando mat[][] normalmente */
        mat = Liberar_matriz_real(l, c, mat);
    //...
}

The exit from the program:

5
5
e e e e e e e e e e e e e e e e e e e e e e e e e

  • 1

    A char variable has a single character. Each position of its matrix has a single character and not a string. Since you are working with C++ it is best to use the string class. This mat[i][j] = 'Nome'; is wrong because the character ' serves to delimit a single character and not a string.

  • @anonymity, what could be done?

  • Or use the string class or that each position of your array is an array of characters and not a single character. C uses the function strcpy to copy C-style strings (an array of characters followed by the terminator ' 0') and not a simple assignment instead of mat[i][j] = 'Nome'; utilize strcpy(mat[i][j], "Nome");.

1 answer

0

As stated in the comments, a variable of type char can contain only a single character. Even, the compiler warns of this problem with a Warning when compiling this code.

Another problem is that you mix C with C++ and the solution is different depending on whether you use C, or if you use C++. In the case of C, it does not have a type representing a string and C uses a "character array" for this (where the last character in the array is the null character) and gives you a set of functions to manipulate character array. I mean, let’s add one * in several places for more this indirect, as well as modify the functions Alocar_matriz_real and Liberar_matriz_real. An important detail is that instead of

mat[i][j] = 'Nome';

we’ll have to use

mat[i][j] = (char*)malloc(5);
strcpy(mat[i][j], "Nome");

Note that we have to allocate memory to our character array. How "Nome" has 4 characters allotted memory for 5 characters (to fit the null character at the end that will be added by the function strcpy.

Follow the code below. Also note that you have not placed keys { and } to delimit the for loops. I added since now some loops perform more than one command.

#include <stdlib.h>
#include <iostream>
#include <cstring>

using namespace std;

char*** Alocar_matriz_real(int m, int n)
{
    char*** v;  /* ponteiro para a matriz */
    int   i;    /* variavel auxiliar      */
    if (m < 1 || n < 1) { /* verifica parametros recebidos */
        printf("** Erro: Parametro invalido **\n");
        return (NULL);
    }
    /* aloca as linhas da matriz */
    v = (char***)calloc(n, sizeof(char**)); // Um vetor de m ponteiros para char* /
        if (v == NULL) {
            printf("** Erro: Memoria Insuficiente **");
            return (NULL);
        }
    /* aloca as colunas da matriz */
    for (i = 0; i < m; i++) {
        v[i] = (char**)calloc(m, sizeof(char*));  /* m vetores de n floats */
        if (v[i] == NULL) {
            printf("** Erro: Memoria Insuficiente **");
            return (NULL);
        }
    }
    return (v); /* retorna o ponteiro para a matriz */
}

char*** Liberar_matriz_real(int m, int n, char*** v)
{
    int  i, j;  /* variavel auxiliar */
    if (v == NULL) return (NULL);
    if (m < 1 || n < 1) {  /* verifica parametros recebidos */
        printf("** Erro: Parametro invalido **\n");
        return (v);
    }
    for(i = 0; i < m; i++) {
        for(j = 0; j < n; j++) {
            free(v[i][j]); /* libera a memória de cada "string" */
        }
        /* libera as linhas da matriz */
        free(v[i]);
    }
    free(v); /* libera a matriz (vetor de ponteiros) */

    return (NULL); /* retorna um ponteiro nulo */
}

int main(int argc, char *argv[])
{
    char*** mat;  /* matriz a ser alocada */
    int   l, c;   /* numero de linhas e colunas da matriz */
    int i, j;
    //...           /* outros comandos, inclusive inicializacao para l e c */
    cin >> l;
    cin >> c;
    mat = Alocar_matriz_real(l, c);

    for(i = 0; i < l; i++) {
        for(j = 0; j < c; j++) {
            // Aloca memória para podermos salvar a string
            mat[i][j] = (char*)malloc(5);
            strcpy(mat[i][j], "Nome");
        }
    }
    for(i = 0; i < l; i++) {
        for(j = 0; j < c; j++) {
            printf("%s ", mat[i][j]);
        }
        printf("\n");
    }

    //...           /* outros comandos utilizando mat[][] normalmente */
    mat = Liberar_matriz_real(l, c, mat);
    //...
}

Solution in C++

The first change is that we can use std::string in place of a char* to represent strings. So we don’t need to manually allocate memory to each string and consequently we don’t need to worry about releasing that memory. In addition, we can use the ticking operator instead of strcpy. Another change is that probably the only reason you use dynamic allocation for mat is to allow the user to indicate the dimensions of the Matrix, correct? In this case we can use std::vector rather than dynamic allocation, which further simplifies the code.

Follow the code C++ below.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector<vector<string>> Alocar_matriz_real(int m, int n) {
    // Passando "m" estando dizendo que o vetor mais externo tem "m" elementos
    vector<vector<string>> v(m);
    if (m < 1 || n < 1) { /* verifica parametros recebidos */
        // Ao invés de imprimir uma ensagem e retornar um valor que o usuário da
        // função precisa checar, em C++ podemos disparar uma exceção no caso de
        // valores inválidos
        throw std::runtime_error("Erro: Parametro invalido");
    }

    for(int l = 0; l < n; l++) {
        // Vamos indicar que cada vetor mais interno possui "n" elementos
        // chamando o método "resize" da classe "std::vector"
        v[l].resize(n);
    }

    return v;
}

int main(int argc, char* argv[]) {
    int l, c;     /* numero de linhas e colunas da matriz */
    int i, j;
    //...           /* outros comandos, inclusive inicializacao para l e c */
    cin >> l;
    cin >> c;

    // A função "Alocar_matriz_real" ficou bem simples e nem precisamos mais
    // dela, mas mantive por causa da checagem do número de linhas e colunas.
    //
    // Outro detalhe é que se fornecermos o valor de `mat` já na declaração, o
    // compilador vai perceber e evitar que a matrix criada dentro de
    // `Alocar_matriz_real` seja copiada para `mat`. Se declararmos `mat` em uma
    // linha e só depois passarmos setarmos o valor chamando
    // `Alocar_matriz_real` então uma cópia será necessária.
    vector<vector<string>> mat = Alocar_matriz_real(l, c);

    for(i = 0; i < l; i++)
        for(j = 0; j < c; j++)
            // Podemos usar atribuição normalmente
            mat[i][j] = "Nome";
    for(i = 0; i < l; i++) {
        for(j = 0; j < c; j++) cout << mat[i][j] << " ";
        cout << "\n";
    }
}

Browser other questions tagged

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