-1

Ok so i'm writing a program in wich i have to input the names, first names, and grades of n students.After i've done that i have to arrange them alphabetically and if the names match go after the first names.Then i have another option to sort after grades.This is my code so far:

#include<iostream>
#include<string.h>
#include<conio.h>
#include<stdio.h>

using namespace std;

struct student
{
 char name[30];
 char firstname [50];
 int grade;
}s[50]; 

int i,n,o,done=0;


void add_student()
{
  cout<<"Number of students:"<<" ";
  cin>>n;
  cout<<endl;


   for(i=1; i<=n; i++)
    {

    fflush(stdin);
    cout<<"Student"<<" "<<i<<":"<<endl;

    cout<<"name of student:"<<" ";
    gets(s[i].name);

    cout<<"first name of student:"<<" ";
    gets(s[i].firstname);

    cout<<"grade of student:"<<" ";
    cin>>s[i].grade;
    cout<<endl;
   }
}


void sort_name()
{
 char temp[30];
  while(!done)
  {
    done=1;
    for(i=1; i<n; i++)
     {
    if(strcmp(s[i].name,s[i+1].name)>0)
        {
    strcpy(temp,s[i].name);
    strcpy(s[i].name,s[i+1].name);
    strcpy(s[i+1].name,temp);

        }
     }
  }

for(i=1; i<=n; i++)
  {
    cout<<"Student"<<" "<<i<<":"<<endl;
    cout<<"Name"<<":"<<s[i].name<<endl;
    cout<<"Firstname"<<":"<<s[i].firstname<<endl;
    cout<<endl;
  }
}


void sort_grade()
 {
 int temp;
  while(!done)
  {
    done=1;
    for(i=1;i<n;i++)
    {
        if(s[i].grade>s[i+1].grade)
        {
            temp=s[i].grade;
            s[i].grade=s[i+1].grade;
            s[i+1].grade=temp;
            done=0;
        }
    }
}

for(i=1; i<=n; i++)
{
    cout<<"Student"<<" "<<i<<":"<<endl;
    cout<<"Name"<<":"<<s[i].name<<endl;
    cout<<"Firstname"<<":"<<s[i].firstname<<endl;
    cout<<"Grade"<<":"<<s[i].grade<<endl;
    cout<<endl;
}


}

void list_students()
{
 int i;
 for(i=1; i<=n; i++)
{
    cout<<"Student"<<" "<<i<<":"<<endl;
    cout<<"Name"<<":"<<s[i].name<<endl;
    cout<<"Firstname"<<":"<<s[i].firstname<<endl;
    cout<<"Grade"<<":"<<s[i].grade<<endl;
    cout<<endl;
}
}



int main()
{
 do
 {

    cout<<"Menu:"<<endl;
    cout<<"1.Add students"<<endl;
    cout<<"2.Sort by name"<<endl;
    cout<<"3.Sort by grade"<<endl;
    cout<<"4.List  students"<<endl;
    cout<<"5.Exit"<<endl<<endl;
    cout<<"Pick option : ";
    cin>>o;
    cout<<endl;

        switch (o)
            {   
                case 1:add_student();
                break;
                case 2:sort_name();
                break;
                case 3:sort_grade();
                break;
                case 4:list_students();
                break;
            }
  }while (o!=5);
}

Problem is whenever i sort by grade if for example student A has a grade of 9 and student B has a grade of 7 after sorting it will tell me that student A has a 7 and student B a 9.I know that i am telling the sorting function to only sort the grade and not thouch the name but i dont know how to fix it.It is probably something really simple and i think it involves some kind of pointer but i really dont know.oh and if you can give some kind of info on how to do the sorting after firstname if names are the same bit.I would be really grateful if someone could help me.thanks in advance!!(p.s if anyone can give me any pointers as to how this problem would look like in c i would be really really grateful)

Hjarnor
  • 13
  • 4
  • time to get intimate with the debugger. – bolov Aug 31 '16 at 09:13
  • 3
    This is not 'c', and please don't do `fflush(stdin);`. – unwind Aug 31 '16 at 09:21
  • 1
    Do you know that in c++ first element of array is indexed by `0`? – xinaiz Aug 31 '16 at 09:21
  • i only started from 1 because of the listing of the students would otherwise go from 0 like student 0, student 1 and so on and i dint like that.if it's bad i wont do it again and same case with the fflush.I put the c tag because many of my books and even some of my teachers failed to explain the differences between c and c++ and they just make them look kind of the same which i know is not the case.Anyway thanks everyone for all the help.This was actually my first time here and you guys make me want to improve.Keep up the good work! – Hjarnor Aug 31 '16 at 10:39

