描述:
C程序的注释用/* */来表示。请写一个程序,将输入的C程序源代码中的注释去掉,输出去掉注释之后的源代码。用于测试的C代码保证符合语法,不使用C++的//注释语法。
注意,C语言不允许出现嵌套注释。具体来说,对于/* /* * /”* /”,如果不允许嵌套注释,那么它表示字符串”* / “;如果允许嵌套注释,它表示一个引号”。字符串中出现的注释符 / * 属于字符串的一部分,注释中出现的双引号”属于注释的一部分。
输入
符合语法的C代码文本文件。代码每行不超过200个字符。
输出
去掉注释后的C代码。要求只能去掉注释,不可以做其他的修改,比如调整缩进,去除注释之外的换行符等。
样例输入
#include
#include
#include
/*Hash Search:
Hash function: division method;
handling collisions: open addressing's linear probing.
In this exercise, M is the basic area's length, all keys are non negative integers.*/
#define M 11
int hash(int key)
{
return key % M;
}
void init_hash(int* hashtable)
{
int i;
for(i = 0; i < M; ++i)
{
hashtable[i] = -1;
}
}
/*return value:
1:found, *position is the key's index;
0:not found, *position is where to insert the key;
-1:overflow. */
int search_hash(int* hashtable, int key, int* position)
{
int i, h = hash(key);
for(i = 0; i < M; ++i)
{
if(key == hashtable[h])
{
*position = h;
return 1;
}
if(-1 == hashtable[h])
{
*position = h;
return 0;
}
h = (h+1) % M;
}
*position = -1;
return -1;
}
/*return value: 1:inserted, 0:overflow*/
int insert_hash(int* hashtable, int key)
{
int position, result;
result = search_hash(hashtable, key, &position);
if(-1 == result)
return 0;
hashtable[position] = key;
return 1;
}
void main()
{
int hashtable[M];
init_hash(hashtable);
srand(time(NULL));
int i, j, key;
for(i = 0; i < 8; ++i) /*make a hash table with 8 elements*/
{
key = rand() % 50;
insert_hash(hashtable, key);
printf("Insert %d\n", key);
for(j = 0; j < M; ++j)
printf("%3d", hashtable[j]);
printf("\n");
}
printf("Please input the key to search:\n");
scanf("%d", &key);
i = search_hash(hashtable, key, &j);
if(1 == i)
printf("Found!Its index is %d\n", j);
else
printf("Not found!\n");
}
样例输出
#include
#include
#include
#define M 11
int hash(int key)
{
return key % M;
}
void init_hash(int* hashtable)
{
int i;
for(i = 0; i < M; ++i)
{
hashtable[i] = -1;
}
}
int search_hash(int* hashtable, int key, int* position)
{
int i, h = hash(key);
for(i = 0; i < M; ++i)
{
if(key == hashtable[h])
{
*position = h;
return 1;
}
if(-1 == hashtable[h])
{
*position = h;
return 0;
}
h = (h+1) % M;
}
*position = -1;
return -1;
}
int insert_hash(int* hashtable, int key)
{
int position, result;
result = search_hash(hashtable, key, &position);
if(-1 == result)
return 0;
hashtable[position] = key;
return 1;
}
void main()
{
int hashtable[M];
init_hash(hashtable);
srand(time(NULL));
int i, j, key;
for(i = 0; i < 8; ++i)
{
key = rand() % 50;
insert_hash(hashtable, key);
printf("Insert %d\n", key);
for(j = 0; j < M; ++j)
printf("%3d", hashtable[j]);
printf("\n");
}
printf("Please input the key to search:\n");
scanf("%d", &key);
i = search_hash(hashtable, key, &j);
if(1 == i)
printf("Found!Its index is %d\n", j);
else
printf("Not found!\n");
}
提示
注意字符串,字符,转义字符的情况。看看自己有没有考虑”a\”/* ccc */”这种情况。
解决思路:
#pragma warning(disable:4996)//ignore the warning from 15 vs 10
#include <iostream>
#include <string>
using namespace std;
#define LOCAL //redirect the input && output
bool Affected_by_String = false;
bool Affected_by_Annonate = false;
string s,s_get;
void Remove_the_Annotate()
{
while (getline(cin, s_get))//getLine函数不能读入换行符,需要自己加上
s += s_get + '\n';
//待处理的字符串比真实文本多一个字符是有好处的,保证start != end和start + 1都是正确而有效的
char *start = &s[0];
char *end = &s[s.length() -1];
while ( start != end )
{
//当前字符有效且既不在字符串中也不在注释中
while( !Affected_by_String && !Affected_by_Annonate && start != end)
{
//当前字符是注释的开始标志,注释标志有效且直到注释符结束之前不予输出,退出当前循环
if( *(start) == '/' && *(start + 1) == '*' )
{
Affected_by_Annonate = !Affected_by_Annonate;
start +=2 ;
}
else
{
//当前字符串符号未被转义,字符串开始,标注字符串有效标志,退出当前循环
if(*(start) != '\\' && *(start + 1) == '"' )
{
Affected_by_String = !Affected_by_String ;
//注意这里不要写成cout << *start++ << *start++
//运算符优先级不清楚,包括cout << *start++都需要谨慎使用
cout << *start << *(start + 1 );
start += 2;
}
else
cout << *start++;//当前字符不属于注释或字符串,正常输出
}
}
while( Affected_by_String && start != end)//字符有效且在字符串内
{
//当前字符串结束标志被转义,顺序输出之,当前字符串并未结束
if( *(start) == '\\' && *(start + 1) == '"' )
{
cout << *start << *(start + 1 );
start += 2;
}
else
{
//字符串退出标志有效,退出当前字符串,并标注下一个字符已不属于字符串
if( *(start) == '"' )
{
cout << *start++;
Affected_by_String = !Affected_by_String ;
}
else
cout << *start++;
}
}
while( Affected_by_Annonate && start != end )
{
//注释结束标志有效,与注释开始标志同样的处理
if( *(start) == '*' && *(start + 1) == '/' )
{
start +=2 ;
Affected_by_Annonate = !Affected_by_Annonate;
}
else
start++;//否则在注释内的内容还是被忽略掉
}
}
}
int main()
{
#ifdef LOCAL
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
Remove_the_Annotate();
return 0;
}
后续:程序中还有bug。bug-1:在end的位置是否有效、start + 1的位置是否有效等均可以在字符创末尾额外添加一个换行符来处理。当然还有可能没有发现的bug,如只出现左半边注释符,miss右半边注释符的时候,可能会出现异常。提交平台通过,bug_1没有被发现估计与string动态增长的方式有关,仍需注意。