Трудности с созданием декартова произведения указателя на указатель на символ - PullRequest
1 голос
/ 22 сентября 2010

В качестве входных данных у меня есть указатель на указатель на символ, содержащий:

{"ab", "cd"}

В качестве выходных данных мне нужно создать следующий декартово произведение:

{"abab", "abcd", "cdab", "cdcd"}

Я создал функцию, которая получает "ab, cd "и указатель на символьный указатель, предназначенный для хранения результирующего набора.Хотя внутри функции все работает нормально, после выхода из нее мой вывод остается пустым.Я предполагаю, что я делаю что-то не так во время объединения, но я не уверен, что.

Вот как выглядит мой код:

#include <stdio.h>

void Permute(char**, int, char**);

main() {
    // my input
    int words = 2;
    char **input;
    input = malloc(sizeof(char*) * words);
    input[0] = "ab";
    input[1] = "cd";

    // compute how much memory we need
    char **output;
    output = malloc(sizeof(char*) * (words * 2));

    // start permutation
    Permute(input, words, output);

    // show output
    int i = 0;
    for(i = 0; i < (words * 2); ++i) {
        // should print: {abcd, abab, cdab, cdcd} 
        // but nothing gets printed
        printf("%s\n", output[i]); 
    }
    free(input);
    free(output);
}

void Permute(char **input, int words, char **output){
    int i = 0, j = 0, k = 0;
    char str[5];
    for(i = 0; i < words; ++i) {
        for(j = 0; j < words; ++j) {
            strcpy (str, input[i]);
            strcat (str, input[j]);
            output[k] = str;
            // at this point concatenation is printed correctly
            printf("%s\n", output[k]); correctly
            ++k;
        }
    }
}

Редактировать

Спасибок комментарию Гоза я обновил свою функцию.Теперь указатель на char выделяется, указывается на конкатенацию и затем сохраняется внутри output [k].Таким образом, при возбуждении функции никакие данные не теряются:

void Permute(char **input, int words, char **output){
    int i = 0, j = 0, k = 0;
    char *p;
    for(i = 0; i < words; ++i) {
        for(j = 0; j < words; ++j) {
            p = malloc(sizeof(char*) * 5);
            strcpy(p, input[i]);
            strcat (p, input[j]);
            output[k] = p;
            printf("%d %s \n", k, output[k]); 
            ++k;
        }
    }
}

Редактировать

Буфер, содержащий результат, выделяется перед передачей его функции Permute :

    // compute how much memory we need
    // allocate space for 4 pointers to char
    char **output = malloc(sizeof(char*) * 4); 
    int i = 0;
    // pre-allocate space for every pointer 
    for(i = 0; i < 4; i++)
       output[i] = malloc( sizeof( char ) * 5 ); 

Редактировать

Освободить всю память, на которую указывает указатель на символ, перед очисткой указателя на указатель на символ:

    // free memory
    for(i = 0; i < 4; i++ )
       free( output[i] );
    free(output);

    for(i = 0; i < 2; i++ )
       free(input[i]);
    free(input);

Ответы [ 3 ]

1 голос
/ 22 сентября 2010

Есть пара вопросов. Сначала вы выделяете символ *. Затем вы присваиваете его символу ** и ожидаете, что он будет иметь 2-мерную размерность. Это не так. Вам нужно было бы malloc набор указателей char * (4 * независимо от того, какой у вас размер указателя ... т.е. sizeof (char *)), а затем malloc 5 байтов для каждого из этих указателей.

Кроме того, в Permute вы перезаписываете значение указателя указателем на str (которого нет вне функции). Вы должны strcpy'ть содержимое str для вывода [k].

В ответ на комментарий: Да, это будет работать, но было бы целесообразно выделить буфер перед тем, как идти в цикл.

е

char** ptr = malloc( sizeof( char* ) * 4 );
for( int i = 0; i++; i < 4 )
{
   ptr[i] = malloc( sizeof( char ) * 4 ); // sizeof( char ) == 1 but its a good habit to get into.
}

Затем, как уже было сказано, strcpy временный массив в соответствующий массив char *.

Кроме того, помните, что, когда вы освобождаете память, вам нужно выполнить противоположное вышеописанному циклу. т.е. освободить 4 отдельных массива, а затем освободить массив указателей. а именно:

for( int i = 0; i++; i < 4 )
{
   free( ptr[i] );
}
free( ptr );

т.е. все 5 случаев вызова malloc встречаются с соответствующими свободными. Если вы сначала освободите массив ptr, вы не сможете гарантировать, что память действительна. Поэтому 4 указателя, хранящиеся в этом массиве, могут больше не быть действительными. Так что сначала освободите их, а затем массив указателей.

1 голос
/ 22 сентября 2010
output = malloc(sizeof(char*) * (words * 2));

Хорошо, вы создали output[0], output[1], ... но каковы их значения?

output[0] это char * ... на что это указывает?

И вы не можете скопировать адрес локальной переменной в Permute (str) в output.Этот объект перестает существовать после возврата из функции.

1 голос
/ 22 сентября 2010

char str[5]; в Permute находится в стеке и теряется после выхода из Permute. output[k] будет указывать на неопределенное место после выхода из Permute.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...