Обсуждение Программирование на C/C++

Здравствуйте форумчане, подскажите пожалуйста, допустим у меня есть некая структурная переменная в некой функции, как мне использовать эту структуру в другой функции, кроме как объявлять глобально?
ну и для примера код:
#include "struct.h" - здесь объявлена структура TEST
func()
{
TEST a;
}

func2()
{
int x = a.x; // Как мне использовать её в этой в функции?
}

Спасибо.
 
Здравствуйте форумчане, подскажите пожалуйста, допустим у меня есть некая структурная переменная в некой функции, как мне использовать эту структуру в другой функции, кроме как объявлять глобально?
Глобальные переменные - зло. Передать структуру в функцию параметром по ссылке или значению.
 
Глобальные переменные - зло. Передать структуру в функцию параметром по ссылке или значению.
Это хорошо когда одна структура, а если их куча, то создавать в функции кучу аргументов, а другого способа нет?)
Если надо передавать кучу чего-либо куда-нибудь, то надо пользоваться аггрегированием (аггрегацией). Кроме того, если у тебя возникает необходимость передавать много параметров в функцию, то это означает что она скорее всего перегружена функционалом и что-то неладно с самим дизайном приложения.

В твоём случае можно создать структуру которая будет включать в себя ту кучу которую надо передать.

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

В твоём случае можно создать структуру которая будет включать в себя ту кучу которую надо передать.

Это вообще-то одна из проблем дизайна программ. С одной стороны надо постараться чтобы данные в некую подсистему попадали единственным и легко контролируемым способом - легко понять, легко отлаживаться. С другой стороны, сделать так чтобы попадали только те данные которые ей реально нужны, а к данным которые ей не нужны подсистема не имела бы доступа. С третьей стороны организовать это так чтобы меры предпринятые выше не усложняли программу, были логичны и понятны. Чем более крупная и развесистая программа, тем больше в ней возникает необходимость делать подобное.
Хорошо, спасибо, попробую сделать структуру :)
 
Хорошо, спасибо, попробую сделать структуру :)
Альтернативный подход - использовать рефакторинг выделение метода в класс. Т.е. вместо функции/метода с кучей параметров создаётся класс в котором парметры являются членами этого класса, а собственно действие функции реализуется методом этого класса, который получает на вход минимально необходимое количество параметров. Все прочие "параметры" либо скармливаются в конструктор класса, либо реализуются свойствами.
 
Как мне использовать её в этой в функции?
Никак, т.к. у них разная область действия. В твоем случае переменная создается при вызове func и уничтожается при выходе из функции.
Можно объявить ее выше:
#include "struct.h" - здесь объявлена структура TEST
TEST a;
func()
{

}

func2()
{
int x = a.x; // Как мне использовать её в этой в функции?
}
 

bulldog

Ословед
не создаются проекты в c++ vs2013 ultimate, пишет просто "не удалось создать проект", винда 7 64 бита, может кто решение подсказать?
 
Объявлены не используемые члены класса - .DB_PATH и LIC_PATH. Чтобы исправить удали их описание.
 

TAPAHOB_Х@й

Ословед
Апну немного тему. Есть задача запаковать в один float 3 целочисленных значения. Есть и ее решение:

PHP:
#include <iostream>
#include <math.h>
#include <conio.h>

using namespace std;

#define MULTIPLIER 128.0f

int main()
{
    float values [] = { 10.0f, 20.0f, 30.0f };
    float packed = 0.0f;
    packed =
        values[0] +
        values[1] / MULTIPLIER +
        values[2] / (MULTIPLIER * MULTIPLIER);

    cout << "packed: " << packed << endl;

    float unpacked[3] = { 0.0f, 0.0f, 0.0f };
    unpacked[0] = packed * 1.0f / MULTIPLIER;
    unpacked[1] = packed * 1.0f;
    unpacked[2] = packed * MULTIPLIER;
    
    for (int i = 0; i < 3; ++i)
        unpacked[i] = (unpacked[i] - floor(unpacked[i])) * MULTIPLIER;

    cout << (int)unpacked[0] << " " << (int)unpacked[1] << " " << (int)unpacked[2] << endl;
    getch();
}
Собственно вопрос - какое максимальное значение можно запаковать таким макаром без потерь точности?
Edit1: перебором выходит что максимум во float входит 3 целочисленных числа до 127 при множителе 128, а в double 3 числа до 131071 при множителе 131072 либо 4 числа до 8191 при множителе 8192
 

