Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.63/65: Рейтинг темы: голосов - 65, средняя оценка - 4.63
2 / 2 / 1
Регистрация: 04.03.2009
Сообщений: 30
1

Удаление лишних пробелов в начале и конце строки.

04.03.2009, 13:31. Показов 13585. Ответов 28
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Нужно написать функцию char*alltrim(char*string) для удаления пробелов в начале и конце строки с помощью указателей. Помогите завершить задачку.
Возник ряд вопросов:
1) как создать какую-то произвольную переменную типа char ( у меня это p)и записать туда из строки string подстроку начиная с определённого элемента заканчивая другим элементом с помощью указателей? Надо ли в конце этой строки p записать NULL?
2)Как потом эту произвольную переменную ( у меня это p) вернуть как результат работы функции заместо переменной string?
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
24
25
26
27
28
29
30
31
32
33
34
#include <iostream.h>
char*alltrim(char*string)
 {
  int i=0,d=0,c=0,g=0;
  while(*string==' ')  // Считается количество пробелов в начале строки - i
  {
   c=c+1;
   i=i+1;
   *string++;
  }
  while(*string) // Считается количество пробелов в конце строки - d
  {
   if (*string!='\x0')
   {
    if (*string==' ') d=d+1;
    else d=0;
    c=c+1;
    *string++;
   }
  }
  char*p="";
  for(g=c-i;g>d;g--) // Неверная функция. Копируется подстрока без начальных и           конечных пробелов
   *p++=*(string-g);
   return p;
 }
 
 
void main(void)
 {
  clrscr();
  char*x="      q   w   e r       t     y      ";
  *alltrim(x); //На выходе должно получится  "q   w   e r       t     y"
  
 }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.03.2009, 13:31
Ответы с готовыми решениями:

Удаление лишних пробелов в конце строки
На проверочном сайте мое решение не проходит из-за лишнего пробела в выходной строке, как его...

Удаление пробелов в начале и конце
Подскажите, пожалуйста, функцию удаление пробелов в начеле и конце строки? Вот примерный код: //...

Удаление пробелов в начале и в конце
Задание:Предложите два варианта функции, удаляющей из строки ведущие и концевые пробелы ...

Отрезание пробелов в начале и в конце строки
Разработайте функцию std::string Trims(std::string const&amp; str), выполняющую отрезание пробелов в...

28
MCSD: APP BUILDER
8794 / 1073 / 104
Регистрация: 17.06.2006
Сообщений: 12,602
14.08.2009, 01:40 21
Author24 — интернет-сервис помощи студентам
Кстати, можно и короче

char *trunc_str(char *str){
char *stop;
for ( ; isspace(*str); str++ )
;
for ( stop = str + strlen(str) - 1; isspace(*stop) && stop > str; stop-- )
;
*++stop = 0;

return str;
}
Кстати, отличный индусский код. Его использование может быть таким:

char* p = new char[100];
strcpy(p, " 123 ");
p = trunc_str(p);
delete [] p;

...
Если еще актуально, я просто для себя разбирался, прокомментировал заодно:
char* alltrim( char*string)
{ ...
...
char* trimall2(char* str){ ...
Эти два кода примерно аналогичны. вряд ли юзер будет ожидать дополнительных аллокаций.

char*x=" q w e r t y ";
std::cout<<alltrim(x); //На выходе должно получится "q w e r t y"
а вот за такое надо отрывать руки и отправлять обратно на родину, в Олбанию :LOL:

а теперь - правильный вариант (:

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 <tchar.h>
#include <string.h>
 
TCHAR* trim_left(TCHAR* const str)
{
    if (str == NULL)
        return (NULL);
    const size_t len = _tcslen(str);
    const size_t pos = _tcsspn(str, _T(" \t\r\n"));
    if (pos > len || pos == 0)
        return (str);
    memmove(str, str + pos, (len - pos) * sizeof(TCHAR));
    str[len-pos] = _T('\0');
    return (str);
}
 
TCHAR* trim_right(TCHAR* const str)
{
    if (str == NULL)
        return (NULL);
    TCHAR* p = str + _tcslen(str) - 1;
    while ((p >= str) && _istspace(*p))
        *p-- = _T('\0');
 
    return (str);
}
 
TCHAR* trim(TCHAR* const str)
{
    return trim_left(trim_right(str));
}
 
int main()
{
    TCHAR* p = new TCHAR[100]();
    _tcscpy(p, _T(" \t\r\n\n\r  1 2 3   \r\r\n\n\t"));
    trim(p);
    delete [] p;
 
    return (0);
}
1
Эксперт С++
7175 / 3234 / 81
Регистрация: 17.06.2009
Сообщений: 14,164
14.08.2009, 11:45 22
а теперь - правильный вариант (:
А вот кстати не очень правильный.
1) Если уже хочется скорости - то писать надо сразу trim двойной - слева и справа.
2) tcslen() вызывать два раза совершенно не нужно.
Собственно не нужно вызывать ни одного раза.
3) В условии просили удалить только пробелы.
4) TCHAR - это круто, но насчет Unicode опять же никто не говорил.
5) istspace(), tcsspn() - тоже не нужно вызывать.

