Program wyliczajacy srednia

0

Proszę o pomoc w programie jak liczyć średnią z podanych egzaminów. Jak napisać funkcje aby srednia była policzona dla poszczególnych osób.

#include <iostream>
#include <cstdlib>
#include <conio.h>
#include <windows.h>
using namespace std;

struct Oceny
{
    int numer;
    float srednia;
};

void zapisz_do_bazy(Oceny s[], int n,int p,int a) // funkcja dodaje oceny uczniow do bazy
{
for (int i=0;i<n;i++)
{
for (int i=0;i<n;i++)


s[i].numer = i+1; // numer ucznia

        cout<<s[i].numer<< ".";
    
        for(int i=0;i<1;i++)
        {
		
		cout<<"Podaj imie i nazwisko studenta:";
	
		char wyraz[]="";
	
		cin>> wyraz;
	cin.getline( wyraz, 50 );
			for(i=i+1;i<=p;i++)
			
			{
			
		cout<<" Ocena z egzaminu nr",cout<<i;cout<<": ";
        cin>>a;
        
		}
}
 }
}


void srednia(Oceny s[],int n,int p) // funkcja liczy poszczegolne srednie uczniow i srednia wszystkich uczniow
{
    float srednia;

    for(int i=0;i<n;i++)
    {
    cout<<"\n Uczen nr."<<s[i].numer<<endl;
    for (int i = 0; i < n; i++)
    
	s[i].srednia = (s[i].numer/p); // srednia poszczegolnych uczniow

    cout<<" Srednia: "<< s[i].srednia<<endl;
    cout<<" - - - - - - - - - - -\n\n";
 }
    
	}
    

int main(int argc, char *argv[])

{
		
int n;int p;int a;
cout<<"Wprowadz liczbe studentow: ";
cin>>n; // ile uczniow chcemy zapisac
cout<<"Podaj liczbe egzaminow: ";
cin>>p,cout<<"\n";
Oceny *s = new Oceny [n];

cout<<"Wprowadz teraz imie,nazwisko studentow, oraz ich oceny  z egzamminu:\n\n";
zapisz_do_bazy(s,n,p,a);
srednia(s,n,p);

cout<<"\n";
system("PAUSE");
return EXIT_SUCCESS;
}

Nie wiem czy dobrze.

0

Przepraszam wkleiłem przez przypadek bo w innym pliku miałem tylko to.

1
char wyraz[]="";
	
		cin>> wyraz;
	cin.getline( wyraz, 50 );

Niedobrze tu jest mocno.

EDIT: Wyjaśniam.

Rzecz najważniejsza: char wyraz[]="" - to jest wyraz pusty, i tylko na wyraz pusty masz pamięć. cin.getline(wyraz, 50) – wczytujesz do 50 znaków, podczas gdy pamięć zarezerwowałeś na 0. To ma prawo działać tylko przypadkiem. Będziesz miał szczęście, jeśli ci się program wywali spektakularnie; może być i tak, że będzie źle działał na milion różnych sposobów w miejscach zupełnie odległych od tego problemu.

Ogólnie, wczytywanie powinno wyglądać mniej więcej tak:

char wyraz[50];
cin.getline(wyraz, 50);

Rezerwujesz pamięć na 50 znaków i do tylu wczytujesz. <small>Uściślenie – wczytujesz w ten sposób tylko do 49 znaków, z przyczyn technicznych. Ale to nieistotne.</small>

Druga rzecz:

cin>> wyraz;
	cin.getline( wyraz, 50 );

Rozumiem, że cin >> wyraz to ma być wczytanie imienia, a cin.getline(wyraz, 50) to ma być wczytanie nazwiska? Ale przecież nazwisko wczytujesz do tej samej zmiennej, co imię. Nadpisujesz imię. Tracisz w ten sposób informacje o imieniu.

3

