Форум программистов, компьютерный форум, киберфорум
Наши страницы

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

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 36, средняя оценка - 4.86
recovery101
1 / 1 / 0
Регистрация: 10.06.2011
Сообщений: 10
#1

Удалить комментарии из строки - C++

14.09.2011, 15:19. Просмотров 4777. Ответов 48
Метки нет (Все метки)

Привет. Вообщем такая задача: Прочитать из файла строку символов. Удалить из этой строки комментарии вида "/* ... */" (вложенные комментарии тоже удалить) . Новую строку не создавать. Вывести исходную и преобразованную строки.
Т.е. например: дана строка "gfsgsdsf /* jhasd */ asdas" и на выходе он выдает "gfsgsdsf asdas". Вот мой код
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 "stdafx.h"
#include <conio.h>
#include <stdio.h>
#include <iostream>
using namespace std;
void main ()
{
   setlocale (0,"Rus");
   int m = 0, n = 0;
   FILE * f;
   char buf[100];
   int length;
   f = fopen ("C:\\okfile.txt", "r");
   if (f == NULL) 
       perror ("Ошибка");
   else 
   {
     fgets (buf, 100 , f);
     puts (buf);
     fclose (f);
   }
   length = strlen(buf);
   for(int i = 0; i < length ; i++)
   {
       if ((buf[i] == '/') && (buf[i + 1] == '*'))
       {
          m = i;
       }
       if ((buf[i - 1] == '*') && (buf[i] == '/'))   
       {
          n = i;   
       }
       if ((m != 0) && (i == n))
       {
       int len = strlen(buf)-m;
       memmove(buf+m-1, buf+n+1, len);
       }
   }
   puts (buf);
   getch();
}
Но он не удаляет вложенные комментарии (комментарии в комментарии), т.е. надо чтобы при вводе строки "asdasd /* asd /*123*/ dsa*/ asdasd" выводил "asdasd asdasd".
Помогите пожалуйста исправить.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.09.2011, 15:19
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Удалить комментарии из строки (C++):

Удалить из строки комментарии вида '/* . */". Игнорировать вложенные комментарии - C++
Всем привет! есть строка вида : char str=&quot;abc/*111/*def/*222*/ghi*/333*/jkl&quot;; нужно получить abc /*def ghi*/ jkl Реально ли так...

Удалить из строки комментарии вида '/* ... */". Игнорировать вложенные комментарии. - C++
#include &lt;iostream&gt; #include &lt;stdio.h&gt; #include &lt;string.h&gt; using namespace std; int main(int argc, char *argv) { ...

Удалить из строки слова, которые встречаются заданное число раз (нужны комментарии) - C++
Помогите пояснить программу пожалуйста? Написать комментарии к каждой строке?) #include &lt;iostream&gt; #include &lt;string&gt; #include...

Удалить комментарии из файлов С и С++ - C++
Создать функцию удаляющую комментарии из файлов С и С++. Функция принимает в качестве параметра имя входного и выходного файлов и удаляет...

Удалить комментарии из фаила - C++
Здравствуйте. Есть вот такие фаилы: # 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware # File Created: 07.12.2014...

Прочитать программу на языке C++ и удалить все комментарии - C++
кто-нибудь)помогите написать эту программу=\

