Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 42, средняя оценка - 4.79
besh]<a
13 / 11 / 1
Регистрация: 02.11.2009
Сообщений: 194
#1

Си-шные строки, как вытащить подстроку - C++

05.03.2012, 22:37. Просмотров 6427. Ответов 13
Метки нет (Все метки)

Есть ли для строк типа char*, wchar_t* стандартная функция, которая вытаскивает подстроку, как в классе string.substring(int pos, int count)?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.03.2012, 22:37
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Си-шные строки, как вытащить подстроку (C++):

Как эффективно заменить подстроку в строке на другую подстроку? - C++
И если у подстрок разная длина? есть проверенный готовый способ?

Как вытащить из строки значение? - C++
Есть строка такого вида: подстроки типа &quot;request=3&quot; и &quot;action=11&quot; разделены табуляциями. Как мне получить значение &quot;11&quot; из...

Строки. Удалить из строки S1 последнюю подстроку, совпадающую с S2 - C++
Помогите решить задачу Даны строки S1 и S2. Удалить из строки S1 последнюю подстроку, совпадающую с S2. Если совпадающих подстрок...

Как скопировать подстроку из строки до определенного символа? Или удалить, начиная с этого символа - C++
Добрый вечер. Ответ искал, но не нашёл. Предположим, есть строка: ABC|DEF Надо скопировать всё до | , т.е., в приведённом...

Удаления со строки подстроку! - C++
Здраствуйте! Дано подстроку...найти и уничтожить его со всех слов в строке... помогите плиз....

Выделить подстроку из строки, использую char* - C++
Нужно выделить подстроку из строки в массивах char*. например: char*ch = new char; ch = Hello world; //и дальше получить hello в...

13
go
Эксперт С++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
05.03.2012, 23:11 #2
Не припомню. Но вот почему бы самому не реализовать? Вот список функций для char* (хедер string.h) http://www.cplusplus.com/reference/clibrary/cstring/

Добавлено через 4 минуты
Цитата Сообщение от go Посмотреть сообщение
Но вот почему бы самому не реализовать?
Например так
C
1
2
3
4
5
6
const char* const substr(char* s, size_t pos, size_t count)
{
   static char buf[BUFSIZ];
   memset(buf, '\0', BUFSIZ);
   return strncpy(buf, s + pos, count);
}
Добавлено через 25 минут
А лучше так
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>
 
const char* const substr(char* s, size_t pos, size_t count)
{
   static char buf[BUFSIZ];
   buf[sizeof buf - 1] = '\0';
   if ( count >= BUFSIZ )
      return NULL;
   else
      return strncpy(buf, s + pos, count);
}
 
int main(void)
{
   char *s = "Hello world";
   printf("%s\n", substr(s, 6, 5));
}
http://liveworkspace.org/code/19f593...9c50a3e9e54a44
1
easybudda
Модератор
Эксперт CЭксперт С++
9664 / 5614 / 952
Регистрация: 25.07.2009
Сообщений: 10,778
06.03.2012, 00:19 #3
Цитата Сообщение от go Посмотреть сообщение
const char* const substr(char* s, size_t pos, size_t count)
Модификатор доступа у возвращаемого функцией значения в С - UB. Может и работать, но лучше так не делать.
Цитата Сообщение от go Посмотреть сообщение
return strncpy(buf, s + pos, count);
Тоже не комильфо. Из биэсдишного мануала:
The strncpy() function copies at most len characters from src into dst.
If src is less than len characters long, the remainder of dst is filled
with `\0' characters. Otherwise, dst is not terminated.
...
The following copies as many characters from input to buf as will fit and
NUL terminates the result. Because strncpy() does not guarantee to NUL
terminate the string itself, this must be done explicitly.

char buf[1024];

(void)strncpy(buf, input, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
То есть опять же может работать, может не работать...

Я бы как-то так сделал:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <string.h>
 
/* Копирует в dst не больше cnt символов из src начиная с позиции pos.
Память под принимающую строку должна быть заранее выделена с учётом завершающего нуля. */
char * substr(char * dst, const char * src, size_t pos, size_t cnt){
    size_t len;
    
    if ( ! dst || ! src || strlen(src) < pos )
        return NULL;
    
    if ( ( len = strlen(src + pos) ) > cnt )
        len = cnt;
    strncpy(dst, src + pos, len);
    dst[len] = '\0';
    
    return dst;
}
 
int main(void){
    char src[BUFSIZ], dst[BUFSIZ];
    size_t pos, cnt;
    
    while ( printf("String: ") && fgets(src, BUFSIZ, stdin) && *src != '\n'
        && printf("Start pos: ") && scanf("%u", &pos) == 1
        && printf("Count: ") &&  scanf("%u%*c", &cnt) == 1 )
            printf("Result: %s\n", substr(dst, src, pos, cnt));
    
    return 0;
}
2
go
Эксперт С++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
06.03.2012, 14:02 #4
Цитата Сообщение от easybudda Посмотреть сообщение
Модификатор доступа у возвращаемого функцией значения в С - UB. Может и работать, но лучше так не делать.
Это почему?


Цитата Сообщение от easybudda Посмотреть сообщение
Тоже не комильфо.
Не согласен. Здесь-то Вы не правы точно

Добавлено через 1 минуту
Прототип, описанный в заголовочном файле string.h:
char *strncpy (char *dst, const char *src, size_t len);
dst — указатель на буфер назначения.
src — указатель на исходную строку.
len — максимальное количество копируемых символов (см. раздел Безопасность ниже).
Функция копирует из строки src в буфер dst не более чем len символов (включая нулевой символ), не гарантируя завершения строки нулевым символом (если длина строки src больше или равна len). Если длина строки src меньше len, то буфер добивается до len нулями.
У меня даже строка 7 лишняя.
1
fasked
Эксперт С++
4942 / 2522 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
06.03.2012, 14:45 #5
Но вот static массив то зачем
1
go
Эксперт С++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
06.03.2012, 14:51 #6
Цитата Сообщение от fasked Посмотреть сообщение
Но вот static массив то зачем
Потому что возвращается указатель, на его память. Иначе память будет освобождена
0
-=ЮрА=-
Заблокирован
Автор FAQ
06.03.2012, 15:07 #7
besh]<a, Ниже крайне простой и вместе с тем крайне функциональный код,
для функции substr даже строковых библиотек не нужно будетРаботает и возвращает подстроки абсолютно любой длинны т.к. в коде есть динамическое выделение памяти, а не константный буфер как во всех постах выше
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using namespace std;
 
char * substr(const char * text, int beg, int end)
{
    int i;
    char *sub = 0;
    int len = end - beg;
    if(text)//Ïðîâåðÿåì Г*ГҐ ïóñòîé ëè ââîä
    if(text + beg)//Ïðîâåðÿåì ñóùåñòâîâГ*Г*ГЁГҐ Гў ГІГҐГЄГ±ГІГҐ ïîçèöèè beg
    if(0 < len)//Ïðîâåðÿåì êîððåêòГ*îñòü ГЇГ*Г°Г*ìåòðîâ ГЄГ®Г*ГҐГ¶ äîëæåГ* áûòü áîëüøå Г*Г*Г·Г*Г«Г*
    if((sub = new char[1 + len]))//Åñëè end ïðåâîñõîäèò ïîñëåäГ*ГѕГѕ
        //ïîçèöèþ ГІГҐГЄГ±ГІГ* Г*ГЁГ·ГҐГЈГ® Г±ГІГ°Г*ГёГ*îãî âûäåëèì Г·ГіГІГј áîëüøå ГЇГ*ìÿòè Г·ГҐГ¬ Г*Г*äî
    {
        //ÏðèìèòèâГ*îå êîìïèðîâГ*Г*ГЁГҐ, Г¤Г*æå òåêñòîâûõ áèáëèîòåê Г*ГҐ Г*Г*äî áóäåò
        for(i = beg; text[i] != '\0' && i < end; i++)
            sub[i - beg] = text[i];
        sub[i - beg] = '\0';//Íîëü òåðìèГ*Г*òîð ГўГЄГ®Г*öå ñòðîêè
    }
    return sub;
}
 
int main()
{
    char text[] = "abra kadabra";
    cout<<"input : "<<text<<endl;
    //ГЉ ïðìåðó ГЇГіГ±ГІГј áóäåò ïîäñòðîêГ* Г± 5-ГЈГ® ГЇГ® 15-Г© ñèìâîë
    //ГЄГ±ГІГ*ГІГЁ Гў text ìåГ*ГјГёГҐ Г·ГҐГ¬ 15 ñèìâîëîâ Г*Гі âîò Г§Г*îäГ*Г® ГЁ ïðîâåðèì
    //êîððåêòГ*îñòü Г°Г*áîòû substr
    cout<<"output: ";
    char * sub  = substr(text, 5 , 11);
    if(sub)
    {
        cout<<sub<<endl;
        delete [] sub;
    }
    else
        cout<<"Error substr\n";
    system("pause");
    return 0;
}
Скрин работы прилагаю
1
Миниатюры
Си-шные строки, как вытащить подстроку  
fasked
Эксперт С++
4942 / 2522 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
06.03.2012, 15:22 #8
Цитата Сообщение от go Посмотреть сообщение
Потому что возвращается указатель, на его память. Иначе память будет освобождена
Статические переменные - это, во-первых, ограничение длины строки, а во-вторых невозможность сохранения этого самого возвращаемого указателя на продолжетельное время (несколько вызовов функции). Тут придется либо использовать копирование строки, что есть неоптимально. А в лсучае многопоточности придется добавлять мьютекс на каждый вызов функции.
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Работает и возвращает подстроки абсолютно любой длинны т.к. в коде есть динамическое выделение памяти, а не константный буфер как во всех постах выше
Опять же не есть плюс для функции библиотечного характера. Если мне понадобится статчиеский массив, то я не смогу ее использовать. К тому же для C++ это вообще не актуально.
1
-=ЮрА=-
Заблокирован
Автор FAQ
06.03.2012, 15:44 #9
Цитата Сообщение от fasked Посмотреть сообщение
Если мне понадобится статчиеский массив, то я не смогу ее использовать.
- можешь пояснить на примере???

Добавлено через 3 минуты
fasked, запиши в моём коде
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
char text[] = "abra kadabra";
вот так
static char text[] = "abra kadabra";
и всё отработает без проблем, думаю что то ты перемудрил

Добавлено через 8 минут
Если речь коснулась Си, ну ничем не отличающийся код со static char text[]
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
#include <stdlib.h>
 
char * substr(const char * text, int beg, int end)
{
    int i;
    char *sub = 0;
    int len = end - beg;
    if(text)//Проверяем не пустой ли ввод
    if(text + beg)//Проверяем существование в тексте позиции beg
    if(0 < len)//Проверяем корректность параметров конец должен быть больше начала
    if((sub = (char *)malloc(1 + len)))//Если end превосходит последнюю
        //позицию текста ничего страшного выделим чуть больше памяти чем надо
    {
        //Примитивное компирование, даже текстовых библиотек не надо будет
        for(i = beg; text[i] != '\0' && i < end; i++)
            sub[i - beg] = text[i];
        sub[i - beg] = '\0';//Ноль терминатор вконце строки
    }
    return sub;
}
 
int main()
{
    static char text[] = "abra kadabra";
    printf("input : %s\n",text);
    //К прмеру пусть будет подстрока с 5-го по 15-й символ
    //кстати в text меньше чем 15 символов ну вот заодно и проверим
    //корректность работы substr
    printf("output: ");
    char * sub  = substr(text, 5 , 11);
    if(sub)
    {
        printf("%s\n",sub);
        free((void *)sub);
    }
    else
        printf("Error substr\n");
    getchar();
    return 0;
}
Вот и проверка http://codepad.org/vPp56BAX
Не знаю что тут ещё разбирать, все работает вот и всё...
0
fasked
Эксперт С++
4942 / 2522 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
06.03.2012, 16:14 #10
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Не знаю что тут ещё разбирать, все работает вот и всё...
Речь не о том работает или нет, речь о дизайне. Если я не хочу, чтобы функция выделяла память, то я не могу ее использовать. Потому что она делает это всегда. К тому же мне еще надо контролировать это, освобождать память. На мой взгляд выделять и освобождать память разными сущностями вообще некрасиво (за редкими исключениями).
Простой выход - не заботится о памяти и предоставить это сделать вызывающей стороне. Чем он вам всем не нравится, я не пойму? Посмотрите на стандартную библиотеку, сколько функций там выделяет память самостоятельно?
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
и всё отработает без проблем, думаю что то ты перемудрил
Я имею в виду строку-приемник. Посмотри на код easybudda - он гораздо гибче.
0
go
Эксперт С++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
06.03.2012, 16:22 #11
Цитата Сообщение от fasked Посмотреть сообщение
Чем он вам всем не нравится, я не пойму?
Да писался некий аналог http://www.cplusplus.com/reference/s...string/substr/
А так я согласен, память лучше, чтобы выделял вызывающая сторона (ну а это еще 2 доп. параметра)

Добавлено через 3 минуты
Цитата Сообщение от easybudda Посмотреть сообщение
Я бы как-то так сделал:
http://codepad.org/6ZKn10Xd
0
-=ЮрА=-
Заблокирован
Автор FAQ
06.03.2012, 16:28 #12
Цитата Сообщение от fasked Посмотреть сообщение
Потому что она делает это всегда. К тому же мне еще надо контролировать это, освобождать память. На мой взгляд выделять и освобождать память разными сущностями вообще некрасиво (за редкими исключениями).
Простой выход - не заботится о памяти и предоставить это сделать вызывающей стороне. Чем он вам всем не нравится, я не пойму? Посмотрите на стандартную библиотеку, сколько функций там выделяет память самостоятельно?
- теперь понял к чему относилось замечание. Для случая когда не хотим заботиться о чистке, выносим переменную отвечающую за динамический массив в глобальные и предусматриваем чистку внутри функции, либо изобрести свой маханький класс. На счёт стандартных функций знаю лишь аналоги substr в CString и встречал в php, для char-ов string.h её вроди как и не содержит, поэтому програмисту нужно работать руками самому для реализации указанного функционала

Добавлено через 2 минуты
Чтобы не быть голословным
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Для случая когда не хотим заботиться о чистке, выносим переменную отвечающую за динамический массив в глобальные и предусматриваем чистку внутри функции
- привожу код
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>
#include <stdlib.h>
 
char *sub;
char * substr(const char * text, int beg, int end)
{
    int i;
    if(sub)
        free((void *)sub);
    sub = 0;
    int len = end - beg;
    if(text)//Ïðîâåðÿåì Г*ГҐ ïóñòîé ëè ââîä
    if(text + beg)//Ïðîâåðÿåì ñóùåñòâîâГ*Г*ГЁГҐ Гў ГІГҐГЄГ±ГІГҐ ïîçèöèè beg
    if(0 < len)//Ïðîâåðÿåì êîððåêòГ*îñòü ГЇГ*Г°Г*ìåòðîâ ГЄГ®Г*ГҐГ¶ äîëæåГ* áûòü áîëüøå Г*Г*Г·Г*Г«Г*
    if((sub = (char *)malloc(1 + len)))//Åñëè end ïðåâîñõîäèò ïîñëåäГ*ГѕГѕ
        //ïîçèöèþ ГІГҐГЄГ±ГІГ* Г*ГЁГ·ГҐГЈГ® Г±ГІГ°Г*ГёГ*îãî âûäåëèì Г·ГіГІГј áîëüøå ГЇГ*ìÿòè Г·ГҐГ¬ Г*Г*äî
    {
        //ÏðèìèòèâГ*îå êîìïèðîâГ*Г*ГЁГҐ, Г¤Г*æå òåêñòîâûõ áèáëèîòåê Г*ГҐ Г*Г*äî áóäåò
        for(i = beg; text[i] != '\0' && i < end; i++)
            sub[i - beg] = text[i];
        sub[i - beg] = '\0';//Íîëü òåðìèГ*Г*òîð ГўГЄГ®Г*öå ñòðîêè
    }
    return sub;
}
 
int main()
{
    static char text[] = "abra kadabra";
    printf("input : %s\n",text);
    //ГЉ ïðìåðó ГЇГіГ±ГІГј áóäåò ïîäñòðîêГ* Г± 5-ГЈГ® ГЇГ® 15-Г© ñèìâîë
    //ГЄГ±ГІГ*ГІГЁ Гў text ìåГ*ГјГёГҐ Г·ГҐГ¬ 15 ñèìâîëîâ Г*Гі âîò Г§Г*îäГ*Г® ГЁ ïðîâåðèì
    //êîððåêòГ*îñòü Г°Г*áîòû substr
    printf("output: ");
    char * sub  = substr(text, 5 , 11);
    if(sub)
        printf("%s\n",sub);
    else
        printf("Error substr\n");
    sub  = substr(text, 7 , 9);
    if(sub)
        printf("%s\n",sub);
    else
        printf("Error substr\n");
    getchar();
    return 0;
}
Добавлено через 50 секунд
Всё ок http://codepad.org/irb5mCfD
1
fasked
Эксперт С++
4942 / 2522 / 180
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
06.03.2012, 16:39 #13
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Для случая когда не хотим заботиться о чистке, выносим переменную отвечающую за динамический массив в глобальные и предусматриваем чистку внутри функции
И получаем все недостатки использования статического массива, кроме ограничения по длине строки.
0
besh]<a
13 / 11 / 1
Регистрация: 02.11.2009
Сообщений: 194
12.03.2012, 21:16  [ТС] #14
Всем спасибо за ваши ответы.

Такая беда, когда внутри функции выделяется память оператором new, то в билдере vcl объекты не могут выполнить следующие операции, когда пытаешься сделать
C++
1
2
UnicodeString=substring(...); 
RichEdit->Lines->Add(substrin(...));
Вылетает с ошибкой. При использовании статического массива все нормально.

И еще при таком объявление
C++
1
wchar_t* word=L"hells bells";
, оператор
C++
1
delete [] word;
нужен? При запуске программы оба варианта работают нормально.

И еще один вопрос по по поводу функции возвращающей указатель, на который она выделила память. В след ситуации произойдет утечка памяти?
C++
1
strstr(str, substr(...))
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.03.2012, 21:16
Привет! Вот еще темы с ответами:

Удалить из строки S1 первую подстроку, совпадающую с S2 - C++
Даны две строки: S1 и S2. Удалить из строки S1 первую подстроку, совпадающую с S2. Если такой подстроки нет, то вывести S1 без изменений.

Удалить из строки S последнюю подстроку,совпадающую с S0. - C++
Язык программирования-С++! Даны строки S и S0.Удалить из строки S последнюю подстроку,совпадающую с S0. Если совпадающих подстрок нет,то...

выделить из строки наибольшую монотонную подстроку - C++
помогите.очень нужно) написать программу-выделить из строки наибольшую монотонную подстроку(коды последовательных символов отличаются на...

Удалить из строки последнюю подстроку, совпадающую с заданной - C++
Даны строки S и S0. Удалить из строки S последнюю подстроку, совпадающую с S0 . Если совпадающих подстрок нет, то вывести строку S без...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Yandex
Объявления
12.03.2012, 21:16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru