1 / 1 / 0
Регистрация: 10.06.2011
Сообщений: 10
1

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

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

Author24 — интернет-сервис помощи студентам
Привет. Вообщем такая задача: Прочитать из файла строку символов. Удалить из этой строки комментарии вида "/* ... */" (вложенные комментарии тоже удалить) . Новую строку не создавать. Вывести исходную и преобразованную строки.
Т.е. например: дана строка "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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.09.2011, 15:19
Ответы с готовыми решениями:

Удалить из строки комментарии вида '/* ... */". Игнорировать вложенные комментарии.
#include &lt;iostream&gt; #include &lt;stdio.h&gt; #include &lt;string.h&gt; using namespace std; int...

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

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

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

48
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 14:12 21
Author24 — интернет-сервис помощи студентам
villu, редактор не понимает вложенные комменты (так как их не понимает компилятор). Задача меняется.
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.09.2011, 14:14 22
как-то так
Изображения
 
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 14:21 23
villu, если делать, как думает редактор, то после открывающей последовательности /* нужно ждать закрывающую */, а после закрывающей - снова открывающую. Никаких вложений. По-этому в ситуации с

/**/*/**/

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

Добавлено через 1 минуту
так же вот ещё пример:

/*/*/

в любом редакторе вторые два символа не рассматриваются как вторая открывающая последовательность. вместо этого, последние два символа рассматриваются как закрывающая. с вложениями всё иначе - после одного открывающего может стоять другой
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.09.2011, 14:22 24
1: редактор открой.
2: например студия действительно не понимает комменты вложенные, а некоторые понимают.
а третьи два не рассматриваются как закрывающий коммент, потому что после закрытия ожидается открытие.
Вы говорите глупости (с)
ЛЮБОЙ редактор с такой чепухой справляется. Выше уже кинул картинку. Вот еще одна.
Изображения
 
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.09.2011, 14:24 25
Цитата Сообщение от talis Посмотреть сообщение
[b]
/*/*/
и опять ой!. потмоу что ЛЮБОЙ редактор рассмотрит / внутри /**/ как коммент.

еще картинку прислать?
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 14:26 26
Цитата Сообщение от villu Посмотреть сообщение
Вы говорите глупости (с)
ЛЮБОЙ редактор с такой чепухой справляется
Не любой:

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


Code::Blocks 10.05. Ниже видно, что gcc ругается.
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 14:28 27
Цитата Сообщение от villu Посмотреть сообщение
и опять ой!. потмоу что ЛЮБОЙ редактор рассмотрит / внутри /**/ как коммент.
и опять ой:

Название: 1.JPG
Просмотров: 35

Размер: 1.9 Кб
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.09.2011, 14:30 28
потому что студия не? а я написал что оно не умеет.

Добавлено через 51 секунду
а там ровно такая ситуация, как я и описал.

потмоу что ЛЮБОЙ редактор рассмотрит / внутри /**/ как коммент.
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 14:41 29
Цитата Сообщение от villu Посмотреть сообщение
потмоу что ЛЮБОЙ редактор рассмотрит / внутри /**/ как коммент.
ну правильно, потому что вложенных комментов не может быть. а у нас-то ситуация совсем другая
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.09.2011, 15:00 30
ну правильно, потому что вложенных комментов не может быть. а у нас-то ситуация совсем другая
ууф..ладно.

вот еще одна проверка
1234/**sdfa /*inside*/asdfa **/56789

123456789 вывод так? однозначные вложенные комменты, все просто.
Твой код выдает 1234*inside*/asdfa ***/56789
мой 123456789
1
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 15:15 31
villu, да, действительно. Я забыл обновить предыдущий символ, если текст находится внутри комментария:

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
string nocomment( char * str )
{
    int level = 0;
    string out;
 
    char prev = 0,
         buff[2] = {0, 0};
 
    for( char *p = str; *p; p++ )
    {
        //cout << '\n' << *p << ": ";
 
        if( *p == '/' )
        {
            if( prev == '*' ) // закрываюший коммент
            {
                prev = 0;
 
                if( !level )
                {
                   //prev = 0;
                   //cout << "closing comment outside of comment area ";
                   out += "/";
                   continue;
                }
 
                level--;
 
                //cout << "closing comment:" << prev << " level is now " << level << ' ';
                //prev = 0;
 
                continue;
            }
 
            prev = *p;
            continue;
        }
        else if( *p == '*' )
        {
            if( prev == '/' ) // открываюший коммент
            {
                level++;
 
                //cout << "opening comment. level is now " << level << ' ';
 
                prev = 0;
                continue;
            }
 
            //prev = *p;
        }
 
        if( !level )
        {
            //prev = *p;
            buff[0] = *p;
            out += buff;
        }
 
        prev = *p;
    }
 
    return out;
}
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.09.2011, 15:19 32
и в хвостах тоже
char test0[] = "/123456789/";
что должно получиться?

