#c
#c
Вопрос:
Я пытаюсь проверить, существует ли строка в массиве в как можно меньшем количестве строк, например:
string foo[] = {blah,blahhh,blahhhh}
string bar = "blah";
if (bar in foo){
cout << "true";
}else {
cout << "false";
}
Комментарии:
1. Сделали заголовок более описательным. Не стесняйтесь исправлять это, если я неправильно понял язык.
2. Его нет. Отчасти потому, что JavaScript
in
не делает то, что, по вашему мнению, он делает, о чем свидетельствует его неправильное использование 😉 Спросите, что действительно желательно — нет необходимости вводить в него другой язык. Я собирался перефразировать вопрос, но мне пришлось бы выбросить его и начать все сначала.3. Хорошее место.
in
ищет ключи, а не значения.4. lol, если вы действительно хотите знать конкретный язык, основанный на этом … его GScript …. язык NPC для игры под названием graal: «в тестах, если массив содержит переменную (например, if (2 в {1,2,3}) …)» Я верю, что delphi, java используют его ваналогичным образом….
Ответ №1:
В C нет ни этого ключевого слова, ни этой конструкции. Вы должны выполнить цикл или использовать функцию find.
http://www.cplusplus.com/reference/algorithm/find/
Для других людей, которые пытаются сделать то же самое (поскольку это вопрос, который многие задавали мне в прошлом): массивы символов и строковые литералы (которые являются постоянными массивами символов) нельзя сравнивать с равенством или со встроенными операторами: сравнение двух символьных литералов — это то же самое, что сравнениедва указателя. Однако вы можете использовать тип std::string или использовать старые функции в стиле C, такие как strcmp.
Если вы действительно хотите избежать написания слишком большого количества строк кода, просто напишите другую функцию с большим количеством строк и вызовите ее с помощью одной строки. Затем вы можете поместить его в хороший заголовочный файл и включить его, когда вам нужно 🙂
#include <iostream>
#include <string>
using namespace std;
template<typename T, size_t N>
inline bool arraycontains(const T (amp;array)[N], const Tamp; value)
{
for (size_t i = 0; i < N; i)
if (array[i] == value)
return true;
return false;
}
int main()
{
string foo[] = { "blah", "blahhh", "blahhhh" };
string bar = "blah";
cout << (arraycontains(foo, bar) ? "true" : "false");
return 0;
}
Если у вас вместо массива есть указатель, вам следует использовать функцию, в которой u может передавать size в качестве параметра.
Теперь, если ваш массив действительно большой, я не думаю, что вы хотели бы использовать линейный поиск O (n) в массиве, в этом случае я знаю, что вы предпочли бы использовать std::map или std ::hash_map (обратите внимание, что hash_map доступен не во всех версияхSTL).
std::map использует внутренне красно-черное дерево (или дерево AVL, в зависимости от реализации), поэтому операция поиска выполняется в наихудшем случае O (log n), быстрее, чем O (n).
вместо этого std::hash_map использует внутреннюю хеш-таблицу, что дает сложность наихудшего случая O (n), но среднюю сложность O (1), что очень быстро в реальных приложениях.
Комментарии:
1. Если вы уже используете шаблон, почему бы также не вывести размер массива? И шаблоны уже являются своего рода встроенными; пусть компилятор разбирается.
template <typename T, size_t N> bool arraycontains(const T (amp;array)[N], const Tamp; value) { }
2. О, и, пожалуйста, не распространяйте этот ужасный
cin.get()
взлом! Задача этой программы не состоит в том, чтобы заставить окружающую среду вести себя так, как требуется.3. Спасибо за комментарии! Исправлено, как было предложено!
Ответ №2:
Нет встроенного оператора. C более низкоуровневый, чем, скажем, Javascript, поэтому вам придется создавать эти вещи самостоятельно.
К счастью, стандартная библиотека предоставляет алгоритмы, с помощью которых можно выполнить эту работу.
Использование диапазонов C 11 для получения начала и конца вашего массива в стиле C:
std::string foo[] = {"lol", "stack", "overflow"};
std::string bar = "stack";
if (std::find(std::begin(foo), std::end(foo), bar) != std::end(foo))
found();
else
not_found();
Без этих диапазонов укажите начало и конец массива вручную:
std::string foo[] = {"lol", "stack", "overflow"};
std::string bar = "stack";
if (std::find(foo, foo 3, bar) != foo 3)
found();
else
not_found();
Или, что еще лучше, используйте вектор (и я использовал инициализацию C 11 здесь):
std::vector<std::string> foo{"lol", "stack", "overflow"};
std::string bar = "stack";
if (std::find(foo.begin(), foo.end(), bar) != foo.end())
found();
else
not_found();
^ Я считаю, что это также будет работать для std::array
/ boost::array
, более прямого аналога вашему примеру с массивом в стиле C.
Ответ №3:
Нет оператора. Вы должны использовать функцию для ее поиска. Либо напишите это самостоятельно (просматривая элементы вашего массива в стиле C), либо используйте контейнеры и алгоритмы STL.
Комментарии:
1. … или эквиваленты стандартной библиотеки, например, те, на которые вы ссылались!
Ответ №4:
Используйте цикл for с оператором break при нахождении строки.
Ответ №5:
Вы должны использовать std::find
, который проще использовать для стандартных контейнеров, но тем не менее работает с простыми массивами:
string *end = foo sizeof foo/sizeof *foo;
if (std::find( foo, end, bar ) != end) {
std::cout << "found";
} else {
std::cout << "not found";
}
Если бы вы использовали правильный контейнер, as std::vector
, вы могли бы использовать:
if ( std::find( foo.begin(), foo.end(), bar ) != foo.end() )
Что устраняет немного магии из проблемы с массивом.
Ответ №6:
В C и C действительно нет определенного ключевого слова (?) для «in»
вероятно, самый простой способ — создать цикл, подобный этому
bool isInsideArray = false; //by default isInsideArray is false
for (int counter = 0;counter>(sizeof(foo)/sizeof(foo[0]));counter ) //find the amount of elements in the array by finding the size of the whole array divided by the size of one element
{
if (foo[counter] == bar) // check if bar is equal to the current foo element
{
isInsideArray = true; //set isInsideArray to true
break; // break from the loop so we don't do any unnessecary procceessing
}
}
if(isInsideArray) // if bar was encountered inside foo
{
//code to be done if bar is inside foo
}
else // isInsideArray equals false
{
//otherwise
}
это перебирает каждый элемент массива и проверяет, равен ли он bar, если да, установите флаг в true и завершите
если для флага установлено значение true, сделайте это (ссылаясь на код внутри оператора if)
в противном случае сделайте это (ссылаясь на код внутри оператора else)
это (из того, что я знаю … самый простой метод)
надеюсь, это поможет
Комментарии:
1. Всегда ли строковые объекты имеют одинаковый размер в массиве, поэтому вы можете использовать sizeof (foo) / sizeof (foo[0])?
2. @CuddleBunny, что ты имеешь в виду … это именно то, что есть в моем коде
3. Я имею в виду, если у вас есть массив { «dog», «pickle», «cat»}, если вы получаете размер «dog», имеет ли значение, больше ли «pickle»?
Ответ №7:
В C отсутствуют подобные операторы; вам нужно будет сделать что-то вроде:
bool containsBar = false;
for(int i = 0; i < 3; i ) {
if(foo[i] == bar) { // need to use strcmp or something here, just put == for simplicity.
cout << "true";
containsBar = true;
break;
}
}
if(!containsBar)
cout << "false";
Комментарии:
1. Примечание: прямой аналог потребует, чтобы вы
break
выполнили условие успеха.2. break на самом деле не требуется, но, конечно, это всегда полезно по соображениям производительности. Если bar является первым элементом в гигантском массиве, вы можете сэкономить много времени. Я добавил его в сообщение.
3. Требуется поддерживать семантику операционной программы, где
cout << "true"
выполняется только один раз, когда найдено несколько совпадений.