Страницы

Поиск по вопросам

понедельник, 29 апреля 2019 г.

Java. Изменить название класса динамически из String

Есть некий класс Contakt.class, но названия не имеет значение так как классов много, суть в том что вместо Contakt нужно подставить динамически другие значения.
Я получаю данные text и вставляю их в строку String q2=text; далее у меня есть код где есть Contakt.class, но вместо Contakt нужно вставить q2, где и храняться названия других классов.
Получится что-то вроде q2.class, где вместо q2 будут различные значения.
Есть ли такая возможность на Java?


Ответ

С помощью методов Class.forName() и newInstance() объекта Class можно динамически загружать и создавать экземпляры класса в случае, когда имя класса неизвестно до момента выполнения программы.
Class c = Class.forName("com.xyz.MyClass"); Object obj = c.newInstance(); MyClass myClass = (MyClass) obj;

Как сделать события для соответствующих div?

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

Имя


Редактировать

Фамилия


Редактировать

Ума хватило только на такой вот код , но в этом случае появляются все инпуты сразу
jQuery(".edit-settings").click(function () { if($('.sett-drop').is(":visible")){ $('.sett-drop').hide("fast"); }else { $('.sett-drop').show("fast"); }; });
Как же сделать так , чтобы при клике на ссылку открывался именно тот div, который нужно ? Присваивать id не вариант , так как таких блоков довольно таки много.


Ответ

Чуточку поправила код и:
$(".edit-settings").click(function () { var $this = $(this), wrap = $this.closest('.settings-line'), drop = wrap.find('.sett-drop'); if(drop.is(":visible")){ drop.hide("fast"); }else { drop.show("fast"); } }); .sett-drop { display: none; }

Фамилия

Редактировать

P.S: Небольшой алгоритм (мне помогает) --> Берем ссылку на которую кликаем $(this) --> для нее находим обертку в которой она же находится (.settings-line) --> в этой обертке находим контейнер который скрывается\раскрывается и с ним работаем.

Значение this в С#

Не могу разобраться в сути this. Когда метод вызывается, ему автоматически передается ссылка на вызывающий объект, т.е. тот объект, для которого вызывается данный метод
class SomeClass { private string name = "No name"; private static void WriteToLog(SomeClass aSomeObject) { Console.WriteLine("Обрабатывается объект с именем " + aSomeObject.name); }
public SomeClass(string name) { //Хотим присвоить значение аргумента, полю класса this.name = name; }
public void DoWork() { WriteToLog(this); }
}
А что передается в WriteToLog(this) при его вызове? Ссылка на что?
т.е. при
SomeClass tmpObj = new SomeClass("Иван");
tmpObj.DoWork();
передается ссылка на объект tmpObj ?


Ответ

MSDN
The this keyword refers to the current instance of the class and is also used as a modifier of the first parameter of an extension method.

Ключевое слово this указывает на текущий экземпляр класса. Также используется в качестве модификатора для первого параметры в методах расширениях
Таким образом внутри определения класса - это ссылка на конкретный объект, для которого выполняется тот или иной метод.
SomeClass tmpObj = new SomeClass("Иван"); tmpObj.DoWork();
this внутри DoWork в данном случае указывается на tmlObj, так как эта функция вызывается у этого объекта.

Ключевые кадры в анимации

Доброго времени суток.
Не могу вникнуть в ключевые кадры анимации, а точнее, например делаю слайдер, в нем 3 картинки, задаю анимации 15 секунд скорости, и infinite. Теперь например хочу сделать что бы картинка стояла 3 секунды далее уходила влево за 2 сек. И за ней сразу же шла вторая картинка, и она должна стоять 3 секунды, и уходить влево за 2 секунды, далее за ней третья картинка выдвигается и 3 сек стоит. И т.д. Так вот, очень хочется понять эту тему, объясните пожалуйста подробней, как мне грамотно рассчитать ключевые кадры?
Сам я пытался сделать так:
0%{left: 0px;opacity: 1} 16%{left: 0px;opacity: 1} 25%{left: -680px; opacity: 0} 34%{left: -680px; opacity: 0} 43%{left: 680px;opacity: 0} 52%{left: 680px;opacity: 0} 61%{left: 0;opacity: 1} 70%{left: 0;opacity: 1} 79%{left: -680px;opacity: 0} 88%{left: 680px;opacity: 0} 97%{left: 680px;opacity: 0} 100%{left: 0px;opacity: 0}
Но на конечной точке, первая картинка не выдвигается плавно как до этого, а встает на первую точку резко.


Ответ

Это решение для варианта, когда текущий слайд уезжает со следующего. Если требуется просто сдвиг слайдов, то надо использовать другой способ.
Какова длительность всей анимации?
(3 сек + 2 сек) * 5 шт = 25 сек. 1 сек = 4%.
Как сделать анимацию каждой картинки?
3s картинка просто стоит:
0% { left: 0; } 12% { left: 0; } 2s уезжает влево:
18% { left: -100%; } Потом незаметно возвращается обратно:
18.001% { z-index: -1; left: -100%; } 100% { z-index: -1; left: 0; }
Значения повторно использовать нельзя, поэтому добавляем отклонение на .001%. Но надо, чтобы за 2 секунды до конца блок уже был видим, поэтому последнюю строку заменяем на:
92% { z-index: 0; left: 0; } 100% { z-index: 0; left: 0; } Исправить косяк с анимацией z-index - не показывать элемент раньше чем нужно:
91.999% { z-index: -1; left: 0; }
Как сделать анимацию слайдера?
Использовать animation-delay для слайдов.
Что Можно улучшить?
Производительность за счёт использование transform:translate вместо left.
section { position: relative; height: 10em; overflow: hidden; } div { position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: -1; animation: slide 25s linear infinite both; } @keyframes slide { 0% { z-index: 1; left: 0; } 12% { z-index: 1; left: 0; } 18% { z-index: 1; left: -100%; } 18.001% { z-index: -1; left: -100%; } 18.002% { z-index: -1; left: 0; } 91.999% { z-index: -1; left: 0; } 92% { z-index: 0; left: 0; } 100% { z-index: 0; left: 0; } }


section { position: relative; height: 10em; overflow: hidden; } div { position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: -1; transform: translateX(0); animation: slide 25s linear infinite both; } @keyframes slide { 0% { z-index: 1; transform: translateX(0); } 12% { z-index: 1; transform: translateX(0); } 18% { z-index: 1; transform: translateX(-100%); } 18.001% { z-index: -1; transform: translateX(-100%); } 18.002% { z-index: -1; transform: translateX(0); } 91.999% { z-index: -1; transform: translateX(0); } 92% { z-index: 0; transform: translateX(0); } 100% { z-index: 0; transform: translateX(0); } }

Git Bash/Git GUI некорректное отображение ярлыка

Установил Git-2.10.0-64-bit на Windows 7. Проблема в том что некорректно отображается ярлык в Пуске
и при правом щелчке мышки на рабочем столе.
Как сделать что б отображался нормальный ярлык.


Ответ

Для того, чтобы отображались верные значки в контекстном меню необходимо изменить два значения Icon в ветках реестра HKEY_CLASSES_ROOT\Directory\Background\shell\git_gui и HKEY_CLASSES_ROOT\Directory\Background\shell\git_shell. Соответственно указать путь до какого-либо значка, например, "C:\Program Files\Git\mingw64\share\git-gui\lib\git-gui.ico"

random заполняет две матрицы одинаковыми значениями

Рандом работает не так как нужно: при каждом вызове функции Random, матрицы заполняются одинаково
public void Random() { Random random = new Random();
for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { matrix[i, j] = random.Next(0, 10); } } }


