patterncppMajor
Creating .cpp, .c, .h. and .java file templates
Viewed 0 times
filecreatingcppjavatemplatesand
Problem
This code builds template .cpp, .c, .h and .java files based on a file name and #include, import lines provided at the command line. The file opens after creation.
I am looking for a review of this code and seeing if there is anything that can be more efficient.
```
/* .cpp Example:
* template awesome.cpp iostream vector string
* Output:
*
* #include
* #include
* #include
*
* using namespace std;
*
int main(int argc, char argv[])
* {
*
* return 0;
* }
*
* .c Example:
* template something.c stdio.h
* Output:
*
* #include
*
int main(int argc, char argv[])
* {
*
* return 0;
* }
*
*
* .h Example:
* template awesome.h vector string
*
* Output:
*
* #ifndef TEST_H
* #def TEST_H
*
*
* #include
* #include
*
*
* #endif // TEST_H
*
*
*
*
* .java Example:
template something.java util. math.*
*
* Output:
*
import java.util.;
import java.math.;
*
* public class something {
*
* public static void main(String[] args) {
*
*
*
*
* }
* }
*
***/
#include
#include
#include
#include
#include
using namespace std;
// helper functions
string getFileType(string & filename);
void addImportAndIncludeLines(vector & linesOfFile,
string & fileType, char * dependency);
void buildFile(vector & linesOfFile, string & fileType);
void buildCOrCPlusPlusFile(vector & linesOfFile, string & fileType);
void buildHeaderFile(vector & linesOfFile, string & filename);
void buildJavaFile(vector & linesOfFile, string & filename);
void writeToFile(vector & linesOfFile, string & filename) throw(string);
void addHeaderFileDeclaration(vector & linesOfFile, string & filename);
void capitalizeHeaderFileName(string & filename);
/***
* main - handles the command line arguments and builds
* the template file, then opens it.
I am looking for a review of this code and seeing if there is anything that can be more efficient.
```
/* .cpp Example:
* template awesome.cpp iostream vector string
* Output:
*
* #include
* #include
* #include
*
* using namespace std;
*
int main(int argc, char argv[])
* {
*
* return 0;
* }
*
* .c Example:
* template something.c stdio.h
* Output:
*
* #include
*
int main(int argc, char argv[])
* {
*
* return 0;
* }
*
*
* .h Example:
* template awesome.h vector string
*
* Output:
*
* #ifndef TEST_H
* #def TEST_H
*
*
* #include
* #include
*
*
* #endif // TEST_H
*
*
*
*
* .java Example:
template something.java util. math.*
*
* Output:
*
import java.util.;
import java.math.;
*
* public class something {
*
* public static void main(String[] args) {
*
*
*
*
* }
* }
*
***/
#include
#include
#include
#include
#include
using namespace std;
// helper functions
string getFileType(string & filename);
void addImportAndIncludeLines(vector & linesOfFile,
string & fileType, char * dependency);
void buildFile(vector & linesOfFile, string & fileType);
void buildCOrCPlusPlusFile(vector & linesOfFile, string & fileType);
void buildHeaderFile(vector & linesOfFile, string & filename);
void buildJavaFile(vector & linesOfFile, string & filename);
void writeToFile(vector & linesOfFile, string & filename) throw(string);
void addHeaderFileDeclaration(vector & linesOfFile, string & filename);
void capitalizeHeaderFileName(string & filename);
/***
* main - handles the command line arguments and builds
* the template file, then opens it.
Solution
-
Do not use
-
Consider not using prototypes (which requires you to maintain the same function header in two places) unless necessary. This means putting
-
Comments such as
-
Reverse the sense of the
Do not use
using namespace std;, instead explicitly use std:: where required. [Why is “using namespace std;” considered bad practice?]-
Consider not using prototypes (which requires you to maintain the same function header in two places) unless necessary. This means putting
main() at the bottom of your code and functions that it uses above it.-
Comments such as
// declare variables add little value.-
Reverse the sense of the
if (argc > 1) test and check if (argc
-
Use fileType == "h" instead of strcmp. In general, avoid use of the str* library functions when using std::string.
-
Always always always put braces around blocks, even if the block is one statement. Otherwise, you'll get errors like Apple's goto fail bug.
-
In getFileType(), what happens if there is no . in the filename?
-
In addHeaderFileDeclaration(), also consider the possible missing ..
-
If filename contains more than one ., then the include guard will have a syntax error (since . is not permitted).
-
#def should be #define.
-
You should decide whether linesOfFile contains lines with or without a newline. In some places you do linesOfFile.push_back("\n") which will add two blank lines (perhaps you meant to do linesOfFile.push_back("")?)
-
capitalizeHeaderFileName modifies its parameter. It would be better to take a const string & parameter and modify a temporary value within the function, and return that.
-
Anywhere you take a string & parameter and don't modify it within the function, you should use const string &. For example the fileType parameter of addImportAndIncludeLines.
-
Switching on the last character of the filename works for your current set of files, but will fail as soon as you get a conflicting last character (eg. .scala files would confict with .java). Use the full file extension when you need to make a decision based on file type.
-
Only allowing import from the java.* namespace seems like an unnecessary limitation.
-
In buildFile(), you are missing a break; in the case 'a'. It's true that it's not required there, but it's a bug just waiting to happen.
-
In buildHeaderFile, you are computing the name of the include guard again, when you already did the same logic in addHeaderFileDeclaration. Consider unifying this somehow so you only have to compute it once.
-
Do not throw a string! Use a proper exception class if you decide to use exceptions.
-
Use an iterator to write out the lines of the file in writeToFile. In fact, you could use std::copy() and avoid the loop entirely.
-
Consider using the ofstream constructor that takes a file name, instead of using a separate call to open.
-
Don't use filename.c_str() because ofstream has an overload that takes a string.
-
The ofstream destructor will automatically close the output file so you don't have to explicitly call output.close()`.Context
StackExchange Code Review Q#54339, answer score: 25
Revisions (0)
No revisions yet.