Naprawdę chciałam pomóc ale ten kod jest tak niechlujny :(

  • Przy buildzie - 5 warning(s)
  • Brak formatowania - zero czytelności
  • for (int i=0;i<n;i++) - używasz wszędzie zmiennej i a masz pętle w pętli - zero czytelności

Nikt nie będzie tracił czasu na babranie się w syfie, jeśli ty nie poświęcisz chwili, żeby to było w znośnej postaci.

2

@Piotr9592 Przeglądam Twój kod dalej.

void zapisz_do_bazy(Oceny s[], int n,int p,int a) // funkcja dodaje oceny uczniow do bazy
{
for (int i=0;i<n;i++)
{
for (int i=0;i<n;i++)

Na pewno dwie pętle, jedna w drugiej? Nie wstawiłeś tej drugiej czasem przez omyłkę?

Okej, ignoruję to, usuwam drugą pętlę. Funkcja wygląda jakoś tak:

void zapisz_do_bazy(Oceny s[], int n,int p,int a) // funkcja dodaje oceny uczniow do bazy
{
for (int i=0;i<n;i++)
{

  // Wczytywanie imienia i nazwiska i-tego ucznia tutaj powinno być, wycięte dla czytelności

			for(i=i+1;i<=p;i++)
			
			{
			
		cout<<" Ocena z egzaminu nr",cout<<i;cout<<": ";
        cin>>a;
        
		}
 }
}

Zdajesz sobie sprawę, co się tutaj dzieje? for(int i = 0; i < n; ++i) - pętla, jej licznikiem jest i. Za każdym przebiegiem pętli i zwiększa się od 1 i kiedy i dojdzie do n, pętla się kończy.

ALe w środku pętli masz:
for(i=i+1; i<=p; i++)

TO JEST WCIĄŻ TO SAMO i!!! Jak ma działać pętla zewnętrzna, jeśli w środku modyfikujesz licznik?

Załóżmy, że n=10, a p=5.

Pierwszy przebieg pętli zewnętrznej : i=0. Wchodzimy do for(i=i+1; i<=p; i++). Po kolei: i=i+1, czyli i ustawia ci się na 1. Potem pętla wewnętrzna ci się przebiega aż i stanie się równe p, czyli 5. Wracamy do pętli zewnętrznej: for(int i = 0; i < n; ++i). Przebieg pętli się skończył, i się zwiększa i staje się równe 6 (czyli w ogóle ignorujesz uczniów o numerach od 1 do 5). Jedziemy dalej, znów dochodzimy do pętli wewnętrznej. for(i=i+1; i<=p; i++) - na „dzień dobry” zwiększasz i, staje się ono równe 7. Pętla się kończy, gdy i jest większe od p, a skoro i jest równe 7, a p jest równe 5, to pętla nie wykona się ani razu. Nie wczytasz ocen.

2

@Piotr9592

Błędy kolejne.

void zapisz_do_bazy(Oceny s[], int n,int p,int a) // funkcja dodaje oceny uczniow do bazy

// Kod tutaj, usunięty dla czytelności

			for(i=i+1;i<=p;i++)
			
			{
			
		cout<<" Ocena z egzaminu nr",cout<<i;cout<<": ";
        cin>>a;
        
		}
}

Znowu to samo: wczytujesz w pętli do tej samej zmiennej. Każde następne wczytanie nadpisuje dane z poprzedniego. W dodatku nic nie robisz ze zmienną a. Tracisz wczytane wartości. Rozwiązanie: struktura Oceny musi posiadać tablicę zawierającą oceny każdego ucznia.

1

Wiesz co, @Piotr9592 , mam propozycję. Spróbuj najpierw napisać taki program, który wczyta w pętli średnią każdego spośród n uczniów, i później w pętli dla każdego ucznia wypisze wczytaną wcześniej średnią. Potem ten program rozwiniesz tak, by sam liczył średnie.

Najpierw ogarnij mniejszy program, to zdołasz ogarnąć większy.

Myślę, że w ten sposób szybciej dojdziesz do rezultatu.

EDIT: Najpierw chodzi mi o program, który zachowywałby się po prostu w ten sposób:

Podaj liczbe uczniow:
5
Podaj imie i nazwisko 1. ucznia:
Alojzy Szpak
Podaj srednia ocen 1. ucznia:
3.7
Podaj imie i nazwisko 2. ucznia:
Maria Pieron
Podaj srednia ocen 2. ucznia:
1.9
Podaj imie i nazwisko 3. ucznia:
Magdalena Kowalska
Podaj srednia ocen 3. ucznia:
4.1
Podaj imie i nazwisko 4. ucznia:
Szymon Nowak
Podaj srednia ocen 4. ucznia:
2.4
Podaj imie i nazwisko 5. ucznia:
Marcin Paczkowski
Podaj srednia ocen 5. ucznia:
5.6

Uczen Alojzy Szpak ma srednia 3.7
Uczen Maria Pieron ma srednia 1.9
Uczen Magdalena Kowalska ma srednia 4.1
Uczen Szymon Nowak ma srednia 2.4
Uczen Marcin Paczkowski ma srednia 5.6

Tylko tyle na razie. Zrobisz to, pogadamy dalej.

0

Problem leży w tym jak wczytać imiona i nazwiska (ZE SPACJĄ) jeśli wpisze ze spacja to i tak cout<<imie; wczyta tylko imie a nie imie i nazwisko.
O tę część programu chodzi. Próbowałem z cin.get ale to chyba działa tylko do pisanego tekstu przez użytkownika. A ja chcę wczytać z tego co wpisałem wcześniej.


for(int i=1;i<n+1;i++)
{
cout<<"Uczen "; cout<<imie;

cout<<" ma srednia: "<<a<<endl;

}

}

A cały kod:

#include<iostream>
#include <cstdlib>
#include <conio.h>
#include <windows.h>

using namespace std;

struct Dane
{public:
	char imie,nazwisko;//liczba osob
	int numer; 	
  
};
int main(int argc, char *argv[])
{
int n;
float a;
string imie;
const short rozmiar=50;
char lancuch[rozmiar];


cout<<"Podaj liczbe uczniow: ";
cin>>n;
	{
		for(int i=1;i<n+1;i++)	
	{
cout<<"Podaj imie i nazwisko "<<i;cout<<". ucznia: "<<endl;
cin>>imie;
cin.getline( lancuch, rozmiar);
cout<<"Podaj srednia ocen "<<i;cout<<". ucznia: "<<endl;
cin>>a;
}
}
{

for(int i=1;i<n+1;i++)
{
	
	
	cout<<"Uczen ";	cout<<imie;
	
	cout<<" ma srednia: "<<a<<endl;
	
}

}
	




system("PAUSE");
return EXIT_SUCCESS;
}
3

Nie wypiszesz tych danych co wczytales wczesniej, bo ich nigdzie nie zapamiętujesz, pamiętasz ostatnie tylko - wróć do książki, bo uczysz się po łebkach i nic nie rozumiesz!

1
  1. Zapoznaj się z pojęciem formatowania kodu: http://4programmers.net/Forum/998482
  2. Nie naduzywaj inkrementacji przyrostkowej: http://4programmers.net/Forum/1101404 for(int i=1;i<n+1;++i) - zadziała tak samo ale uchroni przed ewentualnymi problemami
  3. Warunek i<n+1 jest tym samym co i<=n z tym że ten ostatni szybciej się wykona.
  4. Naucz się iterować od zera, przyda ci się to już w tym projekcie.
0

Zmieniłem troszkę dodałem
string imie[20];
string nazwisko[20];
Jest problem ze zmienna a czyli srednia wczytuje tylko ostatnia dla kazdej osoby.

#include<iostream>
#include <cstdlib>
#include <conio.h>
#include <windows.h>
#include <stdio.h>

using namespace std;

struct Dane
{
	char imie,nazwisko;//liczba osob
	int numer; 	
  
};
int main(int argc, char *argv[])
{
	int n;
	float a;
	string imie[20];
	string nazwisko[20];
	const short rozmiar=50;
	char lancuch[rozmiar];
	cout<<"Podaj liczbe uczniow: ";//podaje liczbe osob
	cin>>n;
	{
		for(int i=1;i<=n;++i)	
	{
cout<<"Podaj imie i nazwisko "<<i;cout<<". ucznia: "<<endl;    //podaje dane osob
	cin>>imie[i];cin>>nazwisko[i];                       //wczytuje z klawiatury imie oraz nazwisko
	cin.getline( lancuch, rozmiar);
	cout<<"Podaj srednia ocen "<<i;cout<<". ucznia: "<<endl; 
	cin>>a;                                                  //wczystuje z klawiatury podana srednia
}
}
{
const short rozmiar=50;
char lancuch[rozmiar];
for(int i=1;i<n+1;i++)
{
		
	cout<<"Uczen ";	
	

cout<<imie[i]<<" ";
cout<<nazwisko[i];
cout<<" ma srednia: ";
cout<<a<<endl;              //BLAD!!!
}
}
system("PAUSE");
return EXIT_SUCCESS;
}
2

EDIT: O przepraszam, w międzyczasie wstawiłeś następny kod. Ten mój post tyczy się twojego POPRZEDNIEGO kodu. Już patrzę na następny.

for(int i=1;i<n+1;i++)    
    {
cout<<"Podaj imie i nazwisko "<<i;cout<<". ucznia: "<<endl;
cin>>imie;
cin.getline( lancuch, rozmiar);
cout<<"Podaj srednia ocen "<<i;cout<<". ucznia: "<<endl;
cin>>a;
}

Masz 1 zmienną imię, 1 zmienną lancuch, 1 zmienną a. Do każdej z tych zmiennych zapisujesz n wartości. Tak to nie idzie. Każda zmienna przechowuje 1 wartość, a jeżeli próbujesz do niej zapisać następną, to ta druga NADPISUJE tą pierwszą.

Przykład, „jak to działa”.

    #include <iostream>
    #include <string>
    using namespace std;
     
    int main() {
    	string slowo;

    	cout << "Podaj 1. slowo:\n";
    	cin >> slowo;
    	cout << "Podaj 2. slowo:\n";
    	cin >> slowo;
     
    	cout << "Zawartosc zmiennej slowo: " << slowo << '\n';
    	cout << "Zawartosc zmiennej slowo po raz drugi: " << slowo << '\n';

        system("pause");
        return 0;
    }

Uruchom ten przykładowy program, daj mu 2 słowa (np. Pianino i Fortepian), i zobacz, co się stanie.

Aby rozwiązać ten problem, potrzebujesz TABLICY zmiennych. Tablica ma mieć miejsce na tyle wartości, ile chcesz móc pamiętać.


Tyle jeśli chodzi o błędy. Teraz napiszę o kilku sprawach w kwestii tzw. „ładnego kodu”. Czyli – o co konkretnie rzucają się wszyscy ci, którzy zarzucają Ci niechlujność.


string imie;
const short rozmiar=50;
char lancuch[rozmiar];

To jest oczywiście poprawne. Ale po co? Chodzi mi o to, że zmienne typu string duplikują funkcjonalność tablic znaków, tyle że łatwiej się ich używa. Na twoim miejscu zdecydowałbym się (dla prostoty), czy chcę używać stringów, czy tablic znaków (char lancuch[costam]). Czyli albo:

string imie;
string nazwisko;

albo:

const short rozmiar = 50;
char imie[rozmiar];
char nazwisko[rozmiar];

(Skoro już sam zacząłeś używać stringów, to proponowałbym to pierwsze, bo trudniej o błędy).

ALe jeszcze raz: to co tu piszę, to tylko kwestia prostoty, nie poprawności. Tu akurat „twardego” błędu nie ma.


char lancuch[rozmiar];

Nazewnictwo. Nazywasz zmienną lancuch, a przechowujesz w niej nazwisko. To nie byłoby lepiej nazwać tej zmiennej tak: char nazwisko[rozmiar]?


Na marginesie: nie przyszło Ci do głowy, że możesz przechowywać imię i nazwisko RAZEM?

string imienazwisko;
cout << "Podaj imie i nazwisko:\n";
getline(cin, imienazwisko);

Albo:

char imienazwisko[50];
cout << "Podaj imie i nazwisko:\n";
cin.getline(imienazwisko, 50);

Niestety, o jednym trzeba pamiętać: kiedy używasz tablic znaków, to piszesz cin.getline(zmienna, liczbaZnakow). Kiedy używasz stringów, to piszesz getline(cin, zmienna). Życie.


struct Dane
{public:
    char imie,nazwisko;//liczba osob
    int numer;     
 
};

Po co definiujesz strukturę, skoro nigdzie niżej z niej nie korzystasz?

Pomijając to, że struktura jest niewykorzystana:


struct Dane
{public:

public jest zbędne (ale nie niepoprawne), kiedy używasz struct.


    char imie,nazwisko;

UWAGA – TWARDY BŁĄD. Byłby, gdybyś użył tej struktury.

char imie – uwaga, to jest JEDEN znak! JEDNA litera! Rzadko kiedy imiona składają się tylko z jednej litery. To samo z nazwiskiem.

DO przechowywania napisów (a takimi są imiona i nazwiska) musisz używać tablic znaków, albo stringów, o których pisałem wyżej.


Zbędne klamerki.

cin>>n;
    {
        for(int i=1;i<n+1;i++)

Po co klamerka przed for?

TO samo tutaj:

cin>>a;
}
}
{
 
for(int i=1;i<n+1;i++)

Nie jest to niepoprawne, ale może się stać, gdybyś zaczął w tych zbędnych klamerkach deklarować jakieś zmienne.


#include <conio.h>
#include <windows.h>

Te nagłówki są zbędne, bo nie wykorzystujesz oferowanej przez nie funkcjonalności. Można je wyrzucić. Nie znaczy to, że ich dołączenie jest niepoprawne.


Z drugiej strony, skoro używasz zmiennych typu string:

string imie;

To musisz dołączyć nagłówek:

#include <string>

Twój kod może, ale nie musi działać, nawet jeśli tego nagłówku nie dołączysz. Można niedołączenie tego nagłówku uważać za „twardy” błąd.


Formatowanie. Tutaj pokażę ci po prostu na przykładzie, jak by moi „przedpiścy” chcieli, żeby twój kod wyglądał (nic nie zmieniałem w kwestii poprawności oprócz nagłówków i klamerek):

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
 
struct Dane
{
public:
    char imie, nazwisko;
    //liczba osob
    int numer;     
 
};

int main(int argc, char *argv[])
{
    int n;
    float a;
    string imie;
    const short rozmiar=50;
    char lancuch[rozmiar];
 
    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    
    for(int i=1;i<n+1;i++)    
    {
        cout << "Podaj imie i nazwisko " << i << ". ucznia: " << endl;
        cin >> imie;
        cin.getline(lancuch, rozmiar);
        cout << "Podaj srednia ocen "<< i << ". ucznia: " << endl;
        cin >> a;
    }
 
    for(int i=1;i<n+1;i++)
    {
        cout << "Uczen " << imie;
        cout << " ma srednia: " << a << endl;
    }
    
    system("PAUSE");
    return EXIT_SUCCESS;
}
2

Zostawiając w studencie nieużywane imie i nazwisko, dorzucając parę rzeczy na przyszłość;

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <type_traits>
#include <iterator>
#include <cmath>
#include <limits>
#include <numeric>
#include <cassert>

#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
using namespace std;

template<typename floating_point>
bool is_close(floating_point a, floating_point b, floating_point epsilon = numeric_limits<floating_point>::epsilon()) { 
    return fabs(a - b) < epsilon; 
}

struct MarkRepr{
    using floating_point_type = long double;
    
    char repr[3];
    floating_point_type value;
};

constexpr MarkRepr marks_table[] = {
    {{'2', '\0', '\0'}, 2.0},
    {{'3', '\0', '\0'}, 3.0}, {{'3', '+', '\0'}, 3.5},
    {{'4', '\0', '\0'}, 4.0}, {{'4', '+', '\0'}, 4.5},
    {{'5', '\0', '\0'}, 5.0}, 
};

enum class Mark: size_t{
    min = 0,
    max = extent<decltype(marks_table)>::value,
};

constexpr bool is_valid(Mark mark){
    return Mark::min <= mark && mark < Mark::max;
}

Mark operator ""_mark(long double val){
    auto find_result = find_if(begin(marks_table), end(marks_table), [&](MarkRepr mrepr){
        return is_close(val, mrepr.value);
    });
    size_t dist = abs(distance(find_result, begin(marks_table)));
    auto result = static_cast<Mark>(dist);
    assert(is_valid(result));
    return result;
}

string to_string(MarkRepr mrepr){
    return string{ begin(mrepr.repr), end(mrepr.repr) };
}

string to_string(Mark mark){
    auto repr = marks_table[static_cast<underlying_type_t<Mark>>(mark)];
    return to_string(repr);
}

MarkRepr::floating_point_type mark_value(Mark mark){
    auto repr = marks_table[static_cast<underlying_type_t<Mark>>(mark)];
    return repr.value;
}

auto value_of(Mark mark){
    return mark_value(mark);
}

Mark to_mark(const string &str){
    auto find_result = find_if(begin(marks_table), end(marks_table), [&](const MarkRepr &mrepr){
        return to_string(mrepr) == str;
    });
    
    size_t dist = abs(distance(find_result, begin(marks_table)));
    auto result = static_cast<Mark>(dist);
    assert(is_valid(result));
    return result;
}

istream &operator>>(istream &in, Mark &mark){
    string str;
    in >> str;
    mark = to_mark(str);
    return in;
}

ostream &operator<<(ostream &out, Mark mark){
    return out << to_string(mark);
}

struct Student{
    string name, surname;
    vector<Mark> marks;
};

int main() {
    using boost::copy;
    using boost::adaptors::transformed;
    
	const vector<Student> students = {
        {"Piotr", "Pierwszy", {3.0_mark, 3.0_mark, 4.0_mark, 5.0_mark}},
        {"Adam", "Drugi", {3.0_mark, 3.5_mark, 3.0_mark, 4.5_mark}}
    };
    
    for(auto &student: students){
        vector<long double> values(student.marks.size());
        boost::copy(
            student.marks | transformed(mark_value),
            begin(values));
        cout << accumulate(begin(values), end(values), 0.0) / values.size() << endl;
    }
    
	return 0;
}

http://melpon.org/wandbox/permlink/vi7VxYFiAlaFPU42

1

Dobra, komentarze nt. Twojego ostatniego kodu.

    int n;
    float a;
    string imie[20];
    string nazwisko[20];
    const short rozmiar=50;
    char lancuch[rozmiar];
    cout<<"Podaj liczbe uczniow: ";//podaje liczbe osob
    cin>>n;
    {
        for(int i=1;i<=n;++i)    
    {
cout<<"Podaj imie i nazwisko "<<i;cout<<". ucznia: "<<endl;    //podaje dane osob
    cin>>imie[i];cin>>nazwisko[i];                       //wczytuje z klawiatury imie oraz nazwisko

Trochę lepiej, ale!

Chcesz pamiętać n uczniów. A piszesz: string imie[20], string nazwisko[20]. Tak zapamiętujesz dane dokładnie 20 uczniów, a nie n uczniów. Jeśli n jest większe niż 20, to masz problem i Twój program może się wywalić. Z kolei jeśli n jest mniejsze niż 20, to niepotrzebnie tracisz pamięć na nadmiarowych uczniów.

Należy napisać: string *imie = new string[n]; To samo z nazwiskiem.


cin>>imie[i];cin>>nazwisko[i];                       //wczytuje z klawiatury imie oraz nazwisko
    cin.getline( lancuch, rozmiar);

Ile wczytujesz? Wczytałeś już imię i nazwisko, to co tu jeszcze robi cin.getline( lancuch, rozmiar);? Co chcesz w ten sposób wczytać?

Podasz swojemu programowi imię i nazwisko, a on dalej będzie czekał na kolejne dane, bo ma jeszcze to cin.getline.


    const short rozmiar=50;
    char lancuch[rozmiar];
    
  //kod tutaj, usunięty dla czytelności
{
const short rozmiar=50;
char lancuch[rozmiar];

//kod tutaj, usunięty dla czytelności
}

Po co 2 razy deklarujesz lancuch i rozmiar i jeszcze sztucznie mnożysz klamerki, żeby ci się to wszystko skompilowało? Teoretycznie nie jest to niepoprawne, ale jest to niepotrzebne mnożenie bytów i niepotrzebne komplikowanie i przepis na to, żeby stracić kontrolę nad kodem i zacząć mnożyć błędy.


```cpp for(int i=1;i<=n;++i) { cout<"Podaj imie i nazwisko "<i;cout<<". ucznia:="ucznia:" "<<endl;="&quot;&lt;&lt;endl;" //podaje="//podaje" dane="dane" osob="osob" cin="cin">>imie[i];cin>>nazwisko[i]; ```

Zdajesz sobie sprawę, że tablice są indeksowane począwszy od 0, a nie od 1?

Może lepiej napisać:

for(int i=0; i<n; ++i)
{
    cout << "Podaj imie i nazwisko " << i+1 << ". ucznia: " << endl;
    cin >> imie[i] >> nazwisko[i];
}

I tak samo poprawić wszędzie niżej.


WIele z punktów z mojego poprzedniego postu pozostaje wciąż aktualnych, więc radzę go wciąż przeczytać.

1

Jedno wyjaśnienie.

Załóżmy, że mamy tablicę na 20 elementów.

int tablica[20];

Ta tablica ma 20 prawidłowych indeksów: tablica[0], tablica[1], … , tablica[18], tablica[19].
UWAGA: tablica[20] jest NIEPOPRAWNE, a co gorsze ten błąd NIE ZAWSZE musi spowodować błędne działanie programu. (choć często powoduje). Co gorsza, błąd ten może powodować nieporawne działanie na pierdylion różnych nieoczywistych sposobów, a dojście do tego, co się tak naprawdę dzieje, może być niełatwe.

Teraz weźmy 2 przykłady pętli:

for(int i = 1; i <= 20; ++i)
{
    cout << "Podaj " << i << ". element tablicy:"
    cin >> tablica[i];
}

Niepoprawne. Nie wykorzystujesz zerowego indeksu tablicy, zaczynasz od 1. Co gorsza, wykorzystujesz indeks 20, który jest niepoprawny.

Poprawić to można na dwa sposoby. Albo indeksować pętlę tak jak tablicę i przwsuwać indeks zawsze, gdy go wypisujesz:

for(int i = 0; i < 20; ++i)
{
    cout << "Podaj " << i+1 << ". element tablicy:"
    cin >> tablica[i];
}

Albo numerować pętlę od 1 i przesuwać indeks zawsze, gdy używasz tablicy:

for(int i = 1; i <= 20; ++i)
{
    cout << "Podaj " << i << ". element tablicy:"
    cin >> tablica[i-1];
}

Ten pierwszy sposób jest preferowany. M.in. dlatego, że w tym pierwszym sposobnie jeśli coś schrzanisz, to będzie to widoczne od razu. W tym drugim sposobie ukryty błąd może się okazać dużo bardziej złośliwy.

2

Dlaczego nie zaczniesz nauki od podstaw? (Od prostych przykładów, np. wczytywanie elementów w pętli itp.)
Miotasz się strasznie i nie rozumiesz kodu, który piszesz.

1

@Piotr9592 , przykłady:

Poprawne:

int main(int argc, char *argv[])
{
    // cokolwiek, chociażby to:
    string s;
    cout << "Podaj napis:\n";
    getline(cin, s);
    cout << "Wpisałeś:\n" << s;
}

Poprawne:

int main()
{
    // cokolwiek, chociażby to:
    string s;
    cout << "Podaj napis:\n";
    getline(cin, s);
    cout << "Wpisałeś:\n" << s;
}

Niepoprawne:

int main(int argc, string argv[])
{
    // cokolwiek
}
0

Czy o taki program chodziło?

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
    int n, k, s;
    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    int tab[s];
    s = n;
    float a[s];
    string imie[s];
    string nazwisko[s];


    {
        for (int i = 0; i < n; ++i)
        {

            cout << "Podaj imie i nazwisko " << i + 1 << ". ucznia: " << endl;
            cin >> imie[i];
            getline(cin, nazwisko[i]);
            cout << "Podaj srednia ocen " << i + 1 << ". ucznia: " << endl;
            cin >> a[i];
        }

        for (int k = 0; k < n; ++k)

        {

            cout << "Uczen " << imie[k] << " " << nazwisko[k];
            cout << " ma srednia: " << a[k] << endl;
        }
    }
    system("PAUSE");
    return EXIT_SUCCESS;
}
2

@Piotr9592

    int n, k, s;
    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    int tab[s];
    s = n;

Jaką wartość ma zmienna s w momencie, kiedy piszesz int tab[s]??

Nie przypisałeś w tym miejscu zmiennej żadnej wartości. Albo ją przypiszesz, albo nie możesz tej zmiennej używać.

Czy to s=n nie powinno być raczej powyżej, a nie poniżej int tab[s]?


int n, k, s;
    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    // ...
    s = n;
    float a[s];
    string imie[s];
    string nazwisko[s];

Już pisałem. Nie możesz deklarować tablicy od zmiennej, tylko od stałej. Przykłady:

int tablica[50];

Powyższe jest poprawne bo 50 to stała

const int rozmiar = 50;
int tablica[rozmiar];

Powyższe jest poprawne bo rozmiar to stała (zadeklarowałeś ją jako const, a więc jest stałą) i od razu przypisałeś tej stałej wartość, znaną w czasie pisania kodu.

int rozmiar = 50;
int tablica[rozmiar];

Powyższe jest prawie dobrze (ale „prawie” robi wielką różnicę). Jeśli deklarujesz w ten sposób tablicę o rozmiarze określonym zmienną, to musisz tą zmienną zadeklarować jako const (jak wyżej).

int rozmiar;
cin >> rozmiar;
int tablica[rozmiar];

Powyższe jest niepoprawne bo rozmiar nie jest stałą znaną w czasie pisania kodu. Jej wartość zależy od tego, co wprowadzisz do programu.

Zasada: W ten sposób możesz deklarować tablice, jeśli obliczenie ich rozmiaru nie wymaga uruchomienia programu (JEŚLI ICH ROZMIAR JEST LICZBĄ, KTÓRĄ RĘCZNIE WPISUJESZ W KOD).

int rozmiar;
cin >> rozmiar;
int *tablica = new int[rozmiar];

Powyższe jest poprawne, w ten sposób wolno Ci tworzyć tablicę od dowolnych wartości, znanych w czasie pisania kodu bądź nie. Tylko pamiętaj o:

delete[] tablica;

kiedy tylko tablica przestanie Ci być potrzebna.


{
        for (int i = 0; i < n; ++i)
        {
 
            cout << "Podaj imie i nazwisko " << i + 1 << ". ucznia: " << endl;
            cin >> imie[i];
            getline(cin, nazwisko[i]);
            cout << "Podaj srednia ocen " << i + 1 << ". ucznia: " << endl;
            cin >> a[i];
        }
 
        for (int k = 0; k < n; ++k)
 
        {
 
            cout << "Uczen " << imie[k] << " " << nazwisko[k];
            cout << " ma srednia: " << a[k] << endl;
        }
    }

Czemu to wszystko jest w klamrach? Te klamry są tu całkowicie zbędne.


            cin >> imie[i];
            getline(cin, nazwisko[i]);

Nie piszę, że to jest niepoprawne, bo nie jest. Jeśli chcesz, możesz to tak zostawić.

Ale wracam do mojej dawniejszej sugestii, że może wygodnie będzie trzymać imię i nazwisko w jednej zmiennej: string imienazwisko.

Wtedy powyższe dwie linijki skrócą się do jednej:

getline(cin, imienazwisko);

To już bardziej kwestia projektowa, do rozważenia, nie jest to w żadnym razie „twardy” błąd.


Reszta NA PIERWSZY RZUT OKA wydaje się być poprawna. Jesteśmy coraz bliżej celu.

Popraw to, co piszę wyżej, i można będzie przejść do kwestii liczenia średniej.

1

@Piotr9592 Z tymi klamrami chodziło mi o coś takiego:

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
 
int main(int argc, char* argv[])
{
    int n, s;
    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    int tab[s];
    s = n;
    float a[s];
    string imie[s];
    string nazwisko[s];
 
 
    for (int i = 0; i < n; ++i)
    {
 
        cout << "Podaj imie i nazwisko " << i + 1 << ". ucznia: " << endl;
        cin >> imie[i];
        getline(cin, nazwisko[i]);
        cout << "Podaj srednia ocen " << i + 1 << ". ucznia: " << endl;
        cin >> a[i];
    }
 
    for (int k = 0; k < n; ++k)
    {
        cout << "Uczen " << imie[k] << " " << nazwisko[k];
        cout << " ma srednia: " << a[k] << endl;
    }
    system("PAUSE");
    return EXIT_SUCCESS;
}

Nie deklaruj k na samej górze, powinno zadziałać.

Znowu – nie poprawiałem tu nic oprócz samych klamer.

2
#include <iostream>
#include <vector>
using namespace std;

#define dla for
#define kazdego (auto
#define rob ){
#define wystarczy }
#define w :
#define kontenerze
auto &wypisz = cout;
auto &pobierz = cin;
auto koniec_linii = '\n';

using Napis = string;
using Zmiennoprzecinkowa = float;
struct Student{
	Napis imie, nazwisko;
	Zmiennoprzecinkowa srednia; //-15 to całkowicie prawidłowa średnia, prawda?
};
using Studenci = vector<Student>;

using Liczba = int;

int main() {
	wypisz << "Ile studentow?" << koniec_linii;
	Liczba ilosc;
	pobierz >> ilosc;
	
	Studenci studenci(ilosc);
	
	dla kazdego studenta w kontenerze studenci rob
		wypisz << "Podaj imie, nazwisko i srednia";
		pobierz >> studenta.imie >> studenta.nazwisko >> studenta.srednia;
	wystarczy
	
	dla kazdego studenta w kontenerze studenci rob
		wypisz << "Uczen " << studenta.imie << " " << studenta.nazwisko
		       << " ma srednia " << studenta.srednia << koniec_linii;
	wystarczy
	return 0;
}
0

Wpisałem zamiast 2 string-ów jeden ale nie odczytuje mi drugiej czesci (nazwiska).

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
    int n, k,s;
    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    s = n;
	int tab[s];  
    float a[s];
    string imienazwisko[s];
    


    
        for (int i = 0; i < n; ++i)
        {

            cout << "Podaj imie i nazwisko " << i + 1 << ". ucznia: " << endl;
            cin >> imienazwisko[i];
			getline(cin, imienazwisko[i]);
            cout << "Podaj srednia ocen " << i + 1 << ". ucznia: " << endl;
            cin >> a[i];
        }

        for (int k = 0; k < n; ++k)

        {

            cout << "Uczen " << imienazwisko[k];
            cout << " ma srednia: " << a[k] << endl;
        }
    
    system("PAUSE");
    return EXIT_SUCCESS;
}
2

Oczywiście.

cin >> imienazwisko[i];
getline(cin, imienazwisko[i]);

Co robi ten kod?

Najpierw wczytuje samo imię: cin >> imienazwisko[i];
Potem NA TO SAMO MIEJSCE wczytuje pozostałą część wiersza (czyli nazwisko): getline(cin, imienazwisko[i]);

Jeszcze raz: getline(cin, imienazwisko) SAMO wczyta zarówno imię, jak i nazwisko. Nie potrzebne (a nawet w tym przypadku błędne) jest pisanie wyżej cin >> imienazwisko[i].


Druga rzecz, że wciąż nie naprawiłeś błędu tutaj: int tab[s]; Pisałem już o tym.

0

Czy moge zapisać tak? za rozmiar przyjme uczniów

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
    int n;
    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    float a;
    string imienazwisko[n];
 
        for (int i = 0; i < n; ++i)
        {

            cout << "Podaj imie i nazwisko " << i + 1 << ". ucznia: " << endl;
			getline(cin, imienazwisko[i]);
            cout << "Podaj srednia ocen " << i + 1 << ". ucznia: " << endl;
            cin >> a[i];
        }

        for (int k = 0; k < n; ++k)

        {

            cout << "Uczen " << imienazwisko[k];
            cout << " ma srednia: " << a[k] << endl;
        }

    system("PAUSE");
    return EXIT_SUCCESS;
}
1

@Piotr9592

Wiesz, jak deklarować tablice:

int tab[20];
for(int i = 0; i < 20; ++i)
{
    cout << "Podaj liczbe: " << endl;
    cin >> tab[i];
}

cout << "Wpisałeś liczby: " << endl;
for(int i = 0; i < 20; ++i)
{
    cout << tab[i] << " ";
}

tab jest tu podobną tablicą jak w twoim kodzie imienazwisko czy a.

Ale można też tę tablicę zadeklarować tak:

int *tab = new int[20];
for(int i = 0; i < 20; ++i)
{
    cout << "Podaj liczbe: " << endl;
    cin >> tab[i];
}

cout << "Wpisałeś liczby: " << endl;
for(int i = 0; i < 20; ++i)
{
    cout << tab[i] << " ";
}
delete[] tab; // UWAGA NA TĘ LINIĘ! Poniżej jej NIE WOLNO ci już używać tablicy tab

int tab[20]
oraz
int *tab = new int[20]

To są dwa alternatywne sposoby na które możesz stworzyć tablicę 20 elementów.
Oba mają swoje wady i zalety, o których nie będę się rozwodził oprócz tego, że ten drugi sposób wymaga delete na końcu i pozwala na deklarowanie tablic o długości zadanych zmienną a nie tylko stałą.

0
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
    int n;
    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    float *a;
	a = new float[n];
    string *imienazwisko; 
	imienazwisko= new string[n];
 
        for (int i = 0; i < n; ++i)
        {

            cout << "Podaj imie i nazwisko " << i + 1 << ". ucznia: " << endl;
			getline(cin, imienazwisko[i]);
            cout << "Podaj srednia ocen " << i + 1 << ". ucznia: " << endl;
            cin >> a[i];
        }

        for (int k = 0; k < n; ++k)

        {

            cout << "Uczen " << imienazwisko[k];
            cout << " ma srednia: " << a[k] << endl;
        }
delete[] a;
delete[] imienazwisko;
    system("PAUSE");
    return EXIT_SUCCESS;
}
0

