связанный список построен, но не работает должным образом

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

Вот функция, в которой, вероятно, существует проблема.

char* int_str(struct Node** head,char* result) //head is pointer to singly linked list
{
  struct Node* temp = *head;
  char* string1="";
  char* str;
  while(temp != NULL)
  {
    string1=myitoa(temp->data,string1); // myitoa() works fine 
    str=(char*)malloc(1+strlen(string1));
    strcpy(str,string1);
    strcat(result,str);
    temp=temp->next;
  }
  return result;
}

Последний вызов temp->data всегда приводит к неизвестным мусорным значениям. (Связанный список построен правильно, так как печать связанного списка работает правильно.)

Пример: связанный список 1->2->3

Последний вызов temp->data в функции дает 50 (какое-то мусорное значение), т.е. 1->2->50

в то время как в основной функции список правильно дает 1-> 2-> 3

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


person solinvictus    schedule 05.03.2015    source источник
comment
строка1 не инициализирована. Как это должно работать?   -  person chmike    schedule 05.03.2015
comment
myitoa() возвращает char* при каждом вызове   -  person solinvictus    schedule 05.03.2015
comment
у вас есть утечка памяти с str. Вы не освобождаете выделенный блок. Почему бы просто не strcat(result, string1)   -  person chmike    schedule 05.03.2015
comment
myitoa() преобразует int в последовательность символов, я полагаю. Но где он хранит эти символы?   -  person chmike    schedule 05.03.2015
comment
@chmike да, это так?   -  person solinvictus    schedule 05.03.2015


Ответы (3)


Этот фрагмент кода, скорее всего, выполнит эту работу. Нет необходимости в malloc. str определяется как массив из 20 символов. Здесь хранится число в ASCII.

char* int_str(struct Node** head,char* result) //head is pointer to singly linked list
{
    struct Node* temp = *head;
    char str[20];
    while(temp != NULL)
    {
        strcat(result, myitoa(temp->data, str));
        temp=temp->next;
    }
    return result;
}
person chmike    schedule 05.03.2015
comment
Спасибо, я был одержим использованием malloc, мое эго взяло верх надо мной. Приведенный выше код, очевидно, будет работать нормально. Но как мне заставить этот код работать? - person solinvictus; 05.03.2015
comment
Сначала измените char *string1 = ""; на char string1[20];. Во-вторых, добавьте free(str); после temp=temp->next;. Это заставит ваш код работать. char string1[20]; обеспечивает память, необходимую myitoa(). - person chmike; 05.03.2015
comment
Да, я забыл здесь выделить память. Почему объявление массива работает, а не char* . - person solinvictus; 05.03.2015
comment
Потому что char *string1 = ""; объявляет string1 как указатель на константную строку. В пустой строке нет места для хранения целого числа в ASCII, и вы не должны изменять постоянную строку. - person chmike; 05.03.2015
comment
Ах ха! теперь все это имеет смысл. Спасибо! это было на самом деле основным. Я изучаю C с Python в качестве моего первого языка. C Заставляет меня задуматься, кто еще будет использовать такой загадочный язык :), но я думаю, что каждый язык имеет свое собственное применение. - person solinvictus; 05.03.2015
comment
Я понимаю. С C вы должны управлять хранилищем самостоятельно. Таким образом, ваш код может быть намного эффективнее, чем Python. Но это действительно не тривиально и подвержено ошибкам. - person chmike; 05.03.2015

char* string1;

Это объявляет указатель, но не выделяет буфер для строки. Немного сбивает с толку то, что этот неинициализированный указатель передается myitoa, потому что myitoa ничего не может с ним сделать, не вызывая неопределенного поведения.

Эта строка всегда выделяет 5 байтов в 32-битных системах:

str=(char*)malloc(1+sizeof(string1));

sizeof(string1) — это размер указателя, а не строки. Использовать

str=(char*)malloc(1+strlen(string1));

вместо этого или, что еще лучше, используйте

str=malloc(1+strlen(string1));

потому что результат malloc не должен быть приведен.

person alain    schedule 05.03.2015
comment
я не понимаю, в чем проблема со строкой 1 в myatoi(). Я использовал операторы печати, и он работает нормально. Но спасибо за ссылку, сегодня узнал кое-что новое :) - person solinvictus; 05.03.2015
comment
Пожалуйста :-). string1 указывает на случайный адрес, потому что нет оператора, устанавливающего указатель (string1 = .....). Если этот случайный адрес читается или записывается, это чистая удача, что программа не падает. - person alain; 05.03.2015

Я не думаю, что проблема заключается в манипуляциях со строками. Скорее всего, это связано с созданием связанного списка. Попробуй это:

Прежде всего, попробуйте напечатать значение temp->data в цикле. Возможно, это должен быть мусор (в этом случае создание списка содержит проблемы). Если напечатанное значение правильное, проверьте, содержит ли возвращаемая строка «результат» то же значение или нет. Если нет, то проблема в функции myitoa.

Здесь я предполагаю, что myitoa выделяет память для строки1. (Если нет, то вам нужно выделить для нее часть памяти либо перед передачей в функцию, либо внутри myitoa.

person coolVick    schedule 05.03.2015
comment
Из вопроса: Связанный список построен правильно, так как печать связанного списка работает правильно. - person solinvictus; 05.03.2015
comment
Из ответа: здесь я предполагаю, что myitoa выделяет память для строки1 (если нет, то вам нужно выделить для нее некоторую память либо перед передачей ее функции, либо внутри myitoa.) - person coolVick; 05.03.2015