Вот небольшая программа, которая удаляет комментарии C почти во всех случаях.
/* strip C comments by chqrlie */
#include <errno.h>
#include <stdio.h>
#include <string.h>
/* read the next byte from the C source file, handing escaped newlines */
int getcpp(FILE *fp, int *lineno_p) {
int ch;
while ((ch = getc(fp)) == '\\') {
if ((ch = getc(fp)) != '\n') {
ungetc(ch, fp);
return '\\';
}
*lineno_p += 1;
}
if (ch == '\n')
*lineno_p += 1;
return ch;
}
int main(int argc, char *argv[]) {
FILE *fp = stdin, *ft = stdout;
const char *filename = "<stdin>";
int ch, lineno;
if (argc > 1) {
if ((fp = fopen(filename = argv[1], "r")) == NULL) {
fprintf(stderr, "Cannot open input file %s: %s\n",
filename, strerror(errno));
return 1;
}
}
if (argc > 2) {
if ((ft = fopen(argv[2], "w")) == NULL) {
fprintf(stderr, "Cannot open output file %s: %s\n",
argv[2], strerror(errno));
return 1;
}
}
lineno = 1;
while ((ch = getcpp(fp, &lineno)) != EOF) {
int startline = lineno;
if (ch == '/') {
if ((ch = getcpp(fp, &lineno)) == '/') {
/* single-line comment */
while ((ch = getcpp(fp, &lineno)) != EOF && ch != '\n')
continue;
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated single line comment\n",
filename, startline);
break;
}
putc('\n', ft); /* replace comment with newline */
continue;
}
if (ch == '*') {
/* multi-line comment */
int lastc = 0;
while ((ch = getcpp(fp, &lineno)) != EOF) {
if (ch == '/' && lastc == '*') {
break;
}
lastc = ch;
}
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated comment\n",
filename, startline);
break;
}
putc(' ', ft); /* replace comment with single space */
continue;
}
putc('/', ft);
/* keep parsing to handle n/"a//"[i] */
}
if (ch == '\'' || ch == '"') {
int sep = ch;
const char *const_type = (ch == '"') ? "string" : "character";
putc(sep, ft);
while ((ch = getcpp(fp, &lineno)) != EOF) {
putc(ch, ft);
if (ch == sep)
break;;
if (ch == '\\') {
if ((ch = getcpp(fp, &lineno)) == EOF)
break;
putc(ch, ft);
}
if (ch == '\n') {
fprintf(stderr, "%s:%d: unescaped newline in %s constant\n",
filename, lineno - 1, const_type);
/* This is a syntax error but keep going as if constant was terminated */
break;
}
}
if (ch == EOF) {
fprintf(stderr, "%s:%d: unterminated %s constant\n",
filename, startline, const_type);
break;
}
continue;
}
putc(ch, ft);
}
if (fp != stdin)
fclose(fp);
if (ft != stdout)
fclose(ft);
return 0;
}
Поскольку вы получите полный ответ бесплатно, попробуйте и узнайте, как приведенный выше код обрабатывает строки и экранированные символы новой строки. Есть еще некоторые угловые случаи, которые не поддерживаются, можете ли вы их найти?
\
символов. . Так как Вы знаете, что все классы будут прибывать из того же пространства имен, настроить его однажды и использование что:
<appConfig>
<SuperAppConfig handlerNamespace="BigCorp.SuperApp">
<Handler class="ClassB" />
</SuperAppConfig>
</appConfig>
Редактирование: я изменился имя к класс для лучше обозначения значения того атрибута.
Или используйте полностью определенное имя блока, или овладейте блоком и используйте Assembly.GetType(name)
. В этом случае, так как Вы хотите типы в файле конфигурации, квалифицированный к блоку допустимый способ пойти - но так как Вы знаете, что все Ваши типы находятся в том же блоке:
Assembly assembly = typeof(SomeKnownType).Assembly; // in the same assembly!
Type type = assembly.GetType(name); // full name - i.e. with namespace (perhaps concatenate)
object obj = Activator.CreateInstance(type);
помехи Type.GetType(string)
имеют правила зондирования, которые часто вызывают беспорядок... это смотрит на блок вызова, и несколько системных блоков - но не все загруженные блоки.
(I will not be loading a type from outside this assembly/namespace)
из-за вышеупомянутой строки, безопасно предположить, что Вы знаете, каково пространство имен. Не могли Вы делать что-то как:
Type t = Type.GetType("Namespace." + className);
BaseClass c = Activator.CreateInstance(t) as BaseClass;
, Если Вы ожидаете возможно мочь добавить дополнительные классы стратегии, которые будут загружены в будущем, возможно, через дополнительный блок, необходимо было бы полностью определить имя класса. Это рекомендуется так или иначе, так как Вы смогли бы обеспечить улучшенный extendability для своего приложения.
Я иду с полным именем типа в конфигурации приложения. Ниже немного больше полного, но все еще тривиального примера
<SuperAppConfig>
<ObjectConfig provider="BigCorp.SuperApp.ClassA">
<add name="one" />
<add name="two" />
</ObjectConfig>
</SuperAppConfig>
И класс фабрики, который на самом деле создает это
private static Assembly a = typeof(IFactoryObject).Assembly;
public static IFactoryObject CreateObject(String providerName)
{
Type t = a.GetType(providerName)
IFactoryObject o = Activator.CreateInstance(t) as IFactoryObject;
return o;
}