如果.cpp 或.h 文件有#includes(例如#include "ready.h"),我需要制作一个包含这些文件名的文本文件。由于 ready.h 可能有自己的#include,因此必须递归调用。不知道该怎么做。
问问题
242 次
3 回答
2
@OneSolitaryNoob 的解决方案可能会正常工作,但有一个问题:对于每次递归,它都会启动另一个进程,这非常浪费。我们可以使用子程序更有效地做到这一点。假设所有头文件都在工作目录中:
sub collect_recursive_includes {
# Unpack parameter from subroutine
my ($filename, $seen) = @_;
# Open the file to lexically scoped filehandle
# In your script, you'll probably have to transform $filename to correct path
open my $fh, "<", $filename or do {
# On failure: Print a warning, and return. I.e. go on with next include
warn "Can't open $filename: $!";
return;
};
# Loop through each line, recursing as needed
LINE: while(<$fh>) {
if (/^\s*#include\s+"([^"]+)"/) {
my $include = $1;
# you should probably normalize $include before testing if you've seen it
next LINE if $seen->{$include}; # skip seen includes
$seen->{$include} = 1;
collect_recursive_includes($include, $seen);
}
}
}
这个子例程记住它已经看过的文件,并避免在那里再次递归——每个文件只被访问一次。
在顶层,您需要提供一个 hashref 作为第二个参数,它将在 sub 运行后将所有文件名作为键保存:
my %seen = ( $start_filename => 1 );
collect_recursive_includes($start_filename, \%seen);
my @files = sort keys %seen;
# output @files, e.g. print "$_\n" for @files;
我在代码注释中暗示您可能必须规范化文件名。例如,考虑一个起始文件名./foo/bar/baz.h
,它指向qux.h
. 那么我们不想递归到的实际文件名是./foo/bar/qux.h
,而不是./qux.h
. 该Cwd
模块可以帮助您找到您当前的位置,并将相对路径转换为绝对路径。该File::Spec
模块要复杂得多,但对独立于平台的文件名和路径操作有很好的支持。
于 2013-04-29T04:50:52.417 回答
0
在 Perl 中,递归很简单:
sub factorial
{
my $n = shift;
if($n <= 1)
{ return 1; }
else
{ return $n * factorial($n - 1); }
}
print factorial 7; # prints 7 * 6 * 5 * 4 * 3 * 2 * 1
顺便说一句,我只能想到两件事需要注意:
- 在 Perl 中,变量默认是全局的,因此默认是静态的。由于您不希望一个函数调用的变量践踏另一个函数调用的变量,因此您需要确保本地化您的变量,例如使用
my
. - 原型和递归存在一些限制。如果你想使用原型(例如
sub factorial($)
,而不是justsub factorial
),那么你需要在函数定义之前提供原型,以便它可以在函数体内使用。(或者,您可以&
在递归调用函数时使用;这将阻止应用原型。)
于 2013-04-29T01:18:49.250 回答
0
不完全清楚你希望显示的样子,但基本的将是一个名为 follow_includes.pl 的脚本:
#!/usr/bin/perl -w
while(<>) {
if(/\#include "(\S+)\"/) {
print STDOUT $1 . "\n";
system("./follow_includes.pl $1");
}
}
像这样运行它:
% follow_includes.pl somefile.cpp
如果你想隐藏任何重复的包含,运行它:
% follow_includes.pl somefile.cpp | sort -u
通常,您希望在某种树形打印中使用它。
于 2013-04-29T01:22:02.593 回答