Ответ

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

invalid initialization of non-const

#include #include
using namespace std;
class complex { double re, im; public: complex(double = 0, double = 0); ~complex();
complex operator+(complex&); complex operator-(complex&); complex operator*(complex&); complex operator/(complex&); complex operator^(unsigned); friend istream& operator >> (istream &, complex&); friend ostream& operator << (ostream &, complex &); };
complex::complex(double r, double i) { re = r; im = i; }
complex::~complex() { }
complex complex::operator+(complex&y) { return complex(re + y.re, im + y.im); }
complex complex::operator-(complex&y) { return complex(re - y.re, im - y.im); }
complex complex::operator*(complex&y) { return complex(re*y.re - im*y.im, re*y.im + im*y.re); }
complex complex::operator/(complex&y) { double r1 = re; double i1 = im; double r2 = y.re; double i2 = y.im; return complex((r1*r2 - i1*i1) / (r2*r2 + i2*i2), (-r1*i2 + i1*r2) / (r2*r2 + i2*i2)); }
complex complex::operator^(unsigned n) { complex y(1, 0); for (int i = 1; i <= n; i++) y = y*(*this); return y; }
istream& operator >> (istream& is, complex& x) { char c; cin >> c; assert(c == '('); cin >> x.re; cin >> c; assert(c == ','); cin >> x.im; cin >> c; assert(c == ')'); return is;
}
ostream& operator<<(ostream&os, complex&x) { os << '(' << x.re << ',' << x.im << ')' << endl; return os; }
int main(){
complex a(1, 1); complex b(1, 1); complex c(1, 1); complex x;
cout << "Введите комплексное число в формате: (re,im) ->"; cin >> x; cout << "Результат =" << a*(x ^ 2)) + b*x + c << endl; return 0; }
На линуксе выводит ошибку:
invalid initialization of non-const
для строки:
cout << "Результат =" << a*(x ^ 2) + b*x + c << endl;
Саму программу скопировал с Windows, ошибки исправил, только эту выдает. В чем здесь проблема? И как можно ее решить? На Visual Studio работала нормально.


Ответ

