Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
n0n4m3r
25 / 25 / 15
Регистрация: 12.10.2013
Сообщений: 183
#1

Функция удаления текста в скобках [2], непосредственно функция + 12кб вложений

04.03.2015, 13:00. Просмотров 702. Ответов 12
Метки нет (Все метки)

Доброго времени суток, случилось так, что пришлось работать с с-строками

Не по теме:

(лаба, угу)

, в которой нужно удалить весь текст в скобках, например на входе строки типа:
fail(one);
fail(one)ed;
(one)failtwo;
На выходе должно быть:
fail;
failed;
failtwo;

Есть функция, принимающая с-строку и длинну (на самом деле тут дело больше в логике, а не в передаче данных, надеюсь) по указателю, а значит работает с оригиналом.
В общем, позанимавшись любовью с гуглом (видимо что-то не то гуглил), cplusplus.com, ни к чему не пришел (лох, чо). Остановился на варианте:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void remover(char *arr, const int len){
    int start=-1, end=-1;
    for (int i = 0; i < len; ++i){
        if (((int)arr[i] == int('(')) | ((int)arr[i] == int(')'))){ //Такой вот костыль, ибо strcmp требует const char*, а не char, может и тут чего сможете подсказать?
            switch (arr[i]){
            case '(':
                start = i;
                break;
            case ')':
                end = i;
                break;
            } //default не нужен.
        }
        
        if (start < end){
            for (int j = start; j <= end; ++j)
                arr[j] = 8;
        } //тут еще планировалось обнулять переменные start/end, но пока и с одной работает "криво"
    }
    std::cout << "\nExit line: " << arr << '\n';
}
Получается что первое условие обрабатывает нормально, а вот во втором уже "шалит", выводя текст за скобками куда-то вперед строки (см. скрин)
Для двух и более наборов скобок даже проверять боюсь.
Подскажите, пожалуйста, что я делаю не так? (Не считая того, что говнокодю)
0
Миниатюры
Функция удаления текста в скобках [2], непосредственно функция + 12кб вложений   Функция удаления текста в скобках [2], непосредственно функция + 12кб вложений   Функция удаления текста в скобках [2], непосредственно функция + 12кб вложений  

Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.03.2015, 13:00
Ответы с готовыми решениями:

Функция удаления текста в скобках
Есть задание: Написать функцию, которая из строки удаляет подстроки,...

Какая функция производит непосредственно копирование значение тега?
Доброго времени суток. Впервые приходится работать с библиотекой TinyXML и,...

Функция удаления на С
Помогите исправить ошыбки в удалении вот полный код: #include &lt;stdio.h&gt;...

Не выполняется функция удаления
Функция удаления не выполняется. Вот код: #include &lt;iostream&gt; #define MAX...

Функция удаления из списка
помогите разобраться почему не работает функция удаления? плз #include...

12
S_el
2138 / 1668 / 353
Регистрация: 15.12.2013
Сообщений: 6,625
04.03.2015, 13:23 #2
n0n4m3r, будет проще использовать std::string + regex.

