目的
创建一个书类结构体,循环读取书名、作者和价格
解决scanf()跳过空白、fgets()保留换行符的问题
所以创建了一个s_gets()
函数,可以读取空格分隔的一行字符
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'); // look for newline
if (find) // if the address is not NULL,
*find = '\0'; // place a null character there
else
while (getchar() != '\n')
continue; // dispose of rest of line
}
return ret_val;
}
第一次代码
#include <stdio.h>
#include <string.h>
char * s_gets(char * st, int n);
#define MAXTITL 41 /* maximum length of title + 1 */
#define MAXAUTL 31 /* maximum length of author's name + 1 */
struct book { /* structure template: tag is book */
char title[MAXTITL];
char author[MAXAUTL];
float value;
}; /* end of structure template */
int main(void)
{
struct book library[2]; /* declare library as a book variable */
for(int i = 0; i < 2; i ++){
printf("Please enter the book title.\n");
s_gets(library[i].title, MAXTITL); /* access to the title portion */
printf("Now enter the author.\n");
s_gets(library[i].author, MAXAUTL);
printf("Now enter the value.\n");
scanf("%f", &library[i].value);
}
printf("现在开始打印\n");
for(int i = 0; i < 2; i ++){
printf("%s: \"%s\" ($%.2f)\n", library[i].author,
library[i].title, library[i].value);
}
printf("Done.\n");
return 0;
}
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'); // look for newline
if (find) // if the address is not NULL,
*find = '\0'; // place a null character there
else
while (getchar() != '\n')
continue; // dispose of rest of line
}
return ret_val;
}
执行效果:
如图所示,在第二次循环的时候,发现title
和author
同时跳了出来导致下面打印的时候title
没有值
审查代码
为了保留价格的格式,所以使用了scanf()
函数来获取输入,而我们在命令行界面输入1然后回车,实际传送的字符为1\n
,而scanf()
接受了1却会把回车符留在输入缓冲中,这就导致第二次循环时,title
就把留下的回车符读入了,这也就是出现上图情况的原因
解决
清理输入行:
#include <stdio.h>
#include <string.h>
char * s_gets(char * st, int n);
#define MAXTITL 41 /* maximum length of title + 1 */
#define MAXAUTL 31 /* maximum length of author's name + 1 */
struct book { /* structure template: tag is book */
char title[MAXTITL];
char author[MAXAUTL];
float value;
}; /* end of structure template */
int main(void)
{
struct book library[2]; /* declare library as a book variable */
for(int i = 0; i < 2; i ++){
printf("Please enter the book title.\n");
s_gets(library[i].title, MAXTITL); /* access to the title portion */
printf("Now enter the author.\n");
s_gets(library[i].author, MAXAUTL);
printf("Now enter the value.\n");
scanf("%f", &library[i].value);
while (getchar() != '\n')
continue;
}
printf("现在开始打印\n");
for(int i = 0; i < 2; i ++){
printf("%s by %s: $%.2f\n",library[i].title,
library[i].author, library[i].value);
}
printf("Done.\n");
return 0;
}
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'); // look for newline
if (find) // if the address is not NULL,
*find = '\0'; // place a null character there
else
while (getchar() != '\n')
continue; // dispose of rest of line
}
return ret_val;
}
在循环中添加代码片段while (getchar() != '\n') continue;
这样就把回车符给过滤掉了