Creating a dynamic array that stores text with breaks

0

Attempt to create a dynamic array using malloc() . I am in doubt if the parameters I submit for the different function cycles 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);
    
asked by anonymous 10.11.2017 / 09:33

2 answers

3

Isac's answer is correct. I decided to only give an option that gives greater speed efficiency by paying the price to further fragment the memory. If it is a better option it is debatable and would need to analyze each case and test very well. I just wanted to give you a choice. 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] != '
#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] != '%pre%'; caractere++, coluna++) {
        if (str[caractere] == '\n' || str[caractere] == '%pre%') {
            matriz[linha][coluna] = '%pre%';
            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]);
    }
}
'; caractere++, coluna++) { if (str[caractere] == '\n' || str[caractere] == '%pre%') { matriz[linha][coluna] = '%pre%'; 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]); } }

See running on ideone . And no Coding Ground . Also put it in GitHub for future reference .

I based the same Isac algorithm, but I deleted the need to go through it 3 times.

Because there is too much memory, you need to cut what you do not use. There is a limitation that can only have 255 phrases with 254 characters each. Nothing has been verified if this is popping up, but the original algorithm also does not check whether malloc() fails or even other problems that may occur.

You can also go relocating as per the character character requirement, but this will probably slow down. You can do hybrid algorithms.

    
10.11.2017 / 16:28
2

As you pointed out in the comments you are trying to split a string into small strings according to a separator, which is often called split . In the case presented the separator to be considered is \n , of change of line.

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

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

      

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

    The same goes for coluna .

  • while (str[i]!='\n') - Here you use a two-dimensional array while but this does not have previously allocated space, either static or dynamic (with \n ), which will give you access to memory that does not it belongs to, and potentially give a Segmentation Fault .

  • i - Finally the matriz[*linha][*coluna] = str[i]; is shown as a matriz normal, that is a malloc when it is actually printf("%s",matriz); . The correct way to show is with a loop.

Trying to pick up on the logic you have and change it so that you can do split, you can use another approach. What is usually simpler is to count the number of separators that exist and with that amount allocate the array to those matriz . Then each string is allocated as it goes through the original sentence and considering each of its 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]='
memcpy(destino, origem, tamanho_em_bytes)
'; //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]); }

See the example of this logic in Ideone

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

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]='
memcpy(destino, origem, tamanho_em_bytes)
'; //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]); }

To use it, you must include char** .

Documentation for the strings

    
10.11.2017 / 15:39