А вот memmove() похоже пригодится - возможно будет быстрее, чем без него.
0
Заблокирован
Автор FAQ
14.08.2009, 12:46 23
Выкладываю то что у меня получилось...
Исходный текст содержится в текстовике, подстрока находится между словами в тексте begin и end. Если этих слов в текстовике нето, то подстрока не извлекается. Привожу также результат работы и текстовики (их названия говорят сами за себя)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
 
//Возвращает подстроку из chBuf 
//sLeft  - указатель на 0-й элемент подстроки в строке chBuf
//sRight - указатель на последний элемент подстроки в строке chBuf
 
//Поясняю
//chBuf = "123456aa789";
//Допустим надо вернуть аа
//sLeft = strchr(chBuf,'a');
//sRight= strrchr(chBuf,'a');
//Это всего лиш пример
//sLeft можно задать как aa789 а sRight как a789
char * GetMidStr(LPCTSTR chBuf, char * sLeft, char * sRight);
 
//Чистка пробелов
char * TrimSpace(char * str);
 
//Для выбора файла с текстом
LPTSTR SelectFile();
 
char * str = (char *)malloc(sizeof(char));
 
FILE *f;
 
void main()
{
    int sLen = 0;
    char * sLeft, * sRight, * chBuf;
    char sPath[MAX_PATH];sPath[0] = '\0';
    if(sprintf(sPath,SelectFile()))
    {
        if((f = fopen(sPath,"rb+")))
        {
            fseek(f,0,SEEK_END);
            sLen = ftell(f);
            fseek(f,0,SEEK_SET);
            str = (char *)realloc(str,sLen);
            //считываем строку для анализа
            fread(str,1,sLen,f);
            str[sLen - 1] = '\0';
            fclose(f);
            printf("INPUT str : %s\r\n",str);
            sLen = (int)(&str[0]);//Запоминаем начало строки
            //верней запоминаем адресс начала
            //нужно чтоб realloc потом сработал!!!!
            str = TrimSpace(str);
            printf("TRIMS str : %s\r\n",str);
            //Допустим нам нужна подстрока которая начинается
            //со слова begin и оканчивается словом end
            //одновременно проверим есть ли такая подстрока вообще
            sLeft = strstr(str,"begin");
            sRight = strstr(str,"end");
            if(!sLeft)
                printf("str isn't contain word [begin]\r\n");
            else
            {
                if(!sRight)
                    printf("str isn't contain word [end]\r\n");
                else
                {
                    chBuf = GetMidStr((LPCTSTR) str, sLeft, sRight);
                    printf("SUBSTRING : %s\r\n",chBuf + strlen("begin"));
                    //Тут чёт free выделывается, даж сам не пойму((((
                    //free(chBuf);
                }
            }
            str -= ((int)&str[0] - sLen);
            str = (char *)realloc(str,sizeof(char));
        }
    }
    printf("Enter NUM1 to choose next file with text\r\n");
    scanf("%d",&sLen);
    if(sLen == 1)
        main();
}
 