Witam moim zdaniem udało mi sie wykonać kolejny krok.

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

int main(int argc, char* argv[])
{
    int n;

    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    cin.ignore();
    float* a;
    a = new float[n];
    string* imienazwisko;
    imienazwisko = new string[n];

    for (int i = 0; i < n; ++i)
    {

        cout << endl << "Podaj imie i nazwisko " << i + 1 << ". ucznia: " << endl;
        getline(cin, imienazwisko[i]);
        cout << "Podaj srednia ocen " << i + 1 << ". ucznia: " << endl;

        cin >> a[i];
        cin.ignore();
    }

    for (int k = 0; k < n; ++k)

    {

        cout << "Uczen " << imienazwisko[k];
        cout << " ma srednia: " << a[k] << endl;
    }
    float suma = 0, srednia;
    for (int j = 0; j < n; ++j)
    {


        suma = suma + a[j];
    }
    srednia = suma / n;
    cout << endl << "srednia = " << srednia << endl;

    delete[] a;
    delete[] imienazwisko;
    system("PAUSE");
    return EXIT_SUCCESS;
}
4
  1. float tab[n]; - WTF? Chyba jednak @kmph dziś na próżno się udzielał :/
  2. Zapoznaj się z: +=
  3. Czy wiesz że każda ztych twoich pętli może używać i
  4. Staraj się deklarować zmienne tuż przed użyciem: float suma=0; for (int i=0;i<n;++i) sum+=a[j];
  5. Nie musisz najpierw zliczać w zmiennej, wystarczy od razu: cout<<endl<<"srednia = "<<suma/n<<endl;
  6. Skoro potrzebujesz system("PAUSE"); to zmień środowisko na jakieś z tego tysiąclecia.
