There's strictly no warranty for the correctness of this text. You use any of the information provided here at your own risk.
The program's "main()"-function can also have the parameters "int argc" and "char *argv[]".
"argv" is an array of "pointers to char". So it's an array of C-strings.
The first of these strings is the name of the script.
"argc" is the number of elements of "argv". It is at least 1. Neither the programmer, nor the user passes the number "argc" (or "argv") explicitely to the "main()"-function. Instead, the user passes options on the command-line, and "argc" and "argv" are automatically set accordingly.
It is relatively easy to convert the C-strings in "argv" to C++-strings (which are of type "std::string"). Here's an example:
#include <iostream> #include <vector> using namespace std; int main(int argc, char *argv[]) { cout << argc << endl; vector<string> v; string s; for (int i = 0; i < argc; i++) { s = argv[i]; // "v.push_back(argv[i]);" would also be possible: v.push_back(s); } for (string i : v) { cout << i << endl; } return 0; }
For simpler search- and replace-operations in C++strings, the methods
string.find()
and
string.replace()
can be used. Since C++-20, there are also
string.starts_with()
and
string.ends_with()Since C++11, it is also possible to use more complicated regular expressions.
#include <iostream> #include <regex> using namespace std; int main() { if (regex_search("Hello", regex("He"))) { cout << "Found." << endl; } }
This searches for characters that aren't numbers:
#include <iostream> #include <regex> using namespace std; int main() { if (regex_search("123a", regex(R"(\D)"))) { cout << "Found." << endl; } }
The "R" somehow indicates a raw string. Otherwise you'd have to write "\\D" all the time.
As can be expected, there's also "regex_replace()".
Here we're writing some lines of text to a file called "schiller.txt", then we read in the contents of that file into a vector and print it:
#include <iostream> #include <vector> #include <fstream> using namespace std; void printStringVector(vector<string> &vecref) { int vecsize = vecref.size(); cout << "["; for (int i=0; i < vecsize; i++) { cout << "\""; cout << vecref[i]; cout << "\""; if (i < vecsize - 1) { cout << ", "; } } cout << "]" << endl; } vector<string> readfile(string filename) { vector<string> a; string buf; ifstream fh(filename); if (fh.good() == false) { cout << "Warning: Couldn't read from file '" << filename << "'." << endl; fh.close(); return a; } while (getline(fh, buf)) { a.push_back(buf); } fh.close(); return a; } void writefile(const string &filename, vector<string> &text) { ofstream fh; fh.open(filename); if (fh.good() == false) { cout << "Warning: Cannot write to file '" << filename << "'. Nothing done." << endl; fh.close(); return; } for (string i: text) { fh << i << endl; } fh.close(); } int main() { string filename = "schiller.txt"; vector<string> schiller = {"Und blicket sie lange verwundert an.", "Drauf spricht er: 'Es ist euch gelungen,", "Ihr habt das Herz mir bezwungen,", "Und die Treue, sie ist doch kein leerer Wahn.'"}; // Writing to file: // Commented out for security reasons. If you want to write the file // "schiller.txt", delete the leading "//" of the next line: // writefile(filename, schiller); // Reading from file: vector<string> a = readfile(filename); printStringVector(a); return 0; }
Notice, that you have to use "getline(fh, [string]);" to read a line from a file, just like you have to use getline(), when reading a line from "cin". If you just did "fh2 >> buf", it would read the file word by word.
The language update "C++17" introduced "std::filesystem", which made certain important file-operations in C++ a lot easier. (Before C++17, these functions could be found in the C++-library "Booth"; some people also kept solving the problem in C-style.)
Here's an example program. As "C++17" is required, it has to be compiled using the compiler-executable "g++-14" or such.
The example program then shows, how the following operations can be done:
#include <iostream> #include <vector> #include <filesystem> // Compile with g++-14 (C++17 and above) using namespace std; void printStringVector(vector<string> &vecref) { int vecsize = vecref.size(); cout << "["; for (int i=0; i < vecsize; i++) { cout << "\""; cout << vecref[i]; cout << "\""; if (i < vecsize - 1) { cout << ", "; } } cout << "]" << endl; } vector<string> listdir(string &path, bool wantfullpath = false) { vector<string> v; std::filesystem::path p; // Code from: https://stackoverflow.com/questions/612097/how-can-i-get-the-list-of-files-in-a-directory-using-c-or-c for (const auto & entry : std::filesystem::directory_iterator(path)) { p = entry.path(); if (wantfullpath) { v.push_back(p); } else { v.push_back(p.filename()); } } return v; } int main() { // Getting the current working directory: string cwd = std::filesystem::current_path(); cout << endl << "The current working directory is '"; cout << cwd << "'." << endl; cout << endl; // Printing the contents of the current working directory: vector<string> v = listdir(cwd); cout << "The content of the current working directory is:" << endl; printStringVector(v); cout << endl; // Check, if a file exists: string filename; if (v.size() > 0) { filename = cwd + "/" + v[0]; if (std::filesystem::exists(filename)) { cout << "The file '" << filename << "' exists." << endl; } else { cout << "The file '" << filename << "' doesn't exist." << endl; } } cout << endl; }
Creating a library from a ".cpp"-source-file isn't as difficult as one might think. This tutorial explained, how it's done.
To create and use a dynamic C++-library on Linux, two files are needed: One is the library-file, which is called something like "libsomelibrary.so", the other one is a header-file with an extension ".h" (or as we are in C++ with no extension at all).
The ".so"-file is copied to the directory "/usr/lib64", the header-file to a directory under "/usr/include".
Then, the header file is included in a new source-file with "#include <somelibrary>".
And finally, the compiler has to be told to use the library: "g++ -lsomelibrary sourcefile.cpp".
Ok, let's create the two mentioned files first: If you have a source-file "somelibrary.cpp" that contains all the functions of the library, you just need to run these commands:
g++ -fPIC -c somelibrary.cpp -o somelibrary.o g++ -shared -o libsomelibrary.so somelibrary.o
This creates a file "libsomelibrary.so". Here's a little Perl-script around the two commands above:
#!/usr/bin/perl use warnings; use strict; my $LIBNAME = "somelibrary"; my $e; $e = "g++ -fPIC -c "; $e .= $LIBNAME; $e .= ".cpp -o "; $e .= $LIBNAME; $e .= ".o"; print "$e\n"; # system($e); $e = "g++ -shared -o lib"; $e .= $LIBNAME; $e .= ".so "; $e .= $LIBNAME; $e .= ".o"; print "$e\n"; # system($e);
Then you need a file "somelibrary.h". This file basically exposes the available functions to a developer, who wants to use the library. The ".h"-file shows what's there, while the ".cpp"-file defines, how it works.
In general, definitions say, how a thing works, while declarations just say that the thing exists.
The file "somelibrary.h" could for example look like this:
// somelibrary.h // This is a C++ Library header. #ifndef SOME_LIBRARY #define SOME_LIBRARY using namespace std; // Functions: void someFunction(string ¶meter); #endif
When you have "libsomelibrary.so" and "somelibrary.h", these files should be copied to directories in the path of the compiler. ".so"-files are typically in
/usr/lib64
while header files (".h") are in or below
/usr/include
On my system there is for example a directory
/usr/include/c++/7
that contains files like "iostream", which should sound familiar.
The ".h"-suffix of the header file can also be left out, so you can for example do as root:
#!/bin/bash if [[ $EUID -ne 0 ]]; then echo echo "Error: This script must be run as root." echo exit 1 fi cp -v libsomelibrary.so /usr/lib64 cp -v somelibrary.h /usr/include/c++/7/somelibrary
After that, the library is ready to use.
In the ".cpp"-file that uses it, the headerfile can be included with
#include <somelibrary>
And when a new program is compiled, to use the library, the command-line option "-lsomelibrary" has to be added to the compilation-line like this:
g++ -lsomelibrary newprogram.cpp