好的所以我正在编写一个程序,我必须输入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真的很感激)
答案 0 :(得分:1)
您应该交换整个结构,而不是仅交换部分结构(s[i].grade
内sort_grade()
和s[i].name
内sort_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);
}
总之,任重而道远!但要研究你的代码,并阅读一些好书,以便你可以改进。
编辑:
接头:
命名空间:
Why is "using namespace std" considered bad practice?
全局变量:
使用C / C ++编制索引:
Why does the indexing start with zero in 'C'?
在C ++和cin / get~问题解决方案中刷新输入/输出:
(输出)
(输入)
cin and getline skipping input
反cout垃圾邮件:
http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt
交换结构:
答案 2 :(得分:0)
您的泡泡排序的一般问题
temp
应为struct student
。1
开始到n-1
,但索引为i
和i+1
:缺少第一个元素并且溢出数组一个。名称“冒泡排序”是错误的(缺少完成的做法):
我会这样做
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