如果.cpp或.h文件有#includes(例如#include“ready.h”),我需要制作一个包含这些文件名的文本文件。由于ready.h可能有自己的#includes,因此必须以递归方式进行调用。不知道怎么做。
答案 0 :(得分: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作为第二个参数,它将在子运行后将所有文件名保存为键:
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
模块要复杂得多,但对平台无关的文件名和路径操作有很好的支持。
答案 1 :(得分: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
另一方面,我只能想到两件需要注意的事情:
my
。sub factorial($)
而不仅仅是sub factorial
),那么你需要在函数定义之前提供原型,以便它可以在功能体。 (或者,当您递归调用函数时,可以使用&
;这将阻止原型的应用。)答案 2 :(得分: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
通常你会想要某种树形图。