383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
1

Segmentation fault (iterator)

27.12.2013, 00:52. Показов 1106. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
И снова здравствуйте!
Кратко: функция некоторым образом парсит строку (не в этом проблема) и удаляет из нее НЕ алфавитно-цифровые символы.
Призываю не обдумывать возможные частные случаи, которые еще не предусмотрены в функции, ибо пока входная строка "подгоняется", чтобы регулярное выражение нашло то, что искало.
Прошу помощи ибо бесконечный цикл в 51 строке уморил основательно. Я так понял проблема с итератором mainIter
C++ (Qt)
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
#include "app_headers/abstractconverter.h"
#include <iostream> // std::cerr
#include <boost/regex.hpp>
 
/*-> static <-*/ void AbstractConverter::filter_string(std::string &str) try {
    typedef std::string::iterator SIt_t;
    typedef std::string::const_iterator CSIt_t;
    typedef std::string::difference_type diff_t;
    bool withMinus;
    char* prevLocale = setlocale(LC_CTYPE, "C");
 
    // If the first non-whitespace character is '-'
    SIt_t mainIter = std::find_if_not(str.begin(), str.end(),
                                     [](char ch) -> bool {return isspace(ch);});
    // we consider, that the number is negative, otherwise - non negative.
    if(mainIter == str.end())
        throw prevLocale;
    if(*mainIter == '-')
    {
        withMinus = true;
        ++mainIter;
    }
    else withMinus = false;
 
    if(withMinus)
    {
        // Erase all unnecessary symbols between
        // '-' and first digit of the number.
        // This is requirement of GMP functions
        // mpf_set_str() and mpz_set_str().
        // See their documentation for details.
 
        // Find First Alpha-Numeric Symbol after minus.
        SIt_t fans = std::find_if(mainIter,
                                  str.end(),
                                  [](char ch) -> bool { return isalnum(ch); }
                                );
        if(fans == str.end())
            throw prevLocale;
        else str.erase(mainIter, fans);
    }
    // Here we at the position of the first meaning digit of the number.
 
    boost::regex reg(R"_([[:alnum:]]+\.[[:alnum:]]+)_", boost::regex_constants::extended);
    boost::smatch match;
    CSIt_t search_begin(mainIter);
 
    if ( boost::regex_search(search_begin, str.cend(), match, reg) )
    {
        diff_t capture_pos = match.position();
        for( ; mainIter != mainIter + capture_pos; ++mainIter)
            if(!isalnum(*mainIter))
                *mainIter = ' ';
        mainIter += match.length();
    }
 
 
    // Replace all unnecessary symbols in the number with spaces ' ';
    // If in the number presented multiple dots ('.'), only first dot
    // is accepted, while others replaced with spaces.
    // GMP funcs mpf_set_str() and mpz_set_str() are ignore spaces.
 
    for( ; mainIter != str.end(); ++mainIter)
        if(!isalnum(*mainIter))
            *mainIter = ' ';
 
    setlocale(LC_CTYPE, prevLocale);
}
 
