-3

I am building up a program where I create a vector of objects, the input variables that create the object are read from a .txt file. I want to check if the "ID" of the object introduced by the user exists in order to continue.

vector<Producto> vectorProductos;

while(file >> sID >> sDesc >> sUMed >> sFam >> sClass >> dVolumen >> dLongitud >> sPrecio){
    vectorProductos.push_back(Producto(sID, sDesc, sUMed,sFam, sClass, dVolumen, dLongitud, stringToDouble(sPrecio)));
    iNumProductos++;
}
file.close();

int iNumPartidas;
cout << "iNumPartidas? " << endl;
cin >> iNumPartidas;

for(unsigned int iP = 1; iP <= iNumPartidas; iP++){
    cout << endl << "Partida " << iP << ":" << endl;
    cout << "Clave de partida:\t";
    cin >> sPartida;
    for(unsigned int iPrd = 0; iPrd < iNumProductos; iPrd++){
        cout << endl << "Clave de producto " << iPrd+1 << ":\t";
        cin >> sClave;
        if(sClave == vectorProductos[iPrd].getClave()){
            cout << endl << "Cantidad:\t";
            cin >> iCantProdxP;
        }else{
            cout << "Producto no existe" << endl;
        }
    }
}

Producto class

#ifndef Producto_h
#define Producto_h

#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;

class Producto{
protected:
    string _sClave, _sDescripcion, _sUMed, _sClass, _sFam;
    double _dVolumen, _dPrecio, _dLongitud;

public:
    Producto();
    Producto(string, string, string, string, string, double, double, double);
    inline string getClave(){return _sClave;}
    inline string getDescripcion(){return _sDescripcion;}
    inline string getUMed(){return _sUMed;}
    inline string getFam(){return _sFam;}
    inline string getClass(){return _sClass;}
    inline double getVol(){return _dVolumen;}
    inline double getPrecio(){return _dPrecio;}
    inline double getLongitud(){return _dLongitud;}
    inline void setClave(string sClave){_sClave = sClave;}
    inline void setDescripcion(string sDescripcion){_sDescripcion = sDescripcion;}
    inline void setUMed(string sUMed){_sUMed = sUMed;}
    inline void setFam(string sFam){_sFam = sFam;}
    inline void setClass(string sClass){_sClass = sClass;}
    inline void setVol(double dVolumen){_dVolumen = dVolumen;}
    inline void setPrecio(double dPrecio){_dPrecio = dPrecio;}
    inline void setLongitud(double dLongitud){_dLongitud = dLongitud;}
    void toString();
};

Producto::Producto(){
    _sClave = "";
    _sDescripcion = "Falta descripcion";
    _sUMed = "N/A";
    _sFam = "Sin Familia";
    _sClass = "Sin clase";
    _dVolumen = 0.0;
    _dPrecio = 0.0;
    _dLongitud = 0.0;
}

Producto::Producto(string sClave, string sDescripcion, string sUMed, string sFam, string sClass, double dVolumen, double dLongitud, double dPrecio){
    _sClave = sClave;
    _sDescripcion = sDescripcion;
    _sUMed = sUMed;
    _sFam = sFam;
    _sClass = sClass;
    _dVolumen = dVolumen;
    _dPrecio = dPrecio;
    _dLongitud = dLongitud;
}

void Producto::toString(){
    cout << "\nProducto: " << _sClave;
    cout << "\nDescripcion: " << _sDescripcion;
    cout << "\nUnidad de Medida: " << _sUMed;
    cout << "\nFamilia: " << _sFam;
    cout << "\nClase: " << _sClass;
    cout << "\nVolumen: " << _dVolumen;
    cout << "\nLongitud: " << _dLongitud;
    cout << "\nPrecio: " << _dPrecio;
    cout << endl;
}