4 Answers4

1

Instead of swapping only parts of you structure (s[i].grade inside sort_grade() and s[i].name inside sort_name()) you should swap the entire structure. It should be something like the following:

void swap(int n, int m)
{
    char temp_string[50];
    int  temp_int;

    strcpy(temp,s[n].name);
    strcpy(s[n].name,s[m].name);
    strcpy(s[m].name,temp);

    strcpy(temp,s[n].firstname );
    strcpy(s[n].firstname ,s[m].firstname );
    strcpy(s[m].firstname ,temp);

    temp_int = s[n].grade;
    s[n].grade = s[m].grade;
    s[n].grade = temp_int;
}

void sort_name()
{
    char temp[30];
    while(!done)
    {
        done=1;
        for(i=1; i<n; i++)
        {
            if(strcmp(s[i].name,s[i+1].name)>0)
            {
                swap(i, i+1);
            }
       }
   }
}
GMichael
  • 2,726
  • 1
  • 20
  • 30
  • Structures are assignable, so `swap` only needs `student temp = s[n]; s[n] = s[m]; s[m] = temp;`.(But there's already a `swap` in the standard library ready for use.) – molbdnilo Aug 31 '16 at 10:16
  • thanks a lot for the help.i only started coding and most books i read are really ambiguous.I hope i can learn and help others too. – Hjarnor Aug 31 '16 at 10:30
1

There are many wrong things in the code.

Here, I fixed them all just for you, but it has probably suffered from my coding style impact:

Headers:

 #include <iostream>
 #include <cstring> //not <string.h>
 #include <cstdio> //not <stdio.h>
 //#include <conio.h> //you don't use any functionality from this header
 #include <limits>
 #include <cinttypes>

Namespace:

// dont use "using namespace std;", it's considered bad (here it might not be visible)

Struct is like ok? I think:

struct student
{
    char name[30];
    char firstname [50];
    int grade;
}s[50];

Don't rely on global variables (this program model requires n however:

int /*i,*/n=0/*,o,done=0*/; //don't declare global variables if you don't need them to be global

Fixed add_student() (many errors):

void add_student()
{
    std::cout<<"Number of students:"<<" ";
    std::cin>>n;
    std::cout<<std::endl;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //this is how you flush in c++

    for(int i=0/*1*/; i</*=*/n; i++) //declare iterator in loop
    {                       //also, first element index is 0, not 1!

        //fflush(stdin); //NEVER do that in C++, std::std::endl flushes output anyways
        std::cout<<"Student"<<" "<<i+1<<":"<<std::endl/*;*/ //dont spam std::cout too much
              /*std::cout*/<<"name of student:"<<" ";      //just go to next line and start with "<<"
        std::gets(s[i].name);

        std::cout<<"first name of student:"<<" ";
        std::gets(s[i].firstname);

        std::cout<<"grade of student:"<<" ";
        std::cin>>s[i].grade;
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout<<std::endl; //this std::std::endl call flushes output, so that "C flushin" didn't do anything
    }
}

Sorting functions (many errors):

void sort_name()
{
    bool done = false; //prefer bool over int for logical expressions
    /*char temp[30];*/ //not gonna use this, you need whole student, not only name
    student temp;
    while(!done)
    {
        // this whole section is wrong, you just go around swapping
        // students names, not students themselfs
        //        done=1;
        //        for(i=0/*1*/; i<n-1; i++)
        //        {
        //            if(strcmp(s[i].name,s[i+1].name)>0)
        //            {
        //                strcpy(temp,s[i].name);
        //                strcpy(s[i].name,s[i+1].name);
        //                strcpy(s[i+1].name,temp);

        //            }
        //        }
        done = true;
        for(int i=0; i<n-1; ++i)
        {
            if(strcmp(s[i].name, s[i+1].name)>0)
            {
                std::cout << "swapping" << std::endl;
                temp = s[i];
                s[i] = s[i+1];
                s[i+1] = temp;
                done = false;
            }
        }
    }

    for(int i=0/*1*/; i</*=*/n; i++)
    {
        std::cout<<"Student"<<" "<<i+1<<":"<<std::endl
            <<"Name"<<":"<<s[i].name<<std::endl
            <<"Firstname"<<":"<<s[i].firstname<<std::endl
            <<std::endl;
    }
}


void sort_grade()
{
    bool done = false;
    student temp;

    //exact same mistakes like in sort_name()
    while(!done)
    {
        done = true;
        for(int i=0; i<n-1; ++i)
        {
            if(s[i].grade > s[i+1].grade)
            {
                temp = s[i];
                s[i] = s[i+1];
                s[i+1] = temp;
                done = false;
            }
        }
    }

    for(int i=0/*1*/; i</*=*/n; i++)
    {
        std::cout<<"Student"<<" "<<i+1<<":"<<std::endl
            <<"Name"<<":"<<s[i].name<<std::endl
            <<"Firstname"<<":"<<s[i].firstname<<std::endl
            <<"Grade"<<":"<<s[i].grade<<std::endl
            <<std::endl;
    } 
}

list_students() function (cout spam and index shift again):

void list_students()
{
    for(int i=0/*1*/; i</*=*/n; i++)
    {
        std::cout<<"Student"<<" "<<i+1<<":"<<std::endl
            <<"Name"<<":"<<s[i].name<<std::endl
            <<"Firstname"<<":"<<s[i].firstname<<std::endl
            <<"Grade"<<":"<<s[i].grade<<std::endl
            <<std::endl;
    }
}

And main() (made int o a local variable and fixed cout spam):

int main()
{
    int o;
    do
    {
        //please, don't spam std::cout like that, it hurts
        std::cout<<"Menu:"<<std::endl
            <<"1.Add students"<<std::endl
            <<"2.Sort by name"<<std::endl
            <<"3.Sort by grade"<<std::endl
            <<"4.List  students"<<std::endl
            <<"5.Exit"<<std::endl<<std::endl
            <<"Pick option : ";
        std::cin>>o;
        std::cout<<std::endl;

        switch (o)
        {
        case 1:add_student();
            break;
        case 2:sort_name();
            break;
        case 3:sort_grade();
            break;
        case 4:list_students();
            break;
        }
    }while (o!=5);
}

In short, long way to go! But study your code, and read some good books so you can improve.

EDIT:

Headers:

cstdio stdio.h namespace

Namespace:

Why is "using namespace std" considered bad practice?

Global variables:

Are global variables bad?

Indexing in C/C++:

Why does the indexing start with zero in 'C'?

Flushing input/output in C++ and cin/get~ problem solution:

(output)

C++: "std::endl" vs "\n"

(input)

cin and getline skipping input

Anti-cout spam:

http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt

Swapping structures:

c++ sort with structs

Community
  • 1
  • 1
xinaiz
  • 7,744
  • 6
  • 34
  • 78
  • thanks a lot for the insight.I am only starting to program and many of the books i read just cover really basic stuff but i am trying and i want to improve – Hjarnor Aug 31 '16 at 10:18
  • That's ok :) I'll post some links to good explanations about things I commented/used. – xinaiz Aug 31 '16 at 10:22
  • 1
    thanks again.I will study the code and links you gave me and i will try to find some better books and ask my teachers more questions.thanks thanks thanks :D – Hjarnor Aug 31 '16 at 10:48
0

General problems with your bubble sorts

  1. you sort using a criteria, but only swap the criteria without swapping the other characteristics! temp should be struct student in both cases.
  2. indices are shifted by 1. In both sort cases, you're starting from 1 to n-1 but with indices i and i+1: missing first element and overflowing array by one.

And the name "bubble sort" is wrong (missing the affectation to done):

I'd do this

while(!done)
  {
    done = 1;
    for(i=0; i < n-1; i++)
      {
        if(strcmp(s[i].name, s[i+1].name) > 0)
          {
            done = 0; // still work to do
            temp = s[i];
            s[i] = s[i+1];
            s[i+1] = temp;
          }
      }
  }

sort grade is also wrong: fixed version:

void sort_grade()
  {
    struct student temp;
    while(!done)
      {
        done = 1;
        for(i=0; i < n-1; i++)    // loop boundaries were not OK
          {
            if(s[i].grade > s[i+1].grade)
              {
                temp = s[i];
                s[i] = s[i+1];
                s[i+1] = temp;
                done = 0;
              }
          }
      }
  }

Not to mention that C++ has efficient sort functions using a criteria, much better than this (unless you have to do this)

sokkyoku
  • 2,161
  • 1
  • 20
  • 22
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • i know there are other better sorting functions but the problem specified that it must be done with this one.Also thank you for pointing out my errors.i'm new to this and although i mostly know what is wrong with my code i still dont know how to fix it or how to improve it.Still lacking experience – Hjarnor Aug 31 '16 at 10:24
-2

while swapping use memcpy() like functions and swap entire structure instead of name / gRade

AnilChalla
  • 33
  • 1
  • 1
  • 7