R Script : QA.dat R Author : Richard A. O'Keefe R Edited : 2013.02.22 R Purpose: Demonstrate QA little language. R This is the PILOT example of COSC345 Lecture 2 converted to QA. R Remarks begin with R. Questions begin with Q and end with E. R A begins a right answer, D a distractor, where exactly one answer is right. R T begins a true answer, F a false one, where many answers may be picked. R When several answers can be picked, they must be entered in alphabetic order. Q In the context of COMP160, Q which of the following is an example of a run time error? D a false start at a track and field event D an overflowing bathtub D leaving the cricket crease early A an error in coding which compiles correctly but does not run E Q Which of the following statements about local variables are true? F Local variables may have a specified visibility. F Local variables can be declared as static. T Local variables are defined within methods. T Local variables are automatically initialised. F None of them. E
#!/bin/awk # Script : QAI.awk # Author : Richard A. O'Keefe # Updated: 2013.02.22 # Purpose: Question-Answer Interpreter BEGIN { right = 0 wrong = 0 } /^Q / { print substr($0, 3) position = 0 expect = "" next } /^[DAFT] / { position++ label = substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", position, 1) print "(" label ") " substr($0, 3) if ($0 ~ /^[AT]/) expect = expect label next } /^E/ { getline answer <"/dev/tty" gsub(/[^A-Za-z]+/, "", answer) if (toupper(answer) == expect) { print "Correct." right++ } else { print "Sorry, the right answer is " expect "." wrong++ } print "" next } /^[^QDAFTER]/ { printf "Oh dear, there is an error at line %d of the script %s.\n" \ "This is our fault, not yours.\n<%s>\n", FNR, FILENAME, $0 \ >"/dev/stderr" exit 1 } END { print "You got", right, "questions right out of", right+wrong if (wrong == 0) print "Congratulations!" }
#!/bin/awk # Script : QAC.awk # Author : Richard A. O'Keefe # Updated: 2013.02.22 # Purpose: Question-Answer Compiler : QA -> C89. BEGIN { print "#include <ctype.h>" # toupper() print "#include <stdio.h>" # gets(), puts(), printf() print "#include <stdlib.h>" # EXIT_SUCCESS, EXIT_FAILURE print "#include <string.h>" # strchr() print "" print "static int right = 0;" print "static int wrong = 0;" print "" print "static void check(char const *expected) {" print " char buffer[128];" print " int i;" print " int flag = 1;" print "" ## This used to generate a call to gets(), which is a security hole, ## but for this application, who cared? MacOS X now whinges about ## it every time you run a program that uses gets(), whether it ever ## calls it or not, so now we generate a call to fgets(), which is a ## much nastier function to use. In this program we get lucky. print " if (fgets(buffer, sizeof buffer, stdin) == 0) abort();" print " for (i = 0; buffer[i] != '\\0'; i++) {" print " buffer[i] = toupper(buffer[i]);" print " }" print " for (i = 0; expected[i] != 0; i++) {" print " if (strchr(buffer, expected[i]) == 0) flag = 0;" print " }" print " if (flag) {" print " puts(" to_C_string("Correct.") ");" print " right++;" print " } else {" print " printf(\"Sorry, the right answer is %s.\\n\", expected);" print " wrong++;" print " }" print "}" print "" print "int main(void) {" } function to_C_string(s) { gsub(/\\/, "\\\\", s) gsub(/"/, "\\\"", s) gsub(/\t/, "\\t", s) return "\"" s "\"" } /^Q / { print " puts(" to_C_string(substr($0, 3)) ");" position = 0 expect = "" next } /^[DAFT] / { position++ label = substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", position, 1) print " puts(" to_C_string("(" label ") " substr($0, 3)) ");" if ($0 ~ /^[AT]/) expect = expect label next } /^E/ { print " check(" to_C_string(expect) ");" print "" next } /^[^QDAFTER]/ { printf "Oh dear, there is an error at line %d of the script %s.\n" \ "This is our fault, not yours.\n<%s>\n", FNR, FILENAME, $0 \ >"/dev/stderr" exit 1 } END { print " printf(\"You got %d questions right out of %d.\\n\"," print " right, right+wrong);" print " if (wrong == 0) puts(\"Congratulations!\");" print " return wrong == 0 ? EXIT_SUCCESS : EXIT_FAILURE;" print "}" print "" }
This is generated from QA.dat by QAC.awk.
#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> static int right = 0; static int wrong = 0; static void check(char const *expected) { char buffer[128]; int i; int flag = 1; if (fgets(buffer, sizeof buffer, stdin) == 0) abort(); for (i = 0; buffer[i] != '\0'; i++) { buffer[i] = toupper(buffer[i]); } for (i = 0; expected[i] != 0; i++) { if (strchr(buffer, expected[i]) == 0) flag = 0; } if (flag) { puts("Correct."); right++; } else { printf("Sorry, the right answer is %s.\n", expected); wrong++; } } int main(void) { puts("In the context of COMP160,"); puts("which of the following is an example of a run time error?"); puts("(A) a false start at a track and field event"); puts("(B) an overflowing bathtub"); puts("(C) leaving the cricket crease early"); puts("(D) an error in coding which compiles correctly but does not run"); check("D"); puts("Which of the following statements about local variables are true?"); puts("(A) Local variables may have a specified visibility."); puts("(B) Local variables can be declared as static."); puts("(C) Local variables are defined within methods."); puts("(D) Local variables are automatically initialised."); puts("(E) None of them."); check("CD"); printf("You got %d questions right out of %d.\n", right, right+wrong); if (wrong == 0) puts("Congratulations!"); return wrong == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }
#!/bin/awk # Script : QAF.awk # Author : Richard A. O'Keefe # Updated: 2013.02.22 # Purpose: Question-Answer Formatter # Usage : mawk -f common.awk -f latex.awk -f QAF.awk QA.dat >QA.tex # : pdflatex QA.tex # Note: this uses a small part (common.awk, latex.awk) of an existing # library for converting SGML/XML files to LaTeX/Troff/HTML. This code # that was written for this example is just this file. BEGIN { begin_document() begin_numbered_list() state = "B" } /^Q / { if (state != "Q") { if (state == "E") end_item() begin_item() state = "Q" } put_text(substr($0, 3)) position = 0 expect = "" next } /^[DAFT] / { if (state == "Q") { begin_unordered_list() state = "A" } else { end_item() } position++ label = substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", position, 1) begin_item("(" label ")") put_text(substr($0, 3)) if ($0 ~ /^[AT]/) expect = expect label next } /^E/ { end_item() end_unordered_list() state = "E" next } /^[^QDAFTER]/ { printf "Oh dear, there is an error at line %d of the script %s.\n" \ "This is our fault, not yours.\n<%s>\n", FNR, FILENAME, $0 \ >"/dev/stderr" exit 1 } END { end_item() end_numbered_list() end_document() }
This is generated from QA.dat by QAF.awk
\documentclass[a4paper]{report} \usepackage{a4wide} \begin{document} \begin{enumerate} \item{} In the context of COMP160, which of the following is an example of a run time error{?} \begin{itemize} \item[(A)] a false start at a track and field event \item[(B)] an overflowing bathtub \item[(C)] leaving the cricket crease early \item[(D)] an error in coding which compiles correctly but does not run \end{itemize} \item{} Which of the following statements about local variables are true{?} \begin{itemize} \item[(A)] Local variables may have a specified visibility. \item[(B)] Local variables can be declared as static. \item[(C)] Local variables are defined within methods. \item[(D)] Local variables are automatically initialised. \item[(E)] None of them. \end{itemize} \end{enumerate} \end{document}