Почему в конкатенации строк перед каждой конкатенацией может стоять мусор? - PullRequest
2 голосов
/ 03 октября 2010

Я довольно новичок в C, поэтому прошу прощения, если это довольно стандартное знание ..

У меня есть такая функция, где я добавляю кучу строк в стиле C и выводю ее:

char *example(int n, int days, int years){
    char *ret;
    if (n < 5) {
        ret = (char*)malloc(sizeof(char)*256);
        sprintf(ret, "There are %d days in %d years", days, years);
        ret = (char*)malloc(strlen(ret));
        return ret;
    }
    else {
        char *s1;
        char *s2;
        char *s3;
        s1 = example(n/2, days, years);
        s2 = example(n + 5, days, years);
        s3 = example(n--, days, years);

        int length = strlen(s1) + strlen(s2) + strlen(s3);
        ret = (char*)malloc(length);
        strcat(ret, s1);
        strcat(ret, s2);
        strcat(ret, s3);

        return ret;
       }
}

Это префикс каждой новой конкатенации с несколькими символами мусора. Я предполагаю, что моя проблема в моем управлении памятью, но я не уверен .. Это просто? Что я сделал не так? Кроме того, как это можно сделать чище?

Ответы [ 6 ]

1 голос
/ 03 октября 2010
char *example(int n, int days, int years){
   char *ret;
   if (n < 5) {
       ret = (char*)malloc(sizeof(char)*256);
       sprintf(ret, "There are %d days in %d years", days, years);
//     ret = (char*)malloc(strlen(ret));  (DELETE THIS LINE)
       return ret;
   }
   else {
       char *s1;
       char *s2;
       char *s3;
       s1 = example(n/2, days, years);
       s2 = example(n + 5, days, years);  // WILL THIS CAUSE INFINITE RECURSION?
       s3 = example(n--, days, years);

       int length = strlen(s1) + strlen(s2) + strlen(s3) + 1; // ALLOW ROOM FOR TERMINATING '\0'
       ret = (char*)malloc(length);
       strcpy(ret, s1);  // CHANGE TO strcpy()
       strcat(ret, s2);
       strcat(ret, s3);

       return ret;
   }
}
1 голос
/ 03 октября 2010

Это

ret = (char*)malloc(sizeof(char)*256);
sprintf(ret, "There are %d days in %d years", days, years);
ret = (char*)malloc(strlen(ret));

выделяет некоторую память, записывает строку в эту память, а затем выделяет и возвращает новую неинициализированную память.

Это:

ret = (char*)malloc(length);
strcat(ret, s1);

добавляет s1 к ret, что не инициализировано.Вам нужно сделать

ret[0] = '\0'

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

1 голос
/ 03 октября 2010

strlen () возвращает количество символов, НЕ включая завершающий ноль ('\ 0').При выделении памяти вы должны добавить 1 к strlen (), чтобы удерживать этот нулевой символ.

Вы должны поместить это '\ 0' вручную в начало вашей строки или использовать strcpy () вместо первого strcat ().

1 голос
/ 03 октября 2010

Вы выделяете кусок памяти, записываете в него с помощью sprintf, затем отбрасываете первый буфер и заменяете его новым буфером с неопределенным содержимым.

    ret = (char*)malloc(sizeof(char)*256);
    sprintf(ret, "There are %d days in %d years", days, years);
    ret = (char*)malloc(strlen(ret));
    return ret;

Удаление третьей строки, вероятно, поможет.

0 голосов
/ 03 октября 2010

Я очень долго не пользовался c, но ...
В случае n < 5 у вас есть следующий код:

ret = (char*)malloc(sizeof(char)*256);
sprintf(ret, "There are %d days in %d years", days, years);
ret = (char*)malloc(strlen(ret));

зачем вам последняя строка?

0 голосов
/ 03 октября 2010

Почему вы написали этот вызов для перераспределения строки?

ret = (char*)malloc(strlen(ret));

Как вы думаете, что символы, которые вы поместили в эту строку в строке выше, перенаправили бы ее во вновь выделенную память?

Возьми второй вызов malloc и посмотри, поможет ли это. Кроме того, когда вы выделяете строку в предложении «else», вам необходимо освободить место для завершающего нулевого символа, поэтому добавьте 1 к своей «length». Сразу после вызова malloc установите *ret на 0.

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