На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Работа с матрицами в С , Не работает сортировка методом просеивания
    Здравствуйте. Помогите, пожалуйста, с задачей: Дана матрица размером n*n. Проверить упорядочены ли элементы столбцов матрицы. Если нет, то упорядочить их в порядке возрастания методом просеивания.
    У меня в программе используется динамическая матрица с указателями и при сортировке выкидывает из программы. Я подозреваю, что там происходит выход за границы матрицы.
    Вот мой исходный код:
    ExpandedWrap disabled
      #include <stdio.h>
      #include <stdlib.h>
      #include <conio.h>
      #include <malloc.h>
       
      int menu(int kp, char*NAZ[]);
      int main(void);
      void vvod(int n, int ***A);
      void vivod(int n, int **A);
      int zadacha1(int n, int kk, int pp, int **A);
      int zadacha2(int n, int **A);
       
      int menu(int kp, char*NAZ[])
      {
          int k, i;
          for (i = 0; i < kp; i++)
          printf("\n %d %s", i + 1, NAZ[i]);
          printf("\n\n Viberite punct menu ->");
          scanf("%d",&k);
          return k;
      }
       
      void vvod(int n, int ***D)
      {
          int i, j;
          printf("Vvedite razmernost matrici n=");
          scanf("%d", n);
          if (*D != NULL) free(*D);
          int **A = (int **) malloc (n * sizeof (int *));
          for (i = 0; i < n; i++)
              A[i] = (int *) malloc(n * sizeof (int));
              
              for (i = 0; i < n; i++)
                  for (j = 0; j < n; j++)
                  {
                      printf("A[%d][%d]=", i,j);
                      scanf("%d", &A[i][j]);
                  }
                  *D = A;  
      }
       
      void vivod(int n, int **A)
      {
          int i,j;
          for (i = 0; i < n; i++)
          {                  
              for (j = 0; j < n; j++)
                  printf("%2d", A[i][j]);
              printf("\n");
          }
      }
       
      int zadacha1(int n, int **A)
      {
          int i, j, kk, pp;
          //kk = 0;
          pp = 0;
          for (j=0; j<n; j++)
          {
              for (i=0; i<n; i++)
                  if (A[i][j]==0) pp=1;
                  if (pp==0) kk++;
          }
          printf("Kolichestvo stolbcov bez 0=%d",kk);
      }
       
      int zadacha2(int n, int **A)
      {
          int i, j, k, p, q, r;
          for (j = 0; j < n; j++)
          {
              k = p = 0;  
              for (j = 0; j < n - 1; j++)
                  if (A[i][j] <= A[i][j + 1]) k++;
                  else
                  p++;
          
              for (j = 0; j < n; ++j)
              {
                  for (i = 0; i < n - 1; ++i)
                  {
                      if (A[i][j] > A[i + 1][j])
                      {
                          r = A[i][j];
                          A[i][j] = A[i + 1][j];
                          A[i + 1][j] = r;
                          q = i;
                      }
                      while (A[q][j] < A[q - 1][j] && q > 0)
                      {
                          r = A[q][j];
                          A[q][j] = A[q - 1][j];
                          A[q - 1][j] = r;
                          q = q - 1;
                      }  
                  }
              }  
          }  
      }
       
      int main()
      {
          int n, **A = 0, kol = 5, nom, i;
          long proizved;
          char*nazv[] = {"Vvod", "Vivod",
          "Kolichestvo stolbcov, ne soderjashix ni 1 nulevogo elementa", "Sortirovka matrici metodom proseivaniya", "Exit"};
          while(1)          
          {
              nom = menu(kol, nazv);
              switch(nom)
              {
                  case 1: vvod(&n, &A);
                  break;
                  case 2: system("cls");
                  if (A != NULL) vivod(n, A);
                      else printf("Vvedite matricu!");
                  getch();
                  break;
                  case 3: system("cls");
                  if (A != NULL)    
                  {
                      vivod(n, A);
                      zadacha1(n, A);  
                  }
                  else printf("Vvedite matricu!");
                  getch();    
                  break;
                  case 4: system("cls");
                  if (A != NULL)    
                  {
                      vivod(n,A);
                      zadacha2(n, A);
                      printf("\n\n");
                      vivod(n, A);
                  }
                  else printf("Vvedite matricu!");
                  getch();    
                  break;
                  case 5:
                  return 0;
                  for(i = 0; i < n; i++)
                      free(A[i]);
                      free(A);
              }
          }
      }
      1. В функции vvod вы в scanf кидаете значение n, а надо - адрес (место, куда запишется размерность)! ;)
      2. В функциях vivod, zadacha1 и zadacha2 компилятор не знает размерность матрицы, а потому обеспечить столь желаемое A[k][j] не сможет правильно.
      3. В функции zadacha1 переменная kk не инициализируется. Несколько опасно сие. "pp=0" надо внести внутрь первого for'а.

      Добавлено
      Ой, виноват: второй пункт замечаний отменяется! :oops:

      Добавлено
      2. В функции vvod надо заменить (видимо) на: "void vvod(int *n,", а в выделении памяти и в циклах там использовать (*n).
      Сообщение отредактировано: Славян -
        Я вроде бы всё исправил, что вы сказали, теперь после ввода размерности матрицы вылетает из программы:
        ExpandedWrap disabled
          #include <stdio.h>
          #include <stdlib.h>
          #include <conio.h>
          #include <malloc.h>
           
          int menu(int kp, char*NAZ[]);
          int main(void);
          void vvod(int *n, int ***A);
          void vivod(int n, int **A);
          int zadacha1(int n, int kk, int pp, int **A);
          int zadacha2(int n, int **A);
           
          int menu(int kp, char*NAZ[])
          {
              int k, i;
              for (i = 0; i < kp; i++)
              printf("\n %d %s", i + 1, NAZ[i]);
              printf("\n\n Viberite punct menu ->");
              scanf("%d",&k);
              return k;
          }
           
          void vvod(int *n, int ***D)
          {
              int i, j;
              printf("Vvedite razmernost matrici n=");
              scanf("%d", &n);
              if (*D != NULL) free(*D);
              int **A = (int **) malloc (*n * sizeof (int *));
              for (i = 0; i < *n; i++)
                  A[i] = (int *) malloc(*n * sizeof (int));
                  
                  for (i = 0; i < *n; i++)
                      for (j = 0; j < *n; j++)    
                      {
                          printf("A[%d][%d]=", i,j);
                          scanf("%d", &A[i][j]);
                      }
                      *D = A;  
          }
           
          void vivod(int n, int **A)
          {
              int i,j;
              for (i = 0; i < n; i++)
              {                  
                  for (j = 0; j < n; j++)
                      printf("%2d", A[i][j]);
                  printf("\n");
              }
          }
           
          int zadacha1(int n, int **A)
          {
              int i, j, kk, pp;
              kk = 0;
              //pp = 0;
              for (j=0; j<n; j++)
              {
                  pp = 0;
                  for (i=0; i<n; i++)
                      if (A[i][j]==0) pp=1;
                      if (pp==0) kk++;
              }
              printf("Kolichestvo stolbcov bez 0=%d",kk);
          }
           
          int zadacha2(int n, int **A)
          {
              int i, j, k, p, q, r;
              for (j = 0; j < n; j++)
              {
                  k = p = 0;  
                  for (j = 0; j < n - 1; j++)
                      if (A[i][j] <= A[i][j + 1]) k++;
                      else
                      p++;
              
                  for (j = 0; j < n; ++j)
                  {
                      for (i = 0; i < n - 1; ++i)
                      {
                          if (A[i][j] > A[i + 1][j])
                          {
                              r = A[i][j];
                              A[i][j] = A[i + 1][j];
                              A[i + 1][j] = r;
                              q = i;
                          }
                          while (A[q][j] < A[q - 1][j] && q > 0)
                          {
                              r = A[q][j];
                              A[q][j] = A[q - 1][j];
                              A[q - 1][j] = r;
                              q = q - 1;
                          }  
                      }
                  }  
              }  
          }
           
          int main()
          {
              int n, **A = 0, kol = 5, nom, i;
              long proizved;
              char*nazv[] = {"Vvod", "Vivod",
              "Kolichestvo stolbcov, ne soderjashix ni 1 nulevogo elementa", "Sortirovka matrici metodom proseivaniya", "Exit"};
              while(1)          
              {
                  nom = menu(kol, nazv);
                  switch(nom)
                  {
                      case 1: vvod(&n, &A);
                      break;
                      case 2: system("cls");
                      if (A != NULL) vivod(n, A);
                          else printf("Vvedite matricu!");
                      getch();
                      break;
                      case 3: system("cls");
                      if (A != NULL)    
                      {
                          vivod(n, A);
                          zadacha1(n, A);  
                      }
                      else printf("Vvedite matricu!");
                      getch();    
                      break;
                      case 4: system("cls");
                      if (A != NULL)    
                      {
                          vivod(n,A);
                          zadacha2(n, A);
                          printf("\n\n");
                          vivod(n, A);
                      }
                      else printf("Vvedite matricu!");
                      getch();    
                      break;
                      case 5:
                      return 0;
                      for(i = 0; i < n; i++)
                          free(A[i]);
                          free(A);
                  }
              }
          }
          ExpandedWrap disabled
                void vvod(int n, int ***D)
                {
                    int i, j;
                    int** A;
                    printf("Vvedite razmernost matrici n=");
                    scanf("%d", &n);
                    if (*D != NULL)
                        free(*D);
                    A = (int **) malloc (n * sizeof (int *));
                    for (i = 0; i < n; i++)
                        A[i] = (int *) malloc(n * sizeof (int));
                
                        for (i = 0; i < n; i++)
                            for (j = 0; j < n; j++)    
                            {
                                printf("A[%d][%d]=", i,j);
                                scanf("%d", &A[i][j]);
                            }
                            *D = A;  
                }


          1. зачем юзать транслитерацию, когда можно заюзать setlocale с руссификацией всех диалогов
          2. слабейшие названия переменных (аля x, y, n, f etc)
          3. не понимаю и никогда не понимал, зачем записывать больше одного оператора в 1-й строке (в отладчике потом запаришься)

          Добавлено
          4. комплияция на чистом СИ (анси 89) не пройдет твоей прожки! есть 1-а ошибка..(хинт: объявление А!)
            Цитата FasterHarder @
            4. комплияция на чистом СИ (анси 89) не пройдет твоей прожки! есть 1-а ошибка..(хинт: объявление А!)
            Пройдёт. Это такое же описание указателя на указатель на целое, как и у тебя. У него в функции vvod ошибка с освобождением D, происходит утечка памяти, так как он массивы второго уровня не освобождает.
              Цитата amk @
              Пройдёт

              не пройдет ;) проверял
              посмотри ф-цию vvod, переменная A объявляется НИЖЕ операторов printf/scanf - по стандарту ANSI C это недопустимо
                Andrey_2019, вы переправили чуть больше, чем надо было! В функции vvod у вас уже посылается адрес n(входной парам.), поэтому при scanf'е не надо снова брать адрес, надо просто n отдать (это ж адрес!). ;)
                  Всё, я уже починил эту программу. Всем огромное спасибо, кто помогал. Вот мой код, если кому нужно:
                  ExpandedWrap disabled
                    #include <stdio.h>
                    #include <stdlib.h>
                    #include <conio.h>
                    #include <malloc.h>
                     
                     
                    int menu(int count, char* menu[])
                    {
                        int k;
                     
                        for (int i = 0; i < count; i++)
                            printf("\n %d %s", i + 1, menu[i]);
                        printf("\n\n Viberite punct menu ->");
                        scanf("%d",&k);
                     
                        return k;
                    }
                     
                    void vvod(int *n, int ***D)
                    {
                        printf("Vvedite razmernost matrici n=");
                        scanf("%d", n);
                        if (*D != NULL) free(*D);
                        int **A = (int **) malloc (*n * sizeof (int *));
                        for (int i = 0; i < *n; i++)
                            A[i] = (int *) malloc(*n * sizeof (int));
                        for (int i = 0; i < *n; i++)
                            for (int j = 0; j < *n; j++)
                            {
                                printf("A[%d][%d]=", i,j);
                                scanf("%d", &A[i][j]);
                            }
                        *D = A;
                    }
                     
                    void vivod(int n, int **A)
                    {
                        for (int i = 0; i < n; i++)
                        {
                            for (int j = 0; j < n; j++)
                                printf("%2d", A[i][j]);
                            printf("\n");
                        }
                    }
                     
                    int zadacha1(int n, int **A)
                    {
                        int kk, pp;
                        kk = 0;
                        for (int j = 0; j < n; j++)
                        {
                            pp = 0;
                            for (int i = 0; i < n; i++)
                                if (A[i][j] == 0)
                                {
                                    pp = 1;
                                    break;
                                }
                     
                            if (pp == 0)
                                kk++;
                        }
                        printf("Kolichestvo stolbcov bez 0=%d",kk);
                    }
                     
                    int zadacha2(int n, int **A)
                    {
                        int q, swapper;
                        for (int i = 0; i < n; i++)
                            for (int j = 0; j < n - 1; j++)
                                if (A[j][i] > A[j + 1][i])
                                {
                                    swapper = A[j][i];
                                    A[j][i] = A[j + 1][i];
                                    A[j + 1][i] = swapper;
                     
                                    if (j == 0)
                                        continue;
                     
                                    q = j;
                                    while (A[q][i] < A[q-1][i])
                                    {
                                        swapper = A[q][i];
                                        A[q][i] = A[q-1][i];
                                        A[q-1][i] = swapper;
                                        if (q-- == 1)
                                            break;
                                    }
                                }
                     
                    }
                     
                    int main()
                    {
                        int kol = 5;
                        int n, **A = 0, nom, i;
                        long proizved;
                        char* mainMenu[] = {
                                "Vvod",
                                "Vivod",
                                "Kolichestvo stolbcov, ne soderjashix ni 1 nulevogo elementa",
                                "Sortirovka matrici metodom proseivaniya",
                                "Exit"};
                     
                        while(1)
                        {
                            nom = menu(kol, mainMenu);
                            switch(nom)
                            {
                                case 1:
                                    vvod(&n, &A);
                                    break;
                                case 2:
                                    system("cls");
                                    if (A != NULL)
                                        vivod(n, A);
                                    else
                                        printf("Vvedite matricu!");
                                    getch();
                                    break;
                                case 3:
                                    system("cls");
                                    if (A != NULL)
                                    {
                                        vivod(n, A);
                                        zadacha1(n, A);
                                    }
                                    else
                                        printf("Vvedite matricu!");
                                    getch();
                                    break;
                                case 4:
                                    system("cls");
                                    if (A != NULL)
                                    {
                                        vivod(n, A);
                                        zadacha2(n, A);
                                        printf("\n\n");
                                        vivod(n, A);
                                    }
                                    else
                                        printf("Vvedite matricu!");
                                    getch();
                                    break;
                                case 5:
                                    return 0;
                                    for(i = 0; i < n; i++)
                                        free(A[i]);
                                    free(A);
                            }
                        }
                    }
                    Цитата FasterHarder @
                    переменная A объявляется НИЖЕ операторов printf/scanf
                    Точно, отвык уже (уточнение: printf и scanf не операторы, а вызовы функций, а вот следующий за ними if - оператор). Правда об этом компилятор сообщит. А утечка памяти пройдёт незамеченной.
                    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                    0 пользователей:


                    Рейтинг@Mail.ru
                    [ Script execution time: 0,0538 ]   [ 16 queries used ]   [ Generated: 29.03.24, 01:34 GMT ]