我是C++的新手,我想知道为什么我的程序在添加新节点后只打印输入文件的最后一个节点。添加新节点后,它只打印最后一个节点和用户输入的节点。
我还需要帮助搜索所有输入学生的最高gpa,并显示哪个学生以及他们的gpa。
这是输入文件:
14
Breen_Jeremy
482929
3.5
Burgess_Patrick
492929
3.2
Catalan_Kristian
393923
2.5
Clark_Brenna
848292
4.0
Duda_Heather
292032
3.7
Freeland_Jesse
391939
4.0
Jarvis_Stephen
392939
2.5
Lemieux_Tyler
392934
3.5
OConnell_Kelly
103939
4.0
Osborne_John
193945
2.8
Richards_Daniel
494585
3.0
Swanbeck_James
693922
3.5
Tayek_Chandler
592022
3.0
Whippen_Andrew
199502
2.8
这是我的程序:
// This program does some basic functionalities of using a linked list
#include<iostream>
#include<string.h>
#include<cstring>
#include<fstream>
using namespace std;
struct node
{
string name;
int student_ID;
double gpa;
node * next;
};
int main()
{
// Variable definitions
node * first; // Pointer to the first node in the list
node * last; // Pointer to the last node in the list
char more_nodes = 'y'; // Control to know if the user wants to enter more
int numStudents;
double largest_GPA;
string best_student;
bool swap = true;
ifstream database;
void print(node * first);
database.open("class_list.txt");
database >> numStudents;
// Creates the first node
first = new node; // Create the first node
first -> next = NULL; // Point it to NULL (since it's the end)
last = first; // Point last to it (since it's the end)
for (int i = 0; i < numStudents; i++)
{
database >> first -> name;
database >> first -> student_ID;
database >> first -> gpa;
print(first);
}//end for
// This loop adds one new node, loads data into it, and updates pointers
while (more_nodes == 'y')
{
last -> next = new node; // Get a new node tacked onto the end of the list
cout << "Enter the name of the student" << endl;
cin >> last -> next -> name;
cout << "Enter the student ID" << endl;
cin >> last -> next -> student_ID;
cout << "Enter the GPA of the student" << endl;
cin >> last -> next -> gpa;
last -> next -> next = NULL; // Point the new node to NULL
last = last -> next; // Toggle last to point to this new node (since it's the new "last")
cout << "Do you have more students to enter? Enter y for yes or n for no" << endl;
cin >> more_nodes;
++numStudents;
print(first);
}//end while
node * temp;
temp = first;
while (temp -> next != NULL)
{
while(swap)
{
swap = false;
if (temp -> next -> gpa > temp-> gpa)
{
largest_GPA = temp -> gpa;
temp -> gpa = temp -> next -> gpa;
temp -> next -> gpa = largest_GPA;
temp -> name = best_student;
swap = true;
}//end if
}//end while
temp = temp -> next;
}//end while
cout << "The best student is " << best_student <<endl;
cout << "The largest GPA is " << largest_GPA <<endl;
database.close();
return 0;
}//end main
// Print out the linked list by having a temporary pointer scroll through the entire list
void print(node * first)
{
node * temp; // Make a temporary (dummy) pointer
temp = first; // Point it to the first node in the list
while(temp != NULL) // Continue until temp reaches NULL (the end)
{
cout << temp -> name << endl;
cout << temp -> student_ID << endl;
cout << temp -> gpa << endl;
temp = temp -> next; // Move temp to the next node
}//end while
}//end function
首先,std::string
定义的正确标头是:
#include <string>
它们以不同的方式引用C字符串库:
#include<string.h> // In the global namespace.
#include<cstring> // In the std namespace.
如果程序是用你的编译器编译的,那是由于iostream
或fstream
头的实现,不应该依赖它。它不是用我的编译器编译。
接下来,从文件加载记录的循环只创建和重用一个节点。这里有一种纠正方法:
for(int i = 0; i < numStudents; i++)
{
node* temp = new node;
database >> temp->name;
database >> temp->student_ID;
database >> temp->gpa;
temp->next = NULL;
if(first == NULL)
{
first = last = temp;
}
else
{
last->next = temp;
last = temp;
}
}//end for
print(first);
最后,要找到最佳GPA,请跟踪GPA最大的节点:
node* temp = first;
node* best = first;
while(temp != NULL)
{
if(temp->gpa > best->gpa)
{
best = temp;
}
temp = temp->next;
}//end while
cout << "The best student is " << best->name << endl;
cout << "The largest GPA is " << best->gpa << endl;
其他一些需要考虑的事项:
- 如果文件为空或不存在怎么办
- 如果文件中的学生人数是
0
怎么办 - 你们如何处理最大平均绩点的平局?文件中存在三方平局
现有代码无法处理这些条件。
嗯,代码对我来说太长了,但是,作为新手和使用指针可能会让人头疼。如果你有多余的时间,先试试Java。您将更难处理指针(因为您无法访问它们),并且您仍然可以构建类似链表的结构。
我也不喜欢你的循环结构,你的循环是初始循环(I=0),然后是它的其余部分(I>=0),当它可以更容易地在一段时间内完成所有内容时。我建议这样做:
continueprocessing = false;
if( filehascontents ) continueprocessing = true;
while( continueprocessing )
{
if( !filestillhascontents )
{
continueprocessing = false;
continue;//or break; whatever your style
}
/*read contents for this loop*/
/*validate contents to process are valid node data*/
if( !valid node data ) continue;
//if we are still here that means we got data, and its valid node data
node *n = new node;
/*also initialize n with the data*/
//you integrate this into the single loop, to me that's better, up to you
if( first == null )
{
first = n;
last = n;
continue;
}
//now we are done with the initial linking case, work the regular cases
last->next = n;
last = n;
}
基本上,在我向您展示的样式中,您假设常规情况,但开始循环检查特殊条件,如果遇到这些条件,则提前退出。这样你的结构就是(循环)(特殊条件块)(常规情况块)(endloop)
无论如何,在你自己的代码中,你的for循环,也就是我的循环(添加节点的循环),将所有内容都设置为第一个,并不断覆盖那里的数据,所以这就是为什么你只有一个节点,因为你从来没有添加节点。
作为一个挑剔的人,你在中间有一个使用"交换"的循环,但交换定义一直在那里,用实际使用它的代码向下移动初始化,以后更容易处理。
最后,你的交换函数是错误的,保持它简单而有效的唯一方法是每次交换发生时将temp重新初始化为第一个,这样你就可以从头开始搜索,直到你确定整个列表都是有序的。
编辑:我明白了,这不仅是错误的,还有各种各样的错误,不确定你是想排序你的列表,还是你只在寻找max节点,所以作为另一个挑剔,试着对你的名字进行过度描述,并试着对语义进行挑剔,这样其他人和你以后可以更容易地阅读代码,例如,我会将temp重命名为maxgpastudent,甚至结果,如果你只是在寻找最大节点,因为这将是你的结果。
然后不要使用largestGPA作为交换的临时变量,它是largestGPA,它应该只包含最大的GPA,如果你需要一个临时变量,请创建一个。最后,如果你试图重新排序,请重做该函数,因为你的作业混合了所有内容,你在交换GPA,但不交换学生姓名,而且你不必交换值,这是一个链表,交换链接。