单链表
我的lib结构体指针只用了一层,可以吗,还有在输入的时候,当我把结构体内的成员改成两个字符数组时,需要输入的数量就变了,但还是有一样的输入问题#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
typedef struct student
{
char a;
int b;
struct student* next;
} s;
void addbook(s*libr);
void scan(s*book);
void pri(s*book);
void fre(s*book);
void scan(s*book)
{
printf("输入书名\n");
scanf("%c\n",&book->a);
printf("输入书号\n");
scanf("%d\n",&book->b);
}
void addbook(s*libr)
{
s* book=(s*)malloc(sizeof(s));
s*temp;
assert(book!=NULL);
scan(book);
if(libr==NULL)
{
libr=book;
book->next=NULL;
}else
{
temp=libr;
libr=book;
book->next=temp;
}
}
void pri(s*libr)
{
s*book;
book=libr;
while(book!=NULL)
{
printf("%c\n",book->a);
printf("%d\n",book->b);
book=book->next;
}
}
void fre(s*book)
{
s* temp;
while(book!=NULL)
{
s* temp=book;
book=book->next;
free(temp);
}
}
int main ()
{
s*lib=NULL;
int u;
while(1)
{
printf("是否要输入书本\n");
u=getchar();
if(u=='y')
{
addbook(lib);
}else
{
break;
}
}
printf("是否要打印书本\n");
scanf("%c",&u);
if(u=='y')
{
pri(lib);
}
fre(lib);
return 0;
} 下面是您代码中的一些问题和建议:
1. **输入问题**:使用`scanf`时,字符输入和格式字符串后的`\n`会造成混淆。去掉格式字符串中的`\n`,在用`getchar()`或其他方法清理缓冲区后再收集输入。
2. **单链表管理问题**:函数`addbook()`中的`libr`应该使用指针的指针。因为函数参数是值传递,修改不了原指针。
3. **字符数组改动问题**:声明结构体时,如果需要字符串类型,可以使用字符数组。若改变结构体内成员的类型,所有相关输入输出逻辑也需调整。
4. **main函数中`getchar()`问题**:获取输入后需清理输入缓冲区,否则后续读取可能会出错。
下面是修改后的代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct student {
char a;// 改为字符数组以存储字符串
int b;
struct student* next;
} s;
void addbook(s** libr);
void scan(s* book);
void pri(s* libr);
void fre(s* book);
void scan(s* book) {
printf("输入书名: ");
scanf("%s", book->a);
printf("输入书号: ");
scanf("%d", &book->b);
}
void addbook(s** libr) {
s* book = (s*)malloc(sizeof(s));
assert(book != NULL);
scan(book);
book->next = *libr;
*libr = book;
}
void pri(s* libr) {
s* book = libr;
while (book != NULL) {
printf("书名: %s\n", book->a);
printf("书号: %d\n", book->b);
book = book->next;
}
}
void fre(s* book) {
s* temp;
while (book != NULL) {
temp = book;
book = book->next;
free(temp);
}
}
int main() {
s* lib = NULL;
char u;
while (1) {
printf("是否要输入书本 (y/n): ");
scanf(" %c", &u);// 注意前面有个空格,忽略换行符
if (u == 'y') {
addbook(&lib);
} else {
break;
}
}
printf("是否要打印书本 (y/n): ");
scanf(" %c", &u);
if (u == 'y') {
pri(lib);
}
fre(lib);
return 0;
}
希望这些建议能够帮助您改进代码!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 本帖最后由 jackz007 于 2024-10-27 22:39 编辑
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct student
{
char name ; // 关注这里
unsigned long long id ;
struct student * next ;
} STUDENT ;
void scan(STUDENT * book)
{
printf("输入书名 : ") ;
scanf("%s" , & book -> name) ; // 关注这里
printf("输入书号 : ") ;
scanf("%llu" , & book -> id) ;
}
void addbook(STUDENT ** libr) // 关注这里
{
STUDENT * p , * r ;
for(p = r = * libr ; p ; r = p , p = r -> next) ;
STUDENT * book = (STUDENT *) malloc(sizeof(STUDENT)) ;
scan(book) ;
book -> next = NULL ;
if(r) r -> next = book ; // 如果 libr 的值不是 NULL,那就续链
else * libr = book ; // 否则,book 就是链表的头结点
}
void pri(STUDENT * libr)
{
STUDENT * p ;
for(p = libr ; p ; p = p -> next) {
printf("%s\n" , p -> name) ;
printf("%llu\n\n" , p -> id) ;
}
}
void fre(STUDENT * libr)
{
STUDENT * p , * r ;
for(p = libr ; p ; p = r) {
r = p -> next ;
free(p) ;
}
}
int main()
{
char u ;
STUDENT * lib = NULL ;
while(1)
{
printf("是否要输入书本 : ") ;
while((u = getchar()) == '\n') ; // 关注这里
if(u == 'y') // 关注这里
{
addbook(& lib) ; // 关注这里
}
else
{
break ;
}
}
printf("是否要打印书本 : ") ;
while((u = getchar()) == '\n') ; // 关注这里
if(u == 'y') // 关注这里
{
pri(lib) ;
}
fre(lib) ;
return 0 ;
}
编译、运行实况:
D:\\C>g++ -o x x.c
D:\\C>x
是否要输入书本 : y
输入书名 : 射雕英雄传
输入书号 : 100000001
是否要输入书本 : y
输入书名 : 江湖奇侠传
输入书号 : 100000002
是否要输入书本 : y
输入书名 : 神雕侠侣
输入书号 : 100000003
是否要输入书本 : n
是否要打印书本 : y
射雕英雄传
100000001
江湖奇侠传
100000002
神雕侠侣
100000003
D:\\C>
【关于函数声明】,在同一个源代码文件内,一个函数,只要满足先定义(定义位于调用位置之前),再调用(调用位于函数定义之后),那就不比对这个函数进行声明。
在本例中,所有的函数均能够满足上述条件,所以,删除所有的函数声明。 jackz007 发表于 2024-10-27 22:20
编译、运行实况:
你好,谢谢你的回答,我想问问结构体里的a为什么不能是字符,而是字符串呢,还有可以解释下u=getchar这段代码吗,我在网上查询后没有看懂
本帖最后由 jackz007 于 2024-10-31 22:39 编辑
结构体 struct student 中的成员 a 是用来保存书名的,书名通常会是一系列字符,而非单个字符,所以,a 必须要定义成能够容纳超过你所见过最长书名字符数量的字符数组。
char a ;
这样定义的 a 并不是字符数组,而是字符变量,充其量只能容纳 1 个字符,肯定不合适,所以,必须这样定义:
char a ;
这样定义的 a 就不是一个字符变量了,而是一个字符数组,编译程序会预留出 100 个字节的存储空间供变量 a 使用,由于字符串最后必须要有一个结束标志字符 '\0',扣除这个字符,a 最多可以储存一个长度为 99 字符的字符串。
while((u = getchar()) == '\n') ;
if(u == 'y')
这个代码的作用是防止从键盘读取到的字符是换行符 ('\n'),由于程序中存在有 scanf() 和 getchar() 混用的情况,执行过 scanf() 后,在键盘缓冲区中会有遗留的 '\n',如果在这个时候执行 getchar() ,拿到的字符就会是这个 '\n',你会感觉到程序根本就没有等待键盘输入,而是直接就按没有按下 'y' 的逻辑走了。这个代码的用意就是过滤掉 '\n',直到拿到的输入字符不是 '\n' 为止。这样,代码的运行才会回到我们预期的轨道上来。 jackz007 发表于 2024-10-31 22:34
结构体 struct student 中的成员 a 是用来保存书名的,书名通常会是一系列字符,而非单个字符,所 ...
噢噢,懂了谢谢
页:
[1]