c - 如何优化从输入中读取字符,以便用户无需事先指定字符数
问题描述
程序的当前状态
我正在制作一个程序,它读取用户输入的字符直到换行并以相反的顺序打印出来。
我得到的输出是正确的,但我想优化代码。
在 main 中,我编写了执行我的 Insert 函数 n 次的代码(n 表示用户想要输入的字符数)。所以现在用户首先需要输入他们想要输入的字符数量,然后他们可以输入字符。
我真的想要它
我想让它让用户只需输入字符,而不必先指定他们想要输入的字符数。
我的尝试
尝试使用 while 循环但得到错误的结果:
输入“asdf”作为输入
并得到“fs”作为输出
int main(){
struct Node* head = NULL;
printf("Enter the chars you want to type: ");
while (getchar() != '\n') {
head = Insert(head,getchar());
}
Print(head);
}
尝试使用 if 语句但得到错误的结果:
输入“asdf”作为输入
并得到“s”作为输出
int main(){
struct Node* head = NULL;
printf("Enter the chars you want to type: ");
if (getchar() != '\n') {
head = Insert(head,getchar());
}
Print(head);
}
我的代码
#include <stdio.h>
#include <stdlib.h>
struct Node {
char data;
struct Node* linkToNext;
};
void Print(struct Node* head){
while (head != NULL) {
printf("%c", head -> data);
head = head -> linkToNext;
}
}
struct Node* Insert(struct Node* head, char input){
struct Node* pointerToNode = (struct Node*)malloc(sizeof(struct Node));
pointerToNode -> data = input;
pointerToNode ->linkToNext = head;
head = pointerToNode;
return head;
}
int main(){
struct Node* head = NULL;
int i, n;
printf("Enter the amout of chars you want to type: ");
scanf("%d", &n);
for (i = 0; i <= n; i++) {
head = Insert(head,getchar());
}
Print(head);
}
运行代码示例结果
输入要输入的字符数量:4
自卫队
食品安全局
解决方案
每次调用都会getchar()
从标准输入中读取并返回另一个字符。
考虑一下代码会发生什么
while (getchar() != '\n') {
// ^^^^^^^^^ #1
head = Insert(head,getchar());
// ^^^^^^^^^ #2
}
和用户输入asdf
。
标记为 #1 的调用读取并返回'a'
(输入的第一个字符),它不是'\n'
,因此执行循环体。
然后标记为 #2 的调用读取并返回's'
(下一个字符),将其添加到列表中。
然后我们回到循环条件。getchar()
#1 读取并返回'd'
,这仍然不是'\n'
...
... 和getchar()
#2 读取并返回'f'
,它也被添加到列表中。
最后getchar()
#1 读取一个换行符,终止循环。
由于getchar
在每次迭代中都调用了两次,因此只有每隔一个字符添加到列表中。
您的第二次尝试类似,但if
不是循环,因此仅将第二个字符总数('s'
in asdf
)添加到列表中。
要解决此问题,您需要将 的返回值存储getchar
在一个变量中,以便您可以比较它并将其添加到列表中而无需读取更多字符:
int c;
while ((c = getchar()) != '\n' && c != EOF) {
head = Insert(head, c);
}
额外的检查EOF
是为了防止您的程序进入无限循环,以防输入未被终止'\n'
。
推荐阅读
- php - phplibsec - 循环登录直到连接
- sql-server - 我应该禁用触发器吗?
- javascript - 反应元素类型无效
- python - python3 和请求:仍然收到“sslv3 警报握手失败”
- sql - SQL Server:Error_Line 返回与存储过程行号不匹配的行号
- oracle - 在 Oracle 的 PL/SQL 中使用游标搜索特定数据的特定行
- bash - 如何拆分一行但在 bash 中保留其余行?
- android - 使用 GoogleSignInOptions for Tasks API 请求范围
- mysql - 知道字符串中是否有电话号码
- scala - YARN 上的 Spark 2.3.1:如何以编程方式监控阶段进度?