如何在大C++中找到所有相互的友谊源树?

发布于 2024-10-06 14:22:11 字数 122 浏览 6 评论 0原文

在一个大型 C++ 源代码树中,定义了大约 600 个左右的类,我想找到所有类对,其中每个类都将另一个类声明为友元。

有很多情况下,一个类是另一个类的朋友,太多了,以至于不值得费力地浏览一个简单的 grep 结果。

In a large C++ source tree, with about 600 or so classes defined, I want to find all pairs of classes where each declares the other a friend.

There are many cases of one class being a friend of another, too many to make it worth wading through a simple grep result.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

你好,陌生人 2024-10-13 14:22:11

你可以在这里实现一种三重循环;算法可以如下:

  1. 第一个循环:找到所有有朋友的班级,并记住朋友的名字和实际班级的名字;
  2. 然后对所有类运行内部循环,并找到一个具有步骤 1 中朋友名称的类。
  3. 然后对步骤 2 中找到的类的所有朋友运行另一个内部循环。如果您找到了具有步骤 1 中名称的类 -瞧——他们是共同的朋友。

我相信 Perl 和正则表达式是处理此类事情的最佳工具。

PS 当然这种方法有其局限性,因为并不是 C++ 中的所有内容都可以用正则表达式进行解析(using namespace 是我首先想到的东西)。但是,在某种程度上,这是可行的方法,如果你没有其他选择,你可以尝试一下。

编辑:
今天早上,当我还躺在床上时,我突然想到了一个想法。 :) 这个想法非常简单明了(就像所有早上的想法一样):使用 SQL!当然,假设您有一个包含 2 列的类表,其中第一列是类名,第二列是它的朋友的名字。比如说:

ClassName FriendName
C1        C2
C1        C3
C1        C4
C2        C1
C2        C8
C3        C1
C3        C2
...       ...

然后您可以对其运行一个简单的查询。比如说,类似这样的事情(抱歉,我手边没有任何 SQL 数据库,所以没有检查查询,但我希望你能明白并根据需要实现它:

SELECT ClassName as c, FriendName as f FROM T
WHERE c in 
  (SELECT FriendName FROM T
     WHERE FriendName = c AND ClassName = f)

这个变体背后的想法是我们应该使用当您需要处理某些数据集时,有什么可以与 SQL 相比呢?

You could implement a kind of triple loop here; the algorithm could be as follows:

  1. First loop: find all classes who have friends, and remember the name of the friend and the name of the actual class;
  2. Then run inner loop for all the classes and find a class with the name of the friend from step 1.
  3. Then run another inner loop through all the friends of the class found at step 2. If you have found class with name from step 1 - voila - they're mutual friends.

I believe Perl and regexes are the best tools for such things.

P.S. sure this approach has its limits, because not everything in C++ could be parsed with regex (using namespace stuff is the first thing came into my mind). But, to some extent, this is working approach, and if you don't have alternatives, you could give it a try.

EDIT:
An idea came to my mind today in the morning, while I still was lying in my bed. :) The idea is quite simple and clear (like all morning ideas): use SQL! Naturally, imagine you have a table of classes with 2 columns, where first column is class name, and second column is it's friend`s name. Say, something like this:

ClassName FriendName
C1        C2
C1        C3
C1        C4
C2        C1
C2        C8
C3        C1
C3        C2
...       ...

Then you can run a simple query against it. Say, something like this (sorry, I don't have any SQL DB handy, so have not checked the query, but I hope you'll got the idea and implement it as needed:

SELECT ClassName as c, FriendName as f FROM T
WHERE c in 
  (SELECT FriendName FROM T
     WHERE FriendName = c AND ClassName = f)

The idea behind this variant is that we should employ those tolls which exactly fit the task. What can compare to SQL when you need to crunch some sets of data?

情徒 2024-10-13 14:22:11

I) 一些优雅的方法:

