Cpp复习(二)
2018-02-14 03:48
288 查看
__________________________________________________________________________________________________________________________________________
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)
fgets and fputs:
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.
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:
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,
4000
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
handling system errors
1,void perror (const char * str)
//print out str to standard error followed by error string translated from the error mode
errno is: 0
Erasing file foo.bar
errno is: 2
Couldn't erase file: No such file or directory
2,char * strerror(int errnum)
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 is a 32bit signed integer, giving the number of seconds since midnight January 1970 GMT
Convert time_t to tm as UTC time
Uses the value pointed by timer to fill a tm structure with the values that represent the corresponding time, expressed as a UTC time (i.e., the time
at the GMT timezone).
Convert time_t to tm as local time
Uses the value pointed by timer to fill a tm structure with the values that represent the corresponding time, expressed for the local timezone.
Format time as string
Copies into ptr the content of format, expanding its format specifiers into the corresponding values that represent the time described in timeptr, with a limit of maxsize characters.
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.
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:
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:
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.
std:copy Now, as far as accessing elements are concerned, input iterators are fine, but
as soon as we have to assign elements in another container, then we cannot use these input iterators for this purpose.(only accessing, no assigning)
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:
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:
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.
Relational Operators: Although,
forward iterators can be used with equality operator (==), but it cannnot be used with other relational operators like , =.
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:
std::random_shuffle: As
we know this algorithm is used to randomly shuffle all the elements present in a container.
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.
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.
Use of offset dereference operator ([ ]): Random-access
iterators support offset dereference operator ([ ]), which is used for random-access.
————————————————
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:
C++98
C++11
C++98
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
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 |
#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,
4000
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);
Convert time_t to tm as UTC time
Uses the value pointed by timer to fill a tm structure with the values that represent the corresponding time, expressed as a UTC time (i.e., the time
at the GMT timezone).
struct tm * localtime (const time_t * timer);
Convert time_t to tm as local time
Uses the value pointed by timer to fill a tm structure with the values that represent the corresponding time, expressed for the local timezone.
size_t strftime (char* ptr, size_t maxsize, const char* format, const struct tm* timeptr );
Format time as string
Copies into ptr the content of format, expanding its format specifiers into the corresponding values that represent the time described in timeptr, with a limit of maxsize characters.
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 |
//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.
std:copy Now, as far as accessing elements are concerned, input iterators are fine, but
as soon as we have to assign elements in another container, then we cannot use these input iterators for this purpose.(only accessing, no assigning)
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
std::random_shuffle: As
we know this algorithm is used to randomly shuffle all the elements present in a container.
// 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
C++98C++11
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
C++98C++11
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
相关文章推荐
- cpp复习2-类型转换
- cpp复习3-字符串操作
- CPP 复习 记录
- 高级编程语言复习(Cpp/API/MFC)
- Cpp复习(三)template library and c++11
- CPP复习笔记 3
- 根据实例复习Cpp
- CPP复习笔记 3
- cpp复习
- CPP复习笔记 1
- CPP复习笔记 4
- 高级编程语言复习(Cpp/API/MFC)
- Cpp环境【POJ3320】Jessica's Reading Problem 洁西卡的复习计划
- C++复习之const限定符
- effective C++ 第二章复习笔记
- 【软考复习】——面向对象
- sql 复习总结(参照博友)
- extern C配合__cplusplus实现CPP文件和C文件的函数互相调用
- Java复习笔记1【Java的基本运算】
- Java复习(3)—java程序代码执行顺序