Каков эквивалент c для Javascript «in»?

#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" выполняется только один раз, когда найдено несколько совпадений.