Alexandr172

Ословед
Апну немного тему. Есть задача запаковать в один float 3 целочисленных значения. Есть и ее решение:

PHP:
#include <iostream>
#include <math.h>
#include <conio.h>

using namespace std;

#define MULTIPLIER 128.0f

int main()
{
    float values [] = { 10.0f, 20.0f, 30.0f };
    float packed = 0.0f;
    packed =
        values[0] +
        values[1] / MULTIPLIER +
        values[2] / (MULTIPLIER * MULTIPLIER);

    cout << "packed: " << packed << endl;

    float unpacked[3] = { 0.0f, 0.0f, 0.0f };
    unpacked[0] = packed * 1.0f / MULTIPLIER;
    unpacked[1] = packed * 1.0f;
    unpacked[2] = packed * MULTIPLIER;
    
    for (int i = 0; i < 3; ++i)
        unpacked[i] = (unpacked[i] - floor(unpacked[i])) * MULTIPLIER;

    cout << (int)unpacked[0] << " " << (int)unpacked[1] << " " << (int)unpacked[2] << endl;
    getch();
}
Собственно вопрос - какое максимальное значение можно запаковать таким макаром без потерь точности?
Edit1: перебором выходит что максимум во float входит 3 целочисленных числа до 127 при множителе 128, а в double 3 числа до 131071 при множителе 131072 либо 4 числа до 8191 при множителе 8192
float - 4 байта - 4 байта и можно записать
double - 8 байт - 8 байт можно записать
 

SunnyMan

Namynnuz
Вопрос, конечно, забавный, но несколько глупый. «Запаковывания» не получится, так как сам по себе float подразумевает некоторое использование информации для передачи как раз таки «дробности».


Вообще, всё несколько сложнее. Вообще, sizeof различных данных бывает разным для разных языков, компиляторов и даже систем. Так, что понимать под целочисленными данными? Так, byte, char, short, int, long — все являются целочисленными (в С++ вообще всё довольно сложно с типами данных, существует большое количество не всегда логичных алиасов). Гораздо проще говорить в таком случае об (u)int8, (u)int16, и т.д. При этом sizeof(int) = 4, как и у float для большинства систем. Имеется ввиду int32.


attachment.php



Так, 9 бит информации уйдут только на запись знака числа и его степени (и если не соблюдать эту структуру, число можно и, пожалуй, следует трактовать совсем по-другому). В этом плане те же 4 байта информации гораздо сподручнее представить как просто 3 числа, слепленные вместе. Проблема лишь в том, что 4 байта — слишком малое количество информации, где можно было бы вовсю развернуться и попытаться определить длину каждого из чисел в битах/байтах по данным в начале. Хотя можно попробовать.


Смотри. Четыре байта это, как бы это очевидно не звучало, 4 подряд идущих байта. Один байт — 8 бит, каждый из которых имеет значение 0 или 1. В двоичной системе счисления максимальное число, которое можно засунуть в байт это 1111'1111. Что в десятичной системе счисления будет равно 255. Каждый бит может быть в двух состояниях: 0 или 1. всего битов 8. По простейшей комбинаторной формуле число полных переборов для двоичного числа из 8 знаков составит 2[SUP]8[/SUP] = 256 (а равно 255, потому что 0 — тоже число, и с него начинается отсчёт; таким образом, чисел 256).


Обычно для сжатия подобной записи числа пишут в шестнадцатеричной системе счисления. Я не зря отделил первые четыре единички. 2[SUP]4[/SUP] = 16. В шестнадцатеричной системе счисления 16 является «десяткой», значением перехода на следующий порядок. Так как у цифр для этого «нет слов», то после 10 идут A, B, C, D, E и F. И так 16[SUB]10[/SUB] = 1111'1111[SUB]2[/SUB] = F'F[SUB]16[/SUB].