catch (char* prevLoc)
{
    str.assign("0");
    std::cerr << "AbstractConverter::filter_string(std::string&): Exception: "
                 "No valid digits in the number\n";
    setlocale(LC_CTYPE, prevLoc);
    return;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.12.2013, 00:52
Ответы с готовыми решениями:

Segmentation Fault
void Coder::set(const char * buf, size_t size) { if ((buf == nullptr)) { throw...

Segmentation fault
Всем привет. Пишу быдлокод для лабы в универе. Мне по определенному алгоритму необходимо получить...

Segmentation fault
Пишу лабу для универа. В общем необходимо использовать только свои функции, никаких, str......

Segmentation fault
Почему при таком варианте происходит Segmentation fault? vec3f trace(const Scene&amp; scene, const...

7
4063 / 3317 / 924
Регистрация: 25.03.2012
Сообщений: 12,483
Записей в блоге: 1
27.12.2013, 00:58 2
Цитата Сообщение от gromo Посмотреть сообщение
[](char ch) -> bool {return isspace(ch);}
у тебя что-то не так скопировалось. Ошибка компиляции Borland C++ 3.1 для DOS
0
gromo
27.12.2013, 02:16  [ТС]
  #3

Не по теме:

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
у тебя что-то не так скопировалось. Ошибка компиляции Borland C++ 3.1 для DOS :rofl::rofl:
ага, очень смешно :cry:
P.s. Господа модераторы, пожалуйста, занесите инклуды под тег форматирования кода, а то опечатался.

0
Форумчанин
Эксперт CЭксперт С++
8215 / 5045 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
27.12.2013, 02:31 4
Он у вас случайно в std::string::npos не уперся?

Добавлено через 28 секунд
Что говорит отладчик и трассировка?

Добавлено через 5 минут
Цитата Сообщение от gromo Посмотреть сообщение
функция некоторым образом парсит строку (не в этом проблема) и удаляет из нее НЕ алфавитно-цифровые символы.
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
 
int main()
{
    std::string str1 = "Enik\ai be678@#niki!, eli varenil789^@!ki", str2;
    std::copy_if(str1.begin(), str1.end(), std::back_inserter(str2),
        [](const char x) { return !isalnum(x); } );
    std::cout << str2 << std::endl;
}
Просто на всякий случай
1
║XLR8║
1212 / 909 / 270
Регистрация: 25.07.2009
Сообщений: 4,361
Записей в блоге: 5
27.12.2013, 04:16 5
Цитата Сообщение от gromo Посмотреть сообщение
for( ; mainIter != mainIter + capture_pos; ++mainIter)
Собственно вот твой вечный цикл и падение из-за доступа к черту на куличики.

Добавлено через 1 минуту
Вот весь цикл
Цитата Сообщение от gromo Посмотреть сообщение
for( ; mainIter != mainIter + capture_pos; ++mainIter)
* * * * * * if(!isalnum(*mainIter))
* * * * * * * * *mainIter = ' ';
надеюсь комментарии лишние

Добавлено через 1 минуту
На всякий случай
C++
1
2
3
int a; // что угодно
int b = 1; // не 0
for (; a != a+b; ++a) // вечный цикл
Так как a != a+b => 0 != b, а b у нас не равно нулю

Добавлено через 2 минуты

Не по теме:

gromo, ставь линк на мой ник в след раз

1
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
27.12.2013, 22:38  [ТС] 6
Цитата Сообщение от MrGluck Посмотреть сообщение
Он у вас случайно в std::string::npos не уперся?
Выяснилось, что еще и как
Цитата Сообщение от MrGluck Посмотреть сообщение
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int main()
{
 std::string str1 = "Enik\ai be678@#niki!, eli varenil789^@!ki", str2;
 std::copy_if(str1.begin(), str1.end(), std::back_inserter(str2),
 [](const char x) { return !isalnum(x); } );
 std::cout << str2 << std::endl;
}
В чем прикол? Ваш код генерирует строку со всеми НЕ алфавитно-цировыми символами. Может вас смутило то, что я не создаю новую строку, а заменяю все ненужные символы на пробелы - просто это для меня более оправдано, потому что если удалять символы, то это может привести к перераспределению памяти, что в моем случае критично - иногда строки могут быть чертовски большими (а функция, которой дальше передается эта строка пробелы игнорирует)
outoftime,
Цитата Сообщение от outoftime Посмотреть сообщение
for( ; mainIter != mainIter + capture_pos; ++mainIter)
Собственно вот твой вечный цикл и падение из-за доступа к черту на куличики.
никому об этом не говори, пожалуйста Чувствую себя ... промолчу) Спасибо

Добавлено через 17 часов 18 минут
Может кому понадобится исправленный и оптимизированый вариант. (функция чистит строку, оставляя только валидные для числа символы. Правила описаны в комментариях к коду)
C++ (Qt)
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
#include <algorithm>
#include <cctype>    // isalnum(), ...
#include <iostream> // std::cerr
#include <string>
#include <boost/regex.hpp>
inline void filter_string(std::string &s) try {
    typedef std::string::iterator SIt_t;
    typedef SIt_t::value_type charT;
    typedef std::string::const_iterator CSIt_t;
    bool withMinus, withDot;
    auto alnum = [](charT c) -> charT {
        return isalnum(c) ? c : ' ';
    };
    char* prevLocale = setlocale(LC_CTYPE, "C");
 
    // If the first non-whitespace character is '-'
    SIt_t mainIter = std::find_if_not(s.begin(), s.end(),
                                     [](char ch) {return isspace(ch);});
    // we consider, that the number is negative, otherwise - non negative.
    if(mainIter == s.end())
        throw prevLocale;
    withMinus = *mainIter == '-' ? true : false;
    if(withMinus)
    {
        // Fill the range from '-' to first digit of the number with spaces and
        // preced this digit with '-'.
        // GMP functions mpf_set_str() and mpz_set_str() in current revision are
        // not allow spaces between minus and first digit of the number.
        // See their documentation for details on [url]https://gmplib.org/manual/[/url]
 
        // Find First Alpha-Numeric Symbol after minus.
        SIt_t fans = std::find_if(mainIter, s.end(),
                                  [](char ch) { return isalnum(ch); });
        if(fans == s.end())
            throw prevLocale;
        else
        {
            mainIter = std::fill_n(mainIter, std::distance(mainIter, fans), ' ');
            *(mainIter-1) = '-';
        }
    }
    // Here we at the position of the first meaning digit of the number.
 
    withDot = std::find(mainIter, s.end(), '.') == s.end() ? false : true;
 
    if(withDot)
    {
        // If in the number presented multiple dots ('.'), only first dot with
        // adjoined one or more alnums is accepted, while others replaced with
        // spaces. GMP funcs mpf_set_str() and mpz_set_str() are simply
        // ignore spaces.
        using namespace boost;
        regex e(R"_([[:alnum:]]+\.[[:alnum:]]+)_", regex_constants::extended);
        smatch what;
        CSIt_t search_begin(mainIter);
        if ( regex_search(search_begin, s.cend(), what, e) )
        {
            SIt_t last = mainIter + what.position();
            mainIter = std::transform(mainIter, last, mainIter, alnum);
            mainIter += what.length();
        }
    }
    std::transform(mainIter, s.end(), mainIter, alnum);
    setlocale(LC_CTYPE, prevLocale);
}
 
catch (const char* prevLoc)
{
    s.assign("0");
    std::cerr << "AbstractConverter::filter_string(std::string&): Exception: "
                 "No valid digits in the number\n";
    setlocale(LC_CTYPE, prevLoc);
    return;
}
0
Форумчанин
Эксперт CЭксперт С++
8215 / 5045 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
27.12.2013, 22:55 7
Почитайте про анти-паттерн "Accidental complexity" (Ненужная сложность).
Цитата Сообщение от gromo Посмотреть сообщение
функция чистит строку, оставляя только валидные для числа символы.
если учесть что под "чистит" подразумевается вставка пробелов заместо символа и что "валидные для числа символы" означает то же, что вы говорили выше
Цитата Сообщение от gromo Посмотреть сообщение
НЕ алфавитно-цифровые символы.
то простое решение вот:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
 
int main()
{
    std::string str = "Enik\ai be678@#niki!, eli varenil789^@!ki";
    std::transform(str.begin(), str.end(), str.begin(),
        [](const char x) { return isalnum(x) ? ' ' : x; } );
    std::cout << str << std::endl;
}
0
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
27.12.2013, 23:10  [ТС] 8
Цитата Сообщение от MrGluck Посмотреть сообщение
если учесть что под "чистит" подразумевается вставка пробелов заместо символа и что "валидные для числа символы" означает то же, что вы говорили выше
Я вас понимаю, но здесь некоторые дополнительные требования к очистке:
1) Если первый непробельный символ в строке это '-', то НЕПОСРЕДСТВЕННО за ним должен следовать алфавитно-цифровой символ и только тогда число будет считаться отрицательным. (в противном случае все минусы отбрасываются)
2) Если в строке много десятичных точек, только первое вхождение [[:alnum:]]+\.[[:alnum:]]+ будет засчитано как разделитель дробной и целой частей, остальные точки будут отброшены.

Кому надо, может удалять ненужные символы, но мне это не нужно и если учесть, что строки порой будут в несколько миллиардов знаков, то лишнее перераспределение памяти может дорого обойтись.

А за антипаттерн спасибо, почитаю. Я тоже стараюсь следовать Главному Техническому Императиву Разработки ПО

Добавлено через 2 минуты
А выше я писал
Цитата Сообщение от gromo Посмотреть сообщение
функция некоторым образом парсит строку (не в этом проблема) и удаляет из нее НЕ алфавитно-цифровые символы.
следовательно, если НЕ алфавитно-цифровые удаляются из строки, то они НЕ валидные для числа, не находите?
0
27.12.2013, 23:10
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.12.2013, 23:10
Помогаю со студенческими работами здесь

Segmentation fault
Здравствуйте. Нужно динамически получить такое: char * a = {&quot;abc&quot;, NULL}; Пробую: char ** a; a...

Segmentation fault
не могу скинуть код по личным причинам. я использую строковые операторы strcmp, strcpy. выводит...

Segmentation fault
Кусок кода: template &lt;typename Type&gt; class Queue { private: struct Elem ...

Segmentation fault
Доброго времени суток. Есть 2 класса. object class object{ void (*f)(object*); public:...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru