SIEMENS, DF&PD

Предыдущее посещение: Вт июн 14, 2016 7:07 Текущее время: Вт июн 14, 2016 7:07

Часовой пояс: UTC + 3 часа




 [ Сообщений: 14 ] 
Автор Сообщение
 Заголовок сообщения: Работа над строками. Удаление
СообщениеДобавлено: Пт июл 15, 2011 8:07 
Не в сети
Известный Писатель

Зарегистрирован: Пн окт 18, 2010 9:28
Сообщения: 158
Откуда: Казахстан
Добрый день, господа!

Как можно реализовать действие, который мог бы вырезать или удалить определенные символы с конца строки в Си. Пример:

а,б,в,г,д => а,б,в

Знаю, что в Си таковоых функции нет как в VB.
На данный момент реализовываю через массив, но ваша помощь, надеюсь, ускорить процесс реализации!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Работа над строками. Удаление
СообщениеДобавлено: Пт июл 15, 2011 8:15 
Не в сети
Писатель со стажем

Зарегистрирован: Ср апр 18, 2007 15:03
Сообщения: 508
Откуда: Красноярск
Aibek_Reale писал(а):
Добрый день, господа!

Как можно реализовать действие, который мог бы вырезать или удалить определенные символы с конца строки в Си. Пример:

а,б,в,г,д => а,б,в

Знаю, что в Си таковоых функции нет как в VB.
На данный момент реализовываю через массив, но ваша помощь, надеюсь, ускорить процесс реализации!

А в си нет строк, они эмулируются через массивы.
Вам только с конца символы удалять или из любого места?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пт июл 15, 2011 8:31 
Не в сети
Известный Писатель

Зарегистрирован: Пн окт 18, 2010 9:28
Сообщения: 158
Откуда: Казахстан
Предпочтительнее было бы с любого места.

Именно, надо осуществить, чтобы код выполнял удаление из символьного массива сочетание "Text" (ковычки не учитываем).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пт июл 15, 2011 10:00 
Не в сети
Писатель со стажем

Зарегистрирован: Ср апр 18, 2007 15:03
Сообщения: 508
Откуда: Красноярск
Код:
char* cleanString(const char* lpszWhere, const char* lpszWhat)
{
   char* lpszDst;
   int dstSize = 0;
   int whereSize;
   int whatSize;
   whereSize = strlen(lpszWhere);
   whatSize = strlen(lpszWhat);
   lpszDst = (char*)malloc(whereSize + 1);

   for (int idx = 0; idx < whereSize; ++idx)
   {
      if ( lpszWhere[idx] != lpszWhat[0] )
      {
         lpszDst[dstSize] = lpszWhere[idx];
         ++dstSize;
      }
      else
      {
         if ( strncmp(&lpszWhere[idx], lpszWhat, whatSize) == 0 )
         {
            idx += whatSize - 1;
         }
         else
         {
            lpszDst[dstSize] = lpszWhere[idx];
            ++dstSize;
         }
      }
   }

   lpszDst[dstSize] = '\0';
   return lpszDst;
}


Код:
char oldStr[] = "bublablabubla";
char* newStr = cleanString(oldStr, "bla");
free(newStr); // или как там SysFree. тогда и где память выделяется нужно использовать SysMalloc

А у вас как?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пт июл 15, 2011 12:48 
Не в сети
Известный Писатель

Зарегистрирован: Пн окт 18, 2010 9:28
Сообщения: 158
Откуда: Казахстан
Просто здорово!
Большое спасибо, что реализовали данную функцию! Респект!
Думаю, не раз буду использовать вашу функцию.

Но, для данной задачи обошолся небольшой строкой программного кода:

int i;
char text[] = "You are welcom!!!";

for (i =1; text[i] != '\0'; i++);
text[i-15] = '\0';
return text; // возвр. "You"

Большое спасибо, Eagle, за помощь!
Тема закрыта!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн июл 18, 2011 4:33 
Не в сети
Писатель со стажем

Зарегистрирован: Ср апр 18, 2007 15:03
Сообщения: 508
Откуда: Красноярск
А ну если будете использовать, то тогда такой:
Код:
void cleanString(char* lpszDst, const char* lpszWhere, const char* lpszWhat)
{
   int dstSize = 0;
   int whereSize;
   int whatSize;
   whereSize = strlen(lpszWhere);
   whatSize = strlen(lpszWhat);

   for (int idx = 0; idx < whereSize; ++idx)
   {
      if ( lpszWhere[idx] != lpszWhat[0] )
      {
         lpszDst[dstSize] = lpszWhere[idx];
         ++dstSize;
      }
      else
      {
         if ( strncmp(&lpszWhere[idx], lpszWhat, whatSize) == 0 )
         {
            idx += whatSize - 1;
         }
         else
         {
            lpszDst[dstSize] = lpszWhere[idx];
            ++dstSize;
         }
      }
   }

   lpszDst[dstSize] = '\0';
}

Но здесь нет проверок указателей и размеров массивов.

Код:
char oldStr[] = "bublablabubla";
char* newStr = (char*)SysMalloc(strlen(oldStr));
cleanString(newStr, oldStr, "bla");
SysFree(newStr);


Код:
int i;
char text[] = "You are welcom!!!";

// i должно начинаться с нуля. в Си индекс массивов начинается с нуля
for (i =1; text[i] != '\0'; i++); // этот цикл может заменить функцией strlen

text[i-15] = '\0'; // а если i будет меньше 15?
return text; // возвр. "You"

Зачем вы используете Си, если плохо его знаете? Не удивляйтесь, если завтра проект у вас начнёт виснуть, жрать память и падать хрен пойми где.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн июл 18, 2011 14:10 
Не в сети
Известный Писатель

Зарегистрирован: Ср фев 16, 2011 14:23
Сообщения: 434
Откуда: Санкт-Петербург, Москва
Eagle, к сожалению, в вашем коде тоже есть ошибка:

Код:
char oldStr[] = "bublablabubla";
char* newStr = (char*)SysMalloc(strlen(oldStr));
cleanString(newStr, oldStr, "bla");
SysFree(newStr);


Не зарезервировано место под ноль-терминатор, надо так:

Код:
char* newStr = (char*)SysMalloc(strlen(oldStr) + 1);


Во-вторых, ну зачем использовать динамическое выделение памяти (malloc / SysMalloc) без особой необходимости, если можно обойтись автоматическим?

Кстати, имхо я бы делал так - при помощи strstr находим начало вхождения и записываем туда ноль. Если на выходе должна быть новая строка, то предварительно копируем ее и работаем с копией. Естественно, со всеми проверками на переполняющиеся буфера (в си без этого никак).

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

Если интересно, могу скинуть свою реализацию функции замены всех вхождений подстроки в строке, в случае необходимости можете ее адаптировать под свои нужды.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн июл 18, 2011 15:19 
Не в сети
Известный Писатель

Зарегистрирован: Пн окт 18, 2010 9:28
Сообщения: 158
Откуда: Казахстан
Как говорится: У каждого плотника свои топор! Главное - иметь фантазию! )))

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Пн июл 18, 2011 16:29 
Не в сети
Писатель со стажем

Зарегистрирован: Ср апр 18, 2007 15:03
Сообщения: 508
Откуда: Красноярск
Alexey_Spb_82 писал(а):
Eagle, к сожалению, в вашем коде тоже есть ошибка:
Не зарезервировано место под ноль-терминатор, надо так:

Спасибо, что поправили.

Alexey_Spb_82 писал(а):
Во-вторых, ну зачем использовать динамическое выделение памяти (malloc / SysMalloc) без особой необходимости, если можно обойтись автоматическим?


Тут явно необходимо.
Там кстати ещё одна ошибка:
Код:
char* get()
{
char str[] = "get me";
return ???;
}


Alexey_Spb_82 писал(а):
Кстати, имхо я бы делал так - при помощи strstr находим начало вхождения и записываем туда ноль. Если на выходе должна быть новая строка, то предварительно копируем ее и работаем с копией. Естественно, со всеми проверками на переполняющиеся буфера (в си без этого никак).

Задача была вырезать из строки все вхождения подстроки.

Alexey_Spb_82 писал(а):
А еще в сишных скриптах винсиси лучше выделение памяти под результат возложить на вызывающую функцию (естественно, внутри функции все проверяем). Это делает реализацию более гибкой (это мое сугубо личное мнение).

Это общее правило для любого Си. Просто я вначале протупил и выложил некорректный код.

ЗЫ: Казалось бы, простой код, а столько ошибок. Ладно бы каждый день писать на си, в голове оседает. А если вот так редко за это браться, то из головы всё вылетает.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт июл 19, 2011 13:12 
Не в сети
Известный Писатель

Зарегистрирован: Ср фев 16, 2011 14:23
Сообщения: 434
Откуда: Санкт-Петербург, Москва
Eagle: Да, вы правы - даже когда каждый день пишешь на си, все равно лезут косяки, из-за случайно пропущенной мелочи или символа. Таковы уж особенности этого языка.

Aibek_Reale: Вот мой вариант с тестовой PDL (для WinCC 7.0)

Код:
unsigned long Str_Replace  // Длина замененной строки.
   (
   char *pszWhat,          // Что заменить.
   char *pszTo,            // На что заменить.
   char *pszSource,        // Исходная строка.
   char *pszDest,          // Результат.
   unsigned long ulMaxLen  // Ограничение на макс. длины результата.
   )



В основе функции - вариант str_replace, созданный Brian Folts (http://www.Planet-Source-Code.com/vb/sc ... 0&lngWId=3).

Вроде за все время использования не глючила, но все равно есть подозрение, что багов там более чем достаточно. Так что используйте исключительно на свой страх и риск.

Не знаю как прикрепить тут аттач, вот ссылка для скачивания:

http://file.qip.ru/file/3DweNiBh/Str_Replace.html

Пароль на архив: WinCC


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт июл 19, 2011 13:16 
Не в сети
Известный Писатель

Зарегистрирован: Ср фев 16, 2011 14:23
Сообщения: 434
Откуда: Санкт-Петербург, Москва
Да, если нужно удалить вхождения строки, то надо в качестве pswTo передавать не NULL, а указатель на ноль-терминатор (например, на переменную char EmptyString = "";).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт июл 19, 2011 14:08 
Не в сети
Писатель со стажем

Зарегистрирован: Ср апр 18, 2007 15:03
Сообщения: 508
Откуда: Красноярск
http://ideone.com/xIY7T

Цитата:
*** buffer overflow detected ***: ./prog terminated


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Вт июл 19, 2011 15:50 
Не в сети
Известный Писатель

Зарегистрирован: Ср фев 16, 2011 14:23
Сообщения: 434
Откуда: Санкт-Петербург, Москва
Eagle: У меня оригинальная функция тоже не работала, правда в дебаггере я ее не тестил, а решил что это связано с реализацией C в WinCC. Поэтому и создал свой вариант, но автора все же упомянул :-)

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения:
СообщениеДобавлено: Ср сен 21, 2011 4:32 
Не в сети
Писатель со стажем

Зарегистрирован: Ср апр 18, 2007 15:03
Сообщения: 508
Откуда: Красноярск
Нашёл интересное замечание
Why should you use the internal C function "SysMalloc()" for providing memory?
http://support.automation.siemens.com/W ... viewreg=WW

Цитата:
It might be necessary to reserve memory in C scripts. One application, for example, is dynamization of a property of the "Text" type of a graphics object via a C function. In this case you should use the internal function "SysMalloc()". "SysMalloc()" reserves memory for an action. The memory area is assigned to the action. Once the action has been run through and the result sent, the system releases the memory again. Using the "SysFree()" function you can release the memory earlier.

If you use other functions to reserve memory, e.g. "malloc()", you must explicitly release the memory to avoid memory leaks.

Если память выделяется SysMalloc, то и заботиться о её возвращении не надо.
Т.е. предпочтительнее использовать SysFree вместо malloc и тогда утечек памяти вообще быть не должно.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
 [ Сообщений: 14 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения

Перейти:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group