char * GetMidStr(LPCTSTR chBuf, char * sLeft, char * sRight)
{
    char * RetVal;
    int sLen = chBuf != NULL ? strlen(chBuf) : -1;
    if(0 < sLen)
    {
        RetVal = (char *)malloc((sLen + 1)*sizeof(char));
        sprintf(RetVal,"%s",chBuf);
        if(*sLeft && *sRight)
        {
            RetVal = strstr(RetVal,sLeft);
            if(RetVal)
            {
                sLen = strlen(sLeft) - strlen(sRight);
                if(0 < sLen)
                    RetVal[strlen(RetVal) - strlen(sRight)] = '\0';
            }
        }
    }
    return RetVal;
    //После использования в проге 
    //обязательно надо предусмотреть чистку памяти!!!!
    //Вот вариант реализации чистки
    //char * someStr = GetMidStr(...);
    //if(someStr)
    //   free(someStr);
}
 
//Думаю так наиболее просто обрезать пробелы
char * TrimSpace(char * str)
{
    char * chBuf = strrchr(str,' ');
    if(chBuf)
        str[strlen(str) - strlen(chBuf) - 1] = '\0';
    if(str)
        while(str[0] == ' ')
            str++;
    return str;
}
 
LPTSTR SelectFile()
{
    char sPath[MAX_PATH];sPath[0] = '\0';
    LPCITEMIDLIST lpItemDList;
    BROWSEINFO bi = {NULL, NULL, sPath,
       "Выберите файл для обработки",
        BIF_DONTGOBELOWDOMAIN|BIF_BROWSEINCLUDEFILES,
        NULL,
        NULL,
        0
    };
    if((lpItemDList=SHBrowseForFolder(&bi)))
    {
        if(SHGetPathFromIDList(lpItemDList, sPath))
            GetShortPathName((LPCTSTR)sPath,sPath,strlen(sPath));
    }
    return &sPath[0];
}
Миниатюры
Удаление лишних пробелов в начале и конце строки.  
Вложения
Тип файла: txt begin_end.txt (62 байт, 22 просмотров)
Тип файла: txt no_begin.txt (56 байт, 19 просмотров)
Тип файла: txt no_end.txt (58 байт, 19 просмотров)
0
MCSD: APP BUILDER
8794 / 1073 / 104
Регистрация: 17.06.2006
Сообщений: 12,602
14.08.2009, 14:31 24
odip,
А вот кстати не очень правильный.
1) Если уже хочется скорости - то писать надо сразу trim двойной - слева и справа.

А кто сказал что я хочу скорости? Для меня на первом месте - стабильность. А скорости я захочу тогда, когда профайлер покажет что это самое тормозное место в программе.

2) tcslen() вызывать два раза совершенно не нужно.
Собственно не нужно вызывать ни одного раза.

попробуй как нибудь переместить область памяти, не зная её размера

3) В условии просили удалить только пробелы.
в том и фишка, только пробелы, или ещё табы etc - код не меняется. так зачем выкладывать недоделанную кривульку, если можно сдлелать как надо (Ж

4) TCHAR - это круто, но насчет Unicode опять же никто не говорил.
см. выше.

5) istspace(), tcsspn() - тоже не нужно вызывать.
а что нужно вызывать?