Добавлено через 3 минуты
А,у вас C-строки...тогда попробуйте
http://www.cplusplus.com/reference/cstring/strtok/
бейте по символам открывающих и закрывающих скобок и объединяйте первый участок с последний в строку.
0
n0n4m3r
25 / 25 / 15
Регистрация: 12.10.2013
Сообщений: 183
04.03.2015, 18:16  [ТС] #3
S_el,
вышло что-то типа
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
void remover(char *arr, const int len){
    int cntr = 1;
    char copy[255];
    strcpy_s(copy, 255, arr);
    memset(arr, 0, 255);
    char* token = NULL;
    char* context = NULL;
    char  delims[] = "()";
 
    // During the first read, establish the char string and get the first token.
    token = strtok_s(copy, delims, &context);
    strcat_s(arr, strlen(token)+1, token);
    // While there are any tokens left in "copy"...
    while (token != NULL)
    {
        // Accumulate the tokens.
        if (cntr++ % 2 != 0)
            strcat_s(arr, strlen(token)+1, token);
        //std::cout << "Token: " << token << '\n';
 
        // NOTE: NULL, function just re-uses the context after the first read.
        token = strtok_s(NULL, delims, &context);
    }
    std::cout << "\nExit line: " << arr << '\n';
}
Про strtok_s спёрто тут.
Теперь при копировании пишет "String is not null terminated", указывая на Line 32, в которой у меня комментарий. (если нужно -- могу показать мейн, но там, кроме вызовов, ничего нет).
0
S_el
2138 / 1668 / 353
Регистрация: 15.12.2013
Сообщений: 6,625
04.03.2015, 18:28 #4
Цитата Сообщение от n0n4m3r Посмотреть сообщение
(если нужно -- могу показать мейн, но там, кроме вызовов, ничего нет).
Лучше привести весь код,так кто-то из форумчан сможет у себя запустить и подправить.
0
n0n4m3r
25 / 25 / 15
Регистрация: 12.10.2013
Сообщений: 183
04.03.2015, 18:31  [ТС] #5
Кликните здесь для просмотра всего текста
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
#include <string>
 
 
void remover(std::string&);
void remover(char[], const int);
 
int main(int argc, char *argv[]){
    std::string *address;
    unsigned int records = 0, length = 0;
 
    while (records < 1){
        std::cout << "Enter ammount of records: "; std::cin >> records; std::cin.ignore();
    }
 
    char **lineC = new char* [records];
    std::string *line = new std::string[records];
 
    for (unsigned int j = 0; j < records; ++j){
        lineC[j] = new char[255];
    }
 
    //Заполнение массивов, начало!
    for (unsigned int i = 0; i < records; ++i){
        do{
            std::cout << "Input " << i + 1 << " line, shorter than 255 symbols: "; std::getline(std::cin, line[i]); //string line
        } while (line[i].length() > 255);
        strcpy_s(lineC[i], line[i].size() + 1, line[i].c_str());
        std::cout << "string: " << line[i];
        std::cout << "\ncString: " << lineC[i] << '\n';
    }
    //Заполнение массивов, конец
 
 
    for (unsigned int i = 0; i < records; ++i){
        length = line[i].length();
        address = &line[i];
        remover(*address);
        remover(lineC[i], length);
        std::cout << "remover line: " << lineC[i] << '\n';
    }
    system("pause");
    return 0;
}
 
void remover(std::string& s){
    int openPos = s.size(), closePos = 0;
    while(1){
        openPos = s.find_last_of('(', openPos-1);
        closePos = s.find(')', s.find_last_of('(', openPos));
        if ((openPos == -1) | (openPos == 0 && closePos == -1))
            break;
        else if ((openPos != -1) && (closePos != -1))
            s.erase(openPos, closePos - openPos + 1);
    }
}
 
void remover(char *arr, const int len){
    int cntr = 1;
    char copy[255];
    strcpy_s(copy, 255, arr);
    memset(arr, 0, 255);
    char* token = NULL;
    char* context = NULL;
    char  delims[] = "()";
 
    // During the first read, establish the char string and get the first token.
    token = strtok_s(copy, delims, &context);
    strcat_s(arr, strlen(token)+1, token);
    // While there are any tokens left in "copy"...
    while (token != NULL)
    {
        // Accumulate the tokens.
        if ((cntr++ % 2) == 0)
            strcat_s(arr, strlen(token)+1, token);
        //std::cout << "Token: " << token << '\n';
 
        // NOTE: NULL, function just re-uses the context after the first read.
        token = strtok_s(NULL, delims, &context);
    }
    std::cout << "\nExit line: " << arr << '\n';
}

