Проверьте, содержит ли строка только пробельные символы в C - PullRequest
1 голос
/ 04 февраля 2020

Я реализую оболочку в C11, и я хочу проверить, имеет ли ввод правильный синтаксис, прежде чем выполнять системный вызов для выполнения команды. Одним из возможных входных данных, от которых я хочу защититься, является строка, состоящая только из символов пробела. Как эффективный способ проверить, содержит ли строка только пробелы, символы табуляции или любые другие символы пробела?

Решение должно быть в C11, и желательно с использованием стандартных библиотек. Строка, прочитанная из командной строки с использованием readline() из readline.h, сохраняется в массиве символов (char[]). Пока что единственное решение, о котором я подумал, это l oop над массивом и проверка каждого отдельного char с помощью isspace(). Есть ли более эффективный способ?

Ответы [ 3 ]

3 голосов
/ 04 февраля 2020

Пока что единственное решение, о котором я подумал, это l oop над массивом и проверка каждого отдельного символа с помощью isspace().

Это звучит примерно так: верно!

Есть ли более эффективный способ?

Не совсем. Вам нужно , чтобы проверить каждый символ, если вы хотите убедиться, что присутствует только пробел. может быть некоторой уловкой с использованием битовых масок для более быстрого обнаружения непробельных символов ( подобно strlen() делает для поиска терминатора NUL), но я бы определенно не не посоветуйте.

Вы можете использовать strspn() или strcspn() для проверки возвращаемого значения, но это, безусловно, будет медленнее, поскольку эти функции предназначены для работы с произвольным принимать / отклонять строки и сначала нужно создать таблицы поиска, в то время как isspace() оптимизируется для этой цели с использованием предварительно созданной таблицы поиска и, скорее всего, также будет встроен компилятором с использованием надлежащих флагов оптимизации. Кроме этого, векторизация кода кажется единственным способом ускорить процесс. Скомпилируйте с -O3 -march=native -ftree-vectorize (см. Также этот пост ) и запустите некоторые тесты.

2 голосов
/ 04 февраля 2020

"l oop над массивом и проверьте каждый отдельный символ с помощью isspace()" -> Да go с этим.

Время для этого тривиально по сравнению с readline().

0 голосов
/ 04 февраля 2020

Я собираюсь предложить альтернативное решение вашей проблемы: используйте strtok. Он разбивает строку на подстроки на основе заданного c набора игнорируемых разделителей. С пустой строкой вы просто не получите никаких токенов.

Если вам нужно более сложное соответствие, чем это для вашей оболочки (например, для использования аргументов в кавычках), вам лучше написать небольшой токенизатор / лексер. Метод strtok в основном состоит в том, чтобы просто найти любой из указанных вами разделителей, временно заменить их на \ 0, вернуть подстроку до этой точки, вернуть старый символ и повторить, пока он не достигнет конца строки.

Редактировать: Как занятое пчела указывает в комментарии ниже, strtok не возвращает символ, который он заменяет на \ 0. Вышеупомянутый абзац был сформулирован плохо, но я намеревался объяснить, как реализовать собственный простой токенизатор / лексер, если вам нужно, а не объяснить, как strtok работает до мельчайших деталей.

...