На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Помощь в автоматическом определении массива , Помощь в автоматическом определении массива, передоваемого в функцию как аргумент
    Добрый день/ночь!
    Прошу помочь в разрешении следующей проблемы:
    В программе на языке Си необходимо создать автоматическое вычисление размера массива, входящего в функцию как аргумент и вывод его на печать
    ExpandedWrap disabled
      #include <stdio.h>
       
       int massive1[] = {1, 2, 3, 4, 5, 55, 55, 66, 66666666};
       void outtput (int *array)
       {
       int lenght = 0;
       lenght = sizeof array/ sizeof array[0];
       
       printf ("\n\r array: %d bytes\n\r", sizeof array);
       printf ("\n\r array[0]:%d bytes\n\r", sizeof array[0]);
       printf("\n\r leenght:%d\n\r", lenght);
       
       for (int i = 0; i < lenght; i++)
       
       {
       printf("\r\n%d:%d\r\n", i, array [i]);
       
       }
       
       return ;
       }
       
       
       int main (void)
       {
       printf ("\r\n\r\n");
       outtput (massive1);
       printf ("\r\n\r\n");
       
       return 0;
       }

    В данном случае не правильно вычисляется размер массива lenght , входящего как аргумент в функцию. Помогите, пожалуйста, разрешить данную дилемму. Я не программист и если возможно решение, то реализовать его с объяснениями как для школьника. Спасибо
    Сообщение отредактировано: Qraizer -
      Примените форматирование кода, для этого есть специальная кнопка "CODE=cpp"

      Цитата дважды пятый @
      размер массива lenght

      Наверное, это потому что никакого массива внутри этой функции не существует)
        Цитата
        В данном случае не правильно вычисляется размер массива lenght

        Ты передаешь в качестве аргумента функции не массив а указатель на Int, sizeof возвращает размер указателя.
        ExpandedWrap disabled
          void outtput (int array[]) //измени аргумент на массив
          Цитата popsa @
          Ты передаешь в качестве аргумента функции не массив а указатель на Int, sizeof возвращает размер указателя.

          В си и в случае передачи int[] будет передаваться указатель.
            да, теперь понятно то, что в этом случае вычисляется размер в байтах указателя. Но, а как можно подкорректировать код, чтобы вычислялся размер длины элементов любого входящего в функцию массива, передаваемого в качестве аргумента?
              Никак. Или передавать количество элементов массива отдельным указателем или переходить на плюсы и писать шаблон функции с размером масиива в качестве параметра шаблона.
                Массивы всегда сводятся к указателям при сопоставлении аргументов параметрам. При этом теряется информация о размере, т.к. массив нигде свой размер не хранит. Однако на C++ это решается посредством ссылок и только для статических массивов, как в твоём коде.
                ExpandedWrap disabled
                  template <size_t N>
                  void outtput(int (&array)[N])
                  {
                    printf("\n\r array:   %d bytes\n\r", sizeof array);
                    printf("\n\r array[0]:%d bytes\n\r", sizeof array[0]);
                    printf("\n\r leenght:%d\n\r", N);
                   
                    for (int i = 0; i < N; i++)
                      printf("\r\n%d:%d\r\n", i, array [i]);
                  }
                Это будет работать, т.к. сведение массивов к указателям не применяется к ссылкам на массивы. Но если массив динамический, то даже это не будет работать, т.к. тут мы сразу имеем указатель:
                ExpandedWrap disabled
                    int *massive2 = new int[5];
                   
                    outtput(massive2);    // error C2784: void outtput(int (&)[N]): не удалось вывести аргумент шаблон для "int (&)[N]" из "int *"
                    delete[] massive2;
                Но можно извратиться с указателем на тип массива, тогда размер будет сохранён в самом типе:
                ExpandedWrap disabled
                    int (*massive2)[5] = new int[1][5];
                   
                    outtput(*massive2);
                    delete massive2;

                На C эта задача нерешаема, т.к. в нём нет ссылок.

                Это сообщение было перенесено сюда или объединено из темы "Размер массива-параметра функции"
                  Dushevny
                  Я понимаю, что можно передавать размер элементов массива вычисляя его:
                  в качестве аргумента как константу,
                  в качестве аргумента как расчетную величину,
                  или еще ка-либо.
                  Но в том и есть смысл, чтобы это происходило автоматически.
                    Цитата дважды пятый @
                    Но в том и есть смысл, чтобы это происходило автоматически.

                    Ничего автоматически происходить не будет. Чтобы не делать вариант, который предложил Qraizer, можешь умышленно увеличить длину всего массива на 1, и в 0 элемент записывать текущее число элементов в массиве, но, в сях нет классов, и применять подобный массив для решения задач - будет сложно... либо придётся мудрить над механизмом, который будет гарантированно следить за твоими шаманствами с массивом и автоматически корректировать этот нулевой элемент в соответствии с длинной массива, либо самостоятельно придётся после каждого new/malloc указывать текущую длину массива.

                    ExpandedWrap disabled
                      int *CreateArray(unsigned int count){
                         int *array = (int*)malloc(sizeof(int)*(count+1));
                         array[0] = count;
                         return array;
                      }


                    Соответственно, при чтении, необходимо опускать нулевой элемент:

                    ExpandedWrap disabled
                      void outtput(int *array) {
                       
                        int size = array[0];
                       
                        printf("\n\r lenght:%d\n\r",size);
                       
                        for (int i = 1; i <= size; i++)
                          printf("\r\n%d:%d\r\n", i, array [i]);
                      }
                       
                      int main(){
                          int *array = CreateArray(2);
                          array[1] = 1;
                          array[2] = 55;
                       
                          outtput(array);
                          free(array);
                       
                          return 0;
                      }
                    Сообщение отредактировано: VisualProg -
                      Можно массив засунуть в структуру и передавать структуру в качестве аргумента, а у аргумента уже получать размер поля типа массив по формуле из первого поста.
                        Цитата KILLER @
                        Можно массив засунуть в структуру и передавать структуру в качестве аргумента

                        Да, я про структуры забыл, это будет самый правильный способ
                          В чем его правильность? Шаблонов в Сях нет, под каждый размер массива придется делать свой уникальный тип структуры и под каждый тип структуры вручную писать свою функцию с уникальным именем - т.е. реализовывать закат солнцаплюсовый шаблон вручную с лишней сущностью в виде структуры. В нормальном удобном виде на голых Сях эта задача не решается. На плюсах - легко. Самое прямое, что можно тут придумать - сделать функию с двумя параметрами (указатель и размер) и вызывать ее через #define call_func(array) func(array, sizeof(array)). Но и это никак не защищает от попыток вызвать call_func() с указателем.
                          Сообщение отредактировано: Dushevny -
                            Цитата Dushevny @
                            В чем его правильность?

                            Соотношение между понятностью (читаемостью) и функциональностью (оно решает задачу). Вы говорите что это нерешаемая задача, KILLER предложил решение.

                            Из худших вариантов - этот самый правильный + такие структурки память потреблять будут в рамках разумного.

                            Цитата Dushevny @
                            Шаблонов в Сях нет, под каждый размер массива придется делать свой уникальный тип структуры и под каждый тип структуры вручную писать свою функцию с уникальным именем

                            Это си, в чём проблема? Я могу сейчас тоже высказать претензии и показать что на явашарпе решается всё проще, а толку? Язык Си, реализация на нём, как вы выразились, "Заката солнца" - это обычное дело. Ну, и про функции с уникальным именем - не соглашусь, хотябы пример приведите, где это нужно?
                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                            0 пользователей:


                            Рейтинг@Mail.ru
                            [ Script execution time: 0,0391 ]   [ 17 queries used ]   [ Generated: 18.04.24, 00:32 GMT ]