任务是让一个程序write
read
file
对象,然后从中创建一个列表,然后删除带有奇数int
-s的Node
-s。删除是通过一些嵌套函数完成的。问题是,某处存在段错误。当然,我通过调试器运行了这个,但我们既没有教过机器代码/汇编语言,也没有教过如何使用调试器。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
typedef struct smallNode {
int val;
char str[10];
}smallNode;
typedef struct Node {
smallNode smallNode;
struct Node *next;
}Node;
Node *head = NULL;
Node *getLast(Node *head);
void queue(Node **head, Node *object);
void print(Node *head);
int countNodes(Node *head);
void check(Node *head);
Node *getNth(Node *head, int n);
void delNth(Node **head, int n);
void popHead(Node **head);
void delOdds(Node *head);
int main(void) {
FILE *fp;
if ((fp = fopen("suka.blyad", "wb")) == NULL) {
return 69;
}
smallNode array[5];
int j;
for (j = 0; j < 5; j++) {
array[j].val = j;
}
strcpy(array[0].str, "zero");
strcpy(array[1].str, "one");
strcpy(array[2].str, "two");
strcpy(array[3].str, "three");
strcpy(array[4].str, "four");
int i;
smallNode *object0 = (smallNode *)malloc(sizeof(smallNode));
for (i = 0; i <5; i++) {
*object0 = array[i];
if (fwrite(object0, sizeof(smallNode), 1, fp) != 1) {
puts("IO error.");
exit(-3);
}
}
fclose(fp);
if ((fp = fopen("suka.blyad", "rb")) == NULL) {
return 4;
}
Node * object = (Node *)malloc(sizeof(Node));
while (1) {
if (fread(object0, sizeof(smallNode), 1, fp) != 1) {
break;
}
object->smallNode = *object0;
queue(&head, object);
}
print(head);
puts("After deleting odds: ");
delOdds(head);
print(head);
return 0;
}
void check(Node *head){ //function to check if the list exists
if(head == NULL){
puts("NaL");
exit(-1);
}
}
Node *getLast(Node *head) {
if (head == NULL) {
return NULL;
}
while (head->next) {
head = head->next;
}
return head;
}
void queue(Node **head, Node *object) {
Node *tmp = (Node *)malloc(sizeof(Node));
Node *last = getLast((*head));
*tmp = *object;
tmp->next = NULL;
if (last != NULL) {
last->next = tmp;
}
else {
*(head) = tmp;;
}
}
void print(Node *head) {
if (head == NULL) {
puts("NaL");
exit(-4);
}
int c = 0;
while (1) {
printf("Node: %d.n", ++c);
puts("-----------------------------------------");
printf("|Int: %6d | String: %7s %3cn", head->smallNode.val, head->smallNode.str, '|');
puts("-----------------------------------------");
if (head->next!=NULL) {
head = head->next;
}
else {
break;
}
}
}
int countNodes(Node *head){ //use this function to check out of bounds
check(head);
int count = 0;
while(1){
count++;
if(head->next){
head = head->next;
}
else{
return count;
}
}
}
Node *getNth(Node *head, int n){
check(head);
if(n > countNodes(head)
|| n < 0){
puts("Out of bounds.");
exit(-5);
}
int i;
for(i = 0; i < n-1; i++){
head = head->next;
}
return head;
}
void delNth(Node **head, int n){ //cant delete the first node
check((*head));
Node *prev = getNth((*head), n-1);
Node *elm = prev->next;
prev->next = elm -> next;
free(elm);
}
void popHead(Node **head){ //can only delete the first node, called only if n == 1
check((*head));
Node *elm = (*head);
(*head) = (*head)->next;
free(elm);
}
void delOdds(Node *head){ //function to go throught the list, check for odds and call the functions doing the deletion
check(head);
int n = 0;
while(1){
++n;
if(head->smallNode.val % 2){
if(n == 1){
popHead(&head);
}
else{
delNth(&head, n);
}
}
if(head->next){
head = head->next;
}
else{
print(head);
break;
}
}
}
我包括整个代码,而不仅仅是有问题的函数,以便程序可以运行。 我认为我创建列表的方式可能是非正统的,因此我将简要解释它,因此您不必费心弄清楚:
使用了 2 种类型的对象。smallNode
没有next
指针,但它是写入和读取文件的对象。它对应于object0
.
Node
是构成列表的对象,它也是传递给创建列表的queue
函数的对象。
出现崩溃是因为您在每次迭代中递增本地 Headhead = head->next;
,并且将相同的本地 Head 传递给使用getNth()
函数获取第 N 个节点delNth()
。由于您的getNth()
函数从列表开始计数并返回第 N 个节点,因此您最终指向无效地址。
如果要继续使用自己的方法,则需要进行以下更改。
- 维护本地指针以循环访问列表。
- 将
delNth(Node **head, int n)
更改为delNth(Node *head, int n)
以避免 更改头节点。 - 删除时传递实际头部。
- 删除后递减
n
,以便节点数和n
数保持不变。
以下是修改后的代码。
void delOdds(Node *head){
check(head);
Node *localHead = head;
int n = 0;
while(1){
printf("processing node=%d n=%dn", localHead->smallNode.val, n);
++n;
if(localHead->smallNode.val % 2){
if(n == 1){
popHead(&head);
}
else{
delNth(head, n);
n--;
}
}
if(localHead->next){
localHead = localHead->next;
}
else{
print(localHead);
break;
}
}
}
我建议您采用以下方法。
void delOdds(Node **head){
check(*head);
Node *prev = NULL;
Node *cur = *head;
int n = 0;
while(cur){
if((cur)->smallNode.val % 2){
if (cur == *head)
{
*head = (*head)->next;
free(cur);
cur = *head;
}
else
{
(prev)->next = (cur)->next;
free(cur);
cur = NULL;
(cur)=(prev)->next;
}
}
else{
prev = cur;
(cur)=(cur)->next;
}
}
}