Объявите данные операторы следующим образом
complex operator+( const complex&) const; complex operator-(const complex&) const; complex operator*(const complex&) const; complex operator/( const complex&) const; complex operator ^( unsigned int ) const; friend ostream& operator << (ostream &, const complex &);
Нельзя связывать временные объекты с неконстантной lvalue ссылкой.
Обратите внимание , что конструктор класса является преобразующим конструктором. Поэтому у вас будет работать выражение complex + double, как, например,
complex a( 10, 10 ); complex b = a + 10;
Но не будет работать выражение double + complex
complex a( 10, 10 ); complex b = 10 + a; // ошибка компиляции
так как ваши операторы являются членами класса. Вы могли бы их объявить как отдельные функции, не являющиеся членами класса, которые принимают два аргумента. Например,
friend complex operator +( const complex &lhs, const complex &rhs ) { return complex( lhs.re + rhs.re, lhs.im + rhs.im ); }
В этом случае второе выражение было бы также верным.
Эта дружественная функция может быть определена как в самом классе, и тогда при использовании оператора будет применен зависящий от аргумента поиск (ADL), либо вне класса.
Что касается Visual Studio, то его компилятор имеет собственные расширения языка (которые активизированы по умолчанию; вы можете отключить эту опцию в настройках компилятора, и тогда будет выдано сообщение об ошибке), которые порой противоречат стандарту C++. Не стоит полагаться на эти расширения языка компилятора C++ Visual Studio, так как код будет не переносимым.
EDIT: Так как у вас возникают трудности правильно набрать код, то приведу для вас рабочий вариант программы. Я не проверял, определены ли правильно операторы с точки зрения математики.
#include #include
class complex { private: double re, im;
public: complex( double = 0, double = 0 ); ~complex();
complex operator +( const complex & ) const; complex operator -( const complex & ) const; complex operator *( const complex & ) const; complex operator /( const complex & ) const; complex operator ^( unsigned int ) const; friend std::istream & operator >>( std::istream &, complex & ); friend std::ostream & operator <<( std::ostream &, const complex & ); };
complex::complex( double r, double i ) : re( r ), im( i ) { }
complex::~complex() { }
complex complex::operator +( const complex &c ) const { return complex( re + c.re, im + c.im ); }
complex complex::operator -( const complex &c ) const { return complex( re - c.re, im - c.im ); }
complex complex::operator *( const complex &c ) const { return complex( re * c.re - im * c.im, re * c.im + im * c.re ); }
complex complex::operator /( const complex & c ) const { double r1 = re; double i1 = im; double r2 = c.re; double i2 = c.im; return complex( ( r1 * r2 - i1 * i1 ) / ( r2 * r2 + i2 * i2 ), (-r1 * i2 + i1 * r2 ) / ( r2 * r2 + i2 * i2 ) ); }
complex complex::operator ^( unsigned int n ) const { complex c( 1, 0 );
for ( unsigned int i = 1; i <= n; i++ ) c = c * *this;
return c; }
std::istream & operator >>( std::istream &is, complex &c ) { char ch;
is >> ch; assert( ch == '(' );
is >> c.re;
is >> ch; assert( ch == ',' );
is >> c.im;
is >> ch; assert( ch == ')' );
return is; }
std::ostream & operator <<( std::ostream &os, const complex &c ) { return os << '(' << c.re << ',' << c.im << ')'; }
int main() { complex a(1, 1); complex b(1, 1); complex c(1, 1); complex x;
std::cout << "Введите комплексное число в формате: (re,im) ->"; std::cin >> x;
std::cout << "x = " << x << std::endl; std::cout << "x ^ 2 = " << ( x ^ 2 ) << std::endl; std::cout << "a * ( x ^ 2 ) = " << a * ( x ^ 2 ) << std::endl; std::cout << "b * x = " << b * x << std::endl; std::cout << "a * ( x ^ 2 ) + b * x = " << a * ( x ^ 2 ) + b * x << std::endl;
std::cout << "Результат =" << a * ( x ^ 2 ) + b * x + c << std::endl;
return 0; }
Если ввести значение (10,10), то вывод будет выглядеть следующим образом:
Введите комплексное число в формате: (re,im) ->(10,10) x = (10,10) x ^ 2 = (0,200) a * ( x ^ 2 ) = (-200,200) b * x = (0,20) a * ( x ^ 2 ) + b * x = (-200,220) Результат =(-199,221)

Что такое .class?

Constructor constructor = User.class.getConstructor(new Class[]{String.class,String.class,String.class}); System.out.println("Constructor "+constructor); constructor.newInstance("Hello","From","Reflection");
Из данного примера мне понятно что при передачи конструктору создаётся Обьект массива типа Class.
Но вводит в заблуждение: Class.class после чего позволяется вызывать методы Reflection API. Что означает этот .class ?
Я знаю что для доступа к методам надо создать обьект любого класса или если метод статичный то доступ будет произведен через имя класса.. В случае с доступом к Reflection API не понятно это окончание .class, я могу вызвать .class у любого класса или интерфейса или примитива int.class как JVM (если так правильно будет сказать) относится к такого рода конструкциям ? Что это и почему оно используется ?


Ответ

Обращение к .class после имени типа возвращает объект типа Class. Этот объект содержит информацию о типе (будь то класс или интерфейс) и используется в тех местах, где нужно передать информацию о типе (рефлексия как один из примеров).
Вызов .class на типе эквивалентен вызову getClass() на экземпляре типа. Обычно .class используется там, где нужно указать тип, но нет конкретного экземпляра этого типа. Пример для String
System.out.println(String.class.getName()); System.out.println("hello".getClass().getName());

В вашем примере в первой строке вы находите конструктор класса User, который принимает три строковых параметра. Для указания типов параметров используется String.class

Как мне сконвертировать IP?

Имеется IP - 95.153.128.120 и данный IP как то конвертируется, на выходе получается - 1603895416
С помощью какой функции и или еще чего конвертируется данный IP?


