So how I was not able to see which numbers repeated in the
matrix, I transformed this matrix into a vector[10], and even managed to count
which numbers repeat, I just need to put now how many times they
repeat.
Maybe you shouldn’t consider "transform". C++ doesn’t have vectors like in FORTRAN. Just vectors. And vector vectors and so on. As the values stay there lined up in memory one after another, line by line, its 5x2 "matrix" is actually a vector of 10 int
from the start address.
Your program is very, very confusing :(
See this excerpt
cout << ("Digite numeros para a matriz:") << endl;
for(cont=0;cont<5;cont++){
for(cont2=0;cont2<2;cont2++) {
cin >> A[cont][cont2];
}
}
Use more expressive names... cont
and cont2
is evil. And never declare those loop control variables out of the loop. It’s a disaster. These values stay alive throughout the program and become impossible to control...
And help the user and yourself by telling what he is typing at every moment. Leaving the screen black and reading the values ONE by ONE is very boring and a hell to control.
Unless the statement clearly states that the matrix should be read from the user NEVER do so. It’s just a headache. Never write an interactive program if you don’t have to.
It is much easier and safer to read from a file. You can repeat the tests easily. You can type the matrix directly into the IDE. Save multiple test files...
And especially in tests you don’t have to keep coming up with 10 values all the time with the program eventually closing in on you.
Back on the show
You don’t pray to have written a program in C++ but a program in C. And you don’t even have the minimum that the statement asks, which is to show the function read.
Once you’ve done that, understand that there are many ways to do this, more to the C-side or more to the C-side++.
A long and inefficient way would be to sort the matrix into another and mark the values that are repeated, and then join a table.
A more C++ way would be to use some of the STL algorithms and some container.
A possible solution would be to do something like Selection Sort, which separates the smaller one with each loop in the matrix, and instead of reversing with the first one and sort you just see if the element is duplicated and how many times it appears in the table and keeps in a result matrix. At the end just show what’s there.
It can have nothing if the matrix is of all distinct elements, can have a single element and have a matrix of 10 constant elements....
Of course in C++ the expected would be to have a class for which you pass the file name on the disk and the number of rows and columns and it reads the matrix and calculates everything...
An example in C++
A class kit
, one struct
in this example, it serves. Declared so in kit.h
#pragma once
#include <iomanip>
#include <iostream>
#include <fstream>
#include <new>
using namespace std;
struct kit
{
string arquivo; // a origem
int C; // colunas
int L; // linhas
int N; // tamanho, so pra nao mult. toda hora.
int* matriz; // a matriz
struct Par
{
int posicao;
int quantos;
}* status; // o mapa de repetidos
int n_repetidos; // o total
int calcula_repetidos();
int le(string arquivo); // le a matriz
kit(int, int, const char*); // o normal: LxC e arquivo
kit() : kit(5, 2, "entrada.txt") {};
~kit();
friend ostream& operator<<( ostream& sai, const kit& uma);
private:
kit::Par busca_menor();
kit::Par busca_menor(int);
};
The idea is simple: when declaring a kit
If the guy does not specify anything the program will try to read an array 2 x 5 of the file "input.txt" in the current directory. It is your original problem. But the problem does not depend on the size of the matrix or the file where it is so the convenient is to be able to pass as parameters, or not?
a program that uses this struct
int main(void)
{
kit teste;
cout << "(Testando com 5x2)\n" << teste << endl;
kit uma55(5, 5, "55.txt");
cout << "(Agora 5x5)\n" << uma55 << endl;
return 0;
}
teste
was declared without parameters so will use the size 5x2 and the file "input.txt". The cout
shows text and operator <<
has been redefined for this struct kit
so that will write what we program, whenever we read Cout << thing and coisa
for a kit
. This is typical of C++ and very convenient.
And I’m showing you an example, after all ;)
The second struct
will use a 5x5 array and the other file. There are examples below. You don’t need to type anything if you want to test and change. Just copy and paste from here :)
functions in the struct
They are only 2 methods and in fact everything walks alone, as you saw in main()
, because the builder of kit
, the function that creates each occurrence of kit
flame le()
to read the file and calcula_repetidos
to, well, calculate the repeated.
status
within the struct
is a pair vector where the repeated occurrences in the matrix are, first the position and then the number of repetitions. Only the values that have repetition will be there.
calcula_repetidos()
That is the code
int kit::calcula_repetidos()
{
Par res = busca_menor();
if (res.quantos > 1)
{ // guarda esse
*status = res;
n_repetidos = 1;
}
// tenta encontrar algum outro elemento
// a matriz pode ser constante
res = busca_menor(*(matriz+ res.posicao));
while (res.quantos > 0)
{
if (res.quantos > 1)
{ // guarda esse
status[n_repetidos] = res;
n_repetidos += 1;
}
int limite = *(matriz + res.posicao);
res = busca_menor( *(matriz+ res.posicao) );
};
return n_repetidos;
};
And the idea is to first identify the least of all in busca_menor()
and then while you have some new value go testing in busca_menor(limite)
if it repeats itself, using as limit the lowest value ever seen. As I said, it is the algorithm of Selection Sort(), the simplest of all. Check the code and ask if you don’t understand something
5 x 2 test file
1 2
3 4
5 6
7 8
9 9
5 x 5 test file
12 12 2 2 3
3 4 4 5 5
6 6 7 7 8
8 9 9 21 12
12 2 3 4 5
the result when rotating main()
as above
Lendo matriz 5x2 a partir de entrada.txt
(Testando com 5x2)
Matriz 5x2 lida de "entrada.txt"
1 2
3 4
5 6
7 8
9 9
1 elementos repetidos:
9 (2X)
Lendo matriz 5x5 a partir de 55.txt
(Agora 5x5)
Matriz 5x5 lida de "55.txt"
12 12 2 2 3
3 4 4 5 5
6 6 7 7 8
8 9 9 21 12
12 2 3 4 5
9 elementos repetidos:
2 (3X)
3 (3X)
4 (3X)
5 (3X)
6 (2X)
7 (2X)
8 (2X)
9 (2X)
12 (4X)
Without great pretensions, it’s just an example and I’ve tested almost nothing.
Here is the code, in a single file that can compile directly
#include "kit.h"
using namespace std;
int main(void)
{
kit teste;
cout << "(Testando com 5x2)\n" << teste << endl;
kit uma55(5, 5, "55.txt");
cout << "(Agora 5x5)\n" << uma55 << endl;
return 0;
}
kit:: kit(int l, int c, const char* nome) :
C(c), L(l), matriz(nullptr), status(nullptr),
n_repetidos(0), arquivo(nome), N(l*c)
{
int res = le(nome);
if (res < 0)
{
cerr << "Erro " << res << " lendo os dados de " << nome << endl;
return;
}
n_repetidos = calcula_repetidos();
};
kit:: ~kit()
{
delete[] matriz;
delete[] status;
}
kit::Par kit::busca_menor()
{
int menor = 0;
Par res;
res.quantos = 1;
for (int i = 1; i < N; i++)
{
if (*(matriz + i) < *(matriz + menor))
{
menor = i;
res.quantos = 1;
}
else
{
if (*(matriz + i) == *(matriz + menor)) res.quantos++;
}
}; // for()
res.posicao = menor;
return res;
};
kit::Par kit::busca_menor(int limite)
{
Par res;
res.quantos = 0;
int achou = 0;
int menor = 0;
for (auto i = 0; i < N; i++)
{
if (*(matriz + i) <= limite) continue;
// ao menos esse maior que limite
menor = i;
achou = 1;
break;
}; // for()
if (achou == 0) return res;
res.quantos = 1;
for (auto i = 0; i < N; i++)
{
if (*(matriz + i) <= limite) continue;
if (i == menor) continue;
if (*(matriz + i) < *(matriz + menor))
{
menor = i;
res.quantos = 1;
}
else
{
if (*(matriz + i) == *(matriz + menor)) res.quantos++;
}
}; // for()
res.posicao = menor;
return res;
};
int kit::calcula_repetidos()
{
Par res = busca_menor();
if (res.quantos > 1)
{ // guarda esse
*status = res;
n_repetidos = 1;
}
// tenta encontrar algum outro elemento
// a matriz pode ser constante
res = busca_menor(*(matriz+ res.posicao));
while (res.quantos > 0)
{
if (res.quantos > 1)
{ // guarda esse
status[n_repetidos] = res;
n_repetidos += 1;
}
int limite = *(matriz + res.posicao);
res = busca_menor( *(matriz+ res.posicao) );
};
return n_repetidos;
};
int kit::le(string arquivo)
{
ifstream entra { arquivo };
istream_iterator<int> in {entra};
istream_iterator<int> FIM {};
if (!entra.good())
{
cerr << "Erro tentando abrir " <<
arquivo << endl;
return -1;
}
// abriu o arquivo, entao aloca os vetores para ler
size_t tamanho = sizeof(int) * L * C; // o simples
// pode estar lendo de novo
if (matriz != nullptr) delete[] matriz;
if (status != nullptr) delete[] status;
matriz = new int[tamanho];
status = new Par[tamanho];
cerr << "Lendo matriz " << L << "x" << C <<
" a partir de " << arquivo << "\n";
for (int i = 0; i < L; i += 1)
for (int j = 0; j < C; j += 1)
{
if (in == FIM)
{
cout << "Fim de arquivo inesperado!\n";
delete[] matriz;
delete[] status;
matriz = nullptr;
return -1;
}; // if()
*(matriz + (i * C) + j) = *in++;
}
entra.close();
return L*C; // retorna o total de itens lidos para a matriz
}
ostream& operator<<(ostream& sai, const kit& uma)
{
cout << "\nMatriz " << uma.L << "x" << uma.C <<
" lida de \"" << uma.arquivo << "\"\n\n";
for (int i = 0; i < uma.L; i += 1)
{
for (int j = 0; j < uma.C; j += 1)
{
cout << setw(10) << *(uma.matriz + (i * uma.C) + j);
}
cout << "\n";
}
if (uma.n_repetidos < 1)
{
cout << "\nSem elementos repetidos\n";
return sai;
}
cout << "\n" << uma.n_repetidos << " elementos repetidos:\n\n";
for (int i = 0; i < uma.n_repetidos; i += 1)
{
cout <<
uma.matriz[uma.status[i].posicao] << " (" <<
uma.status[i].quantos << "X)\n";
}
return sai;
}
I’m not going to explain the whole show because it’s really boring and I don’t know if you need it, but feel free to ask me anything.
Thanks friend, I’ll get your tips and improve here.
– diogoBRRN