我正在开发一个程序,它会加载自己的.cpp文件并找到一些指定的关键字。问题是,如果字符串更长,我不知道如何识别字符串中的单词。 具体的例子: 我们正在寻找一个int,但如果有写的函数会怎么样:
int main(int argc, char* argv[])
?如果我把它作为一个字符串加载,它将是s1 =“int”,s2 =“main(int”等等,但是当我比较keywordInt =“int”和s2 =“main(int”,它们是不一样。我尝试了string :: find函数,但是,有人可以写一个代码“int countSheep(int,int)”,然后再找到一个int。
你能帮助我吗?
更新:嗯,我感觉非常愚蠢,但请...我有点找不到或理解那些词法分析器/解析器/语法荧光笔...而且我甚至不知道该找什么。我试图找到一些人来做的工作 - 将字符串标记并识别它是什么类型,但我仍然失败。你能再给我一个带头吗?
答案 0 :(得分:3)
解析(任何)编程语言语法与“匹配单词”非常不同,但实际上在您的代码中找到您所寻找的信息是必要的:
int internalClass::interestingFunc(int arg1,
internalClass::typeId intId, unsigned int b); // int fun arg, intId unused
在此说明中,语言关键字 int
出现三次,子串int
出现九次,空格分隔的单词int
你找到两次,空格/括号/逗号分隔的单词int
你会发现四次。
所有这些必须要区分,而这不是通过简单的字符串拆分发生的。需要一个能够理解C / C ++结构的源代码解析器。
以下stackoverflow条目提供了一些线索:https://stackoverflow.com/questions/2318347
答案 1 :(得分:2)
您可以将起始索引作为可选的第二个参数传递给string::find
。
// Counts the number of occurrences of `keyword` in `str`.
static size_t
count_keyword (const std::string& str,
const std::string& keyword)
{
size_t pos = 0, count = 0;
const size_t search_len = keyword.length();
pos = str.find (keyword, pos);
while (pos != std::string::npos)
{
++count;
pos = str.find (keyword, pos + search_len);
}
return count;
}
// test
int
main (int argc, char** argv)
{
std::cout << count_keyword (argv[1], argv[2]) << '\n';
return 0;
}
$ ./test "int main(int, char**)" int
=> 2
$ ./test "int main(int, char**)" char
=> 1
$ ./test "int countSheep(int,int)" int
=> 3
答案 2 :(得分:0)
来自示例here:
find()
可以选择一个可选的位置参数。因此,最好的办法就是在给定行的循环中调用find()
,直到找不到该关键字为止。
答案 3 :(得分:0)
如果遇到“(”,“)”或“,”则拆分字符串。 您可以在比较期间执行此操作:如果找到不需要的字符,请拆分字符串并将其添加到列表的后面。
答案 4 :(得分:0)
你可以在这里使用一个简单的正则表达式(\ w +)+,你就得到了一个id列表。
#define BOOST_REGEX_MATCH_EXTRA
#include <boost/regex.hpp>
#include <string>
#include <iostream>
int main()
{
const boost::regex ids("(("
"(int|long|void)" // id to search
"|(\\w+)" // any other id
"|(\\W+)" // nonword
"+)+)");
std::string line = "int main(long p_var, int p_v2)";
std::map<std::string, int> wordsCount;
boost::smatch result;
if (boost::regex_search(line, result, ids, boost::match_extra))
{
// for (unsigned i = 1; i < result.size(); i++)
{
// std::cout << "i: " << i << ", res=" << result[i] << "|" << std::endl;
for(unsigned j = 0; j < result.captures(3).size(); ++j)
{
std::cout << "Num:" << j << ", res=" << result.captures(3)[j] << "|" << std::endl;
wordsCount[result.captures(3)[j]]++;
}
}
}
for (std::map<std::string, int>::const_iterator it = wordsCount.begin(); it != wordsCount.end(); ++it)
» std::cout << "Number of '" << it->first << "' : " << it->second << std::endl;
}
将打印
Num:0, res=int|
Num:1, res=long|
Num:2, res=int|
Number of 'int' : 2
Number of 'long' : 1
答案 5 :(得分:0)
正如Muxecoid在评论中所说,这实际上取决于你是否希望计算任何单词的出现或者想要在“纯粹的代码”中限制自己(通过反对评论或字符串文字)。
int main(int argc, char* argv[])
{
// int argc: the number of arguments
// ^^^ ?
std::string integration = "integration of int: " + argv[1];
// ^^^ ?
}
还有\
的问题。一行\
:
std::string mySoLong\
Identifier = "";
如果您想查看任何出现次数:
\
find
如果你想“更聪明”,那么你需要解析实际的C ++代码。你也不需要一个完整的解析器。只是可以跳过注释和字符串文字的东西就足够了,所以无论你是尝试使用现有的解析器还是自己编写代码,都可以选择。
可能还有一些通用的解析器可以被教导识别注释和字符串文字,并且足以完成你的任务,Notepad ++使用这样的解析器进行着色。
答案 6 :(得分:0)
#include <cctype>
#include <iostream>
#include <set>
int main()
{
std::set<std::string> keywords;
keywords.insert("int");
keywords.insert("double");
keywords.insert("while");
keywords.insert("if");
keywords.insert("else");
// add the rest...
int num_keywords = 0;
std::string input;
if (getline(std::cin, input, '\0'))
{
for (int i = 0; i < input.size(); ++i)
{
char c = input[i];
if (isalpha(c) || c == '_')
{
// entering identifier...
int from = i;
while (++i < input.size() &&
(isalnum(c = input[i]) || c == '_'))
;
// std::cout << "? " << input.substr(from, i - from) << '\n';
if (keywords.find(input.substr(from, i - from)) != keywords.end())
++num_keywords;
}
else if (c == '"' || c == '\'')
{
// skip over string and character literals
while (++i < input.size() &&
input[i] != c)
if (input[i] == '\\')
++i;
}
else if (c == '/' && (i + 1 < input.size()) && input[i+1] == '/')
while (++i < input.size() && input[i] != '\n')
;
// TODO: add case for /* too...
}
}
std::cout << num_keywords << '\n';
}
答案 7 :(得分:0)
这里的麻烦是你没有对你想要阅读的内容有一个很好的定义。
在这种情况下,我会定义一个代表标识符的类 然后定义运算符&gt;&gt;准确读入一个标识符并删除所有其他字符。然后你可以在常规算法中使用它:
#include <istream>
#include <string>
#include <map>
#include <algorithm>
#include <iostream>
class Ident
{
public:
// If used where a std::string is needed
// the object auto converts itself into a string
// very usful.
operator std::string const&() const { return data;}
private:
// The identifer is just a string.
// That is read by the appropriate operator >>
friend std::istream& operator>>(std::istream& str, Ident& dest);
std::string data;
};
std::istream& operator>>(std::istream& str, Ident& dest)
{
char x;
//
// Ignore any input characters that are not identifier.
for(x = str.get(); !::isalnum(x); x= str.get())
{
if (!str)
return str; // If we reach EOF exit
}
// We have the first letter.
// Reset the identifier. Then loop to append
dest.data = "";
do
{
dest.data += x;
x = str.get();
}
while(str && ::isalnum(x));
// done
return str;
}
int main()
{
std::map<std::string,int> count;
// Use Ident just like you would a std::string
// But because we have defined a special operator >>
// it will enter the loop only after each identifier it reads.
Ident word;
while(std::cin >> word)
{
count[word]++;
}
// Quick loop to print the results and show it worked correctly.
for(std::map<std::string,int>::iterator loop = count.begin(); loop != count.end(); ++loop)
{
std::cout << loop->first << " = " << loop->second << "\n";
}
}