Colo allocate a memory based on the size of what the user entered

6

How can I make the program count the number of 'x' characters of the string and give X bytes to it immediately after the user enters a string?

I am not able to do this, I tried for example to make after the user type the string, this:

ponteiro = (char *) malloc (strlen(string));

In the code above, the user giving an entry, for example, type: ABCDEF, would make the strlen count 6 characters, thus allocating to the string 6 bytes.

But it goes wrong, since the memory allocation would be happening later, so before the string is 'taken' there would be no bytes allocated to store it. Does anyone know how I can resolve this?

    
asked by anonymous 04.01.2015 / 17:10

3 answers

4

There are not many options. Basically, you either allocate enough of what you need or ask how much you want to allocate.

The second option really is terrible. From a usability point of view, it makes no sense.

The first option has the disadvantage of possibly allocating more memory than is really necessary. But who cares. This is not a problem anymore on any kind of device unless you want to get really long text, but you would not do it in a simple way anyway, in a long text it would have a data structure to manage it. p>

Someone may think that there is also the disadvantage of imposing a ceiling. But this is an advantage. Letting a user what the maximum limit of text to type is the last thing the program should do. Again, if you need something more complex, you will need a more complex program.

So the solution is to do this:

#include <stdio.h>
#include <stdlib.h>
int main(){
    char *ponteiro = malloc(100); //um caractere será ocupado pelo terminador 
#include <stdio.h>
#include <stdlib.h>
int main(){
    char *ponteiro = malloc(100); //um caractere será ocupado pelo terminador %pre%
    printf("String: ");
    scanf("%99s", ponteiro); //permite digitar um caractere a menos que o alocado 
    free(ponteiro);
    return 0;
}
printf("String: "); scanf("%99s", ponteiro); //permite digitar um caractere a menos que o alocado free(ponteiro); return 0; }

See running on ideone .

Now there are answers that show creative algorithms but that will probably be overkill . My solution wastes memory, the others presented waste allocation time, and in the comet appeared one wastes or two but in moderate amounts.

Realized that there is no free lunch. You have to decide what you want to waste. In a simple example any can be wasted without problems. I would use the Occam's razor and I would stick with the simpler one. If I preferred the more complicated one I would have posted it.

I could use an optimized and better-handled version of more complex problems where I was really having memory problems and did not know the size of what I need in data entry. I do not have any of these problems ever so I never bothered about it. I do not think you should either.

    
04.01.2015 / 17:35
3

There is a way to do what you want, but code performance is questionable depending on the situation.

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

#define ALLOCATION_STEP 5

int main(void)
{
    int mem_left = ALLOCATION_STEP;
    int mem_size = mem_left + 1;
    int length = 0;
    int realloc_cnt = 0;
    char *buff = (char *)malloc(mem_left);
    char c = 0;
    while((c = getchar()) != '\n') {
        if(mem_left == 0) { // precisamos de mais memoria
            char *tmp = (char *)realloc(buff,mem_size + ALLOCATION_STEP);
            if(tmp == NULL) {
                printf("Falha na aquisicao de memoria!\n");
                free(buff);
                return -1;
            }
            buff = tmp;
            mem_left = ALLOCATION_STEP;
            mem_size += mem_left;
            ++realloc_cnt;
        }
        buff[length++] = c;
        --mem_left;
    }

    buff[length] = '
#include <stdio.h>
#include <stdlib.h>

#define ALLOCATION_STEP 5

int main(void)
{
    int mem_left = ALLOCATION_STEP;
    int mem_size = mem_left + 1;
    int length = 0;
    int realloc_cnt = 0;
    char *buff = (char *)malloc(mem_left);
    char c = 0;
    while((c = getchar()) != '\n') {
        if(mem_left == 0) { // precisamos de mais memoria
            char *tmp = (char *)realloc(buff,mem_size + ALLOCATION_STEP);
            if(tmp == NULL) {
                printf("Falha na aquisicao de memoria!\n");
                free(buff);
                return -1;
            }
            buff = tmp;
            mem_left = ALLOCATION_STEP;
            mem_size += mem_left;
            ++realloc_cnt;
        }
        buff[length++] = c;
        --mem_left;
    }

    buff[length] = '%pre%'; // fecha a string

    printf("Tamanho: %d\n",length);
    printf("Memoria: %d\n",mem_size);
    printf("Padding: %d\n",mem_size - (length+1));
    printf("Realocacoes: %d\n",realloc_cnt);
    printf("String: %s\n",buff);

    free(buff);
    buff = NULL;

    return 0;
}
'; // fecha a string printf("Tamanho: %d\n",length); printf("Memoria: %d\n",mem_size); printf("Padding: %d\n",mem_size - (length+1)); printf("Realocacoes: %d\n",realloc_cnt); printf("String: %s\n",buff); free(buff); buff = NULL; return 0; }

The above code allocates an initial amount of memory given by the value of ALLOCATION_STEP , so it starts to read the input stream until it finds a line break \n , throughout the process it copies the stream characters for the variable buff , if the remaining amount of memory indicated by mem_left reaches 0 it reallocates more%% of bytes of memory to continue the process until the end or until an allocation error occurs. p>

The problem is: A very low%% can cause many reallocations to happen making code performance questionable, there is also abuse of the ALLOCATION_STEP function that can cause problems.

    
04.01.2015 / 19:16
2

Simple: just like C ++ does with std::string . It leaves the input buffer, reads from chunk in chunk and allocates more memory as needed.

Use following code :

char *getln()
{
    char *linha = NULL, *tmp = NULL;
    size_t tamanho = 0, index = 0;
    int ch = EOF;

    while (ch) {
        ch = getc(stdin);

        /* Checamos se devemos parar. */
        if (ch == EOF || ch == '\n')
            ch = 0;

        /* Checamos se devemos expandir. */
        if (tamanho <= index) {
            tamanho += CHUNK;
            tmp = realloc(linha, tamanho);
            if (!tmp) {
                free(linha);
                linha = NULL;
                break;
            }
             linha = tmp;
        }

        /* Finalmente adicionamos o caractere */
        linha[index++] = ch;
    }

    return linha;
}

Remembering that CHUNK is a value that is right for you. The flawless way is #define CHUNK 1 . The method may change the results of time ( input longer ).

    
05.01.2015 / 00:30