Menu: Difference between revisions
Added XPL0 |
|||
Line 247: | Line 247: | ||
#include <string.h> |
#include <string.h> |
||
char *menu_select(char **items, char *prompt); |
const char *menu_select(const char *const *items, const char *prompt); |
||
int |
int |
||
main(void) |
main(void) |
||
{ |
{ |
||
char *items[] = {"fee fie", "huff and puff", "mirror mirror", "tick tock", NULL}; |
const char *items[] = {"fee fie", "huff and puff", "mirror mirror", "tick tock", NULL}; |
||
char *prompt = "Which is from the three pigs?"; |
const char *prompt = "Which is from the three pigs?"; |
||
printf("You chose %s.\n", menu_select(items, prompt)); |
printf("You chose %s.\n", menu_select(items, prompt)); |
||
Line 260: | Line 260: | ||
} |
} |
||
char * |
const char * |
||
menu_select(char **items, char *prompt) |
menu_select(const char *const *items, const char *prompt) |
||
{ |
{ |
||
char buf[BUFSIZ]; |
char buf[BUFSIZ]; |
Revision as of 07:19, 23 December 2012
You are encouraged to solve this task according to the task description, using any language you may know.
Given a list containing a number of strings of which one is to be selected and a prompt string, create a function that:
- Print a textual menu formatted as an index value followed by its corresponding string for each item in the list.
- Prompt the user to enter a number.
- Return the string corresponding to the index number.
The function should reject input that is not an integer or is an out of range integer index by recreating the whole menu before asking again for a number. The function should return an empty string if called with an empty list.
For test purposes use the four phrases: “fee fie”, “huff and puff”, “mirror mirror” and “tick tock” in a list.
Note: This task is fashioned after the action of the Bash select statement.
Ada
<lang Ada> -- menu2.adb -- -- rosetta.org menu example -- GPS 4.3-5 (Debian)
-- note: the use of Unbounded strings is somewhat overkill, except that -- it allows Ada to handle variable length string data easily -- ie: differing length menu items text with Ada.Text_IO, Ada.Integer_Text_IO, Ada.Strings.Unbounded,
Ada.Strings.Unbounded.Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO,
Ada.Strings.Unbounded, Ada.Strings.Unbounded.Text_IO;
procedure menu2 is
package tio renames Ada.Integer_Text_IO; -- rename package to use a shorter name, tio, as integer get prefix menu_item : array (1..4) of Unbounded_String; -- 4 menu items of any length choice : integer := 0; -- user selection entry value
procedure show_menu is
-- display the menu options and collect the users input -- into locally global variable 'choice'
begin for pntr in menu_item'first .. menu_item'last loop put (pntr ); put(" "); put( menu_item(pntr)); new_line; end loop; put("chose (0 to exit) #:"); tio.get(choice); end show_menu;
-- main program -- begin
menu_item(1) := to_unbounded_string("Fee Fie"); menu_item(2) := to_unbounded_string("Huff & Puff"); menu_item(3) := to_unbounded_string("mirror mirror"); menu_item(4) := to_unbounded_string("tick tock"); -- setup menu selection strings in an array show_menu;
loop if choice in menu_item'range then put("you chose #:"); case choice is -- in a real menu, each case would execute appropriate user procedures when 1 => put ( menu_item(choice)); new_line; when 2 => put ( menu_item(choice)); new_line; when 3 => put ( menu_item(choice)); new_line; when 4 => put ( menu_item(choice)); new_line; when others => null; end case; show_menu; else put("Menu selection out of range"); new_line; if choice = 0 then exit; end if; -- need a exit option ! show_menu; end if; end loop;
end menu2;
</lang>
<lang Ada> ./menu2
1 Fee Fie 2 Huff & Puff 3 mirror mirror 4 tick tock
chose (0 to exit) #:2 you chose #:Huff & Puff
1 Fee Fie 2 Huff & Puff 3 mirror mirror 4 tick tock
chose (0 to exit) #:55 Menu selection out of range
1 Fee Fie 2 Huff & Puff 3 mirror mirror 4 tick tock
chose (0 to exit) #:0 Menu selection out of range [2010-06-09 22:18:25] process terminated successfully (elapsed time: 15.27s)
</lang>
ALGOL 68
<lang algol68>PROC menu select := (FLEX[]STRING items, UNION(STRING, VOID) prompt)STRING: (
INT choice; IF LWB items <= UPB items THEN WHILE FOR i FROM LWB items TO UPB items DO printf(($g(0)") "gl$, i, items[i])) OD; CASE prompt IN (STRING prompt):printf(($g" "$, prompt)), (VOID):printf($"Choice ? "$) ESAC; read((choice, new line)); # WHILE # 1 > choice OR choice > UPB items DO SKIP OD; items[choice] ELSE "" FI
);
test:(
FLEX[0]STRING items := ("fee fie", "huff and puff", "mirror mirror", "tick tock"); STRING prompt := "Which is from the three pigs : ";
printf(($"You chose "g"."l$, menu select(items, prompt)))
)</lang> Output:
1) fee fie 2) huff and puff 3) mirror mirror 4) tick tock Which is from the three pigs : 2 You chose huff and puff.
AutoHotkey
<lang autohotkey>GoSub, CreateGUI return
Submit: Gui, Submit, NoHide If Input =
GuiControl,,Output
Else If Input not between 1 and 4 {
Gui, Destroy Sleep, 500 GoSub, CreateGUI
} Else {
GuiControlGet, string,,Text%Input% GuiControl,,Output,% SubStr(string,4)
} return
CreateGUI: list = fee fie,huff and puff,mirror mirror,tick tock Loop, Parse, list, `,
Gui, Add, Text, vText%A_Index%, %A_Index%: %A_LoopField%
Gui, Add, Text, ym, Which is from the three pigs? Gui, Add, Edit, vInput gSubmit Gui, Add, Edit, vOutput Gui, Show return
GuiClose: ExitApp</lang>
BASIC
<lang qbasic> function sel$(choices$(), prompt$)
if ubound(choices$) - lbound(choices$) = 0 then sel$ = "" ret$ = "" do for i = lbound(choices$) to ubound(choices$) print i; ": "; choices$(i) next i input ;prompt$, index if index <= ubound(choices$) and index >= lbound(choices$) then ret$ = choices$(index) while ret$ = "" sel$ = ret$
end function</lang>
BBC BASIC
<lang bbcbasic> DIM list$(4)
list$() = "fee fie", "huff and puff", "mirror mirror", "tick tock" selected$ = FNmenu(list$(), "Please make a selection: ") PRINT selected$ END DEF FNmenu(list$(), prompt$) LOCAL index%, select$ IF SUM(list$()) = "" THEN = "" REPEAT CLS FOR index% = 0 TO DIM(list$() ,1) IF list$(index%)<>"" PRINT ; index% ":", list$(index%) NEXT PRINT prompt$ ; INPUT "" select$ index% = VAL(select$) IF select$<>STR$(index%) index% = -1 IF index%>=0 IF index%<=DIM(list$() ,1) IF list$(index%)="" index% = -1 UNTIL index%>=0 AND index%<=DIM(list$(), 1) = list$(index%)</lang>
Empty entries in the list are not offered as options, nor accepted as a selection.
Brat
<lang brat>menu = { prompt, choices |
true? choices.empty? { "" } { choices.each_with_index { c, i | p "#{i}. #{c}" }
selection = ask prompt
true? selection.numeric? { selection = selection.to_i true? selection < 0 || { selection >= choices.length } { p "Selection is out of range"; menu prompt, choices } { choices[selection] } } { p "Selection must be a number"; menu prompt, choices } }
}
p menu "Selection: " ["fee fie" "huff and puff" "mirror mirror" "tick tock"]</lang>
C
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <string.h>
const char *menu_select(const char *const *items, const char *prompt);
int main(void) { const char *items[] = {"fee fie", "huff and puff", "mirror mirror", "tick tock", NULL}; const char *prompt = "Which is from the three pigs?";
printf("You chose %s.\n", menu_select(items, prompt));
return EXIT_SUCCESS; }
const char * menu_select(const char *const *items, const char *prompt) { char buf[BUFSIZ]; int i; int choice; int choice_max;
if (items == NULL) return NULL;
do { for (i = 0; items[i] != NULL; i++) { printf("%d) %s\n", i + 1, items[i]); } choice_max = i; if (prompt != NULL) printf("%s ", prompt); else printf("Choice? "); if (fgets(buf, sizeof(buf), stdin) != NULL) { choice = atoi(buf); } } while (1 > choice || choice > choice_max);
return items[choice - 1]; }</lang>
C++
<lang cpp>#include <iostream>
- include <boost/regex.hpp>
- include <cstdlib>
- include <string>
using namespace std;
void printMenu(const string *, int); //checks whether entered data is in required range bool checkEntry(string, const string *, int);
string dataEntry(string prompt, const string *terms, int size) {
if (size == 0) { //we return an empty string when we call the function with an empty list return ""; } string entry; do { printMenu(terms, size); cout << prompt; cin >> entry; } while( !checkEntry(entry, terms, size) ); int number = atoi(entry.c_str()); return terms[number - 1];
}
void printMenu(const string *terms, int num) {
for (int i = 1 ; i < num + 1 ; i++) { cout << i << ')' << terms[ i - 1 ] << '\n'; }
}
bool checkEntry(string myEntry, const string *terms, int num) {
boost::regex e("^\\d+$"); if (!boost::regex_match(myEntry, e)) return false; int number = atoi(myEntry.c_str()); if (number < 1 || number > num) return false; return true;
}
int main( ) {
const string terms[ ] = { "fee fie" , "huff and puff" , "mirror mirror" , "tick tock" }; int size = sizeof terms / sizeof *terms; cout << "You chose: " << dataEntry("Which is from the three pigs: ", terms, size); return 0;
}</lang>
C#
<lang csharp>
static void Main(string[] args) { List<string> menu_items = new List<string>() { "fee fie", "huff and puff", "mirror mirror", "tick tock" }; //List<string> menu_items = new List<string>(); Console.WriteLine(PrintMenu(menu_items)); Console.ReadLine(); } private static string PrintMenu(List<string> items) { if (items.Count == 0) return "";
string input = ""; int i = -1; do { for (int j = 0; j < items.Count; j++) Console.WriteLine("{0}) {1}", j, items[j]);
Console.WriteLine("What number?"); input = Console.ReadLine();
} while (!int.TryParse(input, out i) || i >= items.Count || i < 0); return items[i]; }
</lang>
Clojure
<lang clojure>(defn menu [prompt choices]
(if (empty? choices) "" (let [menutxt (apply str (interleave (iterate inc 1) (map #(str \space % \newline) choices)))] (println menutxt) (print prompt) (flush) (let [index (read-string (read-line))] ; verify (if (or (not (integer? index)) (> index (count choices)) (< index 1)) ; try again (recur prompt choices) ; ok (nth choices (dec index)))))))
(println "You chose: "
(menu "Which is from the three pigs: " ["fee fie" "huff and puff" "mirror mirror" "tick tock"]))</lang>
Common Lisp
<lang lisp>(defun select (prompt choices)
(if (null choices) "" (do (n) ((and n (<= 0 n (1- (length choices)))) (nth n choices)) (format t "~&~a~%" prompt) (loop for n from 0 for c in choices do (format t " ~d) ~a~%" n c)) (force-output) (setf n (parse-integer (read-line *standard-input* nil) :junk-allowed t)))))</lang>
D
<lang d>import std.stdio, std.conv, std.string, std.array;
string menuSelect(in string[] entries) {
static int validChoice(in string input, in int nEntries) pure nothrow { try { immutable n = to!int(input); return (n >= 0 && n <= nEntries) ? n : -1; } catch (Exception e) // very generic return -1; // not valid }
if (entries.empty) return "";
while (true) { writeln("Choose one:"); foreach (i, const string entry; entries) writefln(" %d) %s", i, entry); writef("> "); immutable input = readln().chomp(); immutable choice = validChoice(input, entries.length-1); if (choice != -1) return entries[choice]; // we have a valid choice else writeln("Wrong choice."); }
}
void main() {
immutable items = ["fee fie", "huff and puff", "mirror mirror", "tick tock"]; writeln("You chose '", menuSelect(items), "'.");
}</lang>
Euphoria
<lang euphoria>include get.e
function menu_select(sequence items, object prompt)
if length(items) = 0 then return "" else for i = 1 to length(items) do printf(1,"%d) %s\n",{i,items[i]}) end for if atom(prompt) then prompt = "Choice?" end if return items[prompt_number(prompt,{1,length(items)})] end if
end function
constant items = {"fee fie", "huff and puff", "mirror mirror", "tick tock"} constant prompt = "Which is from the three pigs? "
printf(1,"You chose %s.\n",{menu_select(items,prompt)})</lang>
Factor
<lang factor>USE: formatting
- print-menu ( seq -- )
[ 1 + swap "%d - %s\n" printf ] each-index "Your choice? " write flush ;
- select ( seq -- result )
dup print-menu readln string>number [ 1 - swap 2dup bounds-check? [ nth ] [ nip select ] if ] [ select ] if* ;</lang>
Example usage:
( scratchpad ) { "fee fie" "huff and puff" "mirror mirror" "tick tock" } select 1 - fee fie 2 - huff and puff 3 - mirror mirror 4 - tick tock Your choice? 1 --- Data stack: "fee fie"
Fantom
<lang fantom>class Main {
static Void displayList (Str[] items) { items.each |Str item, Int index| { echo ("$index: $item") } }
public static Str getChoice (Str[] items) { selection := -1 while (selection == -1) { displayList (items) Env.cur.out.print ("Select: ").flush input := Int.fromStr(Env.cur.in.readLine, 10, false) if (input != null) { if (input >= 0 && input < items.size) { selection = input } } echo ("Try again") } return items[selection] }
public static Void main () { choice := getChoice (["fee fie", "huff and puff", "mirror mirror", "tick tock"]) echo ("You chose: $choice") }
}</lang>
Go
<lang go>package main
import "fmt"
func menu(choices []string, prompt string) string {
if len(choices) == 0 { return "" } var c int for { fmt.Println("") for i, s := range choices { fmt.Printf("%d. %s\n", i+1, s) } fmt.Print(prompt) _, err := fmt.Scanln(&c)
if err == nil && c > 0 && c <= len(choices) { break } } return choices[c-1]
}
func main() {
pick := menu(nil, "No prompt") fmt.Printf("No choices, result = %q\n", pick)
choices := []string{ "fee fie", "huff and puff", "mirror mirror", "tick tock", } pick = menu(choices, "Enter number: ") fmt.Printf("You picked %q\n", pick)
}</lang> Output:
No choices, result = "" 1. fee fie 2. huff and puff 3. mirror mirror 4. tick tock Enter number: 2 You picked "huff and puff"
Haskell
<lang Haskell>module RosettaSelect where
import Data.Maybe (listToMaybe) import Control.Monad (guard)
select :: [String] -> IO String select [] = return "" select menu = do
putStr $ showMenu menu putStr "Choose an item: " choice <- getLine maybe (select menu) return $ choose menu choice
showMenu :: [String] -> String showMenu menu = unlines [show n ++ ") " ++ item | (n, item) <- zip [1..] menu]
choose :: [String] -> String -> Maybe String choose menu choice = do
n <- maybeRead choice guard $ n > 0 listToMaybe $ drop (n-1) menu
maybeRead :: Read a => String -> Maybe a maybeRead = fmap fst . listToMaybe . filter (null . snd) . reads</lang>
Example usage, at the GHCI prompt: <lang Haskell>*RosettaSelect> select ["fee fie", "huff and puff", "mirror mirror", "tick tock"] 1) fee fie 2) huff and puff 3) mirror mirror 4) tick tock Choose an item: 3 "mirror mirror"
- RosettaSelect></lang>
HicEst
<lang HicEst>CHARACTER list = "fee fie,huff and puff,mirror mirror,tick tock,", answer*20
POP(Menu=list, SelTxt=answer)
SUBROUTINE list ! callback procedure must have same name as menu argument
! Subroutine with no arguments: all objects are global ! The global variable $$ returns the selected list index WRITE(Messagebox, Name) answer, $$
END</lang>
Icon and Unicon
<lang Icon>procedure main()
L := ["fee fie", "huff and puff", "mirror mirror", "tick tock"]
every i := 1 to *L do
write(i,") ",L[i])
repeat {
writes("Choose a number from the menu above: ") a := read() if 1 <= integer(a) <= i then break }
write("You selected ",a," ==> ",L[a]) end</lang>
J
Solution: <lang j>require'misc' showMenu =: i.@# smoutput@,&":&> ' '&,&.> makeMsg =: 'Choose a number 0..' , ': ',~ ":@<:@# errorMsg =: [ smoutput bind 'Please choose a valid number!'
select=: ({::~ _&".@prompt@(makeMsg [ showMenu)) :: ($:@errorMsg)</lang> See Talk page for explanation of code.
Example use: <lang j> select 'fee fie'; 'huff and puff'; 'mirror mirror'; 'tick tock'</lang>
This would display:
0 fee fie 1 huff and puff 2 mirror mirror 3 tick tock choose a number 0..3:
And, if the user responded with 2, would return: mirror mirror
Java
<lang java5>public static String select(List<String> list, String prompt){
if(list.size() == 0) return ""; Scanner sc = new Scanner(System.in); String ret = null; do{ for(int i=0;i<list.size();i++){ System.out.println(i + ": "+list.get(i)); } System.out.print(prompt); int index = sc.nextInt(); if(index >= 0 && index < list.size()){ ret = list.get(index); } }while(ret == null); return ret;
}</lang>
JavaScript
for the I/O.
<lang javascript>function select(question, choices) {
var prompt = ""; for (var i in choices) prompt += i + ". " + choices[i] + "\n"; prompt += question;
var input; while (1) { WScript.Echo(prompt); input = parseInt( WScript.StdIn.readLine() ); if (0 <= input && input < choices.length) break; WScript.Echo("\nTry again."); } return input;
}
var choices = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock']; var choice = select("Which is from the three pigs?", choices); WScript.Echo("you selected: " + choice + " -> " + choices[choice]);</lang>
Logo
<lang logo>to select :prompt [:options]
foreach :options [(print # ?)] forever [ type :prompt type "| | make "n readword if (and [number? :n] [:n >= 1] [:n <= count :options]) [output item :n :options] print sentence [Must enter a number between 1 and] count :options ]
end
print equal? [huff and puff] (select
[Which is from the three pigs?] [fee fie] [huff and puff] [mirror mirror] [tick tock])
</lang>
Lua
<lang lua>function choice(choices)
for i, v in ipairs(choices) do print(i, v) end
print"Enter your choice" local selection = io.read() + 0
if choices[selection] then print(choices[selection]) else choice(choices) end
end
choice{"fee fie", "huff and puff", "mirror mirror", "tick tock"}</lang>
Mathematica
<lang Mathematica>textMenu[data_List] := (MapIndexed[Print[#21, ") ", #] &, {a, b, c}];
While[! (IntegerQ[choice] && Length[data] > choice > 0), choice = Input["Enter selection"]]; datachoice)</lang>
Use:
textMenu[{"fee fie", "huff and puff", "mirror mirror", "tick tock"}]
MATLAB
<lang MATLAB>function sucess = menu(list)
if numel(list) == 0 sucess = ; return end
while(true) disp('Please select one of these options:'); for i = (1:numel(list)) disp([num2str(i) ') ' list{i}]); end disp([num2str(numel(list)+1) ') exit']); try key = input(':: '); if key == numel(list)+1 break elseif (key > numel(list)) || (key < 0) continue else disp(['-> ' list{key}]); end catch continue end end sucess = true;
end </lang>
Modula-2
<lang modula2>MODULE Menu;
FROM InOut IMPORT WriteString, WriteCard, WriteLn, ReadCard;
CONST StringLength = 100;
MenuSize = 4;
TYPE String = ARRAY[0..StringLength-1] OF CHAR;
VAR menu : ARRAY[0..MenuSize] OF String;
selection, index : CARDINAL;
BEGIN
menu[1] := "fee fie"; menu[2] := "huff and puff"; menu[3] := "mirror mirror"; menu[4] := "tick tock"; FOR index := 1 TO HIGH(menu) DO WriteString("["); WriteCard( index,1); WriteString( "] "); WriteString( menu[index]); WriteLn; END;(*of FOR*) WriteString("Choose what you want : "); ReadCard(selection); IF (selection <= HIGH(menu)) AND (selection > 0) THEN WriteString("You have chosen: "); WriteString( menu[selection]); WriteLn; ELSE WriteString("Selection is out of range!"); WriteLn; END (*of IF*)
END Menu.</lang>
MUMPS
<lang MUMPS>MENU(STRINGS,SEP)
;http://rosettacode.org/wiki/Menu NEW I,A,MAX ;I is a loop variable ;A is the string read in from the user ;MAX is the number of substrings in the STRINGS list ;SET STRINGS="fee fie^huff and puff^mirror mirror^tick tock" SET MAX=$LENGTH(STRINGS,SEP) QUIT:MAX=0 ""
WRITEMENU
FOR I=1:1:MAX WRITE I,": ",$PIECE(STRINGS,SEP,I),! READ:30 !,"Choose a string by its index: ",A,! IF (A<1)!(A>MAX)!(A\1'=A) GOTO WRITEMENU KILL I,MAX QUIT $PIECE(STRINGS,SEP,A)</lang>
Usage:
USER>W !,$$MENU^ROSETTA("fee fie^huff and puff^mirror mirror^tick tock","^") 1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock Choose a string by its index: 3 mirror mirror USER>W !,$$MENU^ROSETTA("fee fie^huff and puff^mirror mirror^tick tock","^") 1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock Choose a string by its index: 5 1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock Choose a string by its index: A 1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock Choose a string by its index: 0 1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock Choose a string by its index: 1 fee fie
OCaml
<lang ocaml>let rec select choices prompt = (* "choices" is an array of strings *)
if Array.length choices = 0 then invalid_arg "no choices"; Array.iteri (Printf.printf "%d: %s\n") choices; print_string prompt; let index = read_int () in if index >= 0 && index < Array.length choices then choices.(index) else select choices prompt</lang>
OpenEdge/Progress
<lang progress>FUNCTION bashMenu RETURNS CHAR(
i_c AS CHAR
):
DEF VAR ii AS INT. DEF VAR hfr AS HANDLE. DEF VAR hmenu AS HANDLE EXTENT. DEF VAR ikey AS INT. DEF VAR ireturn AS INT INITIAL ?.
EXTENT( hmenu ) = NUM-ENTRIES( i_c ).
CREATE FRAME hfr ASSIGN WIDTH = 80 HEIGHT = NUM-ENTRIES( i_c ) PARENT = CURRENT-WINDOW VISIBLE = TRUE .
DO ii = 1 TO NUM-ENTRIES( i_c ):
CREATE TEXT hmenu ASSIGN FRAME = hfr FORMAT = "x(79)" SCREEN-VALUE = SUBSTITUTE( "&1. &2", ii, ENTRY( ii, i_c ) ) ROW = ii VISIBLE = TRUE . END.
IF i_c = "" THEN ireturn = 1.
DO WHILE ireturn = ?:
READKEY. ikey = INTEGER( CHR( LASTKEY ) ) NO-ERROR. IF ikey >= 1 AND ikey <= NUM-ENTRIES( i_c ) THEN ireturn = ikey.
END.
RETURN ENTRY( ireturn, i_c ).
END FUNCTION.
MESSAGE
bashMenu( "fee fie,huff and puff,mirror mirror,tick tock" )
VIEW-AS ALERT-BOX.</lang>
Oz
<lang oz>declare
fun {Select Prompt Items} case Items of nil then "" else
for Item in Items Index in 1..{Length Items} do {System.showInfo Index#") "#Item} end {System.printInfo Prompt} try {Nth Items {ReadInt}} catch _ then {Select Prompt Items} end
end end
fun {ReadInt} class TextFile from Open.file Open.text end StdIo = {New TextFile init(name:stdin)} in {String.toInt {StdIo getS($)}} end Item = {Select "Which is from the three pigs: "
["fee fie" "huff and puff" "mirror mirror" "tick tock"]}
in
{System.showInfo "You chose: "#Item}</lang>
PARI/GP
<lang parigp>choose(v)=my(n);for(i=1,#v,print(i". "v[i]));while(type(n=input())!="t_INT"|n>#v|n<1,);v[n] choose(["fee fie","huff and puff","mirror mirror","tick tock"])</lang>
Perl
<lang perl>sub menu {
my ($prompt,@array) = @_; return unless @array;
print " $_: $array[$_]\n" for(0..$#array); print $prompt; $n = <>; return $array[$n] if $n =~ /^\d+$/ and defined $array[$n]; return &menu($prompt,@array);
}
@a = ('fee fie', 'huff and puff', 'mirror mirror', 'tick tock'); $prompt = 'Which is from the three pigs: ';
$a = &menu($prompt,@a);
print "You chose: $a\n";</lang>
Perl 6
<lang perl6>sub menu ( $prompt, @items ) {
return unless @items.elems; repeat until my $selection ~~ /^ \d+ $/ && @items[--$selection] { my $i = 1; say " {$i++}) $_" for @items; $selection = prompt $prompt; } return @items[$selection];
}
my @choices = 'fee fie', 'huff and puff', 'mirror mirror', 'tick tock'; my $prompt = 'Enter the number corresponding to your selection: ';
my $answer = menu( $prompt, [] ); say "You chose: $answer" if $answer.chars;
$answer = menu( $prompt, @choices ); say "You chose: $answer" if $answer.chars;</lang>
PL/I
<lang PL/I> test: proc options (main);
declare menu(4) character(100) varying static initial (
'fee fie', 'huff and puff', 'mirror mirror', 'tick tock');
declare (i, k) fixed binary;
do i = lbound(menu,1) to hbound(menu,1);
put skip edit (trim(i), ': ', menu(i) ) (a);
end; put skip list ('please choose an item number'); get list (k); if k >= lbound(menu,1) & k <= hbound(menu,1) then
put skip edit ('you chose ', menu(k)) (a);
else
put skip list ('Could not find your phrase');
end test; </lang>
PicoLisp
<lang PicoLisp>(de choose (Prompt Items)
(use N (loop (for (I . Item) Items (prinl I ": " Item) ) (prin Prompt " ") (NIL (setq N (in NIL (read)))) (T (>= (length Items) N 1) (get Items N)) ) ) )
(choose "Which is from the three pigs?"
'("fee fie" "huff and puff" "mirror mirror" "tick tock") )</lang>
Output:
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock Which is from the three pigs? 2 -> "huff and puff"
PHP
<lang php><?php $stdin = fopen("php://stdin", "r"); $allowed = array(1 => 'fee fie', 'huff and puff', 'mirror mirror', 'tick tock');
for(;;) {
foreach ($allowed as $id => $name) { echo " $id: $name\n"; } echo "Which is from the four pigs: "; $stdin_string = fgets($stdin, 4096); if (isset($allowed[(int) $stdin_string])) { echo "You chose: {$allowed[(int) $stdin_string]}\n"; break; }
}</lang>
PowerShell
<lang powershell>function Get-Choice ([array] $Items) {
Set-StrictMode -Version Latest
do { $Items | ForEach-Object { $i = 0 } { '{0,3}. {1}' -f (++$i),$_ } $choice = Read-Host Your choice } while ($choice -notmatch '^\d+$' -or !(1..$Items.Length -eq $choice))
$Items[$choice-1]
}</lang> Trying it out: <lang powershell>Get-Choice 'fee fie', 'huff and puff', 'mirror mirror', 'tick tock'</lang>
1. fee fie 2. huff and puff 3. mirror mirror 4. tick tock Your choice: 0 1. fee fie 2. huff and puff 3. mirror mirror 4. tick tock Your choice: 5 1. fee fie 2. huff and puff 3. mirror mirror 4. tick tock Your choice: 2 huff and puff
ProDOS
<lang>
- a
printline ==========MENU========== printline 1. Fee Fie printline 2. Huff Puff printline 3. Mirror, Mirror printline 4. Tick, Tock editvar /newvar /value=a /userinput=1 /title=What page do you want to go to? if -a- /hasvalue 1 printline You chose a line from the book Jack and the Beanstalk. & exitcurrentprogram 1 if -a- /hasvalue 2 printline You chose a line from the book The Three Little Pigs. & exitcurrentprogram 1 if -a- /hasvalue 3 printline You chose a line from the book Snow White. & exitcurrentprogram 1 if -a- /hasvalue 4 printline You chose a line from the book Beauty and the Beast. & exitcurrentprogram 1 printline You either chose an invalid choice or didn't chose. editvar /newvar /value=goback /userinput=1 /title=Do you want to chose something else? if -goback- /hasvalue y goto :a else exitcurrentprogram 1 </lang>
PureBasic
<lang PureBasic>If OpenConsole()
Define i, txt$, choice Dim txts.s(4) EnableGraphicalConsole(1) ;- Enable graphical mode in the console Repeat ClearConsole() Restore TheStrings ; Set reads address For i=1 To 4 Read.s txt$ txts(i)=txt$ ConsoleLocate(3,i): Print(Str(i)+": "+txt$) Next ConsoleLocate(3,6): Print("Your choice? ") choice=Val(Input()) Until choice>=1 And choice<=4 ClearConsole() ConsoleLocate(3,2): Print("You chose: "+txts(choice)) ; ;-Now, wait for the user before ending to allow a nice presentation ConsoleLocate(3,5): Print("Press ENTER to quit"): Input()
EndIf End
DataSection
TheStrings: Data.s "fee fie", "huff And puff", "mirror mirror", "tick tock"
EndDataSection</lang>
Python
<lang python>def _menu(items):
for indexitem in enumerate(items): print (" %2i) %s" % indexitem)
def _ok(reply, itemcount):
try: n = int(reply) return 0 <= n < itemcount except: return False
def selector(items, prompt):
'Prompt to select an item from the items' if not items: return reply = -1 itemcount = len(items) while not _ok(reply, itemcount): _menu(items) # Use input instead of raw_input for Python 3.x reply = raw_input(prompt).strip() return items[int(reply)]
if __name__ == '__main__':
items = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock'] item = selector(items, 'Which is from the three pigs: ') print ("You chose: " + item)</lang>
Sample runs:
0) fee fie 1) huff and puff 2) mirror mirror 3) tick tock Which is from the three pigs: -1 0) fee fie 1) huff and puff 2) mirror mirror 3) tick tock Which is from the three pigs: 0 You chose: fee fie >>> ================================ RESTART ================================ >>> 0) fee fie 1) huff and puff 2) mirror mirror 3) tick tock Which is from the three pigs: 4 0) fee fie 1) huff and puff 2) mirror mirror 3) tick tock Which is from the three pigs: 3 You chose: tick tock
R
Uses menu. <lang R>showmenu <- function() {
choices <- c("fee fie", "huff and puff", "mirror mirror", "tick tock") ans <- menu(choices) if(ans==0) "" else choices[ans]
} str <- showmenu()</lang>
REXX
<lang rexx>/*REXX program shows a list, asks user for a selection number (integer).*/
do forever /*keep asking until response OK. */ call list_create /*create the list from scratch. */ call list_show /*display (show) the list to user*/ if #==0 then return /*if empty list, then return null*/ say right(' choose an item by entering a number from 1 ───►' #, 70, '═') parse pull x /*get the user's choice (if any).*/
select when x= then call sayErr "a choice wasn't entered" when words(x)\==1 then call sayErr 'too many choices entered:' when \datatype(x,'N') then call sayErr "the choice isn't numeric:" when \datatype(x,'W') then call sayErr "the choice isn't an integer:" when x<1 | x># then call sayErr "the choice isn't within range:" otherwise leave /*this leaves the DO FOREVER loop*/ end /*select*/ end /*forever*/ /*user might've entered 2. or 003*/
x=x/1 /*normalize the number (maybe). */ say; say 'you chose item' x": " #.x return #.x /*stick a fork in it, we're done.*/ /*──────────────────────────────────LIST_CREATE─────────────────────────*/ list_create: #.1='fee fie' /*one method for list-building. */
#.2='huff and puff' #.3='mirror mirror' #.4='tick tock'
- =4 /*store number of choices in #. */
return /*(above) is just one convention.*/ /*──────────────────────────────────LIST_SHOW───────────────────────────*/ list_show: say /*display a blank line. */
do j=1 for # /*display the list of choices. */ say '[item' j"] " #.j /*display item # with its choice.*/ end /*j*/
say /*display another blank line. */ return /*──────────────────────────────────SAYERR──────────────────────────────*/ sayErr: say; say '***error!***' arg(1) x; say; return</lang> output (up to the point of the prompt):
[item 1] fee fie [item 2] huff and puff [item 3] mirror mirror [item 4] tick tock ════════════════════ choose an item by entering a number from 1 ───► 4
REBOL
<lang REBOL>REBOL [ Title: "Text Menu" Author: oofoe Date: 2009-12-08 URL: http://rosettacode.org/wiki/Select ]
choices: ["fee fie" "huff and puff" "mirror mirror" "tick tock"] choice: ""
valid?: func [ choices [block! list! series!] choice ][ if error? try [choice: to-integer choice] [return false] all [0 < choice choice <= length? choices] ]
while [not valid? choices choice][ repeat i length? choices [print [" " i ":" choices/:i]] choice: ask "Which is from the three pigs? " ] print ["You chose:" pick choices to-integer choice]</lang>
Output:
1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock Which is from the three pigs? klf 1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock Which is from the three pigs? 5 1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock Which is from the three pigs? 2 You chose: huff and puff
Ruby
<lang ruby>def select(prompt, items)
return "" if items.length == 0 while true items.each_index {|i| puts "#{i}. #{items[i]}"} print "#{prompt}: " begin answer = Integer(gets()) rescue ArgumentError redo end return items[answer] if answer.between?(0, items.length - 1) end
end
- test empty list
response = select("Which is empty", []) puts "empty list returns: >#{response}<" puts ""
- "real" test
items = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock'] response = select("Which is from the three pigs", items) puts "you chose: >#{response}<"</lang>
Run BASIC
<lang runbasic>dim choose$(5) choose$(1) = "1 Fee Fie" choose$(2) = "2 Huff Puff" choose$(3) = "3 Mirror, Mirror" choose$(4) = "4 Tick, Tock" choose$(5) = "Exit"
[start] print "Menu Selection" listbox #lb,choose$(),5 button #sel, "Accept",[select] wait
[select] selected$=#lb selection$() print " " if selected$<>"" then
print "You selected ";selected$ else print "No selection made"
end if
button #con, "Continue",[go2]
wait [go2] if selected$<>"Exit" then
cls goto [start] else cls end
end if</lang>
Seed7
<lang seed7>$ include "seed7_05.s7i";
const func string: menuSelect (in array string: items, in string: prompt) is func
result var string: selection is ""; local var string: item is ""; var integer: index is 0; var integer: num is 0; begin if length(items) <> 0 then repeat for item key index range items do writeln(index <& ". " <& item); end for; write(prompt); readln(num); until num >= 1 and num <= length(items); selection := items[num]; end if end func;
const array string: items is [] ("fee fie", "huff and puff", "mirror mirror", "tick tock"); const string: prompt is "Which is from the three pigs? ";
const proc: main is func
begin writeln("You chose " <& menuSelect(items, prompt)); end func;</lang>
Tcl
<lang tcl>proc select {prompt choices} {
set nc [llength $choices] if {!$nc} {
return ""
} set numWidth [string length $nc] while true {
set i 0 foreach s $choices { puts [format " %-*d: %s" $numWidth [incr i] $s] } puts -nonewline "$prompt: " flush stdout gets stdin num if {[string is int -strict $num] && $num >= 1 && $num <= $nc} { incr num -1 return [lindex $choices $num] }
}
}</lang> Testing it out interactively... <lang tcl>% puts >[select test {}]< >< % puts >[select "Which is from the three pigs" {
"fee fie" "huff and puff" "mirror mirror" "tick tock"
}]<
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs: 0
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs: skdfjhgz
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs:
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs: 5
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock
Which is from the three pigs: 2 >huff and puff<</lang>
UNIX Shell
This example uses the Bash select statement, but Bash did not invent this feature. The select loop comes originally from the Korn Shell, and appears in some other shells. This loop always continues to read menu choices until the script breaks the loop, or the standard input reaches end of file (EOF).
- If the user enters a blank line, the select loop repeats the list of choices. This is the only way to print the list again. An invalid choice only repeats the prompt, not the list.
Our choose function wraps a select loop. This wrapper implements the task requirement to provide an empty string from an empty list of choices. It also breaks the select loop after the first good choice.
<lang bash># choose 'choice 1' 'choice 2' ...
- Prints menu to standard error. Prompts with PS3.
- Reads REPLY from standard input. Sets CHOICE.
choose() {
CHOICE= # Default CHOICE is empty string. $# -gt 0 || return # Return if "$@" is empty. select CHOICE; do # Select from "$@". if -n $CHOICE ; then break else echo Invalid choice. fi done
}
PS3='Which is from the three pigs: ' choose 'fee fie' 'huff and puff' 'mirror mirror' 'tick tock' -n $CHOICE && echo You chose: $CHOICE -z $CHOICE && echo No input.</lang>
$ bash menu.sh 1) fee fie 2) huff and puff 3) mirror mirror 4) tick tock Which is from the three pigs: 5 Invalid choice. Which is from the three pigs: 2 You chose: huff and puff $
$ zsh menu.sh 1) fee fie 2) huff and puff 3) mirror mirror 4) tick tock Which is from the three pigs: 2 You chose: huff and puff
es
There is no select loop, but this es script provides just enough code to mimic one.
- Deviation from task: When the list of choices is empty, this function returns an empty list, not an empty string.
<lang es># choose 'choice 1' 'choice 2' ...
- Prints menu to standard error. Prompts with $prompt.
- Returns choice. If no input, returns empty list.
fn choose args { # If args are empty, return empty list. ~ $#args 0 && return
# Echo to standard error. let (reply =; choice =; fn-menu =; fn-ch =) >[1=2] { fn-menu = { # Show menu. let (i = 1) for (c = $args) { echo $i') '$c i = `{expr $i + 1} } } fn-ch = { # Set choice = $args($reply), but ignore error # if $reply is not a valid index. choice = <={catch @ e {result} { result $args($reply) }} }
menu forever { # Show prompt, read reply. echo -n $prompt reply = <={%read}
# If no input, return empty list. ~ $#reply 0 && return
# Parse reply and return choice. reply = <={%split \ \t\n $reply} if {~ $#reply 0} { # Empty reply: show menu again. menu } {~ $#reply 1 && ch; ~ $#choice 1} { return $choice } { echo Invalid choice. } } } }
let (choice = <={ local (prompt = 'Which is from the three pigs: ') choose 'fee fie' 'huff and puff' 'mirror mirror' 'tick tock' }) { ~ $#choice 1 && echo You chose: $choice ~ $#choice 0 && echo No input. }</lang>
$ es menu.es 1) fee fie 2) huff and puff 3) mirror mirror 4) tick tock Which is from the three pigs: 2 You chose: huff and puff
XPL0
<lang XPL0>include c:\cxpl\codes; string 0;
func Menu(List); int List; int Size, I, C; [Size:= List(0); if Size < 1 then return List(0); for I:= 1 to Size-1 do
[IntOut(0, I); Text(0, ": "); Text(0, List(I)); CrLf(0); ];
CrLf(0); Text(0, List(Size)); \display prompt loop [C:= ChIn(0); \buffered keyboard requires Enter key
if C>=^1 & C<=Size-1+^0 then return List(C-^0); Text(0, "Please enter 1 thru "); IntOut(0, Size-1); Text(0, ": "); ];
];
Text(0, Menu([5, "fee fie", "huff and puff", "mirror mirror", "tick tock",
"Which phrase is from the Three Little Pigs? "]))</lang>
Example output:
1: fee fie 2: huff and puff 3: mirror mirror 4: tick tock Which phrase is from the Three Little Pigs? 5 Please enter 1 thru 4: 2 huff and puff
- Programming Tasks
- Text processing
- Ada
- ALGOL 68
- AutoHotkey
- BASIC
- BBC BASIC
- Brat
- C
- C++
- C sharp
- Clojure
- Common Lisp
- D
- Euphoria
- Factor
- Fantom
- Go
- Haskell
- HicEst
- Icon
- Unicon
- J
- Java
- JavaScript
- Logo
- Lua
- Mathematica
- MATLAB
- Modula-2
- MUMPS
- OCaml
- OpenEdge/Progress
- Oz
- PARI/GP
- Perl
- Perl 6
- PL/I
- PicoLisp
- PHP
- PowerShell
- ProDOS
- PureBasic
- Python
- R
- REXX
- REBOL
- Ruby
- Run BASIC
- Seed7
- Tcl
- UNIX Shell
- Es
- XPL0
- GUISS/Omit