Ответ

в php есть функция
int ip2long ( string $ip_address )
ip2long — Конвертирует строку, содержащую (IPv4) Интернет-адрес с точками в целое число (long)
Пример
$long = ip2long($ip);
Возвращает целое число или FALSE, если параметр ip_address содержит ошибку.
документация

и обратное функция
string long2ip ( string $proper_address )
long2ip — Конвертирует адрес в формате "длинное целое"(long integer) в, содержащую адрес Интернет сети(IPv4), стандартную строку с точками
Возвращает Интернет IP адрес в виде строки.
документация

Перегрузка оператора +=

// Реализовать класс String для работы со строками. Перегрузить операторы = + += - > < [] (подстрока) ++ -- #pragma once #include using namespace std;
class String {
char* s; int length;
public:
String(const char* str="") { this->length = strlen(str); this->s = new char[this->length+1]; for (int i = 0; i < length; i++) this->s[i] = str[i]; }
String(const String& s1) { this->length = s1.length; this->s = new char[this->length]; for (int i = 0; i < this->length; i++) this->s[i] = s1.s[i]; }
~String() { delete[] s; }

String& String::operator=(String& right); String String::operator+(String right); //String& String::operator+=(const String& right); friend String& operator+=(String& left, const String& right); void String::show();
};
А это цпп файл:
#include "String.h"
void String::show() { for (int i = 0; i < this->length; i++) cout << this->s[i]; }
String& String::operator=(String& right) { delete[] this->s; this->length = right.length; this->s = new char[this->length]; for (int i = 0; i < this->length; i++) this->s[i] = right.s[i]; return *this; }
String String::operator+(String right) { String new_string; new_string.length = this->length + right.length; new_string.s =new char[this->length + right.length+1]; for (int i = 0; i < this->length; i++) new_string.s[i] = this->s[i]; for (int i = 0; i < right.length; i++) new_string.s[this->length + i] = right.s[i]; return new_string; }
String& operator+=(String& left, const String& right) { return left+right; }
Почему у меня s3 всё равно при выводе пустая? Помогите начинающему!
#include "String.h"
void main() { String s2("Hello"); String s3; s3 += s2; s3.show(); system("pause"); }


Ответ