48
soon
2542 / 1307 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
14.09.2011, 15:59 #2
Вам надо найти первое вхождение /* и последнее */, я правильно понял?
Если да, то вам надо вводить флаг(к примеру bool firstComment = 0) на нахождение первого комметария. И менять ветвление в 26 строчке, добавляя && !firstComment к условию, а к самому выполняемому действию firstComment = 1. Таким образом вы найдете первый комментарий в строке.
ps/ а в строке 30, при i == 0 не будет выхода за границу массива?
0
alkagolik
Заблокирован
14.09.2011, 19:19 #3
Цитата Сообщение от soon Посмотреть сообщение
а в строке 30, при i == 0 не будет выхода за границу массива?
будет конечно. надо учесть так же "//комментарий" и использовать конструкцию
C++
1
2
3
if()
else if()
else if()
0
soon
2542 / 1307 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
14.09.2011, 20:10 #4
будет конечно.
Своим вопросом я хотел натолкнуть самого ТС на ваше умозаключение. Ну да ладно.
Еще вдруг мысля посетила мой мозг - а в строке один комментарий? Если строка вида 123 /* 123 /* 123 */ 321 */ 123 /* йцук */ ен, то придется несколько раз проходить по строке, причем учитывать количество /*, и, пока их количество не будет равно */ не вырезать строку.
0
xdozorx
15 / 16 / 1
Регистрация: 13.12.2009
Сообщений: 138
Записей в блоге: 1
14.09.2011, 20:33 #5
C++
1
2
3
4
5
6
7
8
  if ((buf[i] == '/') && (buf[i + 1] == '*'))
           {
                  m = i; break;
           }
           if ((buf[i - 1] == '*') && (buf[i] == '/'))   
           {
                  n = i;   break;
           }
так попробуй
0
soon
2542 / 1307 / 81
Регистрация: 09.05.2011
Сообщений: 3,086
Записей в блоге: 1
14.09.2011, 20:59 #6
Нужно будет 2 цикла. Как минимум. Для нахождения начальной и конечной позиции.
0
villu
203 / 204 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
14.09.2011, 23:02 #7
1 цикл.
можно значительно упростить, как сейчас понял.
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
std::string remove_comment(const std::string &in) {
 
    enum state_t {
        state_clean = 0,
        state_start,
        state_rem,
        state_stop
    } state = state_clean;
 
    std::string clean;
    std::string out;
 
    std::string::const_iterator itr;
 
    size_t len = in.size();
    clean.reserve(len);
    out.reserve(len);
 
    std::string *cursor = &out;
    bool use_clean = false;
 
    for(itr = in.begin(); itr!=in.end(); ++itr) {
        switch( state ) {
        case state_clean:
            if(*itr == '/') state = state_start;
            else cursor->push_back(*itr);
            break;
        case state_start:
            if(*itr == '*') {
                if( use_clean ) {
                    use_clean = false;
                    cursor = &out;
                    out += clean;
                    clean.clear();
                }
                state = state_rem;
            } else {
                cursor->push_back('/');
                cursor->push_back(*itr);
                state = state_clean;
            }
            break;
        case state_rem:
            if(*itr == '*') state = state_stop;
            else if(*itr == '/') state = state_start;
            else if( use_clean ) cursor->push_back(*itr);
            break;
        case state_stop:
            if( *itr == '/' ) {
                use_clean = true;
                clean.clear();
                cursor = &clean;
            } else {
                cursor->push_back('*');
                cursor->push_back(*itr);
            }
            state = state_rem;
            break;
        }
    }
    if(!clean.empty()) out += (clean);
    return out;
}
C++
1
2
3
    std::string rem_str = "Kirje sinulle /* а это комент, да */ kyllГ¤! siina kaiiki; конец коммента */ siina kaikki.";
 
    cout << remove_comment(rem_str);
Bash
1
Kirje sinulle  siina kaikki.
может где есть какие глюки. не проверял сильно.
0
xAtom
915 / 740 / 60
Регистрация: 09.12.2010
Сообщений: 1,346
Записей в блоге: 1
14.09.2011, 23:11 #8
recovery101, вот накидал вариант, неограниченное удаление кол-во вложенных конструкций и т.п.
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 <stdio.h>
#include <string.h>
 
