一 分析
使用函数getc(stdin)可以从键盘获得用户输入
二 实现
1 简单的输入回显
代码
#include <stdio.h> #include <stdlib.h> int main() { char input; while(1) { printf("Enter:"); input = getc(stdin); printf("You enter:%c\n",input); } }
理想输出:
Enter:a
You enter:a
实际输出1
Enter:1 You enter:1 Enter:You enter:
实际输出2
Enter:asd
You enter:a
Enter:You enter:s
Enter:You enter:d
Enter:You enter:
2 getc() 从缓存中读取字符
getc()函数从缓存中读取字符,这就导致了1中理想和实际输出的差异。
从缓存读取字符的含义:用户在终端输入字符的时侯,终端并不知道用户输入了些什么,直到用户输入回车字符,终端将回车字符输入前的所有字符及回车字符本身存入缓存等待其他函数调用。此时若执行一次getc就从缓存中取出一个字符,并将该字符从缓存中清除。getc函数可以循环读取,直到缓存中所有字符,包括回车符都被读取完毕为止。若缓存被读完,getc返回EOF。
对于1的代码来说,用户输入字符a前后发生了如下事情:
(1)执行 printf("Enter:"); 界面输出提示符“Enter:”
(2)执行 input = getc(stdin); 等待用户输入
(3)用户输入字符'a', 缓存中包含“a”
(4)用户输入‘回车’, 缓存中包含“a、回车”,执行下一步
注意,input只能读取1个字符'a';缓存中a被读出,现在只剩“回车符”
(5)执行 printf("You enter:%c\n",input); 界面输出缓存中第一个字符 "You enter:a"
(6)程序回到一开始,执行printf("Enter:"); 在下一行输出提示符“Enter:”
(7)执行input = getc(stdin); 因为现在缓存中还有个“回车符”呢,所以程序认为用户已输入,input=回车,缓存被清空
(8)执行 printf("You enter:%c\n",input); 界面输出"You enter:"并换行
(9)程序回到一开始,执行printf("Enter:"); 在下一行输出提示符“Enter:”
(10)执行input = getc(stdin); 由于缓存是空的,所以程序执行到这里就等待用户输入。
3 如何读取完整的用户输入并输出,做一个getline
从2中我们可以看到,执行getc后,程序等待用户输入,用户在这里可以输入删减任何字符,直到用户输入回车符后,程序将用户全部的输入放入缓存,但是,此时getc只能返回缓存中的第一个字符,再次执行getc,返回第二个字符,一直到返回‘回车符’后结束,再次执行getc函数,则程序等待用户输入。
(在Ubuntu上实验发现,getc函数在获取用户输入时,缓存读取完毕并没有返回EOF,获得回车符之后,再次支持getc直接进入等待用户输入,所以我们只能使用回车符来判断用户的全部输入已读完。)
1)如何做一个getline
使用getc如何做一个一次返回全部用户输入的getline呢?大概过程如下:
(1)先是有个大循环
(2)循环里先执行getc等待用户输入
(3)用户输入完成后,getc返回第一个字符
(4)判断该字符是否为‘回车符’,是的话就结束循环,返回保存的字符串,否的话执行下一步
(5)将该字符保存,返回第二步,如果缓存里还有东西没输出,那就不会等用户输入,getc直接返回下一个字符
流程图:
2)getline的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int getsline(char *result) { int point = 0; int word; while(1) { word = getc(stdin);//等待用户输入或从缓存中读一个字符 if(word != '\n')//读到回车符就认为一行指令被读完了 { *result = word;//记录这个字符 result ++; point ++; } else { result = '\0';//给指针末尾添加一个结束符 result = result - point;//让指针指回字符串的头 return 0; } } } int main() { char *line; line = malloc(100); getsline(line); printf("You enter:%s\n",line); return 0; }