为什么我打印简单链表的代码不起作用?
Why doesn't my code for printing a simple Linked List work?
#include <iostream>
using namespace std;
typedef struct NODE node;
typedef struct NODE {
int marks;
char name[100];
node *next;
} node;
node *getinput() {
node *n;
n = (node *)malloc(sizeof(node));
if (n) {
cin >> n->marks; // STATEMENT 1
gets_s(n->name);
n->next = NULL;
}
return n;
}
node *populateList(node *list) {
node *temp;
node *newptr = getinput();
if (list == NULL) {
list = newptr;
return list;
}
temp = list;
while (temp->next) {
temp = temp->next;
//(COMMENT 1)temp->next = newptr;
}
temp->next = newptr;
return list;
}
void printlist(node *list) {
node *p = list;
// temp = list;
while (p->next) {
cout << p->marks << endl; // STATEMENT 2
//(COMMENT 3) cout << list->marks << endl;
puts(p->name);
p = p->next;
}
}
void main() {
int x = 1;
node *n = NULL;
for (; x <= 6; x++)
n = populateList(n);
printlist(n);
}
所以,我面临着一些问题:
我不能取6个成员想要的分数和名字,但是我可以取6个成员的名字,但不能取他们的分数。 (如果我删除 STATEMENT 1 AND/OR STATEMENT 2,则会显示相同的输出)。
我假设成员的标记被认为是链表指针node * list的垃圾值,因为它似乎是所有成员都一样。
那么我该如何解决程序中的问题呢?我知道这个问题对很多人来说似乎太微不足道了,我可以很容易地在互联网上查找链表程序,但我决心解决这个问题。我想进一步了解代码中的issues/optimizations,以便我自己纠正。
谢谢
您正在将 C++ 与 C 代码混合,
一些小的修复。
使用 std::string name
而不是 char name[100]
使用 n = new node()
最后,对于你 "bug" 你应该将 gets_s(n->name);
切换为 cin >> (n->name);
这将起作用并为标记和名称填写正确的值。
我很确定问题来自于使用 C++ 函数 cin
和 C 函数 gets_s
混合来自 stdin 的输入,看起来 gets_s 在第一个 [=15= 之后取值的分隔符] 被调用。
也不要忘记删除分配的节点。
您的代码中存在几个问题;导致错误处理输入的一个原因是您将 cin
与 gets_s
混合使用,这通常不会按预期工作;顺便说一句:gets_s
或 gets
是“老式的 C-style 并且在较新的标准中已弃用(甚至删除)。例如,使用 std::getline
作为替代。
将整数值和字符串与白色space混合读取实际上有点棘手。例如,如果输入是 10 john doe
,那么 cin >> marks
将读入 10
,但会在输入缓冲区中留下空白;你将不得不跳过白色 spaces,例如通过 cin >> ws
;否则,您的字符串输入将立即终止,或者 - 如果使用 getline
- 在开头包含一个空白。然后,如果你写 string name; cin >> name
,那么只会读取 john
,因为字符串输入在第一个白色 space 处停止。所以我建议使用 getline
读取名称直到行尾,这样你才能真正得到 john doe
作为名称。
此外,请注意输入可能会失败(例如文件末尾或无效格式),这样 getinput
可能必须 return 一个无效节点(应由 nullptr
).
很多事情,所以我稍微重写了您的代码以将上述事情考虑在内。希望能帮助到你;享受编码的乐趣!
struct node {
int marks;
string name;
node *next;
};
node *getinput() {
int marks;
string name;
if (! (cin >> marks >> std::ws)) {
return nullptr;
}
if (! getline(cin, name, '\n')) {
return nullptr;
}
return new node { marks, name, nullptr };
}
node *addToList(node *list, node* newNode) {
if (list == NULL) {
return newNode;
}
if (newNode == nullptr) {
return list;
}
node* temp = list;
while (temp->next) {
temp = temp->next;
}
temp->next = newNode;
return list;
}
void printlist(node *list) {
node *p = list;
while (p) {
cout << p->marks << " " << p->name << endl;
p = p->next;
}
}
int main() {
int x = 1;
node *n = NULL;
node *list = NULL;
while (x <= 3 && (n = getinput()) != nullptr) {
list = addToList(list, n);
x++;
}
printlist(list);
}
#include <iostream>
using namespace std;
typedef struct NODE node;
typedef struct NODE {
int marks;
char name[100];
node *next;
} node;
node *getinput() {
node *n;
n = (node *)malloc(sizeof(node));
if (n) {
cin >> n->marks; // STATEMENT 1
gets_s(n->name);
n->next = NULL;
}
return n;
}
node *populateList(node *list) {
node *temp;
node *newptr = getinput();
if (list == NULL) {
list = newptr;
return list;
}
temp = list;
while (temp->next) {
temp = temp->next;
//(COMMENT 1)temp->next = newptr;
}
temp->next = newptr;
return list;
}
void printlist(node *list) {
node *p = list;
// temp = list;
while (p->next) {
cout << p->marks << endl; // STATEMENT 2
//(COMMENT 3) cout << list->marks << endl;
puts(p->name);
p = p->next;
}
}
void main() {
int x = 1;
node *n = NULL;
for (; x <= 6; x++)
n = populateList(n);
printlist(n);
}
所以,我面临着一些问题:
我不能取6个成员想要的分数和名字,但是我可以取6个成员的名字,但不能取他们的分数。 (如果我删除 STATEMENT 1 AND/OR STATEMENT 2,则会显示相同的输出)。
我假设成员的标记被认为是链表指针node * list的垃圾值,因为它似乎是所有成员都一样。
那么我该如何解决程序中的问题呢?我知道这个问题对很多人来说似乎太微不足道了,我可以很容易地在互联网上查找链表程序,但我决心解决这个问题。我想进一步了解代码中的issues/optimizations,以便我自己纠正。
谢谢
您正在将 C++ 与 C 代码混合,
一些小的修复。
使用 std::string name
而不是 char name[100]
使用 n = new node()
最后,对于你 "bug" 你应该将 gets_s(n->name);
切换为 cin >> (n->name);
这将起作用并为标记和名称填写正确的值。
我很确定问题来自于使用 C++ 函数 cin
和 C 函数 gets_s
混合来自 stdin 的输入,看起来 gets_s 在第一个 [=15= 之后取值的分隔符] 被调用。
也不要忘记删除分配的节点。
您的代码中存在几个问题;导致错误处理输入的一个原因是您将 cin
与 gets_s
混合使用,这通常不会按预期工作;顺便说一句:gets_s
或 gets
是“老式的 C-style 并且在较新的标准中已弃用(甚至删除)。例如,使用 std::getline
作为替代。
将整数值和字符串与白色space混合读取实际上有点棘手。例如,如果输入是 10 john doe
,那么 cin >> marks
将读入 10
,但会在输入缓冲区中留下空白;你将不得不跳过白色 spaces,例如通过 cin >> ws
;否则,您的字符串输入将立即终止,或者 - 如果使用 getline
- 在开头包含一个空白。然后,如果你写 string name; cin >> name
,那么只会读取 john
,因为字符串输入在第一个白色 space 处停止。所以我建议使用 getline
读取名称直到行尾,这样你才能真正得到 john doe
作为名称。
此外,请注意输入可能会失败(例如文件末尾或无效格式),这样 getinput
可能必须 return 一个无效节点(应由 nullptr
).
很多事情,所以我稍微重写了您的代码以将上述事情考虑在内。希望能帮助到你;享受编码的乐趣!
struct node {
int marks;
string name;
node *next;
};
node *getinput() {
int marks;
string name;
if (! (cin >> marks >> std::ws)) {
return nullptr;
}
if (! getline(cin, name, '\n')) {
return nullptr;
}
return new node { marks, name, nullptr };
}
node *addToList(node *list, node* newNode) {
if (list == NULL) {
return newNode;
}
if (newNode == nullptr) {
return list;
}
node* temp = list;
while (temp->next) {
temp = temp->next;
}
temp->next = newNode;
return list;
}
void printlist(node *list) {
node *p = list;
while (p) {
cout << p->marks << " " << p->name << endl;
p = p->next;
}
}
int main() {
int x = 1;
node *n = NULL;
node *list = NULL;
while (x <= 3 && (n = getinput()) != nullptr) {
list = addToList(list, n);
x++;
}
printlist(list);
}