Мы, начинающие программисты, должны помогать друг другу.:)
Начнем с того, что вам следует включить заголовок
#include
так как вы используете функции, объявленные в этом заголовке.
Длину строки лучше определять, как имеющую тип size_t вместо int
class String { char* s; size_t length; //...
Ваши конструкторы неверно копируют строки. Они не копируют в результирующую строку завершающий символ нуля '\0'. Например,
String(const char* str="") { this->length = strlen(str); this->s = new char[this->length+1]; for (int i = 0; i < length; i++) // символ нуля не входи в диапазон `[0, length)` this->s[i] = str[i]; }
Иначе непонятно, зачем вы выделяете память длиною this->length+1 вместо this->length. Непонятно, зачем вы вообще используете циклы для копирования строк, когда вы уже используете стандартные C функции из заголовка
Лучше было бы объявить конструктор следующим образом
String( const char *str = "" ) { this->length = std::strlen( str ); this->s = new char[ this->length + 1 ]; std::strcpy( this->s, str ); }
То же самое замечание справедливо и для конструктора копирования.
В определении класса нельзя указывать квалифицированное имя функций-членов класса при их объявлении. Хотя MS VC++ это допускает, но это является его собственным расширением языка, которое не соответствует стандарту.
String& String::operator=(String& right); ^^^^^^^^
Эти объявления
String String::operator+(String right); friend String& operator+=(String& left, const String& right);
лучше переопределить следующим образом
friend String operator + ( const String &left, const String &right ); String & operator += ( const String &right );
Функцию show лучше объявить как
std::ostream & String::show( std::ostream &os = std::cout ) const;
Переопределите соответствующие функции с учетом выше приведенных замечаний.
Что касается копирующего оператора присваивания, то он может быть определен следующим образом
String & String::operator =( const String &right ) { if ( this != &right ) { size_t n = std::strlen( right.s ); char tmp = new char[ n + 1 ];
std::strcpy( tmp, right.s );
delete [] this->s;
this->s = tmp; this->length = n; }
return *this; }
Аналогичным образом вам нужно определить оператор
String & operator += ( const String &right );
Например
String & String::operator +=( const String &right ) { size_t n = this->length + std::strlen( right.s ); char tmp = new char[ n + 1 ];
std::strcpy( tmp, this->s ); std::strcat( tmp, right.s );
delete [] this->s;
this->s = tmp; this->length = n;
return *this; }
Функция show определяется просто
std::ostream & String::show( std::ostream &os ) const { return os << this->s; }
Что касается вашего вопроса
Почему у меня s3 всё равно при выводе пустая?
то этот оператор
String& operator+=(String& left, const String& right) { return left+right; }
не изменяет левый аргумент. И более того имеет неопределенное поведение, так как возвращает ссылку на временный объект, создаваемый выражением left+right.
EDIT: Если оператор operator [], который, как я понимаю, вы также должны определить, позволяет вставлять в объект класса символ '\0', то вам следует изменить определения конструктора копирования, копирующего опреатора присваивания, оператора operator +=, и дружественной функции operator +, заменив стандартные C функции strXXX на memXXX. Ниже приведена демонстрационная программа, которая показывает, как это можно сделать на примере некоторых членов класса. Другие члены класса постарайтесь определить сами.
#include #include
class String { private: char *s; size_t length;
public: String( const char *str = "" ) { this->length = std::strlen( str ); this->s = new char[ this->length + 1 ];
std::strcpy( this->s, str ); }
String( const String &src ) { this->length = src.length; this->s = new char[ this->length + 1 ];
std::memcpy( this->s, src.s, this->length + 1 ); }
String & operator =( const String &src ) { if ( this !=+ &src ) { char *tmp = new char[ src.length + 1 ];
std::memcpy( tmp, src.s, src.length + 1 );
delete [] this->s;
this->s = tmp; this->length = src.length; }
return *this; }
String & operator +=( const String &src ) { size_t n = this->length + src.length; char *tmp = new char[ n + 1 ];
std::memcpy( tmp, this->s, this->length ); std::memcpy( tmp + this->length, src.s, src.length + 1 );
delete [] this->s;
this->s = tmp; this->length = n;
return *this;
}
~String() { delete [] this->s; }
std::ostream & show( std::ostream &os = std::cout ) { return os << this->s; } };
int main() { String s1( "Hello world!" ); String s2;
s2 = s1;
s2.show() << std::endl;
s2 += " Glad to see you!";
s2.show() << std::endl;
return 0; }
Вывод программы будет следующим
Hello world! Hello world! Glad to see you!

Как добавить ведущие нули к hex?

Преобразую число:
int num = 1155; string end = Convert.ToString(num , 16).TrimStart('0'));
В end записывается результат 483, а нужно получить 0483


Ответ

int num = 1155; string end = num.ToString("X8"); // end = @"00000483"
Строки стандартных числовых форматов

Что можно подставлять в качестве значения параметра X при использовании этого класса в программе?

Предположим, у нас есть параметризованный класс
public class Example { ... }
Что можно подставлять в качестве значения параметра X при использовании этого класса в программе?
имя любого интерфейса (например, CharSequence) символ "?" или более сложное выражение с ключевыми словами extends и super значение X можно не указывать, т.е. использовать класс Example как обычный непараметризованный имя любого класса (например, Object) имя любого примитивного типа (например, int) ссылку на метод (например, Object::toString) имя любого перечисления (например, DayOfWeek) значение примитивного типа (например, 42)
Объясните пожалуйста, почему не подходят ответы 1, 2, 3, 4 ?


Ответ

Аргументы типов в Java определены в спецификации в п.п. 4.5.1
В качестве аргумента по спецификации можно поставить ссылочный тип (ReferenceType в Java любой непримитивный тип) либо маску (WildCard, т.е. выражение ? extends/super T).
Вот пример допустимого использования Example
Example a = new Example(); Example b = new Example(); Example c = new Example(); Example d = new Example(); Example e = new Example();

Удалить дубликаты в массиве без использования коллекций. Java

Необходимо удалить дубликаты в массиве без использования коллекций.
C ArrayList или HashSet все понятно, тут делать не чего, но мне задание дали удалить дубликаты не используя ничего, кроме массивов. При чем метод должен работать, даже если дубликатов больше двух.
Исходный массив {1 ,1, 1, 2, 1, 3, 3} Искомый результат {1, 2, 3}
В общем уже голову сломал, может кто поможет?
Спасибо.


Ответ

Как я полагаю, ваше задание на использование циклов при работе с массивами. Если так, то прямолинейный подход с использованием циклов может выглядеть следующим образом
import java.util.*; import java.lang.*; import java.io.*;
class Ideone { public static void main (String[] args) throws java.lang.Exception { int[] a = { 1, 1, 1, 2, 1, 3, 3 };
int n = a.length;
for ( int i = 0, m = 0; i != n; i++, n = m ) { for ( int j = m = i + 1; j != n; j++ ) { if ( a[j] != a[i] ) { if ( m != j ) a[m] = a[j]; m++; } } }
if ( n != a.length ) { int[] b = new int[n]; for ( int i = 0; i < n; i++ ) b[i] = a[i];
a = b; }
for ( int x : a ) System.out.print( x + " " ); System.out.println(); } }
Вывод программы
1 2 3

Аннотация @intDef

Пытаюсь создать свою аннотацию на основе @intDef , имеется следующая конструкция - но он её не видит:
import android.support.annotation.IntDef;
@intDef(Importance.noMatter, Importance.green, Importance.yellow, Importance.red) public @interface Importance {
public static int noMatter = 0; public static int green = 1; public static int yellow = 2; public static int red = 3; }
Создал через java класс.
Пытался через @Annotations, выдает следующее:


Ответ

Ошибка с @annotation все еще остается загадкой, но основную проблему я исправил.
Дело было в том, что @intDef написано с маленькой буквы.
Напомню, что @IntDef является правильной заменой Enum в Android и гугл не рекомендует использовать последнее, поскольку @IntDef хранит простые инты, а не сложные объекты, которые всегда подгружаются, и занимают уйму памяти.

Приведение const char* к char*

Пытаюсь с QByteArray получить указатель на данные с помощью data(), ругается:
ошибка: invalid conversion from 'const char*' to 'char*' [-fpermissive] char * TempPtrBuff = ARes.data();
В документации пишется, что возвращается char *
Почему может возникать ошибка?


Ответ

Результат вывода QByteArray::data() зависит от константности метода, в котором производится вызов обозначенной функции. Проще говоря:
void MyClass::method() { char *data = ARes.data(); }
void MyClass::method() const { const char *data = ARes.data(); }
Соответственно, если вывод QByteArray::data() отличен от желаемого, то измените константность метода или осуществите приведение типа, например, тем же const_cast()

Можно-ли изменить данные в массиве VBO?

Здравствуйте. Обращаюсь к специалистам OpenGL. Рисую трехмерную сцену с группой объектов VAO
for(auto VAO: vao_list) { glBindVertexArray(VAO); glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, nullptr); glBindVertexArray(0); }
Все по "букварю", все работает. Но вот один из объектов, размером этак 40К вершин, потребовалось немного изменить: удалить 3 из 40 000 вершин. Можно конечно перезалить модифицированный объект, но для этого его образ надо вначале построить в оперативной памяти а потом перезалить в память графического процессора. А если меняющихся объектов в сцене большинство, то все их (копии) придется держать в оперативке, там править и перезаливать в графичекий буфер. Получается двойная работа, наверно тогда проще использовать "glDrawArrays", который рисует массивы прямо из оперативной памяти:
glEnableVertexAttribArray(idx_vertex_coord3d); glEnableVertexAttribArray(idx_texture_coord); glDrawArrays(GL_TRIANGLES, 0, count_of_vertices); glDisableVertexAttribArray(idx_texture_coord); glDisableVertexAttribArray(idx_vertex_coord3d);
но в этом случае память графического процессора (очень дорогая и быстрая) простаивает. Вот собственно вопрос: а можно ли как-то частично изменять объект размещенный в VAO (в графической памяти), удаляя/добавляя часть вершин в нем не перезаписывая VAO полностью?


