我正在使用数组实现Stack数据结构。要在诸如Push或Pop或Exit from Program之类的堆栈上执行操作,我将以整数形式从用户那里获取输入(Say 1 for Push)。
为了连续从用户那里获取输入,我正在运行while(1)循环并在循环内部要求用户给出一个整数作为所需操作的输入。
问题:在执行过程中,程序没有等待用户输入并进入无限循环。我试图使用fflush清除标准输入但仍然无效。
请查看以下代码并给出评论和帮助。
感谢。
//Main function
int main(){
STACK marks, roll_number; //marks and roll_number are two stacks of type STACK
//Initialize both Stacks with required size
initStack(&marks, 10);
initStack(&roll_number, 10);
int choice, marks_data;
//Menu for user to choose from available operations
printf("1. Push\n");
printf("2. Pop\n");
printf("3. Exit\n");
//Taking user input for operations
while(1){
printf("Enter choice of Operation:\n");
//Clearing standard input. Although not a best practice but implementing to
//take user input
fflush(stdin);
// program is not stopping here and taking invalid choice
//hence executing 'default statement' of switch case
scanf("%d", &choice);
switch(choice){
case 1: printf("Enter Marks");
scanf(" %d", &marks_data);
push(&marks, marks_data);
break;
case 2: marks_data = pop(&marks);
printf("Deleted Data : %d\n", marks_data);
break;
case 3: exit(0);
default: printf("Invalid Choice of Operation !!\n");
}
//using to clear \n character from user and taking valid input
printf("Press Enter Key to continue...");
while(getchar() != '\n')
getchar();
}
return 0;
}
答案 0 :(得分:2)
当您使用scanf
时,您必须将您的"帐户"打开并说明从输入缓冲区读取的所有字符,或者在输入缓冲区中保留未读取的字符。在数字和字符输入之间混合输入或在代码中混合输入函数时尤其如此。
在您的情况下,您为scanf ("%d", ...)
和choice
致电marks
,但随后尝试通过以下方式控制您的循环执行:
printf("Press Enter Key to continue...");
while(getchar() != '\n')
getchar();
作为优秀的scanf
会计师,您知道使用'%d'
格式说明符阅读会读取stdin
到第一个非数字的数字数字字符并终止读取,使stdin
中的非数字字符保持未读。 (假设在choice
或mark
之后没有输入任何杂散字符),这将是您在上次输入后按 Enter 生成的'\n'
字符。
当您测试while(getchar() != '\n')
时,第一个字符可能是'\n'
字符,导致您的循环测试 TRUE 并跳过getchar()
内的getchar()
调用循环。
最简单的解决方案是在当前版本之下添加额外的fflush(stdin)
。
下一个fflush(stdin)
几乎是除了Windows之外的所有系统的未定义行为。在Linux上,stdin
已定义,但仅适用于可搜索流 - 仅当文件已重定向到您的程序时才适用于stdin
在./yourexe < somefile.txt
,例如
fflush(stdin)
否则未定义stdin
。所以你必须问自己 - 除了stdin
因为重定向而导致> views
> layouts
- _pwa.html.erb # single layout for all steps
> orders
> optionA
- _place_A.html.erb # unique content for a shared view file that is further shared across options
- flow_layout.html.erb # iterator that pulls in views from the various pages relevant to this option from shared_views folder
> optionB
- _place_B.html.erb # unique content for a shared view file that is further shared across options
- flow_layout.html.erb # iterator that pulls in views from the various pages relevant to this option from shared_views folder
> shared_views
> views
- _open.html.erb # unique content for a given page
- _place_A.html.erb # unique content for a given page
- _place_B.html.erb # unique content for a given page
> layouts
- _place.html.erb # similar content for a page that's different than other pages (i.e., open and place are different pages), but with elements shared across options (i.e., place_A and place_B have a lot of sharing)
之外的所有东西都是不可移植的 - &#34;在任何地方使用都是不错的做法?&#34;和&#34;如何强制用户将文件重定向到<!-- shared layout file: layouts/_pwa.html.erb -->
<%= render "/layouts/navbar", progress_counter: @pages.count %>
<div class="container-fluid zero-padding non-navbar">
<div class="row-fluid ">
<%= yield %> <!-- main content, varies for each of X pages -->
</div>
<div class="row-fluid troubleshooter_title">
<div class="col-xs-12">
<h4 class="cursor-point underline text-center">
<span class="glyphicon glyphicon-menu-right"></span> <%= troubleshooter_title %> <!-- named content varies for each of X pages -->
</h4>
</div>
</div>
<%= yield :troubleshooter_content %> <!-- named content varies for each of X pages -->
</div>
# Orders Controller file for 2 set of steps (optionA vs optionB)
# as implied below, "place_A" and "place_B" are VERY similar, with a few tweaks
def optionA
# second element of inner array stores other info not relevant to this answer here
@pages = [
["open"],
["place_A"],
]
render "#{action_name}/flow_layout"
end
def optionB
@pages = [
["place_B"],
]
render "#{action_name}/flow_layout"
end
<!-- flow_layout as rendered by controller -->
<!-- optionA/flow_layout.html.erb -->
<%= render layout: "layouts/pwa", locals: {troubleshooter_title: "Having trouble?" } do %>
<% @pages.each do |p| %>
<%= render "shared_views/views/#{p[0]}" %>
<% end %>
<% end %>
<!-- optionA/flow_layout.html.erb -->
<%= render layout: "layouts/pwa", locals: {troubleshooter_title: "How it works" } do %>
<% @pages.each do |p| %>
<%= render "shared_views/views/#{p[0]}" %>
<% end %>
<% end %>
<!-- above note one important fact, I wanted the troubleshooter_title to CHANGE between optionA & optionB -->
<!-- shared_view partials -->
<!-- shared_views/views/_open.html.erb -->
<!-- first div goes into main yield -->
<div class="col-xs-12">
<h1>Open the door</h1>
</div>
<% content_for :troubleshooter_content do %>
Try pushing instead of pulling
<% end %>
<!-- shared_views/views/_place_A.html.erb -->
<!-- given the fact that place_A and place_B are very similar, there's a nesting here of a place layout file that holds all the commonalities. the minor differences are placed with the optionA view folder itself -->
<%= render layout: "shared_views/layouts/place" do %>
<%= render "optionA/place_A" %>
<% end %>
<!-- shared_views/views/_place_B.html.erb -->
<!-- same as above -->
<%= render layout: "shared_views/layouts/place" do %>
<%= render "optionB/place_B" %>
<% end %>
<!-- place layout -->
<div class="col-xs-12">
<h1><%= yield %></h1>
</div>
<% content_for :troubleshooter_content do %>
<%= yield :nested_troubleshooter_content %>
<% end %>
<!-- optionA/_place_A.html.erb -->
Place A: put on table
<% content_for :nested_troubleshooter_content %>
Table is directly in front of you
<% end %>
<!-- optionB/_place_B.html.erb -->
Place B: put on rug
<% content_for :nested_troubleshooter_content %>
Rug is to the right of you
<% end %>
?&#34; (你不能)。所以最好避免一路走来。
仔细看看,如果您有其他问题,请告诉我。