Dynamic matrix creation that stores broken text

Asked

Viewed 349 times

0

Attempt to create a dynamic matrix using malloc(). I am in doubt if the parameters I send to the different cycles of the function will be right.

int size=0,i,j,n=20;
char str[]="Ola. Tudo bem?\n Sim e contigo?\n Comigo esta tudo bem! Que tens feito?\n Trabalho no projeto!\n";
char **matriz;
int *linha;
int *coluna;
size = strlen(str);
printf("%d\n",size);


*linha = (int*)malloc(n*sizeof(int));
*coluna = (int*)malloc(n*sizeof(int));

for (i=0; i<size; i++)
{
    while (str[i]!='\n')
    {
        matriz[*linha][*coluna] = str[i];
    }
    if (str[i]=='\n')
    {
        *(linha++);
        *(coluna)=0;
    }
}
printf("%s",matriz);
  • But the matriz is it supposed to store that information ? An array of strings ? This is an attempt to split by \n ? What result would be waiting for the last printf("%s",matriz); ?

  • "make a printf that showed me if the matrix was correctly sorted" - how so? split by \n would not sort the strings, just keep them in the order they appear.

  • I think it’s best to try to make as clear as possible what your code intends to do, even exemplifying with expected input and output data. I say this because there are several things that are not well in the code that do not allow to understand the exact intention, as for example: uses the linha and coluna as an array of integers, but saves the ASCII number of a letter, and then increments the array pointer itself (*(linha++);) as if it were a number. At the end it shows the matriz as a string when it is an array of strings that does not even have the allocations in memory with malloc

  • Fez this example from the code shown. See if this is what you are looking for.

  • There are many ways to do split some simpler even using strtok, i tried to use one more similar to the logic I had. I just used the function memcpy to simplify the copying of characters, but could have been copied by hand with a for. The detail that makes the process simpler is to count the separators first to know how many strings you have to allocate

  • Yes that’s how it works. If you want I can elaborate an answer explaining what I did and how I did it. I just didn’t put it out there because I wasn’t sure that’s what I was really trying to do.

Show 1 more comment

2 answers

3

The answer of Isac is correct. I decided to only give an option that gives greater speed efficiency by paying the price of fragmenting more memory. Whether it is a better option is debatable and would need to analyze each case and test very well. I just wanted to give an option. This form is usually more idiomatic for C.

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

int main() {
    char str[] = "Ola. Tudo bem?\n Sim e contigo?\n Comigo esta tudo bem! Que tens feito?\n Trabalho no projeto!\n";
    char **matriz = malloc(sizeof(char *) * 255);
    int linha = 0;
    matriz[linha] = malloc(255);
    for (int caractere = 0, coluna = 0; str[caractere] != '\0'; caractere++, coluna++) {
        if (str[caractere] == '\n' || str[caractere] == '\0') {
            matriz[linha][coluna] = '\0';
            matriz[linha] = realloc(matriz[linha], coluna + 1);
            matriz[++linha] = malloc(255);
            coluna = -1;
        } else {
            matriz[linha][coluna] = str[caractere];
        }
    }
    matriz = realloc(matriz, sizeof(char *) * linha);
    for (int i = 0; i < linha; i++) {
        printf("%s\n", matriz[i]);
    }
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

I based myself on Isac’s algorithm, but eliminated the need to go through everything 3 times.

As there is a surplus allocated memory need to cut out what is not used. There is the limitation that can only have 255 phrases with 254 characters each. Nothing has been verified if this is crashing, but the original algorithm also does not check whether the malloc() failure or even other problems that may occur.

It is also possible to relocate according to the need of character in character, but this will probably slow down. It has how to make hybrid algorithms.

  • That’s another code, another problem. There’s no way to know without seeing the code.

  • No, you need to do another, this has already been answered, if you change the answers given are invalid and mix problems.

  • Creates another question. There are errors visible in this code, but it seems that it is running as it should at least in this trivial example, no?

2

From what you pointed out in the comments, you’re trying to split a string in small strings according to a separator, what is commonly called split. In the case presented the separator to be considered is the \n, line-changing.

Your code has several small problems that do not allow it to work properly:

  • *linha = (int*)malloc(n*sizeof(int)); - Here made the value pointed by the pointer linha be an array of ints, which can’t be. Being linha one int* has to point to an integer only. This same error is visible as a build warning:

    assignment makes integer from Pointer without a cast [enabled by default]

    The same happens for the coluna.

  • while (str[i]!='\n') - This while test while the letter is not a \n but within it the i does not advance, so it will be an infinite loop/loop.

  • matriz[*linha][*coluna] = str[i]; - Here uses a two-dimensional array matriz but this has no previously allocated space, either static or dynamic (with malloc), which will give you access to memory that doesn’t belong to you, and potentially give you a Segmentation Fault.

  • printf("%s",matriz); - At the end of matriz is shown as if it were a string normal, that is to say a char* when it’s actually a char**. The correct way to show is with a loop/loop.

Trying to take a little bit of the logic that you have and change it so that you can do the split, may use another approach. What is usually simpler is to count the number of separators that exist and with this amount allocate the array to these strings. Then each string is allocated as it traverses the original sentence and considers each of the respective sizes:

int size=0;
char str[]="Ola. Tudo bem?\n Sim e contigo?\n\n Comigo esta tudo bem! Que tens feito?\n Trabalho no projeto!\n";

size = strlen(str);
printf("%d\n",size);

int separadores = 0, i;

//contar quantos separadores existem
for (i=0; i < size; ++i){ 
    if (str[i] == '\n'){
        separadores++;
    }
}

//a quantidade de elementos é o numero de separadores mais um
char **matriz = malloc(sizeof(char*)*(separadores+1));
int ultimo = 0, j=0;

//percorrer todas as linhas para construir cada string
for (i=0; i < size; ++i){ 
    if (str[i] == '\n' || i == (size-1)){ //se apanhou um '\n' ou está no fim
        if (i-ultimo > 1){ //if para considerar separadores seguidos

            //criar espaço para a string que apanhada até esta letra. A string vai 
            //desde o ultimo indice até ao i, logo tem o tamanho i-ultimo
            matriz[j] = malloc(sizeof(char)*(i-ultimo));
            memcpy(matriz[j], str+ultimo, i-ultimo); //copia os carateres
            matriz[j][i-ultimo]='\0'; //coloca o terminador no fim pela vez do \n
            j++; //j marca a string que se está a construir
        }

        ultimo=i+1;//atualiza o inicio da próxima string
    }
}

//mostrar todas as strings construidas. A quantidade delas é dada por j
for(i=0; i < j;++i){
    printf("%s\n",matriz[i]);
}

Take the example of this logic in Ideone

Note that I used the function memcpy to simplify the code itself, but it only copies bytes from one place in memory to another. I could implement this logic by hand using a simple for. The signature of the function is:

memcpy(destino, origem, tamanho_em_bytes)

To use it it is necessary to include <string.h>.

Documentation for the memcpy

Browser other questions tagged

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