Ответ

VAO и VBO
На всякий случай вначале скажу немного про VAO и VBO. VAO не хранит данные объекта, а хранит только ссылки на один или несколько VBO и прочее состояние, необходимое для рисования объекта. Поэтому работать мы будем с VBO. Если несколько атрибутов вершин хранятся в нескольких VBO, то все их придётся править по отдельности. Изменение VBO будет сразу же доступно пользователям связанного VAO.
Рассуждения об удалении
Начнём с экстремально простого случая: при удалении вершин с конца вообще ничего изменять не нужно. Просто рисуем вызовом
glDrawElements(GL_TRIANGLE_STRIP, num_elements - 3, GL_UNSIGNED_BYTE, nullptr);
вместо
glDrawElements(GL_TRIANGLE_STRIP, num_elements, GL_UNSIGNED_BYTE, nullptr);
Если же удаляемые вершины хранятся в начале или в середине, то задача их удаления аналогична задаче удаления элементов из середины обычного массива в памяти. Например, если есть массив:
int a[] = {1,2,3,4,5,6};
то мы не можем удалить из него элементы 2 и 3, не оставив на их месте нули или какие-нибудь специальные значения значения, указывающие на то, что данные удалены. Чтобы не оставлять этих значений, мы можем либо перевыделить память под новый массив нужной длины и скопировать туда значения, либо скопировать 5 и 6 на место 2 и 3 и запомнить, что теперь длина массива равна 4 вместо 6. Оставшаяся в хвосте память под 2 элемента будет потрачена впустую, но при 40000 элементов ей можно пренебречь.
То же самое можно применить и к массиву в видеопамяти:
Можно вызвать glBufferData для выделения нового буфера. Можно заменить кусок данных от начала удаляемого куска до конца буфера новыми значениями с помощью glBufferSubData, не забыв про уменьшение num_elements. Сдвинуть данные копированием внутри буфера не получится, ибо регионы памяти при копировании внутри буфера не должны пересекаться.
Вышеперечисленные методы могут иметь смысл при изменении/"удалении" большого количества данных, но, как вы заметили, совершенно не подходят для удаления трёх точек из 40000. То есть полностью удалить точки не получится, и придётся искать обходной путь.
Возможное решение
Функция glBufferSubData позволяет указывать смещение и длину заменяемых данных. Поэтому с её помощью можно переписать как весь буфер, так и любую его часть, хоть один единственный элемент. Если нам нужно удалить 3 из 40000 точек из модели, то не обязательно их удалять из буфера! Давайте просто перезапишем их значениями подходящей соседней вершины. Например, пусть есть ломаная из 8 вершин на плоскости:
2 3 5 7 /-------\ /\ /----8 / \ / \ / / \/ \/ /1 4 6
Если мы сделаем вершину 5 равной вершине 6, то получим тот же эффект, что и при удалении вершины 5: появится отрезок, визуально соединяющий вершины 4 и 6, а длина отрезка 5-6 станет нулевой:
2 3 7 /-------\ /----8 / \ / / \------/ /1 4 5,6
В выборе между перерасходом памяти на 3 вершины или расходом времени на пересоздание буфера на 40000 вершин логично отдать предпочтение первому варианту.
Usage pattern
Из вашего описания кажется, что "удалять" удалять точки вы будете редко, т.е. не на каждом кадре. Буфер же будет использоваться только для вывода графики, но не для transform feedback и прочих таких хитростей. Если так, то при создании буфера не забудьте в последнем аргументе glBufferData указать GL_DYNAMIC_DRAW. Однако, без тестов производительности конкретного приложения здесь нельзя давать однозначную рекомендацию. При очень редком обновлении буфера GL_STATIC_DRAW может оказаться быстрее. Напротив, при очень частом лучшим выбором может быть GL_STREAM_DRAW
Комментарий от автора вопроса
Небольшой пример. Спасибо, все встало на свои места. В добавление к вашему ответу хочу добавить демо-код для одного из перечисленных вами вариантов решения:
GLfloat* vertices = new GLfloat[9]; // элемент из 3 вершин ...
GLuint pos_Buf; glGenBuffers(1, &pos_Buf); // передаем данные в GPU glBindBuffer(GL_ARRAY_BUFFER, pos_Buf); glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), vertices, GL_STATIC_DRAW); // освободить память после переноса данных в GPU delete [] vertices; ...
// Если надо изменить, например, седьмой элемент массива: // Пример изменения данных, размещенных в графической памяти // Вариант - glUnmapBuffer // ---------------------------------------------------- glBindBuffer(GL_ARRAY_BUFFER, pos_Buf); data = (GLfloat *) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); data[7] = 0.4f; glUnmapBuffer(GL_ARRAY_BUFFER); ...
// Вариант 2 - glBufferSubData // ---------------------------------------------------- glBindBuffer(GL_ARRAY_BUFFER, pos_Buf); GLintptr offset = 7*sizeof(float); float pos_SubD[] = {0.0f}; glBufferSubData(GL_ARRAY_BUFFER, offset, sizeof(float), pos_SubD); ...
// В нужный момент этот VBO можно удалить glDeleteBuffers(1, &vboId);

