Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 64, средняя оценка - 4.75
Zion3439
2 / 2 / 0
Регистрация: 04.03.2009
Сообщений: 30
#1

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

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

Нужно написать функцию 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"
  
 }
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.03.2009, 13:31     Удаление лишних пробелов в начале и конце строки.
Посмотрите здесь:

C++ Удаление лишних пробелов
C++ Удаление пробелов в начале и конце
C++ Удаление лишних пробелов с помощью вспомогательного массива
C++ Удаление лишних пробелов
Удаление лишних пробелов C++
C++ Создание программы со своей библиотекой ( удаление элементов с N по M в строке и удаление лишних пробелов(если 2 и более оставить один))
Удаление лишних (подряд идущих) разделителей при разделении строки C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Rififi
2336 / 1051 / 44
Регистрация: 03.05.2009
Сообщений: 2,656
14.08.2009, 01:40     Удаление лишних пробелов в начале и конце строки. #21
Кстати, можно и короче

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);
}
odip
Эксперт С++
7155 / 3295 / 59
Регистрация: 17.06.2009
Сообщений: 14,164
14.08.2009, 11:45     Удаление лишних пробелов в начале и конце строки. #22
а теперь - правильный вариант (:
А вот кстати не очень правильный.
1) Если уже хочется скорости - то писать надо сразу trim двойной - слева и справа.
2) tcslen() вызывать два раза совершенно не нужно.
Собственно не нужно вызывать ни одного раза.
3) В условии просили удалить только пробелы.
4) TCHAR - это круто, но насчет Unicode опять же никто не говорил.
5) istspace(), tcsspn() - тоже не нужно вызывать.

А вот memmove() похоже пригодится - возможно будет быстрее, чем без него.
-=ЮрА=-
Заблокирован
Автор 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 байт, 21 просмотров)
Тип файла: txt no_begin.txt (56 байт, 18 просмотров)
Тип файла: txt no_end.txt (58 байт, 18 просмотров)
Rififi
2336 / 1051 / 44
Регистрация: 03.05.2009
Сообщений: 2,656
14.08.2009, 14:31     Удаление лишних пробелов в начале и конце строки. #24
odip,
А вот кстати не очень правильный.
1) Если уже хочется скорости - то писать надо сразу trim двойной - слева и справа.

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

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

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

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

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

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

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

1. Помните, что любой код может быть тщательно исследован и, возможно, атакован. Это нормально. На ваш код нападают, и ничего страшного в этом нет. Однако главный вопрос заключается в том, будет ли ваш код уязвим? Ответ на этот вопрос зависит от вас. Поэтому вы должны гордиться своим кодом. Вы должны быть довольны качеством своего кода и спокойно спать ночью, зная, что, если он будет атакован, вы сделали все возможное, чтобы защитить его от взлома.
2. Я уже говорил это миллион раз и повторю снова: все входящие данные – зло, пока не доказано обратного. Если посмотреть на самые ужасные уязвимости безопасности, все они имеют общую черту: разработчик доверял поступающим данным. Проблема состоит в том, что, если ваш код предполагает, что данные формально правильны, что же случится, если ваше предположение неверно? Если вам повезет, то в вашем приложении может просто произойти сбой. А если не повезет, то взломщик может внедрить в ваш процесс вредоносный программный код и причинить ущерб
easybudda
Эксперт С++
9454 / 5467 / 926
Регистрация: 25.07.2009
Сообщений: 10,490
14.08.2009, 16:11     Удаление лишних пробелов в начале и конце строки. #25
Цитата Сообщение от odip Посмотреть сообщение
5) istspace(), tcsspn() - тоже не нужно вызывать.
isspace - оно же макрос... ну не хотите - не вызывайте:

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

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

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

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

Добавлено через 1 минуту 33 секунды
а что нужно вызывать?
isspace() еще туда-сюда.
А вот tcsspn() думаю сильно тормознутая функция.
firefox1913
27 / 27 / 2
Регистрация: 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;
}
Rififi
2336 / 1051 / 44
Регистрация: 03.05.2009
Сообщений: 2,656
15.08.2009, 01:34     Удаление лишних пробелов в начале и конце строки. #28
odip,
Ладно - isspace() можно вызывать.
мая имеет благодарить, насяльника! (D

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

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

А вот tcsspn() думаю сильно тормознутая функция.
think different
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.03.2010, 16:51     Удаление лишних пробелов в начале и конце строки.
Еще ссылки по теме:

C++ Рекурсия. Удаление лишних пробелов
Во введенной пользователем строке удалите все пробелы в начале и конце строки C++
C++ Удаление лишних пробелов
Функция удаляющая пробелы в начале и в конце строки C++
C++ Отрезание пробелов в начале и в конце строки

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

Или воспользуйтесь поиском по форуму:
alter-sl
Сообщений: n/a
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;
 }
Не мог бы ты написать комментарии к каждой строке?просто я только начинаю изучать язык и не до конца понял как она работает)только основную идею уловил... Буду очень благодарен! Заранее Спасибо!
Yandex
Объявления
30.03.2010, 16:51     Удаление лишних пробелов в начале и конце строки.
Ответ Создать тему
Опции темы

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