第一步:定义相应结构
由于实现链表的编程语言为C,不能够使用类,故使用结构来实现链表中的节点;
1 2 3 4 5
| typedef struct LinkList { char name[MAX_INPUT]; long number; LinkList* next; }Link;
|
该结构由一个字符数组,一项编号和一个指向此结构的指针组成。
第二步:定义输入函数
为了更容易、更准确的获取输入,在程序中重新定义输入函数,在原有fgets()函数的基础上略作修改,得到新的输入函数s_gets();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| char* s_gets(char* st, int n) { char* ret_val; char* find; ret_val = fgets(st, n, stdin); if (ret_val) { find = strchr(st, '\n'); if (find) { *find = '\0'; } else { while (getchar() != '\n') { continue; } } } return ret_val; }
|
该函数为返回类型为字符指针、接受参数为一个字符指针和一个整数的输入函数,其中字符指针就是字符数组名称,因为数组名称本质上就是数组首元素的地址,而该数组为字符数组,故该字符数组名称本质上就是字符指针;
在函数内部,我声明了两个字符指针,一个用来接受fgets函数的返回值,一个用来接受查找字符函数(strchr)的返回值;
关于fgets()函数:
- 如果接受输入的字符数量超过字符数组的大小(MAX_INPUT),fgets()函数会返回先前传入的地址,即字符数组的名称,并且把末尾的字符换为空字符('\0'),使之成为一个字符串;
- 如果接收输入的字符数量在字符数组的大小以内,那么fgets()函数会将空字符放置在换行符之前,然后同样返回先前传入的地址;
- 需要注意的是:fgets()函数在遇到文件结尾(EOF End Of File)时将会返回一个空指针;
关于strchr()函数:
- 在某个字符数组中查找某字符,并返回指向该字符的指针
- r如果字符串中不包含该字符,则返回一个空指针
经过重写,修改如下:
首先使用fgets()函数接收输入,并将返回值存储在指针ret_val中,然后对该指针进行判断,如果不为空指针,则使用字符查找函数查找换行符,并将该换行符替换为空字符,如果查找换行符失败,说明输入的字符数量超过了字符数组的大小,这时使用一个while循环接收其余的输入并抛弃;如果ret_val为空指针,说明遇到文件结尾;最后返回ret_val;
第三步:编写主函数进行测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| int main() { char input[MAX_INPUT]; Link* p = (Link*)malloc(sizeof(Link*)); Link* temp = p; printf("Now start recording: \n"); printf("Name : "); while (s_gets(input,MAX_INPUT) != NULL && input[0] != '\0') { Link* a = (Link*)malloc(sizeof(Link)); a->next = NULL; temp->next = a; temp = temp->next; strcpy(a->name, input); printf("Number: "); scanf("%ld", &(a->number)); getchar(); printf("Name : "); } temp = p->next; printf("Recorded Data: \n"); while (temp) { printf("Name: %s\tNumber: %ld\n", temp->name, temp->number); temp = temp->next; } return 0; }
|
- 首先声明一个字符数组用来储存输入,然后声明一个节点类型的指针作为头节点,并为其分配内存,接着再声明一个同样的临时指针指向该头指针,这里使用临时指针的目的是作为当前指针与下一个指针的过渡指针,同时保持头指针指向的内容不变,方便最后的输出;
- 在输出提示信息之后进入循环,退出条件为输入空行;在循环中,首先声明指向当前节点的指针并为其分配内存,接着将该指针指向的结构中的指针声明为NULL,然后将当前节点的指针赋给临时指针指向的结构的指针,使其与上一个节点相连,然后再将临时指针指向的指针赋给自身(其实就相当于使临时指针指向下一个节点);接着将刚刚接收的输入复制到当前节点的name变量中,然后再接收编号的输入并存储到当前节点的number变量中;值得注意的是,在使用scanf()函数接收输入后该函数似乎会将换行符留在缓存区中,所以这里需要使用getchar()函数来将该换行符从缓存区中去除;
- 在循环结束之后,我将临时指针指向了头节点的下一个节点(请注意,头节点中并没有储存除下一个节点的地址之外的任何信息,故此处从头节点的下一个节点开始);然后进入下一个while循环,退出条件为临时指针为空指针(因为在上一个while循环中已经将当前节点中的指针声明为NULL了,所以一旦第一个循环结束,最后一个节点中的指针必为NULL),然后打印出当前节点的信息并将临时指针指向下一个节点。
源代码
最后附上源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| #include<stdio.h> #include<stdlib.h> #include<string.h>
#define MAX_INPUT 20
char* s_gets(char* st, int n);
char* s_gets(char* st, int n) { char* ret_val; char* find; ret_val = fgets(st, n, stdin); if (ret_val) { find = strchr(st, '\n'); if (find) { *find = '\0'; } else { while (getchar() != '\n') { continue; } } } return ret_val; }
typedef struct LinkList { char name[MAX_INPUT]; long number; LinkList* next; }Link;
int main() { char input[MAX_INPUT]; Link* p = (Link*)malloc(sizeof(Link*)); Link* temp = p; printf("Now start recording: \n"); printf("Name : "); while (s_gets(input,MAX_INPUT) != NULL && input[0] != '\0') { Link* a = (Link*)malloc(sizeof(Link)); a->next = NULL; temp->next = a; temp = temp->next; strcpy(a->name, input); printf("Number: "); scanf("%ld", &(a->number)); getchar(); printf("Name : "); } temp = p->next; printf("Recorded Data: \n"); while (temp) { printf("Name: %s\tNumber: %ld\n", temp->name, temp->number); temp = temp->next; } return 0; }
|