Чтение из TreeMap по порядковому номеру?

Приветствую, коллеги!
Есть готовый и отсортированный как надо TreeMap
Как получить из него пары ключ-значение на основании порядкового номера i? По типу:
for (i = 0; i < map.size(); i++)


Ответ

Получить определенную пару по индексу index можно, например, так:
TreeMap foo = new TreeMap(); Object key = foo.keySet().toArray(new Object[foo.size()])[index]; Object value = foo.get(key);

Перегрузка оператор С++

Такой вопрос. Я перегружаю операторы для работы с вектором, который состоит из трек точек. Есть несколько задач:
Найти скалярное произведения векторов; (возвращает double) Найти векторное произведения векторов; (возвращает вектор)
И получается такая проблема, что компилятор не знает какой из двух методов вызвать (хотя они отличаются возвращающимися параметрами). И как все это решить?
using namespace std; class Vec3D { private: double x, y, z; public: Vec3D(double xx = 0, double yy = 0, double zz =0); Vec3D operator+ (const Vec3D & V); // double operator* (const Vec3D & V); // проблема тут friend ostream& operator<< (ostream& cout, Vec3D & V); friend Vec3D operator* (const double c, const Vec3D & V); friend Vec3D operator* (const Vec3D & V1,const Vec3D & V2); // и тут };
P.S. То что нужно реализовать семеричные\бинарные операции через friend функции я знаю


Ответ

Компилятор в общем случае не может определить, какую вызывать перегруженную функцию только по возвращаемому значению. Например, рассмотрите следующий фрагмент кода
void f() {} int f() { return 0; }
f();
Как определить, какая функция из двух вызывается?
Поэтому функции не перегружаются по возвращаемому значению.
Перегрузите этот оператор следующим образом, как показано в демонстрационной программе ниже.
#include
class Vec3D { private: double x, y, z;
public: Vec3D( double x = 0, double y = 0, double z =0) : x( x ), y( y ), z( z ) { }
friend std::ostream & operator <<( std::ostream &os, const Vec3D &v ); friend Vec3D operator *( const Vec3D &V, double d ); friend Vec3D operator *( double d, const Vec3D &v ); friend Vec3D operator *( const Vec3D &V1, const Vec3D &V2 ); // и тут };
std::ostream & operator <<( std::ostream &os, const Vec3D &v ) { return os << "( " << v.x << ", " << v.y << ", " << v.z << " )"; }
Vec3D operator *( const Vec3D &v, double d ) { return Vec3D( d * v.x, d * v.y, d * v.z ); }
Vec3D operator *( double d, const Vec3D &v ) { return v * d; } Vec3D operator *( const Vec3D &v1, const Vec3D &v2 ) { return Vec3D( v1.x * v2.x, v1.y * v2.y, v1.z * v2.z ); }
int main() { Vec3D v1( 1, 2, 3 ); Vec3D v2( 1, 2, 3 );
std::cout << ( 2 * v1 ) * ( v2 * 3 ) << std::endl; return 0; }
Ее вывод на консоль
( 6, 24, 54 )
Нельзя перегрузить оператор по возвращаемому типу. Но вы могли бы взять еще один оператор, как, например, operator ^, чтобы использовать его для одного из видов произведения векторов.
В итоге у вас может получиться два оператора
operator *
и
operator ^
Объявление перегруженного оператора operator ^ может выглядеть аналогично объявлению оператора operator * за исключением типа возвращаемого значения.

Как возвращать const ссылку из методов класса? C++

Помогите пожалуйста, как возвращать const ссылку из методов класса?
class CCalculator { public: CRepository GetRepository() const;
....
CRepository CCalculator::GetRepository() const { return m_repository; }


Ответ

Очень просто
class CCalculator { public: const CRepository & GetRepository() const; // ...
и
const CRepository & CCalculator::GetRepository() const { return m_repository; }

Будет ли копироваться значение при передаче умных указателей в функцию или будет передаваться ссылка?

Например, имеется некоторый класс:
class CSomeClass { double GetLengthLine(std::shared_ptr firstVertex, std::shared_ptr secondVertex) const; }

double CTriangle::GetLengthLine(std::shared_ptr firstVertex, std::shared_ptr secondVertex) const { .... return std::hypot(dx, dy); };
Будет ли копироваться значение при передаче умных указателей в функцию, или будет передаваться ссылка?


Ответ

Если я правильно понял вопрос (хотя на этот счет есть сомнение, т.к. уже имеется принятый ответ), то речь всё же о копировании объекта типа CPoint, которым параметризован std::shared_ptr. В этом случае совершенно не важно как будет передаваться объект умного указателя по ссылке или по значению - это не приведет к дополнительному копированию объекта, хранимого в указателе. Пример:
#include #include
struct S { S() { std::cout << "ctor
"; } S(const S&) { std::cout << "copy
"; } S(S&&) { std::cout << "move
"; } };
void f(std::shared_ptr) {} void g(const std::shared_ptr&) {}
int main(){
auto s = std::make_shared(); f(s); g(s); }
Вывод:
ctor
Т.е. был создан только один объект. Ни копирований, ни перемещений не произошло. Это в принципе логично, т.к. подобным же образом не происходит создания (полезных) объектов при передаче обычных (не умных) указателей.
В общем случае, любой достаточно большой (более нескольких sizeof(int)) объект имеет смысл передавать по константной ссылке, если не предполагается его модифицировать.

C# Приложение с входными и выходными параметрами [дубликат]

На данный вопрос уже ответили: Передать параметры программе и получить результат 3 ответа Подскажите, пожалуйста: например
Запуск приложения -> Указываем строковое значение -> Работа приложения -> Получаем строковое значение
Т.е. есть цель создания некоего модуля, который бы мог использоваться разным софтом с указанием некоторых входных данных и получением в зависимости от этого результата. К примеру указали приложению ссылку на сайт , получили результат, есть ли там указанный текст - получили true/false
Вопросы:
можно ли это сделать в консольном приложении? если да то как принимать и как отправлять значения? другой вариант?


Ответ

В других ответах уже написали про параметры командной строки и код возврата.
Но, как мне кажется, вам больше подойдут стандартные потоки ввода-вывода и их перенаправление
Например, напишем такую простейшую консольную программку:
using System;
class Program { static void Main() { // Читаем из стандартного потока ввода string line = Console.ReadLine();
// Обрабатываем введенное значение line = line.ToUpper();
// Пишем в стандартный поток вывода Console.WriteLine(line); } }
Кстати, можно явно писать Console.In.ReadLine() и Console.Out.WriteLine(), указывая потоки ввода и вывода.
Если её запустить, то нужно будет ввести строку в консоли. Результат тоже появится в консольном окне.
Теперь можно использовать перенаправление потоков. Например, подадим на вход нашей программе текстовый файл, из которого она прочтёт значение (одну первую строку). Вывод перенаправим в другой текстовый файл.
app < in.txt > out.txt
Где app.exe - имя нашей программы. in.txt - входной файл. out.txt - выходной файл.
Про конвейер и поток ошибок почитаете сами.

Поддержка уникальности строк в QStringLiteral

Из справки известно, что QStringLiteral размещает текст непосредственно в исполняемом файле в области только для чтения. Однако я не нашёл информации о том, что в случае использования одинаковых строк в разных местах кода проекта, эти строки будут храниться по уникальности значения. Или каждый экземпляр строки будет сохранён отдельно?
Допустим, имеется сетевой запрос к некоему внешнему ресурсу. Этот запрос имеет строковую команду, скажем, "https://ru.stackoverflow.com/". Также есть два класса: class A и class B. В обоих требуется выполнять указанный запрос:
class A { void getSo() { sendRequest(QStringLiteral("https://ru.stackoverflow.com/")); // Далее выполняем что-то специфическое для класса A. } };
class B { void getSo() { sendRequest(QStringLiteral("https://ru.stackoverflow.com/")); // Далее выполняем что-то специфическое для класса B. } };
Вопрос заключается в том, что именно попадёт в исполняемый файл: две строки с адресом запроса или одна? Или я неверно понимаю принцип работы указанного макроса?


Ответ

Стандартом не оговорено. Зависит от компилятора и настроек. Например, в Visual C++ 2015 имеется опция (зависящая от использованных параметров оптимизации)
/GF включить объединение строк только для чтения
Так что эти литералы будут объединены. Но если скомпилировать без этого ключа или с с /GF-, то в exe'шнике каждая займет свое место (при отключенной оптимизации - включение оптимизации автоматически включает эту опцию).