1) Doxygen ( http://www.doxygen.nl/ ) 可能是能够给你你所需要的。 (如果它还没有提供此信息,您可以稍微修改 Doxygen 的 C++ 解析器以获得您需要的信息)。

2) C++ 也有现有的 ANTLR 语法文件。

II)更快的方法(也许是正确的方法):

正如其他人建议的那样,正则表达式应该适合您的目的。考虑以下伪代码:

rm -f result_file;
foreach source_file
do
  sed 's/[ \t\n]\+/ /g' $source_file >  temp_file;  ## remove newlines, etc
  grep -o -P -i "friend [^;]*;"  >> result_file; ## you can improve this regex for eliminating some possible unwanted matches or post-process result_file later
done

现在您在 result_file 中拥有所有好友关系。您可以使用另一个简单的正则表达式删除“友元函数”和/或根据需要进一步处理 result_file 。

I) Some elegant ways:

1) Doxygen ( http://www.doxygen.nl/ ) might be able to give you what you need. (If it doesn't already give this information, you could hack Doxygen's C++ parser a bit to get what you need).

2) There are also existing ANTLR grammar files for C++ as well.

II) Quicker way (perhaps the right approach here):

Regex should just be fine for your purpose as others suggest. Consider the following pseudo code:

rm -f result_file;
foreach source_file
do
  sed 's/[ \t\n]\+/ /g' $source_file >  temp_file;  ## remove newlines, etc
  grep -o -P -i "friend [^;]*;"  >> result_file; ## you can improve this regex for eliminating some possible unwanted matches or post-process result_file later
done

Now you have all friend relations in result_file. You can remove "friend functions" using another simple regex and/or process the result_file further as per needs.

孤城病女 2024-10-13 14:22:11

这个答案与@user534498的类似,但我将更详细地讨论,因为“用正则表达式解析C++”的建议是如此疯狂,我认为它不值得考虑。

我也不认为您会找到一个可以为您完成此操作的自动化工具。如果这是托管代码领域,我会建议类似 Nitriq 的东西,但我不认为类似适用于 C++。

如果您不担心嵌套类,我认为您可以毫无困难地为朋友构建类的配对。您可以找到关键字 class 的实例,后跟大括号,并在大括号内查找友元语句。这应该不会太困难,给你一个列表,列出哪些班级有哪些朋友。

完成此操作后,您可以轻松检查重复的引用。 (取决于您使用的语言...如果您使用 C++,那么您会将结果放入 std::multimap 中,其中键是类名,值是友元)

我想这与 @Haspemulator 的建议类似......但我的观点是,拆分解析可能会更容易,然后根据集合或映射实现循环引用检查,然后尝试将这些操作交织在一起。

This answer is similar to @user534498's, but I'm going to go into a bit more detail, as the suggestion "parse C++ with regex" is so insane, I don't think it bears consideration.

I also don't think you're going to find an automated tool which can already do this for you. If this were managed code land, I'd be suggesting something like Nitriq, but I don't think anything like that works for C++.

If you're not worried about nested classes, I think you can construct parings of classes to friends without too much difficulty. You can find instances of the keyword class, followed by curly braces, and within the curly braces look for friend statements. That should, without too much difficulty, give you a listing of which classes have which friends.

Once you've done that, you can check for duplicate references easily. (Depends on the language you're using... if you're in C++ then you'd put your results in a std::multimap with the keys being class name and values being the friends)

I suppose this is similar to what @Haspemulator is suggesting ... but my point is that it will probably be easier to split out the parsing, then implement the circular ref checking in terms of sets or maps, then it will be to try to intertwine these operations.

转身以后 2024-10-13 14:22:11

使用perl或python或c++正则表达式解析所有文件,记录所有类友对。对于这 600 对来说,匹配应该是微不足道的

Use perl or python or c++ regex to parse all files, record all class-friends pairs. The matching should be trivial for these kind of 600 pairs

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文