Есть задание: Написать функцию, которая из строки удаляет подстроки, заключенные в круглые скобки. Написать программу, которая принимает от пользователя набор строк и удаляет из всех строк этого набора подстроки, заключенные в круглые скобки. Использовать написанную функцию.
Есть условие: В первом варианте функция должна принимать в качестве параметра одну (!) С-строку с использованием механизма передачи ее через указатель, во втором - одну(!) строку класса string с использованием механизма передачи ее по ссылке.

Желательно без "крутых сюжетных поворотов", но, если можно - с указаниями на них.)
Заранее благодарю.
0
n0n4m3r
25 / 25 / 15
Регистрация: 12.10.2013
Сообщений: 183
05.03.2015, 10:47  [ТС] #6
Немного изменил функцию,
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
void remover(char *arr, const int len){
    int cntr = 1;
    char copy[255];
    strcpy_s(copy, 255, arr);
    memset(arr, 0, 255);
    char* token = NULL;
    char* context = NULL;
    char  delims[] = "()";
 
    // During the first read, establish the char string and get the first token.
    token = strtok_s(copy, delims, &context);
    strcat_s(arr, strlen(copy)+1, copy); //Заменил тут token на copy, пропустило дальше.
    // While there are any tokens left in "copy"...
    while (token != NULL)
    {
        // Accumulate the tokens.
        
        std::cout << "Token: " << token << '\n';
 
        // NOTE: NULL, function just re-uses the context after the first read.
        token = strtok_s(NULL, delims, &context);
 
        if ((cntr++ % 2) == 0)
            strcat_s(arr, strlen(token) + 1, token);; //А вот тут - всё равно пишет "Buffer is too small"
    }
    std::cout << "\nExit line: " << arr << '\n';
}
0
Миниатюры
Функция удаления текста в скобках [2], непосредственно функция + 12кб вложений  
S_el
2138 / 1668 / 353
Регистрация: 15.12.2013
Сообщений: 6,625
05.03.2015, 11:41 #7
изменение std::string предлагаю переписать так:
C++
1
2
3
4
5
void remover(std::string& s)
{
  std::regex e ("\\(.*\\)");  
  s=std::regex_replace (s,e,"");
}
только не забудьте подключить заголовочный файл regex

Добавлено через 26 минут
Можно еще проще:
C++
1
2
3
4
void remover2(std::string& s)
{
s.erase(s.find('('),s.size()-s.rfind(')')+1);
}
0
n0n4m3r
25 / 25 / 15
Регистрация: 12.10.2013
Сообщений: 183
05.03.2015, 12:03  [ТС] #8
Цитата Сообщение от S_el Посмотреть сообщение
Можно еще проще:
А не будет ли например такого удаления:
one(two)three(four)five на входе, а на выходе - onefive, похоже что так и будет.) Это просто в примерах для с-строк пока использовалась одна комбинация скобок!

Цитата Сообщение от S_el Посмотреть сообщение
изменение std::string предлагаю переписать так:
Скриншоты с примерами во вложении


А так - с с-строкой вообще какая-то засада =(
0
Миниатюры
Функция удаления текста в скобках [2], непосредственно функция + 12кб вложений   Функция удаления текста в скобках [2], непосредственно функция + 12кб вложений   Функция удаления текста в скобках [2], непосредственно функция + 12кб вложений  

Функция удаления текста в скобках [2], непосредственно функция + 12кб вложений  
S_el
2138 / 1668 / 353
Регистрация: 15.12.2013
Сообщений: 6,625
05.03.2015, 12:10 #9
Цитата Сообщение от n0n4m3r Посмотреть сообщение
one(two)three(four)five на входе, а на выходе - onefive, похоже что так и будет.)
Значит организуйте удаление в цикле и ищите с одного конца.Главное,чтобы количество скобок совпадало.
0
n0n4m3r
25 / 25 / 15
Регистрация: 12.10.2013
Сообщений: 183
05.03.2015, 12:16  [ТС] #10
S_el, да вся беда в том, что функция со std::string работает нормально, а вот с char[] - нет, но спасибо, регулярные тоже помучаю, звучит очень интересно.)
0
AleksandrKos
0 / 0 / 1
Регистрация: 05.03.2015
Сообщений: 3
05.03.2015, 12:49 #11
Понятное дело, что решение уже давно не нужно, но сделал очень простое решение:

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
#include <iostream>
 
