Agora que já aprendemos como declarar e usar structs no tutorial passado, vamos ver neste como usar as estruturas de dados com as funções.
Structs em Parâmetros e Argumentos de uma Função
Quando explicamos que as structs e suas instâncias funcionam como variáveis (mas variáveis especiais, que você mesmo criou), isso vale também para funções.
Por exemplo, uma função que vai receber e retornar um inteiro, tem o seguinte cabeçalho:
- int myFunction(int num);
Ou seja, especificamos o tipo de dado que a função vai receber. Até o momento trabalhamos com int, double, float, char, ponteiros...agora vamos usar o tipo de dado...que nós mesmos vamos criar!
Por exemplo, uma função que vai receber a struct Student, do tutorial anterior, e exibir seus elementos, tem o seguinte cabeçalho:
- void showStudent(Student alumn);
Por exemplo, o programa abaixo exibe os dados de uma struct de nome 'alumn', do tipo 'Student':
#include <iostream> using namespace std; struct Student { char name[50]; float math, physics, science; }; void showStudent(Student alumn) { cout<<"\nDados:"<<endl; cout<<"Nome : "<<alumn.name<<endl; cout<<"Matemática: "<<alumn.math<<endl; cout<<"Física : "<<alumn.physics<<endl; cout<<"Ciência : "<<alumn.science<<endl; } int main() { Student Alex; cout<<"Nome: "; cin.get(Alex.name,50); cout<<"Nota em Matemática: "; cin >> Alex.math; cout<<"Nota em Física: "; cin >> Alex.physics; cout<<"Nota em Ciências: "; cin >> Alex.science; showStudent(Alex); return 0; }
Só para dizer que não é exatamente igual como fizemos com outras variáveis, note que nossa função usar a struct Student...ou seja, ela já deve EXISTIR antes de declararmos a função, por isso colocamos a declaração da struct ANTES da função que vai usar ela, entendido?
Retornando uma Struct de uma Função
Assim como as funções servem para receber informações e performar tarefas específicas, elas também servem para retornar informações. Até o momento, fizemos retorno com int, double, char, void...mas as funções podem retornar qualquer tipo de dado, desde que a sua struct tenha sido declarada antes.
A função getStudent() não recebe nenhum parâmetro/argumento, mas retorna uma variável do tipo Student, e é usada para retornar uma struct preenchida, veja como funciona:
#include <iostream> using namespace std; struct Student { char name[50]; float math, physics, science; }; void showStudent(Student alumn) { cout<<"\nDados:"<<endl; cout<<"Nome : "<<alumn.name<<endl; cout<<"Matemática: "<<alumn.math<<endl; cout<<"Física : "<<alumn.physics<<endl; cout<<"Ciência : "<<alumn.science<<endl; } Student getStudent() { Student alumn; cout<<"Nome: "; cin.get(alumn.name,50); cout<<"Nota em Matemática: "; cin >> alumn.math; cout<<"Nota em Física: "; cin >> alumn.physics; cout<<"Nota em Ciências: "; cin >> alumn.science; return alumn; } int main() { Student Geddy = getStudent(); showStudent(Geddy); return 0; }
Veja como nossa main() ficou enxuta, apenas declaramos um aluno, fazemos ele receber os dados da função getStudent(), e catapimbas, exibimos o seu conteúdo, tá feito.
Passagem por Valor e por Referência de Structs
Vamos criar uma função, chamada fillStudent() que tem como argumento uma instancia da struct Student, nessa função, vamos solicitar ao usuário os dados do aluno.
Nosso código fica:
#include <iostream> using namespace std; struct Student { char name[50]; float math, physics, science; }; void showStudent(Student alumn) { cout<<"\nDados:"<<endl; cout<<"Nome : "<<alumn.name<<endl; cout<<"Matemática: "<<alumn.math<<endl; cout<<"Física : "<<alumn.physics<<endl; cout<<"Ciência : "<<alumn.science<<endl; } void fillStudent(Student alumn) { cout<<"Nome: "; cin.get(alumn.name,50); cout<<"Nota em Matemática: "; cin >> alumn.math; cout<<"Nota em Física: "; cin >> alumn.physics; cout<<"Nota em Ciências: "; cin >> alumn.science; } int main() { Student Geddy; fillStudent(Geddy); showStudent(Geddy); return 0; }
Na main(), criamos o estudante 'Geddy' e enviamos para a fillStudent() para seus dados serem preenchidos. Porém, quando invocamos a função showStudent(), ela exibe o seguinte resultado:
Dados:
Nome : Ћ���
Matemática: 3.0844e-41
Física : 6.11017e-29
Ciência : 3.0844e-41
Ou seja, os membros da struct 'Geddy' não foram preenchidos! O motivo disso é que a passagem de structs foi feita por valor!
Quando fazemos fillStudent(Geddy), a função pega essa instância, cria uma cópia internamente na função, e altera os valores nessa cópia, e não na struct original.
E como fazer para essa função alterar, de fato, os membros da struct? Simples, basta fazer uma passagem por referência, da struct:
#include <iostream> using namespace std; struct Student { char name[50]; float math, physics, science; }; void showStudent(Student alumn) { cout<<"\nDados:"<<endl; cout<<"Nome : "<<alumn.name<<endl; cout<<"Matemática: "<<alumn.math<<endl; cout<<"Física : "<<alumn.physics<<endl; cout<<"Ciência : "<<alumn.science<<endl; } void fillStudent(Student &alumn) { cout<<"Nome: "; cin.get(alumn.name,50); cout<<"Nota em Matemática: "; cin >> alumn.math; cout<<"Nota em Física: "; cin >> alumn.physics; cout<<"Nota em Ciências: "; cin >> alumn.science; } int main() { Student Geddy; fillStudent(Geddy); showStudent(Geddy); return 0; }
Apenas adicionamos & ao parâmetro 'alumn'. Agora, toda struct que mandarmos para a função fillStudent() será alterada.