Один байт, таким образом, вмещает в себя максимальное числе 255[SUB]10[/SUB] которое, для краткости, запишем в виде F'F[SUB]16[/SUB]. У нас же четыре байта, что вмещает в себя число F'F'F'F'F'F'F'F[SUB]16[/SUB]. Что равно 4294967295[SUB]10[/SUB].


Так что, очень сильно извратившись, можно побитово считывать х'х'х'х'х'х'х'х, где первые два числа определённой длины будут указывать максимальную длину. В любом случае, в памяти это будет лишь, по сути, присоединенные друг к другу числа. И именно таким образом можно передать максимальные значения. Допустим, 32 единцы-нолика, если поделить их пополам, дадут 16. Предположим, что-то около этого будет максимальной длиной передаваемого числа. Тогда резервируем первые две F-ки (или байт, или два числа с максимумом в 15, или одно с максимумом в 255) под «разрезы», допустим, 7й бит и 3й (+7). Ну и ещё можно учитывать смещение от первого байта.


Ну и получится: 0111 (7), 0011 (3), 0ххх'хххх [7], 0ххх [3], [всё, что осталось, что, по сути, равно 32 - 4 - 4 - 7 - 3 = 14]. Учитывая такой расклад, в трёх байтах можно будет уместить максимально числа:
0111'1111[SUB]2[/SUB] = 7'F[SUB]16[/SUB]= 127[SUB]10[/SUB];
0111[SUB]2[/SUB] = 7[SUB]16[/SUB] = 7[SUB]10[/SUB];
0011'1111'1111'1111[SUB]2[/SUB] = 3'F'F'F[SUB]16[/SUB] = 16383[SUB]10[/SUB].


А суммарно это всё будет выглядеть, логично, так: 0111'0011'xxxx'xxxx'xxxx'xxxx'xxxx'xxxx, что, при подстановке максимальных значений превратится в 0111'0011'1111'1111'1111'1111'1111'1111[SUB]2[/SUB] = 7'3'F'F'F'F'F'F[SUB]16[/SUB]= 1946157055[SUB]10[/SUB]. Вот такая вот порнография.


В любом случае, это совершенно непонятное дрочево (и ради чего?). Так-то ты, конечно, сегодня много чего нового узнал, но это не отвечает на вопрос. Использование же математических формул, вывод множителей в первые байты, перестановки их и прочее больше похоже на шифрование или хеширование и вряд ли так просто даст результат лучше (опять же, всё зависит от краевых условий, и тут больше к вопросу строгого математического доказательства). К слову, если хочешь действительно «упаковать» что-то, тебе, вероятно, стоит с оным познакомиться. А раз нет задачи — нет и решения.
 

TAPAHOB_Х@й

Ословед
Вопрос, конечно, забавный, но несколько глупый. «Запаковывания» не получится, так как сам по себе float подразумевает некоторое использование информации для передачи как раз таки «дробности».


Вообще, всё несколько сложнее. Вообще, sizeof различных данных бывает разным для разных языков, компиляторов и даже систем. Так, что понимать под целочисленными данными? Так, byte, char, short, int, long — все являются целочисленными (в С++ вообще всё довольно сложно с типами данных, существует большое количество не всегда логичных алиасов). Гораздо проще говорить в таком случае об (u)int8, (u)int16, и т.д. При этом sizeof(int) = 4, как и у float для большинства систем. Имеется ввиду int32.


attachment.php



Так, 9 бит информации уйдут только на запись знака числа и его степени (и если не соблюдать эту структуру, число можно и, пожалуй, следует трактовать совсем по-другому). В этом плане те же 4 байта информации гораздо сподручнее представить как просто 3 числа, слепленные вместе. Проблема лишь в том, что 4 байта — слишком малое количество информации, где можно было бы вовсю развернуться и попытаться определить длину каждого из чисел в битах/байтах по данным в начале. Хотя можно попробовать.


