【反思总结】
2.学习不带头结点的循环单链表的创建
易错点:不带头结点的循环单链表创建要先读入数据,再用尾插法插入结点
3.逆序打印不带头结点的单链表(易错点:要传入两个指针,一个用作循环条件判断,一个作为循环变量进行递归)
【代码】
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <string.h>
#define maxSize 100
#define N 3
typedef struct LNode
{
char data[maxSize];
struct LNode* next;
}LNode;
int PrintReverse(LNode* L,LNode* r, int n)//此处n不能命名为N,否则会产生命名冲突
{
if (r->next == L)
{
printf("倒数第%d行:%s\n", 1, r->data);
return 1;//打印倒数第一行返回1
}
else
{
int i;
i = PrintReverse(L, r->next, n) + 1;//i表示当前是倒数第i行
if (i <= n)
{
printf("倒数第%d行:%s", i, r->data);
}
return i;
}
}
int JudgeMistakes(char* num, char *filename, int *n)
{
int i;
i = atoi(num);
//检查n是否正确
if (i < 0)
{
i = i * -1;
*n = i;
}
else
{
return 0;
}
//检查文件名是否正确
/*略*/
return 1;
}
void tail(int n, char* filename)
{
LNode* L = (LNode*)malloc(sizeof(LNode));
L->next = L;
LNode* r = L;
int count;
count = 0;
LNode* s = NULL;
FILE* fp;
if((fp=fopen(filename,"r"))==NULL)
return;
char str[maxSize];
fgets(str, N, fp);
strcpy(L->data, str);//易错点:不带头结点的循环单链表创建要先读入数据,再用尾插法插入结点
while (fgets(str, N, fp) != NULL)
{
s = (LNode*)malloc(sizeof(LNode));
strcpy(s->data, str);
s->next = r->next;
r->next = s;
r = s;
}
PrintReverse(L, L, n);
}
int main(int argc, char* argv[])//argv是字符指针数组,每一个指针都指向一个字符串
{
int num;
//argv[0]是命令名此处用Project1代替 tail,argv[1]是读取的最后行数,argv[2]是文件名
if (JudgeMistakes(argv[1], argv[2], &num) == 0)
{
printf("Wrong");
return 0;
}
tail(num, argv[2]);
return 0;
}
【运行结果】
【文件】
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z