Podemos fazer dessa forma para manipular data e hora em C++ moderno (inclua as bibliotecas chrono e ctime):
using namespace std;
using namespace chrono;
int main() {
time_t atual = system_clock::to_time_t(system_clock::now()); // Exibe com ctime(&atual)
string data(10, ' ');
strftime(&data[0], data.size() + 1, "%d/%m/%Y", localtime(&atual));
string hora(8, ' ');
strftime(&hora[0], hora.size() + 1, "%H:%M:%S", localtime(&atual));
string ds(1, ' ');
strftime(&ds[0], ds.size() + 1, "%w", localtime(&atual));
string semana[7] = {"Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"};
cout << data << endl;
cout << hora << endl;
cout << semana[stoi(ds)] << endl;
return 0;
}
Podemos até criar uma classe baseada no uso dessas bibliotecas (nesse caso inclua iostream, chrono e ctime no arquivo h):
using namespace std;
using namespace chrono;
class Date {
public:
string now();
string week();
int day();
int month();
int year();
int hours();
int minutes();
int seconds();
private:
static time_t atual;
static string semana[7];
int ds;
string manip(int quant, const char* tex);
};
time_t Date::atual = system_clock::to_time_t(system_clock::now());
string Date::semana[7] = {"Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"};
string Date::now() {
return ctime(&atual);
}
string Date::manip(int quant, const char* tex) {
string data(quant, ' ');
strftime(&data[0], data.size() + 1, tex, localtime(&atual));
return data;
}
string Date::week() {
ds = stoi(this->manip(1, "%w"));
return semana[ds];
}
int Date::day() {
return stoi(this->manip(2, "%d"));
}
int Date::month() {
return stoi(this->manip(2, "%m"));
}
int Date::year() {
return stoi(this->manip(4, "%Y"));
}
int Date::hours() {
return stoi(this->manip(2, "%H"));
}
int Date::minutes() {
return stoi(this->manip(2, "%M"));
}
int Date::seconds() {
return stoi(this->manip(2, "%S"));
}
Dessa forma, podemos simplesmente chamar assim no programa principal (dê o include do arquivo Date.h):
Date dataAtual;
cout << "O dia da semana é: " << dataAtual.week() << endl;
cout << "O dia de hoje é: ";
cout << dataAtual.day() << "/" << dataAtual.month() << "/" << dataAtual.year() << endl;
cout << "A hora atual é: ";
cout << dataAtual.hours() << ":" << dataAtual.minutes() << ":" << dataAtual.seconds() << endl;
Os smart pointer, diferente dos ponteiros normais, ele destrói o elemento automaticamente após a execução ou alguma exceção, liberando memória automaticamente após o uso do objeto sem necessidade de usar free ou delete.
Relembrando, um ponteiro em num, nós fazemos assim:
int *pont; // Criação do ponteiro
int num; // Variável do mesmo tipo
num = 10; // Atribuição de valor à variável
pont = # // Atribuição do endereço de num à variável
cout << "Conteúdo..: " << *pont << endl; // Conteúdo de num
cout << "Endereço..: " << pont << endl; // Endereço de num
delete pont;
Agora deixe o código assim, transformando o int num objeto:
int *pont = new int();
*pont = 10;
cout << "Conteúdo..: " << *pont << endl; // Conteúdo de pont
cout << "Endereço..: " << &pont << endl; // Endereço de pont
delete pont;
Mas até aí, nada de novo.
Para usarmos os ponteiros inteligentes, importamos a biblioteca memory, veja um exemplo de alteração do código acima, dessa forma
unique_ptr<int> pont(new int());
*pont = 10;
cout << "Conteúdo..: " << *pont << endl; // Conteúdo de pont
cout << "Endereço..: " << &pont << endl; // Endereço de pont
Como visto acima, não se usa o delete, e nem é necessário, porque ele já faz a coleta de lixo automaticamente.
Só que tem um porém, o unique_ptr só permite um ponteiro por vez, portanto, isso não é possível fazer:
unique_ptr<int> pont(new int());
unique_ptr<int> pont2 = pont;
Para resolver isso, usamos o ponteiro compartilhado, shared_ptr, dessa forma:
shared_ptr<int> pont(new int());
shared_ptr<int> pont2 = pont;
Em outras palavras, o unique_ptr não pode ser compartilhado, já o shared_ptr permite isso, mas é menos usado. Temos também o auto_ptr, que identifica automaticamente, mas ele foi removido em versões mais recentes do C++ por desuso;
Crie agora um ponteiro tradicional de objeto string, assim:
string *pal = new string("Cursos");
cout << "Palavra: " << *pal << endl;
cout << "Tamanho: " << pal->size() << endl;
O mesmo código usando o ponteiro inteligente:
unique_ptr<string> pal(new string("Cursos"));
cout << "Palavra: " << *pal << endl;
cout << "Tamanho: " << pal->size() << endl;
Crie fora do main, uma classe simples com esse código:
class Carro {
public:
int vel = 0;
int getVel() {
return vel;
}
void setVel(int v) {
this->vel = v;
}
};
E crie um objeto com o método tradicional assim:
Carro *c1 = new Carro();
c1->setVel(100);
cout << "Velocidade: " << c1->getVel() << endl;
delete c1;
Mesmo código acima, só que com ponteiro inteligente:
unique_ptr<Carro> c1(new Carro());
c1->setVel(100);
cout << "Velocidade: " << c1->getVel() << endl;
Outro exemplo, usando o shared_ptr com um segundo objeto:
shared_ptr<Carro> c1(new Carro());
shared_ptr<Carro> c2 = c1;
c1->setVel(100);
c2->setVel(80);
cout << "Velocidade: " << c1->getVel() << endl;
cout << "Velocidade: " << c2->getVel() << endl;
Observe que no código acima, ambos os objetos retornam 80, porque usam o mesmo ponteiro, e portanto, o método de um altera/captura características do outro, por compartilhamento.
Para que cada ponteiro tenhas suas características particulares, use o unique_ptr mesmo:
unique_ptr<Carro> c1(new Carro());
unique_ptr<Carro> c2(new Carro());
c1->setVel(100);
c2->setVel(80);
cout << "Velocidade: " << c1->getVel() << endl;
cout << "Velocidade: " << c2->getVel() << endl;
No C++ 11, caso precise inicializar um ponteiro como nulo, podemos usar nullptr
no lugar do NULL.
O algoritmo for each é mais uma maneira para percorrer um container, usando uma função lambda para isso.
Para trabalhar com foreach, precisamos importar a biblioteca algorithm
.
Veja um exemplo de código com iterator:
vector<int> n{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<int>::iterator it;
for(it = n.begin(); it != n.end(); it++) {
cout << *it << endl;
}
Ou simplificando:
vector<int> n{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for(auto it = n.begin(); it != n.end(); it++) {
cout << *it << endl;
}
Simplificando mais ainda (essa é a forma mais simples de escrever):
vector<int> n{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for(auto it: n) {
cout << it << endl;
}
E claro, podemos usar o for tradicional também.
Mas não é difícil fazer com o for each, que é uma função, que recebe uma função lambda, veja como usar:
vector<int> n{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for_each(n.begin(), n.end(), [](int num){cout << num << endl;}); // Inclua algorithm
Em outras palavras, os parâmetros são o dado inicial, o dado final e a função, que é preferível ser lambda.
Podemos também colocar outras operações dentro dessa função lambda, por exemplo:
vector<int> n{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for_each(n.begin(), n.end(), [](int num) {
num += 10;
cout << num << endl;
});
PS: A alteração acima só acontece dentro do lambda, ele não altera os dados do vector, como podem ver, usando outro for each:
vector<int> n{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for_each(n.begin(), n.end(), [](int num) {
num += 10;
cout << num << endl;
});
cout << endl;
for_each(n.begin(), n.end(), [](int num) {
cout << num << endl;
});