testInputNg.cpp 6.13 KB
 Alvarez, Gonzalo committed Oct 03, 2020 1 2 3 4 5 6 7 /* PSIDOC InputNg_Intro \section{Lesson I: InputNg} In this lesson we'll learn how to read a properly formatted input file. This way when you write your own C++ programs you'll have an already available way to read parameters from an input file and use them in your program.  Alvarez, Gonzalo committed Oct 03, 2020 8   Alvarez, Gonzalo committed Oct 03, 2020 9  You can go ahead an compile this example with  Alvarez, Gonzalo committed Oct 03, 2020 10 \begin{tiny}  Alvarez, Gonzalo committed Oct 03, 2020 11 \begin{verbatim}  Alvarez, Gonzalo committed Oct 04, 2020 12 g++ testInputNg.cpp -std=c++11 -Wall -I ../src/ -I.. -DUSE_BOOST -L ../lib -lpsimaglite -o testInputNg  Alvarez, Gonzalo committed Oct 03, 2020 13 \end{verbatim}  Alvarez, Gonzalo committed Oct 03, 2020 14 \end{tiny}  Alvarez, Gonzalo committed Oct 03, 2020 15 Note that you need boost-dev or boost-devel and also you  Alvarez, Gonzalo committed Oct 03, 2020 16 must have lib/libsimaglite.a already compiled.  Alvarez, Gonzalo committed Oct 03, 2020 17 18 19 20 21 22 23 24 25 26 27 28 29 You can already go ahead an run it with the provided simple input \begin{verbatim} ./testInputNg testInput.ain \end{verbatim} What does this program do? It reads two or three labels'' from testInput.ain and prints some of them to the terminal. The labels have the form \texttt{label=value}, and we have a scalar, a vector, and a string as examples. So, now let's discuss the short program we have here. First, note that we need two includes from PsimagLite. PsimagLite files are usually under src, but in some cases subdirectories are used. Here are the includes.  Alvarez, Gonzalo committed Oct 03, 2020 30 \begin{lstlisting}  Alvarez, Gonzalo committed Oct 04, 2020 31 PSIDOC_CONTINUE  Alvarez, Gonzalo committed Oct 03, 2020 32 33 */  Alvarez, Gonzalo committed Oct 03, 2020 34 35 36 #include "InputNg.h" #include "InputCheckBase.h"  Alvarez, Gonzalo committed Oct 04, 2020 37 /* PSIDOC_RESUME  Alvarez, Gonzalo committed Oct 04, 2020 38 39 \end{lstlisting} InputNg has an option to check the inputs, so that  Alvarez, Gonzalo committed Oct 03, 2020 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60  you can define the labels that you expect to find in your program. This is optional but recommended. For this we create a class, say \texttt{MyInputCheck}, and derive it from PsimagLite's \texttt{InputCheckBase}. This inheritance isn't needed, but save us from having to provide all functions, as the base class implements defaults. For a more realistic use case you can check DMRG++'s InputCheck.h under dmrgpp/src/Engine. For now, here's our short input checking class. \begin{lstlisting} PSIDOCCOPY InputNg_Class_MyInputCheck \end{lstlisting} In our example, we are defining a scalar called myscalar, a vector called myvector, and a string called mystring. This is what we expect to read from the input file, even though the writer of the input may add other labels. */ /* PSIDOC_CODE_START InputNg_Class_MyInputCheck nocapture */  Alvarez, Gonzalo committed Oct 03, 2020 61 62 63 64 65 66 67 68 69 70 71 72 class MyInputCheck : public PsimagLite::InputCheckBase { public: std::string import() const { std::string str("integer myscalar;\n"); str += "vector myvector;\n"; str += "string mystring;\n"; return str; } };  Alvarez, Gonzalo committed Oct 03, 2020 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 /* PSIDOC_CODE_END */ /* PSIDOC InputNg_main1 Now for the actual reading of the input file, we'll use \cppFile{InputNg}. We'll alias its type first with \begin{verbatim} typedef PsimagLite::InputNg InputNgType; \end{verbatim} InputNg expects one template argument, our input checking class, which we have just described. We'll also have to use the actual name provided to this program, which should be in \verb!argv[1]!, which we put in C++ variable \texttt{filename}. We need to create an object of our class MyInputCheck as well. We then have the following code so far \begin{lstlisting} PSIDOCCOPY InputNg_main_part1 \end{lstlisting} */  Alvarez, Gonzalo committed Oct 03, 2020 92   Alvarez, Gonzalo committed Oct 03, 2020 93 /* PSIDOC_CODE_START InputNg_main_part1 nocapture */  Alvarez, Gonzalo committed Oct 03, 2020 94 95 96 97 98 99 100 101 102 103 104 int main(int argc, char* argv[]) { if (argc != 2) { std::cerr<<"USAGE "< InputNgType; std::string filename(argv[1]); MyInputCheck myInputCheck;  Alvarez, Gonzalo committed Oct 03, 2020 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 /* PSIDOC_CODE_END */ /* PSIDOC InputNg_main2 We are now ready to read the file, which we do with the following two statements \begin{lstlisting} PSIDOCCOPY InputNg_main_part2 \end{lstlisting} From now on, we can forget about the myInputCheck object, and the ioWriteable object as well, and consider only the io object, which we will use to read labels. The data from the file is now in memory, and the file does not have to be read or even present anymore. */ /* PSIDOC_CODE_START InputNg_main_part2 nocapture */  Alvarez, Gonzalo committed Oct 03, 2020 121 122  InputNgType::Writeable ioWriteable(filename, myInputCheck); InputNgType::Readable io(ioWriteable);  Alvarez, Gonzalo committed Oct 03, 2020 123 /* PSIDOC_CODE_END */  Alvarez, Gonzalo committed Oct 03, 2020 124   Alvarez, Gonzalo committed Oct 03, 2020 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 /* PSIDOC InputNg_main3 Let's now read some data from the file using the io object. (The data is now in memory, and it is \emph{not actually} read from the file, but we will use that terminology anyway.) We read the scalar first, and print it to the terminal with the following code. \begin{lstlisting} PSIDOCCOPY InputNg_code_main3 \end{lstlisting} The first argument to io.readline will be filled with the value from the file that follows the label myscalar. Even though the value will be filled, it's best practice to initialize it first anyway. */ /* PSIDOC_CODE_START InputNg_code_main3 nocapture */  Alvarez, Gonzalo committed Oct 03, 2020 141 142 143 144 145  int myscalar = 0; io.readline(myscalar, "myscalar="); std::cout<<"I've read label myscalar with value "; std::cout< v; io.read(v, "myvector");  Alvarez, Gonzalo committed Oct 03, 2020 165 /* PSIDOC_CODE_END */  Alvarez, Gonzalo committed Oct 03, 2020 166   Alvarez, Gonzalo committed Oct 03, 2020 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 /* PSIDOC InputNg_main5 The two previous examples required the labels to be present in the input file. But what if we want to have an \emph{optional} label in the input file? To deal with that we put the io.readline statement inside a try and catch block, as follows. \begin{lstlisting} PSIDOCCOPY InputNg_code_main5 \end{lstlisting} This way if the user provides the label mystring then the C++ variable mystr will have the value the user provided. Otherwise, the value of mystr will remain default'', and no error will be issued. */ /* PSIDOC_CODE_START InputNg_code_main5 nocapture */ std::string mystr("default");  Alvarez, Gonzalo committed Oct 03, 2020 184 185 186 187 188  try { io.readline(mystr, "mystring="); } catch (std::exception&) {} }  Alvarez, Gonzalo committed Oct 03, 2020 189 /* PSIDOC_CODE_END */  Alvarez, Gonzalo committed Oct 03, 2020 190   Alvarez, Gonzalo committed Oct 03, 2020 191 192 193 194 195 196 197 /* PSIDOC InputNg_Recap \subsection*{Recap} In this lesson we have learned, blah blah. \subsection*{Exercises} */