Program nie wyświetla dobrze zawartości std::vector

0
#include <iostream>
#include <vector>

typedef std::vector<int>numbers;
typedef std::vector<int>::iterator it;

void makeVector(int number,numbers &num,const int range)
{
    for(int i=0;i<range;i++)
    {
        std::cout<<"Podaj liczbe: ";
        std::cin>> number;
        num.push_back(number);
    }
}

void showVector(numbers num,it iter)
{
    std::cout<<"\n";
    for(;iter!=num.end();iter++)
    {
        std::cout<<*iter<<"\n";
    }
}

void eraseVectorElement(int number,numbers &num,it iter)
{
    std::cout<<"\n";
    std::cout<<"Ktory element vektora usunac: ";
    std::cin >> number;
    number--;

    iter = num.begin();

    num.erase(iter+number);
}

int main()
{
    const int SIZE_VECTOR = 5;
    numbers numb;
    it iteration;

    int index;
    makeVector(index,numb,SIZE_VECTOR);

    iteration = numb.begin();
    showVector(numb,iteration);

    eraseVectorElement(index,numb,iteration);

    showVector(numb,iteration);
    return 0;
}
4

Przekazywanie parametru przez wartość i referencję

void showVector(numbers num,it iter)

przekazujesz wektor przez kopię i przekazujesz iterator do innego wektora jako parametr początkowy.

Ogółem masz dziwną praktykę zapisywania zmiennych wewnętrznych funkcji jako parametrów - nie rób tego.

Funkcje, które bezpośrednio nie odpowiadają za I/O nie powinny tego wykonywać (tutaj tylko showVector się nadaje).

A funkcja makeVector powinna wektor zwracać, a nie przyjmować przez out argument. Po coś te typy zwracane są.

2

Dodam: miejsce typedefów jest w archiwach historii.
Z normalną notacją by cię szybciej "piknęło" że Twój kod mocno odbiega od dobrych przykładów.

0

Rozumiem,że tak to powinno poprawnie wyglądać ? (Kod działa)

#include <iostream>
#include <vector>


void showVector(std::vector<int> &num,std::vector<int>::iterator iter)
{
    iter = num.begin();
    std::cout<<"\n";
    for(;iter!=num.end();iter++)
    {
        std::cout<<*iter<<"\n";
    }
}

int main()
{
    const int SIZE_VECTOR = 5;
    std::vector<int>numbers;
    std::vector<int>::iterator it;
    int index;

    for(int i=0;i<SIZE_VECTOR;i++)
    {
        std::cout<<"Podaj liczbe: ";
        std::cin>> index;
        numbers.push_back(index);
    }

    showVector(numbers,it);

    std::cout<<"\n";
    std::cout<<"Ktory element vektora usunac: ";
    std::cin >> index;
    index--;

    it = numbers.begin();
    numbers.erase(it+index);

    showVector(numbers,it);

    return 0;
}
0

Tak pewnie działa, ale sygnatura funkcji showVector powinna wyglądać tak:

void showVector(std::vector<int> const& vec)
0
#include <iostream>
#include <vector>


void showVector(std::vector<int> const &num)
{
    std::cout<<"\n";
    for(int v: num)
    {
        std::cout<<v<<"\n";
    }
}

int main()
{
    const int SIZE_VECTOR = 5;
    std::vector<int>numbers;
    std::vector<int>::iterator it;
    int index;

    for(int i=0;i<SIZE_VECTOR;i++)
    {
        std::cout<<"Podaj liczbe: ";
        std::cin>> index;
        numbers.push_back(index);
    }

    showVector(numbers);

    std::cout<<"\n";
    std::cout<<"Ktory element vektora usunac: ";
    std::cin >> index;
    index--;

    it = numbers.begin();
    numbers.erase(it+index);

    showVector(numbers);

    return 0;
}

No i niestety wyrzuca mi jakas losowa liczbe w konsoli i petla wyswietlajaca wykonuje sie w nieskonczonosc :(
https://devcode.pl/cpp11-zakresowa-petla-for/

1

https://wandbox.org/permlink/vC1t9br1FzSTGL3f

U mnie działa. Tak na boku: spacje nie gryzą, można je wstawiać między operatory dla czytelności.

0

Funkcje, które bezpośrednio nie odpowiadają za I/O nie powinny tego wykonywać

Czyli wszystkie rzeczy związane z wprowadzaniem danych przez uzytkownika lepiej wsadzać do main.cpp jeśli operujemy na konsoli ?

1
Quanti994 napisał(a):

Funkcje, które bezpośrednio nie odpowiadają za I/O nie powinny tego wykonywać

Czyli wszystkie rzeczy związane z wprowadzaniem danych przez uzytkownika lepiej wsadzać do main.cpp jeśli operujemy na konsoli ?

  1. Ja zawsze doradzam w podobnych szkolnych programach podanie referencji do strumienia jako argument do funkcji typu "wprowadź". Wtedy Twoje pytanie otrzymuje raczej sensowną odpowiedź
  2. w sensownym projekcie obiektowym elementarne dane w obiekcie są niepubliczne, i wtedy by były niedostępne w main()
1

Zamiast funkcji showVector możesz użyć oszczędzającego kod przeładowania operatora <<, działającego dla standardowych kontenerów zawierających typy wbudowane. (C++ 17)

#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <algorithm>

using namespace std;

template< typename T >
using IsCorrectInput = enable_if_t< is_integral_v<T> || is_floating_point_v<T> || is_same<string,T>::value , bool >;

template< template<typename,typename> typename Container, typename T, typename Allocator, IsCorrectInput<T> = true >
ostream& operator<<( ostream& out , const Container<T,Allocator>& container )
{
    copy( container.cbegin() , container.cend() , ostream_iterator<T>(out," ") ); out << "\n";
    return out;
}

int main()
{
    vector<int> data1 {23,54,-23,887};
    list<double> data2 {-2.5,4.02,-0.87,-19.9};

    cout << data1;
    cout << data2;

    return 0;
}

https://wandbox.org/permlink/h9PkTiss7f74ASwX

0

Nie czytałem wątku, ale nie sądziłem, że może być w C++ problem z wyświetleniem wektora; swoją drogą mogliby w końcu nadpisać wyjście, żeby cout << v dawało coś normalnego, np.: [1, 2, 3].

0

Dziękuje wszystkim za porady.
Na szybko jeszcze się spytam,czy poniższy zapis jest ok ? (działa,ale wiadomo...)

#include <iostream>
#include <array>

template<std::size_t SIZE>
void showArray(std::array<int,SIZE>&arr)
{
    std::cout<<'\n';
    for(auto a:arr)
    {
        std::cout<<a<<" ";
    }
}


int main()
{
    std::array<int,5>numbers;

    for(auto &a: numbers)
    {
        std::cout<<"Wprowadz liczbe: ";
        std::cin >> a;
    }
    showArray(numbers);
    return 0;
}
0

Jest ok, ale:

  • jak robisz taki szablon, to możesz go zgeneralizować dla każdej kontenera kompatybilnego z ranged for
  • spacje nie gryzą, możesz je stawiać między identyfikatorami ;​)