0

Nie wiem czy dobrze przetworzyłem program jako zmienna globalna przyjąłem e. Nie wiem co zrobić aby program liczył średnią dla np 2 osób ponieważ przypisuje on wartości sredniej ostatniej osoby każdemu. Obliczało mi prawidłowo średnią ale zaraz po wpisaniu ocen z egzaminu a to ma być jako podsumowanie. Proszę o pomoc w rozwiązaniu problemu.

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
int e;
float srednia(float* listaocen, int ile)
{
    float suma = 0;
    for (int i = 0; i < ile; ++i)
    {
        suma += (*listaocen++);
    }
    return suma / ile;
}
int main(int argc, char* argv[])
{
    int n; // liczba uczniów
    // ilosc egzaminow
    cout << "Podaj liczbe uczniow: ";
    cin >> n;
    float* oceny;
    oceny = new float[e];
    string* imienazwisko;
    imienazwisko = new string[n];
    cout << "Podaj ilosc egzaminow: ";
    cin >> e;   
    for (int i = 0; i < n; ++i)
    {

        cout << endl << "Podaj imie i nazwisko " << i + 1 << ". ucznia: " << endl;
        getline(cin>>ws, imienazwisko[i]);


        for (int j = 0; j < e; ++j)
        {
            cout << "Egzamin nr." << j + 1 << " ocena: ";
            cin >> oceny[j];
            cin.ignore();
        }
    }
    for (int i = 0; i < n; ++i)
    {
        cout << "Srednia ucznia " << imienazwisko[i] << " z egzaminow wynosi: " << srednia(oceny,e )
             << endl;
    }


    delete[] oceny;
    delete[] imienazwisko;
    system("PAUSE");
    return 0;
}

