Вы можете использовать приведенный ниже запрос
Create Table SepvalueTable (Ticket Int, PartNumber char(1))
Insert into SepvalueTable Values (1, 'A'), (1, 'B'),(2, 'C'),(3, 'A'),(3, 'B'),(3, 'C')
SELECT Ticket,
PartNumber =
STUFF ( ( SELECT ' '+InrTab.PartNumber
FROM SepvalueTable InrTab
WHERE InrTab.Ticket = OutTab.Ticket
ORDER BY InrTab.Ticket
FOR XML PATH(''),TYPE
).value('.','VARCHAR(MAX)')
, 1,1,SPACE(0))
FROM SepvalueTable OutTab
GROUP BY OutTab.Ticket;
Вывод такой, как показано ниже
Ticket PartNumber
------------------
1 A B
2 C
3 A B C
Вы можете найти полную демонстрацию данных в реальном времени Демо здесь
Поднимите свой уровень предупреждения компилятора, и он должен сказать Вам.
Помещение исходного фрагмента в "f.c":
% gcc -c -Wall f.c
f.c: In function 'fun':
f.c:1: warning: unused variable 'c'
Хитрый - необходимо будет проанализировать код C для этого. Как близко результат должен быть? Пример того, что я имею в виду:
int a, /* foo */
b, /* << the unused one */
c; /* bar */
Теперь, для людей очевидно, что второй комментарий должен пойти.
Небольшое изменение:
void test(/* in */ int a, /* unused */ int b, /* out */ int* c);
Снова, второй комментарий должен пойти, тот прежде b на этот раз.
В целом Вы хотите проанализировать свой вход, отфильтровать его и испустить все, что это не объявление неиспользуемой переменной. Ваш синтаксический анализатор должен был бы сохранить комментарии и #include операторы, но если Вы не делаете #include заголовков, может быть невозможно распознать объявления (еще больше, если макрос используется для сокрытия объявления). В конце концов, Вам нужны заголовки, чтобы решить если * B (); объявление функции (когда A является типом), или умножение (когда A является переменной),
[редактирование], Кроме того:
Даже если Вы знаете, что переменная неиспользуема, надлежащий способ удалить ее во многом зависит от удаленного контекста. Например, принять
int foo(int a, int b, int c) { return a + b; }
Очевидно, c не использован. Можно ли изменить его на?
int foo(int a, int b) { return a + b; }
Возможно, но не, если &foo хранится интервал a int(*)(int,int,int)
. И это может произойти где-то в другом месте. Если (и только если), который происходит, необходимо изменить его на
int foo(int a, int b, int /*unused*/ ) { return a + b; }
Мой ответ является большим количеством тщательно продуманного комментария к очень полному ответу MSALTER. Я пошел бы вне 'хитрого' и сказал бы, что такой инструмент и невозможен и нецелесообразен.
Если Вы надеетесь просто удалять ссылки на переменную, то Вы могли записать собственный синтаксический анализатор кода, но она должна будет различать функциональный контекст, это находится в таком как
int foo(double a, double b)
{
b = 10.0;
return (int) b;
}
int bar(double a, double b)
{
a = 5.00;
return (int) a;
}
Любой простой синтаксический анализатор испытал бы затруднения и из-за и из-за 'b', являющийся неиспользуемыми переменными.
Во-вторых, если Вы рассмотрите комментарии, как MSalter имеет, Вы обнаружите, что люди последовательно не комментируют;
double a;
/*a is designed as a dummy variable*/
double b;
/*a is designed as a dummy variable*/
double a;
double b;
double a; /*a is designed as a dummy variable*/
double b;
и т.д.
Таким образом, просто удаление неиспользуемых переменных создаст осиротевшие комментарии, которые возможно более опасны, чем не комментарий вообще.
В конечном счете это - неприлично трудная задача сделать изящно, и Вы исказили бы код независимо. Путем автоматизации процесса Вы сделали бы код хуже.
Наконец, необходимо рассматривать, почему переменные были в коде во-первых, и если они удерживаются от использования, почему они не были удалены, когда все их ссылки были.
Почему Вы хотите сделать это? Принятие Вас имеет достойный оптимизирующий компилятор (GCC, Visual Studio и др.), двоичный выход не будет несколько отличаться, удаляете ли Вы 'интервал c' в Вашем исходном примере или нет.
Если это будет примерно очисткой кода, то любой недавний IDE даст Вам быстрые ссылки на исходный код для каждого предупреждения, просто нажать и удалить :)
Статические инструменты анализа кода в дополнительном к предупреждению уровня как Paul правильно указали.
А также способность показать их посредством предупреждений, компилятор будет обычно оптимизировать их далеко, если какие-либо оптимизации будут включены. Проверка, не ссылаются ли на переменную никогда, довольно тривиальна с точки зрения реализации в компиляторе.
Также: шплинт.
Шплинт является инструментом для того, чтобы статически проверить программы C на уязвимости системы обеспечения безопасности и кодировать ошибки. С минимальным усилием Шплинт может использоваться в качестве лучшего линта. Если дополнительное усилие инвестируют, добавляя аннотации к программам, Шплинт может выполнить более сильную проверку, чем может быть сделано каким-либо стандартным линтом.
Вам будет нужен хороший синтаксический анализатор, который сохраняет положение исходного символа маркеров (даже в присутствии препроцессора!). Существуют некоторые инструменты для автоматизированного рефакторинга C/C++, но они далеки от господствующей тенденции.
Я рекомендую Вам проверить Блог Taras. Парень делает некоторые большие автоматизированные рефакторинги кодовой базы Mozilla, как замена-params возвращаемыми значениями. Его основным инструментом для перезаписи кода является Свинина:
Свининой является C++ анализирующий и переписывающий набор инструментальных средств. Ядро Свинины является синтаксическим анализатором C++, который обеспечивает точные позиции символа для запуска и конца каждого узла AST, а также набора макрорасширений, которые содержат любое местоположение. Эта информация позволяет C++ быть автоматически переписанным точным способом.
Из блога:
До сих пор свинина использовалась для “незначительных” вещей как переименование classes&functions, вращение outparameters и исправление prbool ошибки. Кроме того, Свинина оказалась в эксперименте, который включил перезапись почти каждой функции (т.е. генерация 3+MB патч) в Mozilla для использования сборки "мусора" вместо подсчета ссылок.
Это для C++, но это может удовлетворить Вашим потребностям.
На одном из плакатов выше написано «невозможно и нецелесообразно». Другой говорит «сложно», и это правильный ответ. Вам понадобится 1) полный синтаксический анализатор C (или любого другого интересующего языка), 2) процедуры вывода, которые понимают язык ссылки на идентификаторы и потоки данных, чтобы определить, что переменная действительно "мертвый", и 3) способность фактически изменять исходный код.
Трудно во всем этом огромная энергия для создания 1) 2) 3). Вы не можете оправдать какую-либо отдельную задачу по очистке. Что можно сделать, так это построить такую инфраструктуру специально с целью окупить его по множеству различных программный анализ и задачи преобразования.
Моя компания предлагает такой инструмент: DMS Software Reengineering Инструментарий. Видеть http://www.semdesigns.com/Products/DMS/DMSToolkit.html У DMS есть интерфейсы качества продукции для многих языков, включая C, C ++, Java и COBOL.
Фактически мы создали автоматизированный "поиск бесполезных объявлений" инструмент для Java, который выполняет две функции: а) перечисляет их все (таким образом получается список!) б) делает копию кода с бесполезными объявлениями удалено. Вы выбираете, какой ответ хотите сохранить: -)
Сделать то же самое для C не составит труда. Мы готовы есть инструмент, который идентифицирует такие мертвые переменные / функции.
Один случай, который мы не упомянули, - это "бесполезный параметр" случае из-за удаления бесполезного параметра у вас есть чтобы найти все вызовы из других модулей, убедитесь, что настройка аргумента не имеет стороны эффект, и вырвите бесполезный аргумент. Фактически у нас есть полные графики всего ПО интересующей системы, и поэтому это также будет возможно.
Так что это просто сложно, и даже не очень сложно. если у вас есть необходимая инфраструктура.
You can solve the problem as a text processing problem. There must be a small number of regexp patterns how unused local variables are defined in the source code.
Using a list of unused variable names and the line numbers where they are, You can process the C source code line-by-line. On each line You can iterate over the variable names. On each variable name You can match the patterns one-by-one. After a successful match You know the syntax of the definition, so You know how to delete the unused variable from it.
For example if the source line is: "int a, unused, b;" and the compiler reported "unused" as an unused variable in that line, than the pattern "/, unused,/" will match and You can replace that substring with a single ",".