Функция сортировки не работает должным образом внутри цикла - PullRequest
0 голосов
/ 03 апреля 2019

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

Когда я помещаю функцию sort в цикл for, она не работает должным образом и просто заменяет значения. Например, во-первых, если я даю «аба», он печатает «аба», во-вторых, если я даю «плохо», он печатает «аба, плохо», в-третьих, если я даю «папа», он печатает «аба, папа». Сортировка заменяется на последнее значение. Парадокс в том, что вне цикла for он работает нормально. Любое предложение будет оценено.

void sort(char** cities) 
{ 
    int i, j; 

    // Perform sort operation using bubble sort 
    for (i = 0; i < 3 - 1; i++) 
        for (j = 0; j < 3 - i - 1; j++) 
            if (strcmp(cities[j], cities[j + 1]) > 0) { 
                char* temp; 
                temp = (char*)calloc(30, sizeof(char)); 
                strcpy(temp, cities[j]); 
                strcpy(cities[j], cities[j + 1]); 
                strcpy(cities[j + 1], temp); 
            } 
} 

int main(int argc, char** argv) {
    char** cities;

    cities = (char**)calloc(3,sizeof(char*)); 

    for(int i=0;i<3;i++)
    {
         cities[i]=(char*)calloc(3,sizeof(char));
    }

    for(int i=0;i<3;i++)
    {
        printf("Give City %d:\n",i); 
        scanf("%s",cities[i]);
        if (i==0)
            printf("%s\n",cities[0]); //1st case of nothing to compare
        else
        {
            sort(cities);
            printf("\nArray after sorting %d time:\n",i); 
            for (int i = 0; i <3; i++) 
                printf("%s\n", cities[i]);    //prin current array of cites sorted
        }
    }

    free(cities);            
    return (EXIT_SUCCESS);
}

Ответы [ 2 ]

2 голосов
/ 03 апреля 2019

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

Ваша функция сортировки выглядит правильно (-ish) для сортировки массива ровно из трех элементов. Это приводит к утечке памяти, и было бы лучше просто поменять местами указатели, чем копировать содержимое строки, но при этом элементы должны быть расположены в возрастающей лексикографической последовательности. Но, как я заметил в комментариях, вы называете это не только после того, как прочитали все городские данные, но и после того, как прочитали только первые два. Посмотрим, что будет потом.

Ответ: поскольку вы распределяете строковые данные с помощью calloc(), содержимое инициализируется нулевым значением. В частности, тогда изначально байт с нулевым индексом в каждой строке равен 0, так что строка будет интерпретироваться как пустая строка. Когда вы сортируете после заполнения только двух элементов массива, пустая строка в третьей позиции будет сортироваться по началу массива. Когда вы затем читаете название третьего города, вы перезаписываете какая бы строка не сортировалась на третью позицию. Затем, когда вы печатаете города в конце, вы упускаете из виду тот факт, что в начале списка городов есть лишняя пустая строка, в которой была напечатана пустая строка, которую вы отсортировали вперед.

Лучше всего подождать, пока все данные будут введены. Учитывая, что вы читаете все данные одновременно, сортировка на промежуточных этапах дает мало преимуществ. Но если вы должны выполнить сортировку после ввода только некоторых элементов, то вы должны быть уверены, что отсортировали только те элементы, которые были прочитаны до этого момента.

2 голосов
/ 03 апреля 2019
 cities[i]=(char*)calloc(3,sizeof(char));

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

но в

scanf("%s",cities[i]);

возможно, вы вводите более 2 символов ...


Вы вызываете sort , не указывая, сколько было введено цитирований, поэтому sort работает в 3 городах, даже если введено только 2, и доступ к третьей строке до ее инициализации, с неопределенное поведение, когда strcmp обращается к нему


В

temp = (char*)calloc(30, sizeof(char)); 

вы создаете утечку памяти, потому что не освобождаетесь temp ,

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

Вы также не освобождаете названия городов в конце основного


Предложение из вашего кода, управляющее любым количеством городов, ввод заканчивается на EOF (control-d), название города ограничено 30 символами (см. Защиту в scanf )

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

void sort(char** cities, int n) 
{ 
    int i, j; 

    // Perform sort operation using bubble sort 
    for (i = 0; i < n - 1; i++) {
      for (j = 0; j < n - i - 1; j++) {
        if (strcmp(cities[j], cities[j + 1]) > 0) { 
          char* temp = cities[j]; 

          cities[j] =  cities[j + 1];
          cities[j + 1] = temp;
        }
      } 
    }
} 

int main() {
  char ** cities = malloc(0);
  char name[31];
  int n = 0, i;

  while (printf("Give City %d:\n", n), (scanf("%30s", name) == 1))
  {
    cities = realloc(cities, (++n) * sizeof(char *));
    cities[n - 1] = strdup(name);

    if (n == 1)
      printf("%s\n",cities[0]); //1st case of nothing to compare
    else {
      sort(cities, n);
      printf("\nArray after sorting %d time:\n", n); 
      for (i = 0; i < n; i++) 
        printf("%s\n", cities[i]);    //print current array of cites sorted
    }
  }

  for (i = 0; i < n; i++) 
    free(cities[i]);

  free(cities);            

  return (EXIT_SUCCESS);
}

Компиляция и исполнение:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
Give City 0:
qsd
qsd
Give City 1:
aze

Array after sorting 2 time:
aze
qsd
Give City 2:
wxc

Array after sorting 3 time:
aze
qsd
wxc
Give City 3:
<control-d>

Исполнение под valgrind :

pi@raspberrypi:/tmp $ valgrind ./a.out
==23191== Memcheck, a memory error detector
==23191== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==23191== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==23191== Command: ./a.out
==23191== 
Give City 0:
qsdqsdqsd
qsdqsdqsd
Give City 1:
aze

Array after sorting 2 time:
aze
qsdqsdqsd
Give City 2:
wxcwxcwxcwxcwxc

Array after sorting 3 time:
aze
qsdqsdqsd
wxcwxcwxcwxcwxc
Give City 3:
<control-d>
==23191== 
==23191== HEAP SUMMARY:
==23191==     in use at exit: 0 bytes in 0 blocks
==23191==   total heap usage: 9 allocs, 9 frees, 2,102 bytes allocated
==23191== 
==23191== All heap blocks were freed -- no leaks are possible
==23191== 
==23191== For counts of detected and suppressed errors, rerun with: -v
==23191== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...