char*  str_erase(char*  str, const char* first, const char* last) {
    char* ptr;
    char* pa, *pb;
    int len;
 
    for(pa = NULL, ptr = str; ptr; ptr = strstr(ptr, first))  {
          if(ptr)
               pa = ptr;
          ptr += strlen(first);
    }  
    if(pa) {
        if((pb  = strstr(pa, last))) {
              pb += strlen(last);
              len  = pb - pa;
              memmove(str + (pa - str), str + (pb - str), strlen(str) - (pa - str));
              str_erase(str, first, last);
        }
    }
    return str;
}
 
 
int  main(void) {
 
      // тестирующия строка
      char str[] = "asdasd /* asd /*123*/ dsa*/ asdasd\n" \
                      "sample /* ops */HTML/*111*/ end.\n" \
                      "test /*1/*2/*fff*/2*/33*/fin/** /**/  **/:)";
 
      // вывод исходной строки
      printf("string src:\n%s\n\n", str);
    
      str_erase(str, "/*", "*/");
      printf("string dst:\n%s\n", str); // вывод обработанной
 
      getchar();
      return 0;
}
0
recovery101
1 / 1 / 0
Регистрация: 10.06.2011
Сообщений: 10
15.09.2011, 00:02  [ТС] #9
Цитата Сообщение от xAtom Посмотреть сообщение
recovery101, вот накидал вариант, неограниченное удаление кол-во вложенных конструкций и т.п.
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 <stdio.h>
#include <string.h>
 
char*  str_erase(char*  str, const char* first, const char* last) {
    char* ptr;
    char* pa, *pb;
    int len;
 
    for(pa = NULL, ptr = str; ptr; ptr = strstr(ptr, first))  {
          if(ptr)
               pa = ptr;
          ptr += strlen(first);
    }  
    if(pa) {
        if((pb  = strstr(pa, last))) {
              pb += strlen(last);
              len  = pb - pa;
              memmove(str + (pa - str), str + (pb - str), strlen(str) - (pa - str));
              str_erase(str, first, last);
        }
    }
    return str;
}
 
 
int  main(void) {
 
      // тестирующия строка
      char str[] = "asdasd /* asd /*123*/ dsa*/ asdasd\n" \
                      "sample /* ops */HTML/*111*/ end.\n" \
                      "test /*1/*2/*fff*/2*/33*/fin/** /**/  **/:)";
 
      // вывод исходной строки
      printf("string src:\n%s\n\n", str);
    
      str_erase(str, "/*", "*/");
      printf("string dst:\n%s\n", str); // вывод обработанной
 
      getchar();
      return 0;
}
Спасибо, вот только не совсем понял: это полноценный программный код или часть программы? Уж слишком сложные и незнакомые теги
0
talis
792 / 544 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 01:12 #10
recovery101, а что такое теги применительно к c++?

Cуть в том, что вам нужно учитывать уровень вложенности комментария, при входе в блок (/*) увеличивать уровень, при выходе из блока (*/) уменьшать уровень (если он больше нуля). И учитывать (выводить, копировать...) символы только если уровень равен нулю.
0
accept
4828 / 3249 / 165
Регистрация: 10.12.2008
Сообщений: 10,569
15.09.2011, 02:45 #11
у villu правильный подход, можно меньше букв сделать
Удалить комментарии из файла. Помогите найти ошибку.
0
talis
792 / 544 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 10:41 #12
villu,

Цитата Сообщение от villu Посмотреть сообщение
"Kirje sinulle /* а это комент, да */ kyllд! siina kaiiki; конец коммента */ siina kaikki."

Kirje sinulle siina kaikki.
а разве конец коммента не должен быть после слова "да"?
0
villu
203 / 204 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.09.2011, 12:46 #13
а разве конец коммента не должен быть после слова "да"?
первый вариант так и работал.
второй вариант сделал "жадным" (до последнего валидного закрытия без открытия.)
первый вариант выглядит немного страшнее, но тоже ничего сложного.