What I need is to see if that "ID" that the user is going to input actually exists and if not mark error. When I run my program I have to type in the ID of the first product to match it with the index number of the loop, and that is the only way it works but I need the program to match it with any "Producto" regardless of the position or index.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    Unrelated: No need to inline the functions in the class definition. C++ does it for you. `Producto::Producto()` and the friends outside the class definition on the other hand, these guys you need to `inline` if you're leaving them in the header. – user4581301 Jan 22 '19 at 00:43
  • 1
    Unrelated: there is no need for `iNumProductos++`. A `vector` always knows how big it is. – user4581301 Jan 22 '19 at 00:46
  • 1
    On topic: Add a `operator ==` to `Producto` and use [`std::find`](https://en.cppreference.com/w/cpp/algorithm/find). Help on writing `operator==`, and a lot of other information on operators in general, can be found at [What are the basic rules and idioms for operator overloading?](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading) – user4581301 Jan 22 '19 at 00:48
  • It might be worth noting that `inline` is no longer a suggestion to the compiler to replace a function call with the function body. Instead it now means that multiple definitions are allowed to coexist in the current translation unit. – alter_igel Jan 22 '19 at 01:15
  • 1
    @user4581301 `std::find_if()` would be more appropriate than `std::find()`, since only 1 field is being compared instead of all fields. – Remy Lebeau Jan 22 '19 at 01:40

1 Answers1

1

In your inner loop, you are prompting the user for an ID on every loop iteration and then comparing that ID only to the product at the index of the current loop iteration. You need to prompt the user one time BEFORE entering the loop and then compare the ID to every product until you find a match:

std::cout << endl << "Clave de producto:\t";
std::cin >> sClave;
bool found = false;

for (std::size_t iPrd = 0; iPrd < vectorProductos.size(); ++iPrd)
{
    if (sClave == vectorProductos[iPrd].getClave())
    {
        found = true;
        break;
    }
}

if (found) {
    // do something ...
}
else {
    std::cout << "Producto no existe" << std::endl;
}

Alternatively, you should use std::find_if() instead of searching manually, eg:

Producto.h

#ifndef Producto_h
#define Producto_h

#include <iostream>
#include <string>

class Producto
{
protected:
    std::string _sClave, _sDescripcion, _sUMed, _sClass, _sFam;
    double _dVolumen, _dPrecio, _dLongitud;

public:
    Producto();
    Producto(std::string, std::string, std::string, std::string, std::string, double, double, double);

    std::string getClave() const { return _sClave; }
    std::string getDescripcion() const { return _sDescripcion; }
    std::string getUMed() const { return _sUMed; }
    std::string getFam() const { return _sFam; }
    std::string getClass() const { return _sClass; }
    double getVol() const { return _dVolumen; }
    double getPrecio() const { return _dPrecio; }
    double getLongitud() const { return _dLongitud; }

    void setClave(std::string sClave) { _sClave = sClave; }
    void setDescripcion(std::string sDescripcion) { _sDescripcion = sDescripcion; }
    void setUMed(std::string sUMed) { _sUMed = sUMed; }
    void setFam(std::string sFam) { _sFam = sFam; }
    void setClass(std::string sClass) { _sClass = sClass; }
    void setVol(double dVolumen) { _dVolumen = dVolumen; }
    void setPrecio(double dPrecio) { _dPrecio = dPrecio; }
    void setLongitud(double dLongitud) { _dLongitud = dLongitud; }

    std::string toString() const;
};

std::istream& operator>>(std::istream &in, Producto &p);

#endif

Producto.cpp

#include "Producto.h"
#include <sstream>

std::istream& operator>>(std::istream &in, Producto &p)
{
    std::string sID, sDesc, sUMed, sFam, sClass, sPrecio;
    double dVolumen, dLongitud;

    if (in >> sID >> sDesc >> sUMed >> sFam >> sClass >> dVolumen >> dLongitud >> sPrecio)
    {
        p.setClave(sID);
        p.setDescripcion(sDesc);
        p.setUMed(sUMed);
        p.setFam(sFam);
        p.setClass(sClass);
        p.setVol(dVolumen);
        p.setLongitud(dLongitud);
        p.setPrecio(stringToDouble(sPrecio));
    }
    return in;
}

Producto::Producto() :
    _sClave(),
    _sDescripcion("Falta descripcion"),
    _sUMed("N/A"),
    _sFam("Sin Familia"),
    _sClass("Sin clase"),
    _dVolumen(0.0),
    _dPrecio(0.0),
    _dLongitud(0.0)
{
}

Producto::Producto(std::string sClave, std::string sDescripcion, std::string sUMed, std::string sFam, std::string sClass, double dVolumen, double dLongitud, double dPrecio) :
    _sClave(sClave),
    _sDescripcion(sDescripcion),
    _sUMed(sUMed),
    _sFam(sFam),
    _sClass(sClass),
    _dVolumen(dVolumen),
    _dPrecio(dPrecio),
    _dLongitud(dLongitud)
{
}

std::string Producto::toString() const
{
    std::ostringstream oss;
    oss << "Producto: " << _sClave;
    oss << "\nDescripcion: " << _sDescripcion;
    oss << "\nUnidad de Medida: " << _sUMed;
    oss << "\nFamilia: " << _sFam;
    oss << "\nClase: " << _sClass;
    oss << "\nVolumen: " << _dVolumen;
    oss << "\nLongitud: " << _dLongitud;
    oss << "\nPrecio: " << _dPrecio;
    return oss.str();
}

Main

#include <vector>
#include <algorithm>
#include "Producto.h"

std::vector<Producto> vectorProductos;

Producto p;
while (file >> p) {
    vectorProductos.push_back(p);
}
file.close();

...

std::string sClave;

std::cout << std::endl << "Clave de producto:\t";
std::cin >> sClave;

auto iter = std::find_if(vectorProductos.begin(), vectorProductos.end(),
    [&](const Producto &p){ return (p.getClave() == sClave); });

if (iter == vectorProductos.end()) {
    std::cout << "Producto no existe" << std::endl;
}
else {
    std::cout << "Producto existe" << std::endl;

    // use *iter as needed...
    std::cout << iter->toString() << std::endl;

    // if you need the index of the found product, you can use:
    // auto index = std::distance(vectorProductos.begin(), iter);
}

...
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770