Смотри. Четыре байта это, как бы это очевидно не звучало, 4 подряд идущих байта. Один байт — 8 бит, каждый из которых имеет значение 0 или 1. В двоичной системе счисления максимальное число, которое можно засунуть в байт это 1111'1111. Что в десятичной системе счисления будет равно 255. Каждый бит может быть в двух состояниях: 0 или 1. всего битов 8. По простейшей комбинаторной формуле число полных переборов для двоичного числа из 8 знаков составит 2[SUP]8[/SUP] = 256 (а равно 255, потому что 0 — тоже число, и с него начинается отсчёт; таким образом, чисел 256).


Обычно для сжатия подобной записи числа пишут в шестнадцатеричной системе счисления. Я не зря отделил первые четыре единички. 2[SUP]4[/SUP] = 16. В шестнадцатеричной системе счисления 16 является «десяткой», значением перехода на следующий порядок. Так как у цифр для этого «нет слов», то после 10 идут A, B, C, D, E и F. И так 16[SUB]10[/SUB] = 1111'1111[SUB]2[/SUB] = F'F[SUB]16[/SUB].


Один байт, таким образом, вмещает в себя максимальное числе 255[SUB]10[/SUB] которое, для краткости, запишем в виде F'F[SUB]16[/SUB]. У нас же четыре байта, что вмещает в себя число F'F'F'F'F'F'F'F[SUB]16[/SUB]. Что равно 4294967295[SUB]10[/SUB].


Так что, очень сильно извратившись, можно побитово считывать х'х'х'х'х'х'х'х, где первые два числа определённой длины будут указывать максимальную длину. В любом случае, в памяти это будет лишь, по сути, присоединенные друг к другу числа. И именно таким образом можно передать максимальные значения. Допустим, 32 единцы-нолика, если поделить их пополам, дадут 16. Предположим, что-то около этого будет максимальной длиной передаваемого числа. Тогда резервируем первые две F-ки (или байт, или два числа с максимумом в 15, или одно с максимумом в 255) под «разрезы», допустим, 7й бит и 3й (+7). Ну и ещё можно учитывать смещение от первого байта.


Ну и получится: 0111 (7), 0011 (3), 0ххх'хххх [7], 0ххх [3], [всё, что осталось, что, по сути, равно 32 - 4 - 4 - 7 - 3 = 14]. Учитывая такой расклад, в трёх байтах можно будет уместить максимально числа:
0111'1111[SUB]2[/SUB] = 7'F[SUB]16[/SUB]= 127[SUB]10[/SUB];
0111[SUB]2[/SUB] = 7[SUB]16[/SUB] = 7[SUB]10[/SUB];
0011'1111'1111'1111[SUB]2[/SUB] = 3'F'F'F[SUB]16[/SUB] = 16383[SUB]10[/SUB].


А суммарно это всё будет выглядеть, логично, так: 0111'0011'xxxx'xxxx'xxxx'xxxx'xxxx'xxxx, что, при подстановке максимальных значений превратится в 0111'0011'1111'1111'1111'1111'1111'1111[SUB]2[/SUB] = 7'3'F'F'F'F'F'F[SUB]16[/SUB]= 1946157055[SUB]10[/SUB]. Вот такая вот порнография.


В любом случае, это совершенно непонятное дрочево (и ради чего?). Так-то ты, конечно, сегодня много чего нового узнал, но это не отвечает на вопрос. Использование же математических формул, вывод множителей в первые байты, перестановки их и прочее больше похоже на шифрование или хеширование и вряд ли так просто даст результат лучше (опять же, всё зависит от краевых условий, и тут больше к вопросу строгого математического доказательства). К слову, если хочешь действительно «упаковать» что-то, тебе, вероятно, стоит с оным познакомиться. А раз нет задачи — нет и решения.
Спасибо за развернутый ответ. Не думал, что под знак и степень аж 9 бит нужно. Ладно 1 бит под знак но целых 8 под степень..
Саму задачу я похоже не достаточно четко сформулировал - все три числа должны иметь общее максимальное значение (ваш вариант тоже клевый конечно). Очевидно для 3х байт это 0111'1111[SUB]2[/SUB] = 7'F[SUB]16[/SUB]= 127[SUB]10
[/SUB]Такой метод пакинга я нашел в одном немецком вершинном шейдере, где таким макаром в четвертой координате вершины (типа float) передавали 3 индекса костей, к которым привязана данная вершинка, но больше всего заинтересовал именно алгоритм. Я привык к пакингу в целочисленных типах данных, когда значения извлекаются и сохраняются по средствам битовых сдвигов, но в этом алгоритме значения просто суммируются. Еслиб я не знал алгоритм распаковки, был бы на 100% уверен, что восстановить эти значения уже нельзя. (До конца я эту магию с делением\умножением так и не понял. Как умножение сдвигом выполняется уже не помню, возможно в результате то на то и выходит)
Касательно вопроса о максимальном значении, автор заявил, что максимальное поддерживаемое число костей - 100. Но мне небыло очевидно почему ( шейдер писался под устаревший shader model, возможно это было связано с его ограничениями ) и я хотел попробовать также в своем домашнем проекте, где рендерится модель с 500 костями (и с 4 костями на вершину). Теперь ясно, что самым логичным вариантом будет передача одного double.
 