/123456789//**/4

тоже однозначное
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 15:21 33
villu, 123456789, что и получается
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.09.2011, 15:23 34
а слеши на хвостах?
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
15.09.2011, 15:49 35
Цитата Сообщение от villu Посмотреть сообщение
например студия действительно не понимает комменты вложенные, а некоторые понимают.
Значит "некоторые" действуют не по стандарту. Студия-не студия, а исходный код парсит компилятор, он же выкидывает комментарии. И выкидывает он их по определённым правилам, описанным в стандарте. Нас интересует 2.8 - Comments, а именно примечание:
[ Note: The comment characters //, /*, and */ have no special meaning within a // comment and are treated just like other characters. Similarly, the comment characters // and /* have no special meaning within a /* comment. —end note ]
Отсюда видно, что все символы после // обрабатываются как обычные символы, т.е. //, /* и */ после первой пары // никакого особого смысла не имеют. Кроме того, после первого /* остальные символы (в том числе и /* и //) никаким специальным образом не обрабатываются вплоть до */.
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 15:57 36
villu, вот, со слешами на хвостах и с правильной обработкой /**/*/**/. К тому же с гораздо более элегантным кодом:

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
string nocomment( char * str )
{
    unsigned int level = 0;
    string out;
 
    for( char *p = str; *p; p++ )
    {
        if( p != str && *(p - 1) == '*' && *p == '/' && level ) // закрывающий коммент ненулевого уровня
        {
            level--;
            continue;
        }
        else if( *p == '/' && *(p + 1) == '*' ) // открывающий коммент
            level++;
 
        if( !level )
            out.push_back( *p );
    }
 
    return out;
}
 
int main()
{
    cout << "output:\n" << nocomment( "*///*bad*/Hello, /*world*/sailor! How /* is /* your /* comment */ */ doing?**/do/* */ you/***/ do?" )
         << '\n' << nocomment( "***/" ) <<
         '\n' << nocomment( "132/**/*/**/456789" ) <<
         '\n' << nocomment( "1234/**sdfa /*inside*/asdfa **/56789" ) <<
         '\n' << nocomment( "/123456789//**/4" );
 
    return 0;
}
Я вас, наверное, замучал уже. Голова, просто, не варит уже который день, и её хочется расшевелить. Спасибо за примеры!

Добавлено через 1 минуту
Цитата Сообщение от silent_1991 Посмотреть сообщение
Кроме того, после первого /* остальные символы (в том числе и /* и //) никаким специальным образом не обрабатываются вплоть до */.
Да, то есть вложения не учитываются. А у ТС задача совсем другая - со вложениями. Мы с villu тут просто выясняли, что в каких случаях считать открывающей, а что - закрывающей последовательностью именно в случае со вложенными комментами.
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.09.2011, 16:09 37
Sorry
/*///////*/

что должно быть?
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 16:10 38
будем думать...
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
15.09.2011, 16:17 39
Цитата Сообщение от talis Посмотреть сообщение
Мы с villu тут просто выясняли
Да, и villu ссылался на студию, "которая не умеет", и на "другие", "которые умеют". Я же пояснил, что задача ТС не соответствует тому, как принято обрабатывать комментарии в языке С++, и поэтому не следует в этом случае ссылаться на возможности той или иной IDE для этого языка.
0
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
15.09.2011, 16:27 40
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
string nocomment( char * str )
{
    unsigned int level = 0;
    string out;
 
    enum
    {
        s_none,
        s_open,
        s_close
    }
    last_seq = s_none;
 
    for( char *p = str; *p; p++ )
    {
        if( p != str && *(p - 1) == '*' && *p == '/' && level && last_seq != s_open ) // закрывающий коммент ненулевого уровня
        {
            last_seq = s_close;
            level--;
            continue;
        }
        else if( *p == '/' && *(p + 1) == '*' ) // открывающий коммент
        {
            level++;
            last_seq = s_open;
            p++; // мы заведомо знаем, что следующий символ не нужно учитывать
        }
        else
            last_seq = s_none;
 
        if( !level )
            out.push_back( *p );
    }
 
    return out;
}
Добавлено через 9 минут
villu, признайтесь - вы ветеран бетатестирования?
0
15.09.2011, 16:27
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.09.2011, 16:27
Помогаю со студенческими работами здесь

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

Удалить комментарии из файла
Здравствуйте, написал программу, которая удаляет комментарии в файле #include &lt;iostream&gt;...

Из строки удалить среднюю букву, если длина строки нечетная, иначе - удалить две средние буквы
Из строки удалить среднюю букву, если длина строки нечетная, иначе - удалить две средние буквы.

Из строки удалить среднею букву, если длина строки нечетная, иначе удалить две средних буквы
из ряда удалить среднею букву ,если длина ряда не парная ,тогда удалить две средних буквы


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

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

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