Процедура поиска по всей базе данных:
CREATE or REPLACE PROCEDURE SEARCH_DB(SEARCH_STR IN VARCHAR2, TAB_COL_RECS OUT VARCHAR2) IS
match_count integer;
qry_str varchar2(1000);
CURSOR TAB_COL_CURSOR IS
SELECT TABLE_NAME,COLUMN_NAME,OWNER,DATA_TYPE FROM ALL_TAB_COLUMNS WHERE DATA_TYPE in ('NUMBER','VARCHAR2') AND OWNER='SCOTT';
BEGIN
FOR TAB_COL_REC IN TAB_COL_CURSOR
LOOP
qry_str := 'SELECT COUNT(*) FROM '||TAB_COL_REC.OWNER||'.'||TAB_COL_REC.TABLE_NAME||
' WHERE '||TAB_COL_REC.COLUMN_NAME;
IF TAB_COL_REC.DATA_TYPE = 'NUMBER' THEN
qry_str := qry_str||'='||SEARCH_STR;
ELSE
qry_str := qry_str||' like '||SEARCH_STR;
END IF;
--dbms_output.put_line( qry_str );
EXECUTE IMMEDIATE qry_str INTO match_count;
IF match_count > 0 THEN
dbms_output.put_line( qry_str );
--dbms_output.put_line( TAB_COL_REC.TABLE_NAME ||' '||TAB_COL_REC.COLUMN_NAME ||' '||match_count);
TAB_COL_RECS := TAB_COL_RECS||'@@'||TAB_COL_REC.TABLE_NAME||'##'||TAB_COL_REC.COLUMN_NAME;
END IF;
END LOOP;
END SEARCH_DB;
Выполнение инструкции
DECLARE
SEARCH_STR VARCHAR2(200);
TAB_COL_RECS VARCHAR2(200);
BEGIN
SEARCH_STR := 10;
SEARCH_DB(
SEARCH_STR => SEARCH_STR,
TAB_COL_RECS => TAB_COL_RECS
);
DBMS_OUTPUT.PUT_LINE('TAB_COL_RECS = ' || TAB_COL_RECS);
END;
Результаты выборки
Connecting to the database test.
SELECT COUNT(*) FROM SCOTT.EMP WHERE DEPTNO=10
SELECT COUNT(*) FROM SCOTT.DEPT WHERE DEPTNO=10
TAB_COL_RECS = @@EMP##DEPTNO@@DEPT##DEPTNO
Process exited.
Disconnecting from the database test.
Чтобы ответить на ваш реальный вопрос: нет убедительного объяснения, почему это было сделано именно так. "Да просто так".
Поскольку std::map
является ассоциативным контейнером, нет четкого заранее определенного диапазона ключей, которые должны существовать (или не существовать) на карте (в отличие от совершенно разных ситуация с std::vector
). Это означает, что с помощью std::map
вам нужны как непересекающиеся, так и вставные функции поиска. Можно перегрузить []
в неинтегрирующем режиме и обеспечить функцию для вставки. Или можно сделать наоборот: перегрузка []
в качестве оператора вставки и предоставление функции для неинтерактивного поиска. Итак, кто-то когда-то решил следовать последнему подходу. Вот и все.
Если бы они сделали это наоборот, возможно, сегодня кто-то задал бы здесь обратную версию вашего вопроса.
Невозможно избежать создания объекта, потому что оператор [] не знает, как его использовать.
myMap["apple"] = "green";
или
char const * cColor = myMyp["apple"];
Я предлагаю, чтобы контейнер карты добавлял функцию, подобную
if( ! myMap.exist( "apple"))
throw ...
, ее намного проще и лучше читать, чем
if( myMap.find( "apple") != myMap.end())
throw ...
Его назначение предназначено для назначения:
void test()
{
std::map<std::string, int >myMap;
myMap["hello"] = 5;
}
operator[]
для постоянных карт не нужно было бы создавать значение. Но для постоянных карт нет даже operator[]
, вы должны ошибаться.
– sbi
28 October 2009 в 20:40
operator[]
, кажется, указывает, что operator[]
существует чисто i> для модификации карт. Я как-то должен неправильно понимать то, что вы делаете. Если дизайнеры STL не думали, что любой operator[]
имеет смысл для постоянных карт, они, очевидно, видели весь смысл operator[]
при изменении карты, например, с заданием в ответе ...
– sth
28 October 2009 в 21:18
operator[]
, есть две совершенно разные семантики в зависимости от того, является ли карта const
или не звучит как плохая идея для меня. Так оно и есть, []
имеет определенную четко определенную семантику, которая просто не поддерживается для отображения const
- следовательно, ее нет.
– Pavel Minaev
28 October 2009 в 21:19
<sheepish_grin>
Позвольте мне ... Как это, operator[]
выполняет две цели: вы можете использовать его для доступа к существующему элементу, и вы можете вставлять элементы. Для обоих существуют специальные функции, поэтому, по-видимому, это комбинация, почему существует operator[]
. Для семантики добавления у вас есть insert()
, для семантики доступа у вас есть find()
- за исключением того, что find()
может возвращать «несуществующий элемент», в то время как оператор не может. Семантика вставки необходима для для добавления и поиска i> для работы с использованием operator[]
.
– sbi
28 October 2009 в 22:04
Я думаю, что это в основном потому, что в случае карты (в отличие от вектора, например) это довольно дешево и легко сделать - вам нужно создать только один элемент. В случае вектора они могли бы расширять вектор, чтобы сделать новый индекс действительным, но если ваш новый индекс значительно превышает то, что уже существует, добавление всех элементов до этой точки может быть довольно дорогостоящим. Когда вы расширяете вектор, вы также обычно указываете значения добавляемых новых элементов (хотя часто со значением по умолчанию). В этом случае невозможно было бы указать значения элементов в пространстве между существующими элементами и новым.
Также существует принципиальное отличие в том, как обычно используется карта. С вектором обычно существует четкое разграничение между вещами, добавляемыми к вектору, и вещами, которые работают с тем, что уже есть в векторе. С картой это гораздо менее верно - это much более распространено, чтобы видеть код, который манипулирует элементом, который есть, если он есть, или добавляет новый элемент, если он еще не существует. Конструкция оператора [] для каждого отражает это.
Ответ заключается в том, что они хотели, чтобы реализация была удобной и быстрой.
Основная реализация вектора - это массив. Поэтому, если в массиве 10 записей, и вы хотите ввести 5, T & amp; vector :: operator [] (5) функция просто возвращает headptr + 5. Если вы запрашиваете запись 5400, она возвращает headptr + 5400.
Основная реализация карты обычно является деревом. Каждый узел распределяется динамически, в отличие от вектора, который стандарт требует смежного. Итак, nodeptr + 5 ничего не значит, а map ["some string"] не означает rootptr + offset ("some string").
Как и в случае с картами, vector имеет getAt (), если вы требуется проверка границ. В случае векторов проверка границ считалась ненужной для тех, кто этого не хотел. В случае с картами единственный способ не возвращать ссылку - это исключение, которое также считается ненужной для тех, кто этого не хочет.
Стандарт говорит (23.3.1.2/1), что оператор [] возвращает (*((insert(make_pair(x, T()))).first)).second
. Вот в чем причина. Он возвращает ссылку T&
. Невозможно вернуть неверную ссылку. И он возвращает ссылку, потому что это очень удобно, я думаю, не так ли?
operator[]
возвращает ссылку. Поэтому он должен вставить что-то, потому что нет способа вернуть неверную ссылку.
– Kirill V. Lyadvinsky
28 October 2009 в 20:37
map.insert (ключ, элемент); что ключ находится на карте, но не перезаписывает существующее значение.
map.operator [key] = item; что ключ находится на карте и перезаписывает любое существующее значение с помощью элемента.
Обе эти операции достаточно важны, чтобы гарантировать одну строку кода. Дизайнеры, вероятно, выбрали, какая операция была более интуитивной для оператора [] и создала вызов функции для другого.
Рассмотрим такой вход - 3 блока, каждый блок 2 строки, первая строка - количество элементов во втором:
5
13 20 22 43 146
4
13 22 43 146
5
13 43 67 89 146
Проблема: вычислить число целых чисел, которые присутствуют во втором линий всех трех блоков. (Для этого ввода образца выход должен быть 3 до 13, 43 и 146 присутствуют во вторых строках всех трех блоков)
Посмотрите, насколько хорошо этот код:
int main ()
{
int n, curr;
map<unsigned, unsigned char> myMap;
for (int i = 0; i < 3; ++i)
{
cin >> n;
for (int j = 0; j < n; ++j)
{
cin >> curr;
myMap[curr]++;
}
}
unsigned count = 0;
for (auto it = myMap.begin(); it != myMap.end(); ++it)
{
if (it->second == 3)
++count;
}
cout << count <<endl;
return 0;
}
Согласно стандарту operator[]
возвращается ссылка на (*((insert(make_pair(key, T()))).first)).second
. Вот почему я мог написать:
myMap[curr]++;
, и он вставил элемент с ключом curr
и инициализировал значение на ноль, если ключ не присутствовал на карте. А также он увеличил значение, несмотря на то, что элемент был на карте или нет.
Посмотрите, как просто? Это хорошо, не так ли? Это хороший пример того, что это действительно удобно.
Он позволяет вставлять новые элементы с помощью operator[]
, например:
std::map<std::string, int> m;
m["five"] = 5;
5
присваивается значение, возвращаемое m["five"]
, которое является ссылкой на вновь созданный элемент. Если operator[]
не будет вставлять новые элементы, это не сработает.
Поскольку operator[]
возвращает ссылку на само значение, поэтому единственный способ указать проблему - это выбросить исключение (и, как правило, STL редко выдает исключения).
Если вы не нравится это поведение, вы можете использовать map::find
вместо этого. Он возвращает итератор вместо значения. Это позволяет ему возвращать специальный итератор, когда значение не найдено (оно возвращает map::end
), но также требует от вас разыменования итератора, чтобы получить значение.
map[key] = value;
, и карта заменит существующее значение или i> вставить новое по необходимости. Это давняя конвенция, поэтому неудивительно, что std::map
следует за ней. Однако, поскольку operator[]
не может определить, будет ли ссылка, которую он должен вернуть, будет использоваться с левой стороны operator=
или нет, она всегда должна принимать худшее значение и, следовательно, вставить новый элемент.
– Pavel Minaev
28 October 2009 в 21:18
std::vector
. – AnT 29 October 2009 в 14:47