0

Funkcje, które bezpośrednio nie odpowiadają za I/O nie powinny tego wykonywać (tutaj tylko showVector się nadaje).

Jeśli dobrze zrozumiałam taki zapis jest niepoprawny:

#include <iostream>

struct Point
{
    int x;
    int y;
    void addPoint();
    void viewPoint();
};

void Point::addPoint()
{
    std::cout<<"Podaj wspolrzedna x punktu P: ";
    std::cin >> x;
    std::cout<<"Podaj wspolrzedna y punktu P: ";
    std::cin >> y;
}
void Point::viewPoint()
{
    std::cout<<"Wpolrzedne punktu P = ("<<x<<","<<y<<")\n";
}

int main()
{
    Point p;
    p.addPoint();
    p.viewPoint();

    return 0;
}

Natomiast ten jest poprawny i tak powinno się to robić:

#include <iostream>

struct Point
{
    int x;
    int y;
};

std::ostream &operator<<(std::ostream &output,const Point &p)
{
    output << "Wspolrzedne punktu P = ("<<p.x<<","<<p.y<<")\n";
    return output;
}

std::istream &operator>>(std::istream &input, Point &p)
{
    input >> p.x >> p.y;
    return input;
}

int main()
{
    Point p;
    std::cout <<"Podaj wsolrzedna x oraz y punktu P: \n";
    std::cin >> p;
    std::cout << p;

    return 0;
}
0

Tak, bardzo ładnie. Chociaż przeładowanie ostream nie powinno zakładać tego, jak wyjście ma być wyświetlone:

  • czy na pewno "Wspolrzedne punktu P = " jest integralną częścią punktu? Co jeśli będziesz chciała napisać program obsługujący wiele języków?
  • czy na pewno po wypisaniu punktu musi zostać wypisana nowa linia?

Tam, gdzie masz pojedyncze znaki możesz je umieszczać w '', ale nie jest to wielki błąd (imo) jeśli tego nie zrobisz.

#include <iostream>

struct Point
{
    int x;
    int y;
};

std::ostream &operator<<(std::ostream &output,const Point &p)
{
    return output << '(' << p.x << ',' << p.y << ')';
}

std::istream &operator>>(std::istream &input, Point &p)
{
    return input >> p.x >> p.y;
}

int main()
{
    Point p;
    std::cout <<"Podaj wsolrzedna x oraz y punktu P: \n";
    std::cin >> p;
    std::cout << "Wspolrzedne punktu P = " << p << '\n';

    return 0;
}
0

addPoint sugerowało by, że do obiektu klasy Point można dodawać punkty, czyli jest tam jakiś kontener wewnątrz. Przynajmniej mi by się tak wydawało. Zamiast tego konstruktor albo przeciążanie operatorów, ale to dużo zależy od tego jak ma ta klasa być w przyszłości używana w kodzie.

operator<< mógłby wyświetlać coś w tym stylu <Point: x=0, y=0>, będzie krócej. Usuń też znak \n bo jak będziesz chciała w innym miejscu wyświetlić kilka punktów w jednej linii to pozbędziesz się takiej możliwości. Lepiej to zrobić w main -> std::cout << p << std::endl;.

0

Ok dzięki.
Mam tylko ostatnie pytanie. Dlaczego gdy chcę funkcję przeciążające operatory I/O wsadzić do struktury:

struct Point
{
    int x;
    int y;
    std::ostream &operator<<(std::ostream &output,const Point &p);
    std::istream &operator>>(std::istream &input, Point &p);
};
```
To wyrzuca mi błąd : ```error: 'std::ostream& Point::operator<<(std::ostream&, const Point&)' must take exactly one argument```. Rozumiem,że w przypadku klasy trzeba je zdefiniować jako funkcje zaprzyjaźnione ale jak to tu ma wyglądać ?
0

Musisz zadeklarować ją jako friend lub poza klasą.

https://dsp.krzaq.cc/post/304/jak-przeladowywac-operatory-w-mojej-klasie/

1 użytkowników online, w tym zalogowanych: 0, gości: 1