3
  1. listaocen++; Nadal nie rozumiesz inkrementacji: http://4programmers.net/Forum/1101404
  2. Akurat tam gdzie ma sens użyć inkrementacje przyrostkową tego nie robisz:
for(int i=0;i<ile;++i) suma+=*(listaocen++);

lub float stop=listaocen+ile; while(listaocen<stop) suma+=(listaocen++);

3. `oceny = new float[e];` - przed wprowadzeniem tego `e`, @kmph już kilka razy to tłumaczył
4. Zmienne globalne - jak tylko chcesz ich użyć - prawie 100% sygnał że robisz coś źle - patrz punkt wyżej
5. Ponieważ masz tylko jedną tabele `oceny` to są w niej oczywiście oceny ostatniego studenta, potrzebujesz dodatkową tablicę `float *average=new float[n];` aby obliczyć i zanotować średnią dla studenta po każdym wprowadzeniu listy ocen.
6. `float* oceny;` mylący zapis, jak sądzisz co oznacza `float* oceny,average;` ? otóż `oceny` to wskaźnik zaś `average` to zwykły float, pisz z sensem: `float * oceny,*average;`
7. Zamiast dwukrotnego `cin.ignore();` użyj raz `>>ws` - czy może jednak dobrze na początku zrozumiałem z tymi wyścigami?

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