один цикл без рекурсий.
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
std::string remove_comment(const std::string &in) {
 
    enum state_t {
        state_clean = 0,
        state_rem
    } state = state_clean;
 
    typedef std::string::const_iterator strcitr;
    struct str_tok {
        enum {
            token_open = 0,
            token_close,
            token_def
        } token;
        str_tok(): token(token_def) {}
        const strcitr operator()( const strcitr &input, const strcitr &end ) {
            strcitr next_itr;
            if((input != end) && ((next_itr = input + 1) != end)) {
                const char cur = *input;
                const char next = *next_itr;
                switch( cur ) {
                    case '/':
                        if(next == '*') {
                            token = token_open;
                            return next_itr;
                        }
                        break;
                    case '*':
                        if(next == '/' && (token != token_close) ) {
                            token = token_close;
                            return next_itr;
                        }
                        break;
                }
            }
            token = token_def;
            return input;
        }
    } get_tok;
 
    std::string out;
    strcitr itr;
 
    out.reserve(in.size());
    int opened = 0;
 
    for(itr = in.begin(); itr!=in.end(); itr = get_tok(++itr, in.end())) {
        switch( state ) {
        case state_clean:
            if( get_tok.token == str_tok::token_open ) {
                opened++;
                state = state_rem;
            } else if( get_tok.token == str_tok::token_close ) {
                out += "*/";
            } else {
                out.push_back(*itr);
            }
            break;
        case state_rem:
            if( get_tok.token == str_tok::token_close ) {
                if(--opened == 0) state = state_clean;
            } else if(get_tok.token == str_tok::token_open) {
                ++opened;
            }
            break;
        }
    }
    return out;
}
Кстати в варианте xAtom ошибка
C++
1
 char test[] = "1234/**/*/**/56789";
ожидаемо 1234*56789
получается 1234/**/*56789
или как пример "1234/**//**//*56789"
ожидаемо 1234
выводит без изменений. Хотя если принять такую строку за невалидную, то все в норме.

Добавлено через 21 минуту
Кстати в варианте xAtom ошибка
и еще одна
"***/" некорректно обрабатывает.
0
PointsEqual
ниначмуроФ
836 / 520 / 33
Регистрация: 12.10.2009
Сообщений: 1,915
15.09.2011, 12:47 #14
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
#include<algorithm>
 
using namespace std;
 
int main()
{
    string  s = "asdasd /* asd /*123*/ dsa*/ asdasd";
 
    int f = s.find_first_of("/*");
    int l = s.find_last_of("*/");
 
    cout << s << endl;
 
    s.erase(f, l - f + 1);
 
    cout << s;
 
    return 0;
}
0
talis
792 / 544 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 12:50 #15
PointsEqual, а если так:

hello, /* world!*/ my /*car*/friend!

должно быть hello, my friend, а получится hello, friend

Добавлено через 24 секунды
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
#include <iostream>
#include <string>
 
using namespace std;
 
string nocomment( string str )
{
    string data;
    unsigned int level = 0;
 
    string::const_iterator it = str.begin();
 
    while( it != str.end() )
    {
        if( *it == '/' )
        {
            it++;
 
            if( *it == '*' )
            {
               level++;
               it++;
               continue;
            }
 
            if( !level )
               data += '/' + *it;
        }
        else if( *it == '*' )
        {
            it++;
 
            if( *it == '/' )
            {
               if( level )
                  level--;
 
               it++;
               continue;
            }
 
            if( !level )
               data += '*' + *it;
            else
               continue;
        }
        else if( !level )
           data += *it;
 
        it++;
    }
 
    return data;
}
 
int main()
{
    cout << "output: " << nocomment( "Hello, /*world*/sailor! How /* is /* your /* comment */ */ doing?**/do/* */ you/***/ do?" );
 
    return 0;
}
1
15.09.2011, 12:50
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.09.2011, 12:50
Привет! Вот еще темы с ответами:

Удалить комментарии из файла. Помогите найти ошибку. - C++
программа должна распознать комменитарии вида /* */ и // из входного файла, и записать в выходной файл программу без комментариев... 1...

С помощью итераторов удалить комментарии из текста программы - C++
Здравствуйте помогите пожалуйста решить задачу Напишите программу, которая выбрасывает комментарии из C++ программы. То есть, читает из...

Комментарии к программе на строки - C++
#include &lt;iostream&gt; #include &lt;sstream&gt; #include &lt;string&gt; using namespace std; int main() { string...

Заменить комментарии нечетной строки комментариями четной - C++
Исходный текст должен содержаться в одном файле, результат — во втором файле. В программе на ассемблере заменить комментарии нечетной...


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

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

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