PS. И вот еще - если ты возьмешь на вооружение хотя бы эти два правила, многое откровется для тебя с совершенно новой стороны (((((((:

1. Помните, что любой код может быть тщательно исследован и, возможно, атакован. Это нормально. На ваш код нападают, и ничего страшного в этом нет. Однако главный вопрос заключается в том, будет ли ваш код уязвим? Ответ на этот вопрос зависит от вас. Поэтому вы должны гордиться своим кодом. Вы должны быть довольны качеством своего кода и спокойно спать ночью, зная, что, если он будет атакован, вы сделали все возможное, чтобы защитить его от взлома.
2. Я уже говорил это миллион раз и повторю снова: все входящие данные – зло, пока не доказано обратного. Если посмотреть на самые ужасные уязвимости безопасности, все они имеют общую черту: разработчик доверял поступающим данным. Проблема состоит в том, что, если ваш код предполагает, что данные формально правильны, что же случится, если ваше предположение неверно? Если вам повезет, то в вашем приложении может просто произойти сбой. А если не повезет, то взломщик может внедрить в ваш процесс вредоносный программный код и причинить ущерб
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
14.08.2009, 16:11 25
Цитата Сообщение от odip Посмотреть сообщение
5) istspace(), tcsspn() - тоже не нужно вызывать.
isspace - оно же макрос... ну не хотите - не вызывайте:

C
1
2
3
4
...
for ( ; *str == ' ' || *str == '\t'; str++ )
;
...
0
Эксперт С++
7175 / 3234 / 81
Регистрация: 17.06.2009
Сообщений: 14,164
14.08.2009, 16:29 26
isspace - оно же макрос
Ладно - isspace() можно вызывать.
Насколько помню макрос этот разворачивается в обращение к массиву,
что работает быстрее чем два сравнения.

Хотя еще раз повторю: в исходном условии идет речь о пробелах.

Добавлено через 10 минут 29 секунд
PS. И вот еще - если ты возьмешь на вооружение хотя бы эти два правила, многое откровется для тебя с совершенно новой стороны (((((((:
Это ты случайно не Маерса тут цитируешь ?
Книжка называется типа "Написание надежных программ".
Книжке лет 40, но она до сих пор актуальна.

Добавлено через 1 минуту 36 секунд
попробуй как нибудь переместить область памяти, не зная её размера
Я хотел сказать, что если ты будешь обрабатывать оба конца строки,
то ты должен найти второй конец в любом случае - чтобы открутить пробелы справа от конца. А раз ты нашел конец строки - ты знаешь длину строки.
Нет большой необходимости считать длину.

Добавлено через 1 минуту 33 секунды
а что нужно вызывать?
isspace() еще туда-сюда.
А вот tcsspn() думаю сильно тормознутая функция.
0
28 / 28 / 6
Регистрация: 01.07.2009
Сообщений: 58
14.08.2009, 19:28 27
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
#include <iostream>
#include <cstring>
using namespace std;
char *allgoritm(char *str)
{
 int beg,end,i;
 for(i=0; i < strlen(str); i++)
  if(*(str+i)!=' ')
  {
    beg=i;
    break;
  }
 for(i=strlen(str)-1; i >=0; i++)
  if(*(str+i)!=' ')
  {
    end=i;
    break;
  }
 char *st=new char[strlen(str)];
 int j=0;
 for(i=beg; i <=end; i++)
 {
  *(st+j)=*(str+i);
  j++;
 }
 *(st+j+1)='\0';
 return st;
}
int main()
{
    char str[256],*s;
    cin.getline(str,256);
    s=allgoritm(str);
    cout<< s <<endl;
    return 0;
}
0
MCSD: APP BUILDER
8794 / 1073 / 104
Регистрация: 17.06.2006
Сообщений: 12,602
15.08.2009, 01:34 28
odip,
Ладно - isspace() можно вызывать.
мая имеет благодарить, насяльника! (D

Это ты случайно не Маерса тут цитируешь ?
http://msdn.microsoft.com/ru-r... 63518.aspx

но ты должен найти второй конец в любом случае
и как же мне это сделать?

А вот tcsspn() думаю сильно тормознутая функция.
think different
0
alter-sl
30.03.2010, 16:51 29
Цитата Сообщение от Humanitis Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
char*alltrim(char*string)
 {
    char *p,*iter;
    while(*string++==' ');
    iter=--string;
    while(*iter)iter++;
    while(*(--iter)==' ');
    p=new char[iter-string+1];
    char *result=p;
    while(string<=iter)*p++=*string++;
    *p=0;
   return result;
 }
 
int main(void)
 {
  char*x="      q   w   e r       t     y    ";
  std::cout<<alltrim(x); //На выходе должно получится  "q   w   e r       t     y"
  system("pause");
  return 0;
 }
Не мог бы ты написать комментарии к каждой строке?просто я только начинаю изучать язык и не до конца понял как она работает)только основную идею уловил... Буду очень благодарен! Заранее Спасибо!
30.03.2010, 16:51
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.03.2010, 16:51
Помогаю со студенческими работами здесь

Удаление лишних пробелов в середине строки
Я написал как мог, всё работает, но если вы знаете как упростить код и написать более проще, то...

Удаление лишних пустых строк и пробелов на конце строки
open(FIL,&quot;azaz.txt&quot;); my @s =&lt;FIL&gt;; close FIL; for ($i=0; $i &lt;= 9; $i++) { if ( length( $s ) &gt;...

Удаление пробелов в начале и в конце строки
Ошибка: Встречено ';', а ожидалось ':' (в первой строке после filtr). Как исправить , почему...

Удаление пробелов в конце и начале списка
Возможно ли в прологе реализовать удаление пробелов из начала и конца списка? Есть задача -...


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

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