Чтение пользовательского ввода и проверка строки

Как проверить прочитанную строку на наличие подстроки в C?

Если у меня есть следующее

char name[21];
fgets(name, 21, stdin);

Как проверить строку на наличие серии подстрок?

Как проверить наличие подстроки перед символом? Например, как проверить наличие подстроки перед знаком =?


person some_id    schedule 13.02.2011    source источник
comment
Опубликуйте образец входной строки. Если strtok не может токенизировать его, вам, возможно, придется просто сканировать char за char и выбирать подстроки.   -  person Michael Dillon    schedule 13.02.2011


Ответы (3)


Будьте осторожны с strtok(); это не повторный вход. Среди прочего, это означает, что если вам нужно вызвать его в одной функции, а затем вызвать другую функцию, и если эта другая функция также использует strtok(), ваша первая функция испорчена. Он также записывает байты NUL ('\0') поверх разделителей, поэтому он изменяет входную строку по мере ее поступления. Если вы ищете более одного символа-терминатора, вы не сможете сказать, какой из них был найден. Кроме того, если вы пишете библиотечную функцию для использования другими, но ваша функция использует strtok(), вы должны задокументировать этот факт, чтобы вызывающие вашу функцию не были сбиты с толку ошибками их собственного кода, использующего strtok(). после вызова вашей функции. Другими словами, он ядовит; если ваша функция вызывает strtok(), это делает вашу функцию непригодной для использования в целом; аналогично, ваш код, использующий strtok(), не может вызывать чужие функции, которые также используют его.

Если вам все еще нравится идея функциональности - некоторым людям нравится (но я почти всегда избегаю этого) - тогда поищите strtok_r() в своей системе. Это повторный вход; он принимает дополнительный параметр, который означает, что другие функции могут использовать strtok_r() (или strtok()), не затрагивая вашу функцию.

Существует множество альтернатив, которые могут быть уместны. Очевидными являются strchr(), strrchr(), strpbrk(), strspn(), strcspn(): ни один из них не изменяет анализируемые строки. Все они являются частью стандарта C (как и strtok()), поэтому доступны везде. Поиск материала перед одним символом предполагает, что вы должны использовать strchr().

person Jonathan Leffler    schedule 13.02.2011
comment
Мне нужен эквивалент компонентов Objective CSeparatedByString:, который возвращает массив элементов, чтобы вы могли получить доступ к тому, что хотите. - person some_id; 13.02.2011
comment
+1 за то, что победил меня и использовал больше слов одновременно. О третьей strtok проблеме я никогда раньше не задумывался. - person Chris Lutz; 13.02.2011
comment
@alJaree - Вам придется свернуть свое собственное. Должен ли он возвращать массив C (с выходным параметром size_t *)? Или он должен взять буфер и длину в качестве параметров и попытаться их заполнить? Или он должен возвращать определяемую пользователем структуру, которая служит цели массива? Точно так же, как он должен распределять строки? - person Chris Lutz; 13.02.2011
comment
То, что я собираюсь сделать, это иметь коллекцию структур. В этих структурах у меня есть переменные, и одна из переменных представляет собой массив строк. Поэтому мне нужно получить пользовательский ввод, обработать его, назначив его полям tempStruct. Я хочу проверить ввод пользователя и сопоставить первый токен (до «:»), а затем взять остальные и сохранить их в массиве строк. повторять до тех пор, пока первый токен не будет соответствовать тому, что я хочу, а затем добавить эту структуру в структуру коллекции. - person some_id; 13.02.2011
comment
@alJaree: Как будет распределяться память? Как узнать, какой длины будут входные строки? Что произойдет, если строка ввода окажется длиннее, чем вы думали? Как вы можете сказать, что первый токен не соответствует тому, что вы хотите? Когда вы говорите «массив строк», вы разделяете то, что следует за двоеточием? Вам нужно иметь дело с пробелами перед двоеточием? До первого слова? После двоеточия? Сопоставляете ли вы несколько строк с одним и тем же префиксом одной и той же временной структуре или обрабатываете каждую строку отдельно? Что произойдет, если в строке ввода нет двоеточия? - person Jonathan Leffler; 13.02.2011

Используйте strtok(), чтобы разбить строку на токены.

char *pch;
pch = strtok (name,"=");
if (pch != NULL)
{
  printf ("Substring: %s\n",pch);
}

Вы можете продолжать вызывать strtok(), чтобы найти больше строк после =.

person chrisaycock    schedule 13.02.2011
comment
Спасибо. что это вернет или распечатает? Подстрока перед = ? Как можно сравнить это с другой строкой в ​​C? - person some_id; 13.02.2011
comment
Это строка перед =. Все сравнения строк выполняются с помощью strcmp() (или варианта, подобного strncmp()) в C, поэтому просто используйте pch в качестве одного из параметров. - person chrisaycock; 13.02.2011

Вы можете использовать strtok, но он не является реентерабельным и уничтожает исходную строку. Другими (возможно, более безопасными) функциями, на которые стоит обратить внимание, будут strchr, strstr, strspn и, возможно, mem* варианты. В общем, я избегаю вариантов strn*, потому что, несмотря на то, что они выполняют «проверку связей», они все еще полагаются на нулевой терминатор. Они могут потерпеть неудачу на действительной строке, которая просто окажется длиннее, чем вы ожидали, и они фактически не предотвратят переполнение буфера, если вы не знаете размер буфера. Лучше (ИМХО) игнорировать терминатор и точно знать, с каким объемом данных вы работаете, каждый раз, когда работают функции mem*.

person Chris Lutz    schedule 13.02.2011
comment
C кажется таким примитивным. Я просто хочу выучить его для университетского курса. Такая борьба, чтобы делать вещи динамично. Я бы хотел, чтобы obj c был более распространенным. :/ Так что, если я не знаю, сколько данных я буду получать каждый раз. Я разделяю пользовательский ввод. например Язык: английский. Я хочу проверить язык, а затем взять английский и сохранить его. - person some_id; 13.02.2011
comment
@alJaree - Это очень преднамеренно. Это позволяет вам делать вещи быстрее и точнее. Если вы хотите легкого динамического управления (что тоже хорошо и имеет свои достоинства), вам не следует использовать C. Но также важно научиться делать это на языке C. - person Chris Lutz; 13.02.2011
comment
Конечно. Я знаю, что это здорово знать, как все работает. Что произойдет в будущем, когда компьютеры будут иметь практически неограниченную память и вычислительную мощность? В любом случае, это другое обсуждение;) Поэтому я должен вручную сканировать массив символов (пользовательский ввод) и проверять разделитель, сохраняя каждую часть в массив самостоятельно или есть библиотечная функция, которую можно использовать для разделения строки и хранения части в массив? - person some_id; 13.02.2011
comment
@alJaree: это зависит от того, какие у вас есть библиотеки, которые вы можете использовать. В стандартной библиотеке C такой функции нет, но, вероятно, такие функции есть в других библиотеках, созданных поверх стандартной библиотеки C. - person Jonathan Leffler; 13.02.2011
comment
@alJaree - Ну, на самом деле это не сканирование вручную, когда вы можете использовать strchr и strspn, но хранилище массива - это то, что вам придется делать самостоятельно. В C нет встроенного типа динамического массива, как в большинстве других языков. - person Chris Lutz; 13.02.2011