我的第一个c++程序
终于写完了我的第一个c++程序,不是gui的,是个控制台程序,功能是我需要的一个实用小转换程序。A单片机的C编译器很好用,但芯片稍贵,B单片机台湾出的,便宜,但C编译器很烂,两种单片机的汇编语言有90%的相似度,这个小程序用于把A单片机的汇编源程序转化成B单片机的语言。这样,就可以用A的C编译器来开发B了。写了半天,数了数才200行左右的程序,离我3000行的目标还有很大差距阿:'(
把程序贴上来,给自己留个纪念,如果哪位老师有闲工夫,也非常欢迎来给俺提些程序的改进意见。
#ifndef INSTRUCTION_H
#define INSTRUCTION_H
#include <string>
class Rule
{
public:
Rule(const std::string& rule);
std::string Name;
std::string Out;
};
class Command
{
public:
Command(const std::string& In);
std::string Label;
std::string InstructName;
std::string u;
std::string v;
std::string Comments;
};
#endif
#include "instruction.h"
#include <string>
using namespace std;
Rule::Rule(const string& rule)
{
size_tPos1, Pos2, Pos3;
Pos1 = rule.find('=');
Pos2 = rule.find_first_not_of(" \t",Pos1+1);
if (Pos2 != string::npos)
{
Out = rule.substr(Pos2);
}
else
{
Out.clear();
}
Pos2 = rule.find_first_not_of(" \t");
Pos3 = rule.find_first_of(" \t",Pos2+1);
if (Pos2 < Pos1)
{
Name = rule.substr(Pos2,Pos3 >= Pos1 ? Pos1-Pos2 : Pos3-Pos2);
}
else
{
Name.clear();
}
}
Command::Command(const string& In)
{
string Line;
int Pos, Pos1;
Line = In;
Pos = Line.find(';');
if (Pos != string::npos) // if there are comments
{
Comments = Line.substr(Pos);
Line.erase(Pos); // get and erase comments from string
}
else // there's no comment
{
Comments.clear();
}
v.clear();
Pos = Line.find(',');
if(Pos != string::npos) // if there's parameter
{
v = Line.substr(Pos+1);
Line.erase(Pos);
}
u.clear();
InstructName.clear();
Label.clear();
Pos = 0;
if ((Line != ' ') && (Line != '\t')) // if there's Label
{
Pos = Line.find_first_of(" \t");
Label = Line.substr(0,Pos);
}
Pos1 = Line.find_first_not_of(" \t",Pos);
if (Pos1 != string::npos) // if there's command name
{
Pos = Line.find_first_of(" \t",Pos1);
if (Pos != string::npos)
{
InstructName = Line.substr(Pos1, Pos-Pos1); // what if Pos=npos??
}
else
{
InstructName = Line.substr(Pos1);
}
Line.erase(0,Pos);
if (!Line.empty())
{
Pos = Line.find_first_not_of(" \t");
if (Pos != string::npos)
{
u = Line.substr(Pos); // remove label and name, left is
}
}
}
}
#include "instruction.h"
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
ifstream fin, PIC_asm;
ofstream fout;
string line, out;
vector<Rule> Table;
size_t Pos;
Command* Source;
if (argc < 2)
{
cout << "usage: convert source.as" << endl << "Please provide source file name." << endl;
return(0);
}
fin.open(argv);
fin.close();
if (fin.fail())
{
cout << argv << " does not exist, please check again!" << endl;
return(0);
}
fin.open("rules.txt");
fin.close();
if (fin.fail())
{
cout << "rules.txt not exist" << endl;
return (0);
}
fin.open("rules.txt");
int i=0;
while (getline(fin, line))
{
cout << line << endl;
if (line.find('=') != string::npos)
{
Table.push_back(Rule(line));
}
}
fin.close();
string OutfileName(argv);
Pos = OutfileName.rfind('.');
OutfileName = OutfileName.substr(0, Pos)+".dt";
fin.open(OutfileName.c_str());
fin.close();
if (!fin.fail())
{
cout << OutfileName << " exists, do you want to overwrite? ";
while (1)
{
cin >> line;
if ((line == "y") || (line == "yes") || (line == "Y") || (line == "YES"))
{
break;
}
else if ((line == "N") || (line == "n"))
{
return (0);
}
}
}
fout.open(OutfileName.c_str());
if (fout.fail())
{
cout << "Error openning " << OutfileName << " !" << endl;
fout.close();
return (0);
}
fin.open(argv);
fin.seekg(0);
cout << "\nSource file :" << endl;
while (getline(fin,line))
{
cout << line << endl;
}
fin.seekg(0);
// cout << endl << endl << endl << "The source file:" << endl;
fin.close();
PIC_asm.open(argv);
while (getline(PIC_asm,line))
{
// cout << line << " CONVERT TO " ;
if (!line.empty() && (line.find_first_not_of(" \t") != string::npos))
{
Source = new Command(line);
int i;
size_t Pos1;
for (i=0; i<Table.size(); i++)
{
if(Table.Name == Source->InstructName)
{
break;
}
}
if (i == Table.size())
{
out = "; " + Table.Out + " : " + Source->InstructName;
}
else
{
out = Table.Out;
}
if (!out.empty())
{
Pos1 = out.find("");
if (Pos1 != string::npos)
{
out = out.replace(Pos1,3,Source->u);
}
Pos1 = out.find("");
if (Pos1 != string::npos)
{
out = out.replace(Pos1,3,Source->v);
}
}
fout << Source->Label << '\t' << out << '\t' << Source->Comments;
fout << endl;
delete Source;
}
else
{
cout << line << endl;
}
}
PIC_asm.close();
fout.close();
cout << "*** Conversion completed. File \"" << OutfileName << "\" is created." << endl;
return (0);
}
; ### PIC to EMC asm converting rules
bsf , = BS ,
bcf , = BC ,
movlw = MOV A,@
=
= Unknown Command
test.dt exists, do you want to overwrite? y
Source file :
bsf ads,2
bcf 5,6 ; hello
movlw 0x38
; test line
movfw 3,b
Loop: movlw 25
*** Conversion completed. File "test.dt" is created.
jian@jian-laptop:~/codes/convert$ cat test.dt
BS ads,2
BC 5,6 ; hello
MOV A,@0x38
; test line
; Unknown Command : movfw
Loop: MOV A,@25
jian@jian-laptop:~/codes/convert$
不错,很干净,很整齐。
回复 #1 四香油饼 的帖子
程序写得相当工整,赞一下:good :good一点小建议:
1.可以把“using namespace std;”放到instruction.h里面,这样在instrction.h里面就可以不用引用“std::"了。
2.如果有比较的时候,可以把变量写在后面,常量写在前面,避免变量被误赋值(这种bug如果发生了,不好找),比如: if ((line == "y") || (line == "yes") || (line == "Y") || (line == "YES"))建议改为: if (("y" ==line) || ("yes"==line) || ("Y"==line) || ("YES"==line))3.如果在FreeOZ帖代码,建议用code标签而不是quote标签,这样可以避免代码被转为其它符号:【code】 your code 【/code】(把【】改为[])
1.可以把“using namespace std;”放到instruction.h里面,这样在instrction.h里面就可以不用引用“std::"了。
好像记得有本书讲不要在header里放using namespace。 是不是把Rule和Command放在两个文件的好点?
而且,好像两个类的成员都是只读的?是不是应该把他们都搞成private然后用个 const的getter 函数?如果要写,就加个setter, 不过偷懒的时候就都是public. 呵呵,我只是积极举手问答, 等评语吧。 原帖由 GPS 于 8-2-2010 14:08 发表 http://freeoz.org/bbs/images/common/back.gif
好像记得有本书讲不要在header里放using namespace。
有书这样说 类的成员变量,无特殊需要,一律要私有。
类的成员函数,只有自身调用的,私有。
类的成员的名称,一律小写,并且私有、保护的要和公开的有区别。
一个类,放在一个file里面。
尽量避免使用:
using namespace std
这样的声明,让code更清晰。
还有很多,慢慢来吧。 原帖由 GPS 于 8-2-2010 14:22 发表 http://freeoz.org/bbs/images/common/back.gif
是不是把Rule和Command放在两个文件的好点?
而且,好像两个类的成员都是只读的?是不是应该把他们都搞成private然后用个 const的getter 函数?如果要写,就加个setter, 不过偷懒的时候就都是public. 呵呵,我只是 ...
时髦的用visitor 本帖最后由 coolmate 于 12-9-2016 00:59 编辑
这是我的一个小文件的定义文件,你可以看一下。#ifndef HELP_H
#define HELP_H
#include <string>
namespace a {
namespace b{
class help
{
public:
~help(); //Desctructor
help(std::string class_name, std::string command = ""); //Constructor
help(); //Empty constructor
std::string result(); //Get the search result
std::string get_classrange(); //Get class name to search
const void set_classrange(const std::string range); //Set the class to be searched
const void set_searchitem(const std::string item); //Set the item name to be searched
void search(); //Actual search function
bool is_success(); //show whether the search is successful
private:
bool success_; //Indicator of success
std::string class_range_; //Class name in which the command to be searched
std::string search_item_;
std::string result_; //Command to be searched
};
} } //namespace a::b::help
#endif //HELP_H 原帖由 关毅仁 于 8-2-2010 00:32 发表 http://www.freeoz.org/bbs/images/common/back.gif
不错,很干净,很整齐。
大师是按照风水的原则看的么?:P :P :P 看程序后,发现C++都几乎忘光了:'( 原帖由 coolmate 于 8-2-2010 14:35 发表 http://www.freeoz.org/bbs/images/common/back.gif
这是我的一个小文件的定义文件,你可以看一下。#ifndef NICTA_SISM_HELP_H
#define NICTA_SISM_HELP_H
#include
namespace nicta {
namespace sism {
class help
{
public:
...
是不是用const函数好点阿?
std::string result() const;
std::string get_classrange() const;
用get_result, get_classrange, 或者result, classrange应该更一致点.
[ 本帖最后由 GPS 于 8-2-2010 15:19 编辑 ] 原帖由 GPS 于 8-2-2010 15:17 发表 http://www.freeoz.org/bbs/images/common/back.gif
是不是用const函数好点阿?
std::string result() const;
std::string get_classrange() const;
用get_result, get_classrange, 或者result, classrange应该更一致点.
你说的对。这就改。至于const的,这一点我到现在也没真正弄清楚它的真正优点。我们这里有一个c++委员会的member,我是他教出来的。很多时候还是不能完全满足他的要求,即使是code的风格上。呵呵 原帖由 coolmate 于 8-2-2010 15:47 发表 http://www.freeoz.org/bbs/images/common/back.gif
我们这里有一个c++委员会的member,我是他教出来的。
哇,你真幸福阿,呵呵。能不能把你们的coding规范还有培训教材什么的共享一下阿?呵呵。 原帖由 GPS 于 8-2-2010 16:22 发表 http://www.freeoz.org/bbs/images/common/back.gif
哇,你真幸福阿,呵呵。能不能把你们的coding规范还有培训教材什么的共享一下阿?呵呵。
呵呵,是很幸福。那家伙太NB,以至于很多地方不敢用他,因为他的code用起来很简单,理解起来很难,人家怕他走了,再也没有人能接过去干。所有的code全都是模板封装的。
至于规范和材料,那是严禁泄露的。呵呵,对不起哦。
回复 #15 coolmate 的帖子
太幸福了。。。。羡慕 原帖由 coolmate 于 8-2-2010 14:34 发表 http://www.freeoz.org/bbs/images/common/back.gif类的成员变量,无特殊需要,一律要私有。
类的成员函数,只有自身调用的,私有。
类的成员的名称,一律小写,并且私有、保护的要和公开的有区别。
一个类,放在一个file里面。
尽量避免使用:
using namespace...
我这个小破程序引来这么多高人,真高兴,大家以后要多指点阿。
这位达人,俺有几个地方不太清楚,再请教一下:
1。关于变量的命名,一直比较糊涂,看过的程序也有很多种不同的风格,能不能讲讲你们的变量命名规则?这个应该不是保密的范围吧,我没经过系统学习,所以很多基本的东西都不清楚,大致讲讲吧。
2。这个一个类放在一个文件里,如果是base和derived类呢?也分开放吗?
3。对于namespace,一直感到比较深奥,在什么情况下要自己定义namespace呢?像你的程序里面写的,把这个help这个类放在了nicta这个namespace里面,有什么好处呢?那以后程序里面除了include "nicta_sism_help.h" 以外,如果要使用这个类不是还得写nicta::sism::,作用是什么呢?
另外还有一个问题,不是关于coolmate的程序的,是一般编程的问题,如果有一组没规律的数,现在想检验另外一个数是否与这组数中的一个相等,一定要用循环的办法全部比较一遍吗?有没有什么好的办法??
看coolmate高人写程序这么严谨,应该不是搞应用开发的,能大概透露一下一门公司干啥的么?让我仰慕一下。:lol 原帖由 coolmate 于 8-2-2010 16:32 发表 http://www.freeoz.org/bbs/images/common/back.gif
呵呵,是很幸福。那家伙太NB,以至于很多地方不敢用他,因为他的code用起来很简单,理解起来很难,人家怕他走了,再也没有人能接过去干。所有的code全都是模板封装的。
至于规范和材料,那是严禁泄露的。呵呵 ...
别人看不懂的程序有两种,一种是太牛了,一种是太烂了。俺的程序别人理解起来也很困难,不过俺是后一种的
回复 #17 四香油饼 的帖子
另外还有一个问题,不是关于coolmate的程序的,是一般编程的问题,如果有一组没规律的数,现在想检验另外一个数是否与这组数中的一个相等,一定要用循环的办法全部比较一遍吗?有没有什么好的办法??
如果数比较少的话,用循环可能是最简单的办法,如果比较多,循环一边效率低的话,可以用hash表来快速查找。 原帖由 GPS 于 8-2-2010 14:08 发表 http://www.freeoz.org/bbs/images/common/back.gif
好像记得有本书讲不要在header里放using namespace。
在网上搜了一下,这个说法比较有道理,摘录过来:
http://topic.csdn.net/u/20080327/13/dfea9d61-fd59-47c5-b3a5-293f357419e7.html (9楼)
头文件会被很多文件include,这里std空间里的名字全进入了全局名字空间. 造成名字污染!
如果在外面把std using使std进入全局名字空间,那C++为什么还要把标准库的名字放在std?
<thinking in c++> 强烈建议不能在header文件中using namespace std; <C++必知必会>认为在header file中using namespace std"是个馊主义...基本上又退回到了原点."
我查C++primer,但没有找到好的方法.
using std::string;
using std::map;
....
这样做了.敲字母都敲到手痛.
回复 #17 四香油饼 的帖子
变量命名风格,我个人觉得同一个项目中只要采用一套一致变量命名风格即可,当然如果所有的项目都采用同样的命名风格更好。还是从网上搜到的一些相关文章,大家一起讨论分享一下:
《Google C++ Style Guide》: http://www.cppblog.com/Fox/archive/2008/07/22/56845.html
《你如何命名变量?是否推荐匈牙利命名法? by C++之父》:http://stdcpp.cn/html/24/26/0709/313.htm
(原文在:http://www2.research.att.com/~bs/bs_faq2.html#Hungarian,这里还有不少关于c++方面的建议) 原帖由 ubuntuhk 于 8-2-2010 20:17 发表 http://www.freeoz.org/bbs/images/common/back.gif
如果数比较少的话,用循环可能是最简单的办法,如果比较多,循环一边效率低的话,可以用hash表来快速查找。
我很赞同。呵呵。没有分了。。
回复 #15 coolmate 的帖子
太幸福了。。。。羡慕(有分加吗?):yct_32 太幸福了。。。。羡慕
呵呵。没有分了。。
[ 本帖最后由 coolmate 于 8-2-2010 20:49 编辑 ] 原帖由 四香油饼 于 8-2-2010 15:50 发表 http://www.freeoz.org/bbs/images/common/back.gif
我这个小破程序引来这么多高人,真高兴,大家以后要多指点阿。
这位达人,俺有几个地方不太清楚,再请教一下:
1。关于变量的命名,一直比较糊涂,看过的程序也有很多种不同的风格,能不能讲讲你们的变量命名 ...
2. 分开放会比较容易管理,derived类可能有n个,写在一个head里面不便于协同合作。其实这些都是习惯,我一直没有荣幸接触真正了解c++标准的,所以我的风格相当飘逸~~~:loveliness: :loveliness:
菜鸟见了都会笑 本帖最后由 coolmate 于 12-9-2016 01:01 编辑
原帖由 四香油饼 于 8-2-2010 18:50 发表 http://www.freeoz.org/bbs/images/common/back.gif
我这个小破程序引来这么多高人,真高兴,大家以后要多指点阿。
这位达人,俺有几个地方不太清楚,再请教一下:
1。关于变量的命名,一直比较糊涂,看过的程序也有很多种不同的风格,能不能讲讲你们的变量命名 ...
简单说说:
1。变量命名:一律用小写字母,如果有多个section,用下划线链接,如果是保护乘员和私有成员,用下划线结尾。包括函数名。
2。base类自然是一个文件,但是如果这个基类只是一个非常简单的东西,而且你确定没有其他派生类,可以同派生类放在一起。但是这样的话,也就失去了基类存在的意义
3。对于小程序,使用namespace没有什么显著的好处,但在大型开发里面,坚定、清晰并一致地使用namespace,可以极大地是程序清晰可读。尤其是在你有多个类并有多个同样或者类似的函数名称的时候。n_a::n_b::n_c1::foo() will tell it clearly from n_a::n_c::n_d::foo()。这样做,虽然增加了键入时的麻烦,但是习惯了之后,你会觉得非常方便。
呵呵,确实,我现在做的不是一般的应用,而是贴近于research的东西,不过从另一方面说,是一个parser和开发环境的融合体。至于实用价值,不知道。
我的分分呢?为什么不能加分啊。。。 我记得以前Windows下编程都遵循匈牙利命名法,可能是因为M$的SDK都是用的这种命名法吧。 后来皈依Linux之后,就都是小写字母加下划线了。 原帖由 coolmate 于 8-2-2010 14:35 发表 http://www.freeoz.org/bbs/images/common/back.gif
这是我的一个小文件的定义文件,你可以看一下。#ifndef NICTA_SISM_HELP_H
#define NICTA_SISM_HELP_H
#include
namespace nicta {
namespace sism {
class help
{
public:
...
这段代码挺干净的,就是这点比较奇怪:
const void set_classrange(const std::string range); //Set the class to be searched
const void set_searchitem(const std::string item); //Set the item name to be searched
前面的const void干嘛的? 一般如果method不修改class成员,应该用const做后缀说明,如果返回的是引用,但是又不想被修改,用const T&, 如果是RBV (return by value),就啥都不用修饰。可是你这里,返回是void,我第一次看到特意弄个const void的,能不能说明下用意? 原帖由 fred_au 于 9-2-2010 00:22 发表 http://www.freeoz.org/bbs/images/common/back.gif
我记得以前Windows下编程都遵循匈牙利命名法,可能是因为M$的SDK都是用的这种命名法吧。 后来皈依Linux之后,就都是小写字母加下划线了。
匈牙利命名法其实是一个很受争议的方法,即使在windows下也不是每个人都喜欢的。