__________________________________________________________________________________________________________________________________________
standard c library: file IO, strings, memory allocation, date and time, error handling, other utilities, consists of two parts: header files and runtime support.
c: #include<stdio.h>, c++: #include<cstdio> symbol are in std namespace
runtime support is provided by a compiled runtime library(libc, glibc) that is linked to the program as part of the build process.
FILE * fopen(const char * filename, const char * mode)
char * fgets(char * buf, int count, FILE * stream)
int fputs(char * str, FILE * stream)
size_t fread(void * buffer, size_t size, size_t count, FILE * stream) //returns the number of buffers read successfully
int fwrite(void * buffer, size_t size, size_t count, FILE * stream) //non negative number for success, EOF for end of file(failure)
mode string | meaning | if file exists | if file does not exist |
r | open file for reading | read from start | failure |
w | create a file for writing | destroy contents | create new file |
a | append to a file | write from end | create new file |
r+ | open file for read /write | read from start | failure |
w+ | create file for read / write | destroy contents | create new file |
a+ | open file for read / write | write from end | create new file |
b | binary mode |
fgets and fputs:
#include<stdio.h>
int main(int argc, char ** argv){
const char * fn = "test.txt";
const char * str = "This is a literal C-string\n";
const static int maxString = 1024;
printf("writing file\n");
FILE * fw = fopen(fn, "w");
for(int i=0; i < 5; i++){
fputs(str, fw);
/*fputs does not write additional characters,
* while puts appends a newline character at the end automatically.
* The function begins copying from the address specified (str) until it reaches the terminating null character ('\0').
* This terminating null-character is not copied to the stream.
*On success, a non-negative value is returned. On error, the function returns EOF and sets the error indicator (ferror).
*/
}
fclose(fw);
printf("done.\n");
printf("reading file\n");
char * rc;
FILE * fr = fopen(fn, "r");
char buf[maxString];
while((rc = fgets(buf, maxString, fr))){
printf(buf);
/* Reads characters from stream and stores them as a C string into str
* until (num-1) characters have been read or either a newline
* or the end-of-file is reached, whichever happens first.
* A newline character makes fgets stop reading,
* but it is considered a VALID character by the function
* and included in the string copied to str.
* A terminating null character is automatically appended after the characters copied to str.
* On success, the function returns str.
* If the end-of-file is encountered while attempting to read a character,
* the eof indicator is set (feof).
* If this happens before any characters could be read,
* the pointer returned is a null pointer (and the contents of str remain unchanged).
*/
}
fclose(fr);
printf("done.\n");
}
writing file...
Done.
reading file...
This is a literal C-string.
This is a literal C-string.
This is a literal C-string.
This is a literal C-string.
This is a literal C-string.
Done.
#include<stdio.h>
#include<string.h>
#include<stdint.h>
//const int slen = 128;
enum{ slen = 128 }; //define a constant
struct s1{
uint8_t a; //a byte that is used as a integer, not a char(unsigned char)
uint8_t b;
char s[slen];
};
int main(int argc, char ** argv){
const char * fn = "test.txt";
const char * str = "This is a literal C-string.\n";
printf("writing file...\n");
FILE * fw = fopen(fn, "wb");
struct s1 buf1[5];
for(int i=0; i < 5; i++){
buf1[i].a = i;
buf1[i].b = strlen(str);
strncpy(buf1[i].s, str, slen);
/*
* char * strncpy(char * dest, const char * src, size_t num)
* Copies the first num characters of source to destination.
* If the end of the source C string (which is signaled by a null-character)
* is found before num characters have been copied,(so length of the content to be copied <= num-1)
* *destination is padded with zeros until a total of num characters have been written to it.
* No null-character is implicitly appended at the end of destination
* if source is longer than num.
*/
}
fwrite(buf1, sizeof(struct s1), 5, fw);
fclose(fw);
printf("done.\n");
printf("reading file...\n");
FILE * fr = fopen(fn, "rb");
struct s1 buf2;
int rc;
while((rc = fread(&buf2, sizeof(struct s1), 1, fr))){
printf("the number of the buffers read:%d\n", rc);
printf("a: %d, b: %d, s: %s", buf2.a, buf2.b, buf2.s);
}
fclose(fr);
printf("done.\n");
return 0;
}
writing file...
done.
reading file...
the number of the buffers read:1
a: 0, b: 28, s: This is a literal C-string.
the number of the buffers read:1
a: 1, b: 28, s: This is a literal C-string.
the number of the buffers read:1
a: 2, b: 28, s: This is a literal C-string.
the number of the buffers read:1
a: 3, b: 28, s: This is a literal C-string.
the number of the buffers read:1
a: 4, b: 28, s: This is a literal C-string.
done.
int rename(const char * oldname, const char * newname)
int remove(const char * filename)
unformated io:
printf("Hello world!\n");//formatted
puts("Hello world!");
fputs("Hello world!\n", stdout); fgets(buf, maxlen, fr);
formatted io:
%d int, %ld long int, %s char *, %c char, %p pointer, %f float point number; stdout, stdin, stderr
int printf( const char * format, ...)
int fprintf(FILE * fn, const char * format, ...)
//the above two funcs:On success, the total number of characters written is returned; otherwise, a negative number is returned
int sprintf(char * buf, const char * format, ...)
//On success, the total number of characters written is returned. This count does NOT include the additional null-character automatically appended at the end of the string.On failure, a negative number is returned.
int snprintf(char * buf, size_t bufsize, const char * format, ...)
//If the resulting string would be longer than n-1 characters, the remaining characters are discarded and not stored, but counted for the value returned by the function. A terminating null character is automatically appended after the content written.
//The number of characters that would have been written if n had been sufficiently large, NOT counting the terminating null character.If an encoding error occurs, a negative number is returned.
//Notice that only when this returned value is non-negative and less than n(len <= n-1), the string has been completely written.
building string functions
1,char *strncpy(char * dest, const char * src, size_t num)
//Only when the length of content to be copied is <= num-1 can a terminating null be added. (num chars in total)
2,char * strncat(char * dest, const char * src, size_t num)
//Appends the first num characters of source to destination, plus a terminating null-character.
//e.g. strncat(str1, str2, maxBuf - strlen(str1) -1)
3.int strcmp(const char* str1, const char * str2)
4const char* strchr(const char * str, int character)
//Returns a pointer to the first occurrence of character in the C string str.If the character is not found, the function returns a null pointer.
//The terminating null-character is considered part of the C string. Therefore, it can also be located in order to retrieve a pointer to the end of a string
5/const char * strstr(const char * str1, const char * str2)
//Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1. The matching process does not include the terminating null-characters, but it stops there.
6.size_t strlen(char * str)
memory allocation
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char ** argv){
const char * src = "This is a string";
const static int strSize = 1024;
char * string = NULL;
string = (char *)calloc(strSize, sizeof(char));
//string = malloc(strSize * sizeof(char));
//the difference is that calloc actively writes zero to the memory
if(!string){
fputs("cannot allocate memory.\n", stderr);
return 1;
}
strncpy(string, src, strSize);
puts(string);
free(string);
string = NULL;
return 0;
}
handling system errors
1,void perror (const char * str)
//print out str to standard error followed by error string translated from the error mode
#include<stdio.h>
#include<errno.h>
int main(int argc, char ** argv){
printf("errno is: %d\n", errno);
printf("Erasing file foo.bar\n");
remove("foo.bar");
printf("errno is: %d\n", errno);
perror("Couldn't erase file");
return 0;
}
errno is: 0
Erasing file foo.bar
errno is: 2
Couldn't erase file: No such file or directory
2,char * strerror(int errnum)
#include<stdio.h>
#include<errno.h>
#include<string.h>
int main(int argc, char ** argv){
printf("errno is: %d\n", errno);
printf("Erasing file foo.bar\n");
remove("foo.bar");
printf("errno is: %d\n", errno);
printf("the error message is %s\n", strerror(errno));
return 0;
}
errno is: 0
Erasing file foo.bar
errno is: 2
the error message is No such file or directory
date and time functions:
time_t time(time_t * time);
time_t is a 32bit signed integer, giving the number of seconds since midnight January 1970 GMT
struct tm * gmtime (const time_t * timer);
struct tm * localtime (const time_t * timer);
size_t strftime (char* ptr, size_t maxsize, const char* format, const struct tm* timeptr );
Return Value
If the length of the resulting C string, including the terminating null-character, doesn't exceed maxsize , the function returns the total number of characters copied to ptr (not including the terminating null-character).Otherwise, it returns zero, and the contents of the array pointed by ptr are indeterminate.
#include<stdio.h>
#include<time.h>
int main(){
const static int bufSize = 128;
time_t t = time(NULL);
struct tm gmt = *gmtime(&t);
struct tm localt = *localtime(&t);
printf("direct from struct tm:\n");
printf("universal time is now %04d-%02d-%02d %02d:%02d:%02d\n",
gmt.tm_year + 1900, gmt.tm_mon, gmt.tm_mday, gmt.tm_hour, gmt.tm_min, gmt.tm_sec);
char buf[bufSize];
size_t len = strftime(buf, bufSize, "%Y-%m-%d %H:%M:%S", &gmt);
printf("from strftime (gmt):\n");
printf("universal time is now %s (%u characters)\n", buf, len);
len = strftime(buf, bufSize,"%Y-%m-%d %H:%M:%S", &localt);
printf("from strftime (localt):\n");
printf("local time is now %s (%u characters)\n", buf, len);
return 0;
}
direct from struct tm:
universal time is now 2018-01-12 20:48:56
from strftime (gmt):
universal time is now 2018-02-12 20:48:56 (19 characters)
from strftime (localt):
local time is now 2018-02-13 04:48:56 (19 characters)
getting file info:
struct stat:
field | interpretation |
st_mode | size of file in bytes |
st_ino | file ino number |
st_mode | file mode |
st_nlink | number of hard links |
st_uid | owner user id |
st_gid | owner group id |
st_ctime | file creation time |
st_mtime | file modification time |
st_atime | file access time |
int stat( char* filename, struct stat * info);
//0 for success, non-zero for failure.
struct stat fstat;
stat("stat.c", &fstat); // info stored in fstat
__________________________________________________________________________________________________________________________________________
STL standard template library
vector, list, set, map, queue and stack, string, io streams, algorithms
vector:
#include<iostream>
#include<vector>
using namespace std;
int main(int argc, char ** argv){
cout << "vector from initializer list (C++11):" << endl;
vector<int> vi1 = {1,2,3,4,5,6,7,8,9,10};
cout << "size: " << vi1.size() << endl;
cout << "front: " << vi1.front() << endl;
cout << "back: " << vi1.back() << endl;
cout <<"insert 42 at begin + 5:" << endl;
vi1.insert(vi1.begin()+5, 42);
cout <<"size: " << vi1.size() << endl;
cout <<"vi1[5]: " << vi1[5] << endl;
cout << "erase at begin + 5:" << endl;
vi1.erase(vi1.begin()+5);
cout << "size: " << vi1.size() << endl;
cout << "vi1[5]: " << vi1[5] << endl;
cout << "push_back 47:" << endl;
vi1.push_back(47);
cout << "size: " << vi1.size() << endl;
cout << "vi1.back() " << vi1.back() << endl;
cout << "range-based iterator(C++11):" << endl;
for(int & v: vi1){
cout << v << " ";
}
cout << endl << endl;
cout << "vector from C-array:" << endl;
const static int size = 10;
int ia[size] = {1,2,3,4,5,6,7,8,9,10};
vector<int> vi2(ia, ia+size);
cout << "plain old for loop (i:v)" << endl;
for(int i = 0; i < size; i++) {
cout << i << ":" << vi2[i] << " ";
}
cout << endl << endl;
cout << "iterator loop" << endl;
for(vector<int>::iterator it=vi2.begin(); it!=vi2.end(); ++it){
cout << (it-vi2.begin())<< ":" << *it << " ";
}
cout << endl << endl;
cout << "vector of strings, from argc/argv list: " << endl;
vector<string> args(argv, argv+argc);
for(string & v: args){
cout << v << endl;
}
}
vector from initializer list (C++11):
size: 10
front: 1
back: 10
insert 42 at begin + 5:
size: 11
vi1[5]: 42
erase at begin + 5:
size: 10
vi1[5]: 6
push_back 47:
size: 11
vi1.back() 47
range-based iterator(C++11):
1 2 3 4 5 6 7 8 9 10 47
vector from C-array:
0:1 1:2 2:3 3:4 4:5 5:6 6:7 7:8 8:9 9:10
vector of strings, from argc/argv list:
F:\workspace\CppWorking\Debug\CppWorking.exe
one
two
three
pair and tuple:
#include<iostream>
#include<tuple>
#include<utility>
using namespace std;
int main(int argc, char ** argv){
pair<int, string> p(42, "forty-two");
cout << p.first << " " << p.second << endl;
p = make_pair<int, string>(112, "one-one-two");
cout << p.first << " " << p.second << endl;
tuple<string, string, int> t1("one", "two", 3);
cout << get<0>(t1) << " " << get<1>(t1) << " " << get<2>(t1) << endl;
string a, b;
int c;
tie(a, b, c) = t1;
cout << a << " " << b << " " << c << endl;
tuple<int, string, string> t2;
tie(get<2>(t2), get<1>(t2), get<0>(t2)) = t1;
cout << get<0>(t2) << " " << get<1>(t2) << " " << get<2>(t2) << endl;
return 0;
}
42 forty-two
112 one-one-two
one two 3
one two 3
3 two one
types of iterators
https://www.geeksforgeeks.org/forward-iterators-in-cpp/
1, input iterator:
https://www.geeksforgeeks.org/input-iterators-in-cpp/
Input iterators can be used only with single-pass algorithms, i.e., algorithms in which we can go to all the locations in the range at most once, like when we have to search or find any element in the range, we go through the locations at most once.
template
OutputIterator copy(InputIterator first, InputIterator last,
OutputIterator result)
{
while (first != last)
*result++ = *first++;
return result;
}
2, output iterator
https://www.geeksforgeeks.org/output-iterators-cpp/
Output iterators are considered to be the exact opposite of input iterators, as they perform opposite function of input iterators. They can be assigned values in a sequence, but cannot be used to access values.
Output iterators can be used only with single-pass algorithms, i.e., algorithms in which we can go to all the locations in the range at most once, such that these locations can be dereferenced or assigned value only once.
Equality / Inequality Comparison: Unlike input iterators, output iterators cannot be compared for equality with another iterator.
So, the following two expressions are invalid if A and B are output iterators:
A == B // Invalid - Checking for equality A != B // Invalid - Checking for inequality
3.forward iterator
Forward iterators are considered to be the combination of input as well as output iterators. It provides support to the functionality of both of them. It permits values to be both accessed and modified.
- Usability: Performing operations on a forward iterator that is dereferenceable never makes its iterator value non-dereferenceable, as a result this enables algorithms that use this category of iterators to use multiple copies of an iterator to pass more than once by the same iterator values. So, it can be used in multi-pass algorithms.
- Equality / Inequality Comparison: A forward iterator can be compared for equality with another iterator. Since, iterators point to some location, so the two iterators will be equal only when they point to the same position, otherwise not.
So, the following two expressions are valid if A and B are forward iterators:
A == B // Checking for equality A != B // Checking for inequality
std::reverse_copy: As the name suggests, this algorithm is used to copy a range into another range, but in reverse order. Now, as far as accessing elements and assigning elements are concerned, forward iterators are fine, but as soon as we have to decrement the iterator, then we cannot use these forward iterators for this purpose.
// Definition of std::reverse_copy()
template OutputIterator reverse_copy(BidirectionalIterator first,
BidirectionalIterator last,
OutputIterator result)
{
while (first != last)
*result++ = *--last;
return result;
}
Relational Operators:
Although, forward iterators can be used with equality operator (==), but it cannnot be used with other relational operators like , =.
If A and B are forward iterators, then A == B // Allowed A <= B // Not Allowed
3.bidirectional iterators
Bidirectional iterators are iterators that can be used to access the sequence of elements in a range in both directions (towards the end and towards the beginning). They are similar to forward iterators, except that they can move in the backward direction also, unlike the forward iterators, which can move only in forward direction.
It is to be noted that containers like list, map, multimap, set and multiset support bidirectional iterators. This means that if we declare normal iterators for them, and then those will be bidirectional iterators, just like in case of vectors and deque they are random-access iterators.
- Usability: Since, forward iterators can be used in multi-pass algorithms, i.e., algorithm which involves processing the container several times in various passes, therefore bidirectional iterators can also be used in multi-pass algorithms.
. - Equality / Inequality Comparison: A Bidirectional iterator can be compared for equality with another iterator. Since, iterators point to some location, so the two iterators will be equal only when they point to the same position, otherwise not.
So, the following two expressions are valid if A and B are Bidirectional iterators:
A == B // Checking for equality A != B // Checking for inequality
// Definition of std::random_shuffle()
template
void random_shuffle(RandomAccessIterator first,
RandomAccessIterator last,
RandomNumberGenerator& gen)
{
iterator_traits::difference_type i, n;
n = (last - first);
for (i=n-1; i>0; --i)
{
swap (first[i],first[gen(i+1)]);
}
}
4, random access iterator
https://www.geeksforgeeks.org/random-access-iterators-in-cpp/
Random-access iterators are iterators that can be used to access elements at an arbitrary offset position relative to the element they point to, offering the same functionality as pointers. Random-access iterators are the most complete iterators in terms of functionality. All pointer types are also valid random-access iterators.It is to be noted that containers like vector, deque support random-access iterators.
Decrementable: Just like we can use operator ++() with Random-access iterators for incrementing them, we can also decrement them.- Relational Operators: Although, Bidirectional iterators cannot be used with relational operators like , =,but random-access iterators being higher in hierarchy support all these relational operators.
If A and B are Random-access iterators, then A == B // Allowed A <= B // Allowed
- Arithmetic Operators: Similar to relational operators, they also can be used with arithmetic operators like +, – and so on. This means that Random-access iterators can move in both the direction, and that too randomly.
If A and B are Random-access iterators, then A + 1 // Allowed B - 2 // Allowed
// C++ program to demonstrate Random-access iterator
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>v1 = {1, 2, 3, 4, 5};
// Declaring first iterator
vector<int>::iterator i1;
// Declaring second iterator
vector<int>::iterator i2;
// i1 points to the beginning of the list
i1 = v1.begin();
// i2 points to the end of the list
i2 = v1.end();
// Applying relational operator to them
if ( i1 < i2)
{
cout << "Yes";
}
// Applying arithmetic operator to them
int count = i2 - i1;
cout << "\ncount = " << count;
return 0;
}
Use of offset dereference operator ([ ]):
Random-access iterators support offset dereference operator ([ ]), which is used for random-access.
If A is a Random-access iterator, then A[3] // Allowed
// C++ program to demonstrate Random-access iterator
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>v1 = {1, 2, 3, 4, 5};
int i;
// Accessing elements using offset dereference
// operator [ ]
for(i=0;i<5;++i)
{
cout << v1[i] << " ";
}
return 0;
}
————————————————
writing iterator
#include<iostream>
#include<vector>
using namespace std;
int main(int argc, char ** argv){
vector<int> vi1 = {1,2,3,4,5,6,7,8,9,10};
vector<int>::iterator it;
auto beginning = vi1.begin();
for(it = vi1.end()-1; it >= beginning; it--){
cout << *it << " ";
}
cout << endl;
it = beginning + 7;
cout << *it << " ";
it -= 3;
cout << *it << " ";
it += 4;
cout << *it << " ";
cout << endl;
return 0;
}
10 9 8 7 6 5 4 3 2 1
8 5 9
__________________________________________________________________________________________________________________________________________
#include<iostream>
#include<list>
using namespace std;
int main(int argc, char ** argv){
cout << "list of ints from initialize list (C++11)" << endl;
list<int> li1 = {1,2,3,4,5,6,7,8,9,10};
cout << "size: " << li1.size() << endl;
cout << "front: " << li1.front() << endl;
cout << "back: " << li1.back() << endl;
cout << "push_back 47:" << endl;
li1.push_back(47);
cout << "size: " << li1.size() << endl;
cout << "back: " << li1.back() << endl;
cout << "range-based iterator (C++11): " << endl;
for(int v : li1){
cout << v << " ";
}
cout << endl << endl;
list<int>::iterator it1 = li1.begin();
list<int>::iterator it2 = li1.begin();
cout << "insert 112 before 5 " << endl;
while(*it1 != 5)
++it1;
li1.insert(it1, 112);
cout << "erase 7 " << endl;
while(*it2 != 7)
++it2;
li1.erase(it2);
for(int v : li1){
cout << v << " ";
}
cout << endl << endl;
it1 = li1.begin();
it2= li1.begin();
cout << "erase 112 to 8 " << endl;
while(*it1 != 112) ++it1;
while(*it2 != 8) ++it2;
cout << *it1 << " " << *it2 << endl;
li1.erase(it1, it2); //*it2 not included
for(int v : li1){
cout << v << " ";
}
cout << endl << endl;
cout << "list from C-array:" << endl;
const static int size = 10;
int ia[size] = {1,2,3,4,5,6,7,8,9,10};
list<int> li2(ia, ia+size);
for(int v: li2){
cout << v << " ";
}
cout << endl;
cout << "list of strings, from argc/argv list: " << endl;
list<string> args(argv, argv+argc);
cout << "while pop" << endl;
while(args.size() > 0){
cout << args.front() << endl;
args.pop_front();
}
return 0;
}
list of ints from initialize list (C++11)
size: 10
front: 1
back: 10
push_back 47:
size: 11
back: 47
range-based iterator (C++11):
1 2 3 4 5 6 7 8 9 10 47
insert 112 before 5
erase 7
1 2 3 4 112 5 6 8 9 10 47
erase 112 to 8
112 8
1 2 3 4 8 9 10 47
list from C-array:
1 2 3 4 5 6 7 8 9 10
list of strings, from argc/argv list:
while pop
F:\workspace\CppWorking\Debug\CppWorking.exe
one
two
three
set:
std::set::insert
single element (1) | pair<iterator,bool> insert (const value_type& val); pair<iterator,bool> insert (value_type&& val); |
---|---|
with hint (2) | iterator insert (const_iterator position, const value_type& val); iterator insert (const_iterator position, value_type&& val); |
range (3) | template <class InputIterator> void insert (InputIterator first, InputIterator last); |
initializer list (4) | void insert (initializer_list<value_type> il); |
std::multiset::insert
single element (1) | iterator insert (const value_type& val); iterator insert (value_type&& val); |
---|---|
with hint (2) | iterator insert (const_iterator position, const value_type& val); iterator insert (const_iterator position, value_type&& val); |
range (3) | template <class InputIterator> void insert (InputIterator first, InputIterator last); |
initializer list (4) | void insert (initializer_list<value_type> il); |
#include<iostream>
#include<set>
using namespace std;
int main(int argc, char** argv){
cout << "set of strings from initializer list(C++11):" << endl;
set<string> strset = {"one", "two", "three", "four", "five"};
cout << "size: " << strset.size() << endl;
for(string s: strset){
cout << s << " ";
}
cout << endl << endl;
cout << "insert element \"six\"" << endl;
strset.insert("six");
for(string s : strset) {
cout << s << " ";
}
cout << endl << endl;
cout << "insert duplicate element \"five\"" << endl;
pair<set<string>::iterator, bool> rvinsert = strset.insert("five");
bool & insertSuccess = rvinsert.second;
if(insertSuccess){
for(string s: strset){
cout << s << " ";
}
}else{
cout << "insert failed";
}
cout << endl << endl;
cout << "find and erase element \"six\"" << endl;
set<string>::iterator it = strset.find("six");
if(it != strset.end()){
cout << "found " << *it << endl;
strset.erase(it);
}else {
cout << "not found" << endl;
}
for(string s: strset){
cout << s << " ";
}
cout << endl;
return 0;
}
set of strings from initializer list(C++11):
size: 5
five four one three two
insert element "six"
five four one six three two
insert duplicate element "five"
insert failed
find and erase element "six"
found six
five four one three two
multiset:
#include<iostream>
#include<set>
using namespace std;
int main(int argc, char** argv){
cout << "set of strings from initializer list(C++11):" << endl;
multiset<string> strset = {"one", "two", "three", "four", "five"};
cout << "size: " << strset.size() << endl;
for(string s: strset){
cout << s << " ";
}
cout << endl << endl;
cout << "insert element \"six\"" << endl;
strset.insert("six");
for(string s : strset) {
cout << s << " ";
}
cout << endl << endl;
cout << "insert duplicate element \"five\"" << endl;
strset.insert("five");
for(string s : strset) {
cout << s << " ";
}
cout << endl << endl;
cout << "find and erase element \"five\"" << endl;
auto it = strset.find("five");
if(it != strset.end()){
cout << "found " << *it << endl;
strset.erase(it);
}else {
cout << "not found" << endl;
}
for(string s: strset){
cout << s << " ";
}
cout << endl;
return 0;
}
set of strings from initializer list(C++11):
size: 5
five four one three two
insert element "six"
five four one six three two
insert duplicate element "five"
five five four one six three two
find and erase element "five"
found five
five four one six three two
map:
#include<iostream>
#include<map>
using namespace std;
int main(int argc, char ** argv){
cout << "map of strings from initializer list(C++11):" << endl;
map<string, string> strmap = {
{"George", "Father"},
{"Ellen", "Mother"},
{"Ruth", "Daughter"},
{"Spike", "Neighbor Wang's son"}
};
map<string, string>::iterator it;
cout << "size is " << strmap.size() << endl;
cout << "check a couple of key/value pairs" << endl;
cout << "George is " << strmap["George"] << endl;
cout << "Ellen is " << strmap.find("Ellen")->second << endl;
cout << endl;
cout << "iterate the set" << endl;
for(it = strmap.begin(); it != strmap.end(); ++it){
cout << it->first << " is " << it->second << endl;
}
cout << endl;
cout << "insert an element" << endl;
strmap.insert(pair<string, string>("Luke", "Neighbor") );
//strmap.insert({"Luke", "Neighbor"});
cout << "inserted - size is " << strmap.size() << endl;
for(pair<string, string> v: strmap){
cout << v.first << " is " << v.second << endl;
}
cout << endl;
cout << "insert a duplicate" << endl;
strmap.insert({"Luke", "Neighbor wang"});
cout << "after insert size is " << strmap.size() << endl;
for(auto v: strmap){
cout << v.first << " is " << v.second << endl;
}
cout << endl;
cout << "find and erase an element" << endl;
it = strmap.find("Luke");
if(it != strmap.end()){
cout << "found Luke: " << it->second << endl;
strmap.erase(it);
cout << "erased - size is " << strmap.size() << endl;
} else{
cout << "not found" << endl;
}
for(auto v: strmap){
cout << v.first << " is " << v.second << endl;
}
cout << endl;
return 0;
}
map of strings from initializer list(C++11):
size is 4
check a couple of key/value pairs
George is Father
Ellen is Mother
iterate the set
Ellen is Mother
George is Father
Ruth is Daughter
Spike is Neighbor Wang's son
insert an element
inserted - size is 5
Ellen is Mother
George is Father
Luke is Neighbor
Ruth is Daughter
Spike is Neighbor Wang's son
insert a duplicate
after insert size is 5
Ellen is Mother
George is Father
Luke is Neighbor
Ruth is Daughter
Spike is Neighbor Wang's son
find and erase an element
found Luke: Neighbor
erased - size is 4
Ellen is Mother
George is Father
Ruth is Daughter
Spike is Neighbor Wang's son
multimap:
#include<iostream>
#include<map>
using namespace std;
int main(int argc, char ** argv){
cout << "map of strings from initializer list(C++11):" << endl;
multimap<string, string> strmap = {
{"George", "Father"},
{"Ellen", "Mother"},
{"Ruth", "Daughter"},
{"Spike", "Neighbor Wang's son"}
};
multimap<string, string>::iterator it;
cout << "size is " << strmap.size() << endl;
cout << "check a couple of key/value pairs" << endl;
//cout << "George is " << strmap["George"] << endl; //unvalid in multimap
cout << "Ellen is " << strmap.find("Ellen")->second << endl;
cout << endl;
cout << "iterate the set" << endl;
for(it = strmap.begin(); it != strmap.end(); ++it){
cout << it->first << " is " << it->second << endl;
}
cout << endl;
cout << "insert an element" << endl;
strmap.insert(pair<string, string>("Luke", "Neighbor") );
//strmap.insert({"Luke", "Neighbor"});
cout << "inserted - size is " << strmap.size() << endl;
for(pair<string, string> v: strmap){
cout << v.first << " is " << v.second << endl;
}
cout << endl;
cout << "insert a duplicate" << endl;
strmap.insert({"Luke", "Neighbor wang"});
cout << "after insert size is " << strmap.size() << endl;
for(auto v: strmap){
cout << v.first << " is " << v.second << endl;
}
cout << endl;
cout << "find and erase an element" << endl;
it = strmap.find("Luke");
if(it != strmap.end()){
cout << "found Luke: " << it->second << endl;
strmap.erase(it);
cout << "erased - size is " << strmap.size() << endl;
} else{
cout << "not found" << endl;
}
for(auto v: strmap){
cout << v.first << " is " << v.second << endl;
}
cout << endl;
return 0;
}
map of strings from initializer list(C++11):
size is 4
check a couple of key/value pairs
Ellen is Mother
iterate the set
Ellen is Mother
George is Father
Ruth is Daughter
Spike is Neighbor Wang's son
insert an element
inserted - size is 5
Ellen is Mother
George is Father
Luke is Neighbor
Ruth is Daughter
Spike is Neighbor Wang's son
insert a duplicate
after insert size is 6
Ellen is Mother
George is Father
Luke is Neighbor
Luke is Neighbor wang
Ruth is Daughter
Spike is Neighbor Wang's son
find and erase an element
found Luke: Neighbor
erased - size is 5
Ellen is Mother
George is Father
Luke is Neighbor wang
Ruth is Daughter
Spike is Neighbor Wang's son
queue:
queue<int, list<int>> //first type is the type of things the list is made up of; second type is the container being adapted
the default underlying container of queue is deque.
#include<iostream>
#include<list>
#include<queue>
using namespace std;
int main(int argc, char ** argv){
cout << "initialize queue from list" << endl;
list<int> li = {1,2,3,4,5};
queue<int, list<int> > ql(li);
cout << "li has " << li.size() << " entries; " <<
"ql has " << ql.size() << " entries." << endl;
cout << "pop all from ql" << endl;
while(!ql.empty()){
cout << ql.front() << " ";
ql.pop();
}
cout << endl;
cout << "li has " << li.size() << " entries; " <<
"ql has " << ql.size() << " entries." << endl;
cout << "contents of li after ql is emptied:" << endl;
for(auto it = li.begin(); it != li.end(); ++it){
cout << *it << " ";
}
cout << endl;
cout << "push strings onto qd" << endl;
queue<string> qd; // default queue uses deque object
qd.push("one");
qd.push("two");
qd.push("three");
qd.push("four");
qd.push("five");
cout <<"size of qd: " << qd.size() << endl;
cout<< "pop all from qd" << endl;
while(!qd.empty()){
cout << qd.front() << " ";
qd.pop();
}
cout << endl;
cout << "size of qd: " << qd.size() << endl;
return 0;
}
initialize queue from list
li has 5 entries; ql has 5 entries.
pop all from ql
1 2 3 4 5
li has 5 entries; ql has 0 entries.
contents of li after ql is emptied:
1 2 3 4 5
push strings onto qd
size of qd: 5
pop all from qd
one two three four five
size of qd: 0
stack:
// default stack uses deque object
#include<iostream>
#include<list>
#include<stack>
using namespace std;
int main(int argc, char ** argv){
cout << "initialize queue from list" << endl;
list<int> li = {1,2,3,4,5};
stack<int, list<int> > sl(li);
cout << "li has " << li.size() << " entries; " <<
"sl has " << sl.size() << " entries." << endl;
cout << "pop all from sl" << endl;
while(!sl.empty()){
cout << sl.top() << " ";
sl.pop();
}
cout << endl;
cout << "li has " << li.size() << " entries; " <<
"sl has " << sl.size() << " entries." << endl;
cout << "contents of li after sl is emptied:" << endl;
for(int i: li){
cout << i << " ";
}
cout << endl;
cout << "push strings onto qd" << endl;
stack<string> sd; // default queue uses deque object
sd.push("one");
sd.push("two");
sd.push("three");
sd.push("four");
sd.push("five");
cout <<"size of qd: " << sd.size() << endl;
cout<< "pop all from sd" << endl;
while(!sd.empty()){
cout << sd.top() << " ";
sd.pop();
}
cout << endl;
cout << "size of sd: " << sd.size() << endl;
return 0;
}
initialize queue from list
li has 5 entries; sl has 5 entries.
pop all from sl
5 4 3 2 1
li has 5 entries; sl has 0 entries.
contents of li after sl is emptied:
1 2 3 4 5
push strings onto qd
size of qd: 5
pop all from qd
five four three two one
size of sd: 0
deque container:
vector + double ended queue. Unlike vector, it can rapidly pushing things at front and at the end.
#include <iostream>
#include <deque>
using namespace std;
int main( int argc, char ** argv ) {
// from initializer list (C++11)
cout << "deque from initializer list (C++11): " << endl;
deque<int> dq1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
cout << "size: " << dq1.size() << endl;
cout << "front: " << dq1.front() << endl;
cout << "back: " << dq1.back() << endl;
cout << "insert 42 at begin + 5: " << endl;
dq1.insert(dq1.begin() + 5, 42);
cout << "size: " << dq1.size() << endl;
cout << "dq1[5]: " << dq1[5] << endl;
cout << "erase at begin + 5: " << endl;
dq1.erase(dq1.begin() + 5);
cout << "size: " << dq1.size() << endl;
cout << "dq1[5]: " << dq1[5] << endl;
cout << "push_back 47: " << endl;
dq1.push_back(47);
cout << "size: " << dq1.size() << endl;
cout << "dq1.back() " << dq1.back() << endl;
cout << "push_front 192: " << endl;
dq1.push_front(192);
cout << "size: " << dq1.size() << endl;
cout << "dq1.front() " << dq1.front() << endl;
// range-based iterator (C++11)
cout << "range-based iterator (C++11): " << endl;
for(int & v : dq1) {
cout << v << " ";
}
cout << endl << endl;
cout << "dq1.pop_front() " << endl;
dq1.pop_front();
cout << "size: " << dq1.size() << endl;
cout << "dq1.pop_back() " << endl;
dq1.pop_back();
cout << "size: " << dq1.size() << endl;
for(int & v : dq1) {
cout << v << " ";
}
return 0;
}
deque from initializer list (C++11):
size: 10
front: 1
back: 10
insert 42 at begin + 5:
size: 11
dq1[5]: 42
erase at begin + 5:
size: 10
dq1[5]: 6
push_back 47:
size: 11
dq1.back() 47
push_front 192:
size: 12
dq1.front() 192
range-based iterator (C++11):
192 1 2 3 4 5 6 7 8 9 10 47
dq1.pop_front()
size: 11
dq1.pop_back()
size: 10
1 2 3 4 5 6 7 8 9 10
string:
#include <iostream>
#include <string>
using namespace std;
int main( int argc, char ** argv ) {
string s1 = "This is a string";
string::iterator it;
// size & length
cout << "size is same as length: " << s1.length() << endl;
// + for concatenation
cout << "concatenated strings: ";
string s2 = "this is also a string";
cout << s1 + ":" + s2 << endl;
// compare
cout << "is s1 == s2? " << (s1 == s2 ? "yes" : "no") << endl;
cout << "copy-assign s2 = s1" << endl;
s2 = s1;
cout << "is s1 == s2? " << (s1 == s2 ? "yes" : "no") << endl;
// iteration
cout << "each character: ";
for(it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
// for(char c: s1){
// cout << c << " ";
// }
// insert & erase with an iterator
it = s1.begin() + 5;
s1.insert(it, 'X');
cout << "after insert: " << s1 << endl;
it = s1.begin() + 5;
s1.erase(it);
cout << "after erase: " << s1 << endl;
// replace
s1.replace(5, 2, "ain't");
cout << "after replace: " << s1 << endl;
// substr
cout << "substr: " << s1.substr(5, 5) << endl;
// find
size_t pos = s1.find("s");
cout << "find first \"s\" in s1 (pos): " << pos << endl;
cout << "substr at pos: " << s1.substr(pos) << endl;
// rfind
pos = s1.rfind("s");
cout << "find last \"s\" in s1 (pos): " << pos << endl;
cout << "substr at pos: " << s1.substr(pos) << endl;
return 0;
}
size is same as length: 16
concatenated strings: This is a string:this is also a string
is s1 == s2? no
copy-assign s2 = s1
is s1 == s2? yes
each character: T h i s i s a s t r i n g
after insert: This Xis a string
after erase: This is a string
after replace: This ain't a string
substr: ain't
find first "s" in s1 (pos): 3
substr at pos: s ain't a string
find last "s" in s1 (pos): 13
substr at pos: string
algorithms:
#include <iostream>
#include <vector>
#include <locale>
#include <algorithm>
using namespace std;
// functor for count_if
class strhas {
char needle;
strhas(){}
public:
strhas(char c) : needle(c) {}
bool operator () ( string & );
};
bool strhas::operator() ( string & haystack ) {
return haystack.find_first_of(needle) != haystack.npos;
}
string uppercase(string & s) {
string out;
for( char c : s) out += toupper(c);
return out;
};
int main( int argc, char ** argv ) {
vector<string> vs { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
vector<int> vi { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
vector<string>::iterator vsit;
vector<int>::iterator viit;
string s1 = "big light in sky slated to appear in east";
// count
cout << "push two extra sevens onto vs" << endl;
vs.push_back("seven");
vs.push_back("seven");
cout << "count vs \"seven\": " << count(vs.begin(), vs.end(), "seven") << endl;
cout << "pop those extra sevens" << endl;
vs.pop_back();
vs.pop_back();
// find
cout << "find 7 in vi: ";
viit = find(vi.begin(), vi.end(), 7);
if(viit != vi.end()) {
cout << "found: " << *viit << endl;
} else {
cout << "not found" << endl;
}
// equal
string p = "radar";
if(equal(p.begin(), p.begin() + ( p.size() / 2 ), p.rbegin())) {
cout << p << " is";
} else {
cout << p << " is not";
}
cout << " a palindrome" << endl;
// search
string match = "slated";
cout << "string is \"" << s1 << "\", search term is \"" << match << "\"" << endl;
cout << "search: ";
string::iterator search_it = search(s1.begin(), s1.end(), match.begin(), match.end());
if(search_it != s1.end()) {
cout << "search term found at position " << size_t( search_it - s1.begin() ) << endl;
} else {
cout << "search term not found" << endl;
}
// show vs before count_if
cout << "vs is: ";
for( string s : vs ) cout << s << " ";
cout << endl;
// count_if
cout << "count_if vs has 's' (functor): ";
cout << count_if(vs.begin(), vs.end(), strhas('s') ) << endl;
// C++11 count_if with lambda expression
cout << "count_if vs has 's' (lambda): ";
cout << count_if(vs.begin(), vs.end(),
[](string & s) { return s.find_first_of('s') != s.npos; }
) << endl;
// for_each
cout << "for_each uppercase: ";
for_each(vs.begin(), vs.end(), [](string & s){ cout << uppercase(s) << " "; });
cout << endl;
// transform
cout << "transform: " << endl;
vector<int> vi2;
cout << "vi before transformation: ";
for( int i : vi ) cout << i << " ";
cout << endl;
vi2.resize(vi.size()); // make space for transformation
transform(vi.begin(), vi.end(), vi2.begin(), [](int i){ return ++i; });
cout << "vi2 after transformation: ";
for( int i : vi2 ) cout << i << " ";
cout << endl;
transform(vi.begin(), vi.end(), vi2.begin(), vi2.begin(), [](int i, int j){ return i + j; });
cout << "vi2 after second transformation: ";
for( int i : vi2 ) cout << i << " ";
cout << endl;
cout << "vi after all transformations: ";
for( int i : vi ) cout << i << " ";
cout << endl;
cout << "string before initial cap transformation: " << s1 << endl;
char last = 0;
transform(s1.begin(), s1.end(), s1.begin(), [&last](char c) {
if(last == ' ' || last == 0) { last = c; return toupper(c); }
else { last = c; return tolower(c); }
});
cout << "string after initial cap transformation: " << s1 << endl;
return 0;
}
push two extra sevens onto vs
count vs "seven": 3
pop those extra sevens
find 7 in vi: found: 7
radar is a palindrome
string is "big light in sky slated to appear in east", search term is "slated"
search: search term found at position 17
vs is: one two three four five six seven eight nine ten
count_if vs has 's' (functor): 2
count_if vs has 's' (lambda): 2
for_each uppercase: ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE TEN
transform:
vi before transformation: 1 2 3 4 5 6 7 8 9 10
vi2 after transformation: 2 3 4 5 6 7 8 9 10 11
vi2 after second transformation: 3 5 7 9 11 13 15 17 19 21
vi after all transformations: 1 2 3 4 5 6 7 8 9 10
string before initial cap transformation: big light in sky slated to appear in east
string after initial cap transformation: Big Light In Sky Slated To Appear In East