Arg

Самец :)
Привет. Программа на си компилируется, но сразу же вылетает
sad.gif
. Есть подозрение, что последнее условие сравнения и вычисления суммы цифр неверное, но не понимаю как поправить.

Задается динамический массив из N элементов и заполняется случайными числами. Отсортировать и найти максимальное трехзначное число, сумма цифр которого равна введенному числу k. Числа в массиве от 0 до 100000.
Код:
[/FONT][/COLOR]#include <stdio.h>#include <stdlib.h>
#include <malloc.h>
 
 
//Функция по суммированию чисел
int SumDigits ( int L )
 
{
 
int d, sum = 0;
while ( L != 0 )
 
  {
 
  d = L % 10;
  sum = sum + d;
  L = L / 10;
 
  }
 
return sum;
 
}
 
int main()
{
long int *mass, tmp;
long int k, s, max, res=0;
int i, j, N;
 
printf("Zadayte chislo k\n");
scanf("%lg",&k);
printf("Zadayte kolichestvo elementov massiva\n");
scanf("%d", &N);
 
mass = (long int*)malloc(N*sizeof(long int));
//резервируем память под массив
 
for (i = 0; i< N; i++)
{
 
    mass [i] = rand ()%100001;
}
//заполняем массив случайными числами от 0 до 100 000
   
 
//<-сортировка
 
for(i=0;i<N;i++)
{
    for(j=i;j<N;j++)
        {
            if(mass[i]>mass[j])
                {
                    tmp=mass[i];
                    mass[i]=mass[j];
                    mass[j]=tmp;
                }
        }
}
 
 
 
for(i=0;i<N;i++)
{
    if((mass[i]>=100 || mass[i]<=999) && SumDigits(mass[i])==k)
    {
           res++;
    
 //       //res - переменная, в которой запоминаем было ли вообще число, подходящее под условие
          max=mass[i];    
  //        //запоминаем последнее число
    }
}
 
 
 
printf("Your result is %d", max);
printf("Vsego ih bilo %d", res);
   getch();
   free(mass);
   return 0;

}[COLOR=#000000][FONT=verdana]
 
Не сильно вчитываясь в текст программы...
Привет. Программа на си компилируется, но сразу же вылетает
sad.gif
. Есть подозрение, что последнее условие сравнения и вычисления суммы цифр неверное, но не понимаю как поправить.

Чего гадать-то? Запусти программу под отладчиком и будешь точно знать где находится это самое "сразу же". Поверь это гораздо проще чем гадать.
Задается динамический массив из N элементов и заполняется случайными числами. Отсортировать и найти максимальное трехзначное число, сумма цифр которого равна введенному числу k. Числа в массиве от 0 до 100000.

Ну сделай N=3 или 4 и забей туда заранее известные известные числа на одно из которых точно удовлетворяет условиям задачи. Сразу увидишь в чём проблема.
Код:
#include <stdio.h>#include <stdlib.h>
#include <malloc.h>
 
 
//Функция по суммированию чисел
int SumDigits ( int L )
 
{
 
int d, sum = 0;
while ( L != 0 )
 
  {
 
  d = L % 10;
  sum = sum + d;
  L = L / 10;
 
  }
 
return sum;
 
}
 
int main()
{
long int *mass, tmp;
long int k, s, max, res=0;
int i, j, N;
 
printf("Zadayte chislo k\n");
scanf("%lg",&k);
printf("Zadayte kolichestvo elementov massiva\n");
scanf("%d", &N);
 
mass = (long int*)malloc(N*sizeof(long int));
//резервируем память под массив
 
for (i = 0; i< N; i++)
{
 
    mass [i] = rand ()%100001;
}
//заполняем массив случайными числами от 0 до 100 000
   
 
//<-сортировка
 
for(i=0;i<N;i++)
{
    for(j=i;j<N;j++)
        {
            if(mass[i]>mass[j])
                {
                    tmp=mass[i];
                    mass[i]=mass[j];
                    mass[j]=tmp;
                }
        }
}
 
 
 
for(i=0;i<N;i++)
{
    if((mass[i]>=100 || mass[i]<=999) && SumDigits(mass[i])==k)
    {
           res++;
    
 //       //res - переменная, в которой запоминаем было ли вообще число, подходящее под условие
          max=mass[i];    
  //        //запоминаем последнее число
    }
}
 
 
 
printf("Your result is %d", max);
printf("Vsego ih bilo %d", res);
   getch();
   free(mass);
   return 0;

}

Вопрос такой, а заниматься распределением памяти самому обязательно надо или можно не изобретать костыли и ограничиться чем-то стандартным?

Запустил в Visual Studio 2012 программа отработала но вывалилась при выходе с run-time check насчёт коррупции стека вокруг k. См. scanf("%lg", &k);
Потом вывалилось с неинициализированной переменной max, оно и понятно, если число не найдено то в max будет мусор.
И вот ещё какой вопрос. Не очень понятно с какой целью массив сортируется. Здорово тормозят весь процесс если количество элементов большое. Пузырьком-же сортируешь. Всё равно проходишь массив от начала до конца, проще сравнивать найденное число с предыдущим найденым.
Условие mass>=100 || mass<=999) && SumDigits(mass)==k) неверное надо везде && использовать.
 

