Найти максимальное значение и его адрес в списке - PullRequest
1 голос
/ 23 апреля 2020

C язык. Эта функция (Max_Value) должна найти максимальное значение и адрес следующего элемента. Я не знаю, почему это не работает. Это называется «ошибка сегментации».

struct List1 *GetAddress(struct List1* Start, int n)
{
    struct List1 *tmp;
    int count;
    if (n < 0 || n >ListLength(Start))
        return NULL;
    tmp = Start;
    for (count = 0; count < n; count++)
        tmp = tmp -> Next;
    return tmp;
}

int Get_Value(struct List1 *Start, int Number_Element)
{
    struct List1 *Buffer;
    Buffer = GetAddress(Start, Number_Element);
    return Buffer -> Info;
}

void Max_Value(struct List1 *Start)
{
    int Max;
    struct List1 *Max_Address;
    int Count;
    int Amount;
    int tmp;
    Amount = Start -> Info;
    Max = Get_Value(Start, Count);
    Max_Address = GetAddress(Start, Count + 1);
    for (Count = 1; Count < Amount; Count++)
    {        
        tmp = Get_Value(Start, Count);
        if (tmp > Max)
        {
            Max = tmp;
            Max_Address = GetAddress(Start, Count + 1);        
        }        
    }
    printf("\n");
    printf("%d -> %p\n", Max, Max_Address);
}

Ответы [ 3 ]

1 голос
/ 23 апреля 2020

Вы отправляете значение Count в GetAdress без инициализации, в C, если значение не инициализировано, оно получает неожиданное число, которое превышает размер вашего списка. Учитывая это, вы пытаетесь получить доступ за пределы списка, что возвращает ошибку сегментации.

0 голосов
/ 23 апреля 2020

У вас есть неопределенное поведение

Например, в Max_Value вы делаете Get_Value(Start, Count); без инициализации Count, поэтому весьма вероятно

Если GetAddress вызывается с n , оценивающим длину разыменованного вами списка NULL,

   if (n < 0 || n >ListLength(Start))

должно быть

    if (n < 0 || n >= ListLength(Start))

In Get_Value вы делаете

Buffer = GetAddress(Start, Number_Element);
return Buffer -> Info;

без проверки, если GetAddress возвращает NULL, поэтому вы можете разыменовать NULL снова


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


Ваш код также очень сложный и очень медленный потому что вы go бросаете список несколько раз. Простой способ сделать это:

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

struct List {
  int info;
  struct List * next;
};

void Max_Value(struct List * l)
{
  if (l == NULL)
    puts("empty list");
  else {
    struct List * pmax = l;
    int max = l->info;

    while ((l = l->next) != NULL) {
      if (l->info > max)
        pmax = l;
    }

    printf("max value %d (at %p), next is %p\n", max, pmax, pmax->next);
    if (pmax->next != NULL)
      printf("value of the next cell %d\n", pmax->next->info);
  }
}

// to help to make a list

struct List * mk(int v, struct List * n)
{
  struct List * l = malloc(sizeof(struct List));

  l->info = v;
  l->next = n;
  return l;
}

// free resources

void del(struct List * l)
{
  while (l) {
    struct List * n = l->next;

    free(l);
    l = n;
  }
}

int main()
{
  struct List * l;

  l = mk(3, mk(1, mk(4, mk(2, NULL))));
  Max_Value(l);
  del(l);

  l = mk(3, mk(1, mk(4, mk(22, NULL))));
  Max_Value(l);
  del(l);

  return 0;
}
0 голосов
/ 23 апреля 2020

Причина в том, что вы используете переменную Count, которая не имеет начального значения. Следовательно, начальное число является случайным числом. если начальное значение «Count» больше размера List, GetAddress вернет ноль. Затем функция Get_Value попытается получить доступ к Null-> Info, затем вы получили ошибку сегментации

...