列表的一个元素被排序,其他元素则没有

时间:2016-08-31 09:11:01

标签: c++

好的所以我正在编写一个程序,我必须输入n名学生的姓名,名字和成绩。完成后我必须按字母顺序排列,如果名字匹配则在第一个之后然后我有另一种选择来分级。这是我到目前为止的代码:

#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);
}

问题是每当我按年级排序时,例如,如果学生A的成绩为9,而学生B在排序后的成绩为7,则会告诉我学生A有7,学生B有9.我知道我我告诉排序功能只对等级进行排序,而不是打破名称,但我不知道如何解决它。它可能是非常简单的东西,我认为它涉及某种指针,但我真的不知道。哦,如果你能如果名字是相同的位,给出一些关于如何在firstname之后进行排序的信息。如果有人能帮助我,我会非常感激。提前谢谢!!(ps如果有人能给我任何关于这个问题的指示看起来像ci真的很感激)

4 个答案:

答案 0 :(得分:1)

您应该交换整个结构,而不是仅交换部分结构(s[i].gradesort_grade()s[i].namesort_name())。它应该类似于以下内容:

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);
            }
       }
   }
}

答案 1 :(得分:1)

代码中有许多错误的东西。

在这里,我修复了所有这些只是为了你,但它可能会受到我的编码风格影响:

接头:

 #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>

命名空间:

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

结构好吗?我想:

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

不要依赖全局变量(此程序模型需要n但是:

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

修正了add_student()(很多错误):

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
    }
}

排序函数(许多错误):

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()功能(cout垃圾邮件和索引再次转换):

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;
    }
}

main()(将int o设为本地变量且固定cout垃圾邮件):

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);
}

总之,任重而道远!但要研究你的代码,并阅读一些好书,以便你可以改进。

编辑:

接头:

cstdio stdio.h namespace

命名空间:

Why is "using namespace std" considered bad practice?

全局变量:

Are global variables bad?

使用C / C ++编制索引:

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

在C ++和cin / get~问题解决方案中刷新输入/输出:

(输出)

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

(输入)

cin and getline skipping input

反cout垃圾邮件:

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

交换结构:

c++ sort with structs

答案 2 :(得分:0)

您的泡泡排序的一般问题

  1. 您使用条件排序,但只交换条件而不交换其他特征!在这两种情况下,temp应为struct student
  2. 指数移动1.在两种排序情况下,您从1开始到n-1,但索引为ii+1:缺少第一个元素并且溢出数组一个。
  3. 名称“冒泡排序”是错误的(缺少完成的做法):

    我会这样做

    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;
              }
          }
      }
    

    排序等级也是错误的:固定版本:

    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;
                  }
              }
          }
      }
    

    更不用说C ++使用标准有效的排序函数,比这更好(除非你必须这样做)

答案 3 :(得分:-2)

交换使用memcpy()之类的函数并交换整个结构而不是name / gRade