Arg

Самец :)
Не сильно вчитываясь в текст программы...

Чего гадать-то? Запусти программу под отладчиком и будешь точно знать где находится это самое "сразу же". Поверь это гораздо проще чем гадать.

Ну сделай N=3 или 4 и забей туда заранее известные известные числа на одно из которых точно удовлетворяет условиям задачи. Сразу увидишь в чём проблема.

Вопрос такой, а заниматься распределением памяти самому обязательно надо или можно не изобретать костыли и ограничиться чем-то стандартным?

Запустил в Visual Studio 2012 программа отработала но вывалилась при выходе с run-time check насчёт коррупции стека вокруг k. См. scanf("%lg", &k);
Потом вывалилось с неинициализированной переменной max, оно и понятно, если число не найдено то в max будет мусор.
И вот ещё какой вопрос. Не очень понятно с какой целью массив сортируется. Здорово тормозят весь процесс если количество элементов большое. Пузырьком-же сортируешь. Всё равно проходишь массив от начала до конца, проще сравнивать найденное число с предыдущим найденым.
Условие mass>=100 || mass<=999) && SumDigits(mass)==k) неверное надо везде && использовать.


У меня там изначально вместо long int'ов были float'ы, оно бодро создает массив, сортирует, но судя по всему не считает сумму. По известным N проверял :( Массив сортируется сугубо по заданию - отсортировать его. Мне приходится мучаться с такой ветхозаветной вещью, как Turbo C, который умудряется после каждого запуска программы забывать про существование мышки и верхней панели заодно :crazy2:. А при запуске отладки он на scanf("%lg", &k) поперхнулся, но детали ошибки сразу же исчезают, что делает процесс отладки игрой в "угадайку". :crazy2:
Поправил на %d везде. Запускается, работает.. но считает что-то непонятное. Показывает пятизначное число max, но 0 в res. Пойду разбираться
 
Что мешает установить студию? Или какоц нить си билдер. Обратная совместимость эе сохоаниться у кода.
 
Сверху