Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы с изменением буфера и строк 
:(
    Опции темы
fire64
Дата 6.10.2009, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 18.7.2007

Репутация: нет
Всего: нет



Я  для парсинга написал следующий код


Код

char *GetStringValue(char *string, char *word, char *firstbreak, char *endbreak)
{
    //Parser
    char *prename = strstr (string,word);

    char *name = (prename + strlen(word) );

    char *probel = ( strstr (name, firstbreak) + 1 );

    if(strstr (probel, endbreak))
    {
        char *newprobel = ( strstr (probel, endbreak) );
    
        int notprobellen = strlen(probel) - strlen(newprobel);

        char clear[2048];

        strncat (clear, probel, notprobellen);

        return clear;
    }
    else
    {
        return probel;
    }

    return NULL;
}


если я использую GetStringValue только один раз, то все нормально

а если 2 раза, то содержимое строк неправильное

Код

const char *Hubname = GetStringValue(Hubcfg, "$HubName:", "\x20", "\n");

const char *Topicname = GetStringValue(Hubcfg, "$Topic:", "\x20", "\n");


Hubname содержит не правильное значение, а точнее часть содержимого Topicname 

прошу помочь разобраться в проблеме

Это сообщение отредактировал(а) fire64 - 6.10.2009, 14:53
PM MAIL   Вверх
niXman
Дата 6.10.2009, 15:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 4.7.2009

Репутация: 0
Всего: 0



Код

#include <string>
#include <algorithm>

/***************************************************************************/

std::string get_text(const std::string& str, const std::string& beg, const std::string& end) {
    std::string::const_iterator open = std::search(str.begin(), str.end(), beg.begin(), beg.end());
    std::string::const_iterator close= std::search(str.begin(), str.end(), end.begin(), end.end());
    
    if ( open == str.end() || close == str.end() ) {
        return std::string();
    }
    
    std::advance(open, beg.length());
    return std::string(open, close);
}

/***************************************************************************/

int main(int argc, const char** argv) {
    const std::string open_tag("<tag>");
    const std::string close_tag("</tag>");
    const std::string str("gkjeihgei<tag>needle text</tag>kjbsbv");
    
    std::string result = get_text(str, open_tag, close_tag);

    return 0;
}

/***************************************************************************/


Это сообщение отредактировал(а) niXman - 6.10.2009, 15:04
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
xvr
Дата 6.10.2009, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(fire64 @ 6.10.2009,  14:52)
Код

        char clear[2048];
        strncat (clear, probel, notprobellen);



Конкатенация строки с неинициализированным мусором. Используй просто strncpy

Цитата

        return clear;
Возврат указателя на локальную переменную - грубейшая, и очень частая ошибка  smile 

PM MAIL   Вверх
fire64
Дата 6.10.2009, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 18.7.2007

Репутация: нет
Всего: нет



xvr, а что это изменит ?

всеравно первая строка будет содержать содержимое второй

Это сообщение отредактировал(а) fire64 - 6.10.2009, 16:59
PM MAIL   Вверх
niXman
Дата 6.10.2009, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 4.7.2009

Репутация: 0
Всего: 0



передай в функцию еще один параметр, т.е. указатель на буфер куда будет помещаться результат.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 6.10.2009, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 18.7.2007

Репутация: нет
Всего: нет



Проблема решена

xvr,  спасибо за помощь в избавлении от мусора

niXman спасибо за совет с указателем на буфер

п.с.

помог перевод char* в char []

кстати буду рад если кто объяснит почему char* некорректно работал
PM MAIL   Вверх
niXman
Дата 6.10.2009, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 4.7.2009

Репутация: 0
Всего: 0



Цитата(fire64 @  6.10.2009,  15:29 Найти цитируемый пост)
кстати буду рад если кто объяснит почему char* некорректно работал 

Потому что ты возвращал указатель на локальный массив. А запись типа char[] предполагает возвращать копию массива.

п.с.
но я бы так не сделал. лучше передать указатель на массив в функцию.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 6.10.2009, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 18.7.2007

Репутация: нет
Всего: нет



ок спасибо за информацию

возникла новая проблема

программа падает в дебаг билде в функции парсинга (смотрите первый пост) при использовании sprintf
Код

    else
    {
        sprintf(result, "%s", probel);
    }



Код

-        probel    0x0044cb96 "fire64|"    char *
            102 'f'    char
-        result    0x00441064 ""    char *
            0    char


Код

    firehub.exe!write_char()  Строка 1083 + 0x20 байт    C
    firehub.exe!write_string()  Строка 1221 + 0x23 байт    C
    firehub.exe!_output()  Строка 983 + 0x18 байт    C
    firehub.exe!sprintf()  Строка 104 + 0x11 байт    C
    firehub.exe!GetStringValue()  Строка 40 + 0x12 байт    C++
    firehub.exe!ValidateNick()  Строка 51 + 0x20 байт    C++
    firehub.exe!NetworkThread()  Строка 164 + 0x9 байт    C++
    firehub.exe!_threadstart()  Строка 173 + 0xd байт    C
    kernel32.dll!7c80b729()    
    [Указанные ниже фреймы могут быть неверны и (или) отсутствовать, символы для kernel32.dll не загружены]    



PM MAIL   Вверх
Леопольд
Дата 6.10.2009, 20:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(niXman @  6.10.2009,  15:02 Найти цитируемый пост)
Код

#include <string>
#include <algorithm>
/***************************************************************************/
std::string get_text(const std::string& str, const std::string& beg, const std::string& end) {
    std::string::const_iterator open = std::search(str.begin(), str.end(), beg.begin(), beg.end());
    std::string::const_iterator close= std::search(str.begin(), str.end(), end.begin(), end.end());
...



std::string get_text(const std::string& str, const std::string& beg, const std::string& end) {
    std::string::const_iterator open = std::search(str.begin(), str.end(), beg.begin(), beg.end());
    std::string::const_iterator close= std::search(open, str.end(), end.begin(), end.end());

Немного оптимизации не повредит. Но это не распарсишь... :)
"gkjeihgei<tag>not needed text</tag><tag>needle text</tag>kjbsbv"

Это сообщение отредактировал(а) Леопольд - 6.10.2009, 20:02


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
niXman
Дата 6.10.2009, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 4.7.2009

Репутация: 0
Всего: 0



Цитата(fire64 @  6.10.2009,  17:48 Найти цитируемый пост)
программа падает в дебаг билде в функции парсинга

А в релизе?
Кто такой result ?

Добавлено через 10 минут и 35 секунд
Леопольд, Тоже верно smile 
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
fire64
Дата 6.10.2009, 20:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 18.7.2007

Репутация: нет
Всего: нет



niXman, вот код

Код

void GetStringValue(char *string, char *word, char *firstbreak, char *endbreak, char *result)
{
    //Parser
    char *prename = strstr (string,word);

    char *name = (prename + strlen(word) );

    char *probel = ( strstr (name, firstbreak) + 1 );

    char clear[2048];

    if(strstr (probel, endbreak))
    {
        char *newprobel = ( strstr (probel, endbreak) );
    
        int notprobellen = strlen(probel) - strlen(newprobel);

        strncpy (clear, probel, notprobellen - 1);

        sprintf(result, "%s", clear);
    }
    else
    {
        sprintf(result, "%s", probel);
    }
}


в релизе падает тоже, но в другом месте

Код

            else
            {
                char sendcommand[1024];

                GetStringValue(meseg, "$", "", "NOT FOUND", sendcommand);  //падает здесь

                printf ("UNKNOWN COMMAND $%s \n", sendcommand );

                continue;
            }



PM MAIL   Вверх
niXman
Дата 6.10.2009, 20:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 4.7.2009

Репутация: 0
Всего: 0



Возможно, объем буфера мал. Или "probel" равен NULL
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
xvr
Дата 6.10.2009, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Вот тут
Код

        strncpy (clear, probel, notprobellen - 1);
        sprintf(result, "%s", clear);
strncpy не копирует в clear терминирующий ноль, т.к. исходная строка длиннее, чем выходной буфер (размер буфера - 3й параметр). Последующий sprintf пытается печатать в result строку неизвестной длинны (точнее, он шарашит по памяти пока не найдет 0). Происходит запись за границы массива со всеми вытекающими  smile 
Кстати, конструкция 
Код

    if(strstr (probel, endbreak))
    {
        char *newprobel = ( strstr (probel, endbreak) );
    
        int notprobellen = strlen(probel) - strlen(newprobel);
        strncpy (clear, probel, notprobellen - 1);
        sprintf(result, "%s", clear);
    }
    else
    {
        sprintf(result, "%s", probel);
    }
мало того, что неправильная, она еще и неэффективная  smile 
Код

if (char* newprobel = strstr (probel, endbreak))
{
 int len=newprobel-probel-1;
 memcpy(result,probel,len)[len]=0;
}
else
{
 strcpy(result,probel);
}

PM MAIL   Вверх
niXman
Дата 6.10.2009, 21:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 4.7.2009

Репутация: 0
Всего: 0



Я вообще не понимаю, почему бы не воспользоваться моим примером кода.
--------------------
if ( !c++ ) {   *power--;   this->wussiness += 10;}
PM MAIL   Вверх
zim22
Дата 6.10.2009, 21:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 24
Всего: 69



Цитата(niXman @  6.10.2009,  21:01 Найти цитируемый пост)
Я вообще не понимаю, почему бы не воспользоваться моим примером кода.

у тебя код на С++. fire64 же привёл пример на Си.


--------------------
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0632 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.