using namespace std;
 
void main()
{
    char *arr = {"Hello world!(text) My name is (other text)Aleksandr"};
    cout << "Your string: ";
 
    int i = 0;
    while (arr[i] != '\0')
    {
        cout << arr[i];
        i++;
    }
    cout << endl;
    
    i = 0;
    while (arr[i] != '\0')
    {
        if (arr[i] != '(')
        {
            cout << arr[i];
            i++;
        } else
        {
            while (arr[i] != ')')
            {
                i++;
            }
            i++;
        }
    }
    cout << endl;
 
    getchar();
}
0
n0n4m3r
25 / 25 / 15
Регистрация: 12.10.2013
Сообщений: 183
05.03.2015, 14:19  [ТС] #12
Цитата Сообщение от AleksandrKos Посмотреть сообщение
Понятное дело, что решение уже давно не нужно
Решение нужно до сих пор, но сложность в том, что нужен не "вывод" без скобок, а их полное удаление, чтоб вывод массива через
C++
1
std::cout << arr << std::endl;
Показал без скобок.

Добавлено через 1 час 3 минуты
Все "гениальное" - просто:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void remover(char *arr, const int len){
    int j = 0;
    char copy[255];
    strcpy_s(copy, 255, arr);
    memset(arr, 0, 255);
    bool copying = true;
 
        for (int i = 0; i < len; ++i){
            if ((int)copy[i] == (int)'('){
                copying = false;
            }
            else if ((int)copy[i] == (int)')'){
                copying = true;
            }
            else if (copying){
                arr[j] = copy[i];
                ++j;
            }
        }
        arr[j] = '\n';
 
    std::cout << "\nExit line: " << arr << '\n';
}
0
daslex
1291 / 535 / 177
Регистрация: 02.08.2011
Сообщений: 2,756
05.03.2015, 17:35 #13
Лучший ответ Сообщение было отмечено n0n4m3r как решение

Решение

Всё то же самое, но глаза меньше ломаются
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void remover(char *arr){
    bool flag=true;
    unsigned int count=0;
//---------------------------------------------------
        for (unsigned int i=0;i<strlen(arr);i++){
//---------------------------------------------------       
            if (arr[i]=='(' and flag==true)  flag=false;        
            else if (arr[i]==')' and flag==false) {
                    flag=true;
                    continue;
                    }
//-----------------
            if (flag) {
                    arr[count]=arr[i];
                    count++;
            }
//---------------------------------------------------
        } //end for
//---------------------------------------------------
        arr[count]='\0';
}
Вызов
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char ch[]="(1ssfail(one)aa(ddd)";
       remover(ch);  //Так
       cout<<ch<<"\n";
 
 
    strcpy(ch,"chfail(one)"); 
    remover(ch);
    cout<<ch<<"\n";
 
    strcpy(ch,"fail(one)ed;");
    remover(ch);
    cout<<ch<<"\n";
 
    strcpy(ch,"(one)failtwo;");
    remover(ch);
    cout<<ch<<"\n";
1
05.03.2015, 17:35
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.03.2015, 17:35

Двусвязный список - функция удаления
Подскажите,где ошибка. Функция удаляет книгу из списка по названию автора... ...

Функция для удаления элемента
Есть ли функция в си++ для удаления элемента,например из текста?) Запрещено...

Односвязный список.Функция удаления
Здравствуйте.Пытался организовать функцию удаления,но не получилось,добавлял...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

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