T2 CPS393 Practice

Download as pdf or txt
Download as pdf or txt
You are on page 1of 29

C/CPS 393

Introduction to UNIX, C and C++


Prof. Alex Ufkes

Midterm #2 Practice Problems


Problem #1

Write a program that expects one command line argument, the name of an input
file. If the input argument is not a file, print "X is not a file" to stderr, where X is the
argument’s name, and exit with a code of 1.

Each line in the input file contains some combination of words cat, dog, tac, god
(tac and god being cat and dog backwards).

For each line in the file, count the number of cats (and tacs), the number of dogs
(and gods). If there are more cats than dogs print MEOW to stdout. If there are
more dogs than cats, print WOOF. If they are equal, print SAME.

© Alex Ufkes, 2022 2


Problem #1

© Alex Ufkes, 2022 3


© Alex Ufkes, 2022 4
Problem #1: Alex’s Solution

“If the input argument is not a file, print "X is not a file" to stderr, where
X is the argument’s name, and exit with a code of 1.”

#!/bin/bash • Start by testing argument


• If not provided, exit 1
if [ $# = 0 ]; then • If provided but not a file, exit 1
exit 1
elif ! [ -f $1 ]; then
echo "$1 is not a file!" >/dev/stderr
exit 1
fi
© Alex Ufkes, 2022 5
while read x; do

• While loop to iterate through lines, but…


• We need to read from a file, not stdin
• Redirect input to the while loop

done <$1

© Alex Ufkes, 2022 6


while read x; do
catstr=`echo $x | sed -e "s/.a./c/g" -e "s/.o.//g"`
dogstr=`echo $x | sed -e "s/.a.//g" -e "s/.o./d/g"`

Preprocess using sed:


• Create two separate strings, one containing
only cats, one containing only dogs.
• The cat string contains c for every cat/tac
• The dog string contains d for every dog/god

done <$1

© Alex Ufkes, 2022 7


while read x; do
catstr=`echo $x | sed -e "s/.a./c/g" -e "s/.o.//g"`
dogstr=`echo $x | sed -e "s/.a.//g" -e "s/.o./d/g"`

catstr: dogstr:
c d
c c c c c d d d
c d d d
d
c d
(One line per iteration, remember) c c d d
c c c c d d d
done <$1 c

© Alex Ufkes, 2022 8


while read x; do
catstr=`echo $x | sed -e "s/.a./c/g" -e "s/.o.//g"`
dogstr=`echo $x | sed -e "s/.a.//g" -e "s/.o./d/g"`
typeset -i nc=`echo $catstr | wc -w`
typeset -i nd=`echo $dogstr | wc -w`

• Next, we must count the number of cats and dogs.


• We can echo each variable, pipe into wc –w
• Don’t forget to typeset as integer! We’ll need to
compare these as integers later.

done <$1

© Alex Ufkes, 2022 9


while read x; do
catstr=`echo $x | sed -e "s/.a./c/g" -e "s/.o.//g"`
dogstr=`echo $x | sed -e "s/.a.//g" -e "s/.o./d/g"`
typeset -i nc=`echo $catstr | wc -w`
typeset -i nd=`echo $dogstr | wc -w`
if [ $nc -lt $nd ]; then
echo WOOF
elif [ $nc -gt $nd ]; then
echo MEOW
else • Basic if/elif/else to compare
echo SAME number of cats and dogs
fi • Print WOOF, MEOW, or SAME,
done <$1 as appropriate.

© Alex Ufkes, 2022 10


#!/bin/bash
if [ $# = 0 ]; then
exit 1
elif ! [ -f $1 ]; then
echo "$1 is not a file!"
exit 1
fi
while read x; do
catstr=`echo $x | sed -e "s/.a./c/g" -e "s/.o.//g"`
dogstr=`echo $x | sed -e "s/.a.//g" -e "s/.o./d/g"`
typeset -i nc=`echo $catstr | wc -w`
typeset -i nd=`echo $dogstr | wc -w`
if [ $nc -lt $nd ]; then
echo WOOF
elif [ $nc -gt $nd ]; then
echo MEOW
else
echo SAME
fi
done <$1
© Alex Ufkes, 2022 11
© Alex Ufkes, 2022 12
Problem #1: Dr. Woit’s Solution

#!/bin/bash
if [ ! -f "$1" ] ; then
echo "$1 is not a file" >/dev/stderr So far it’s the same…
exit 1
fi

© Alex Ufkes, 2022 13


cat $1 | while read line ; do Pipe line into while loop
typeset -i cats=0 instead of redirecting
typeset -i dogs=0

• Variables to count number of cats and dogs


• Be sure to typeset as int using –i option!

done

© Alex Ufkes, 2022 14


cat $1 | while read line ; do
For loop to go through
typeset -i cats=0
items in each line
typeset -i dogs=0
for i in $(echo $line) ; do
if [ "$i" = "cat" -o "$i" = "tac" ] ; then
cats=cats+1
elif [ "$i" = "dog" -o "$i" = "god" ] ; then
dogs=dogs+1
fi
done • Dr Woit’s logic is more traditional, an
if/else to figure out if item is a cat or dog.
... • Increment cats or dogs accordingly.
• Can simply say cats=cats+1, because cats
done is typeset as an integer!

© Alex Ufkes, 2022 15


cat $1 | while read line ; do
typeset -i cats=0
typeset -i dogs=0
for i in $(echo $line) ; do
if [ "$i" = "cat" -o "$i" = "tac" ] ; then
cats=cats+1
elif [ "$i" = "dog" -o "$i" = "god" ] ; then
dogs=dogs+1
fi
done
...
done

© Alex Ufkes, 2022 16


cat $1 | while read line ; do
typeset -i cats=0
typeset -i dogs=0
for i in $(echo $line) ; do
if [ "$i" = "cat" -o "$i" = "tac" ] ; then
cats=cats+1
elif [ "$i" = "dog" -o "$i" = "god" ] ; then
dogs=dogs+1
fi
done
if [ "$cats" -gt "$dogs" ] ; then
echo MEOW
elif [ "$cats" -lt "$dogs" ] ; then Same logic as my solution for
echo WOOF
else
printing MEOW/WOOF/SAME
echo SAME
fi
done

© Alex Ufkes, 2022 17


© Alex Ufkes, 2022 18
Problem #2

Write a program that reads from stdin and writes to stdout. Each line of
stdin should contain a numeric value, either integer or floating point.

If the number is an integer, simply print that integer back to stdout. If the
number is a float, extract the whole number portion to the left of the
decimal, and the fractional portion to the right of the decimal. Represent
the float as the sum of these two components.

© Alex Ufkes, 2022 19


© Alex Ufkes, 2022 20
Problem #2: Alex’s Solution

#!/bin/bash
while read x; do While loop to iterate through lines of stdin

• Redirection is done when we execute the script.


• No need to redirect into the loop like Problem #1
done

© Alex Ufkes, 2022 21


Problem #2: Alex’s Solution

#!/bin/bash Next, we need to figure out if the


current line contains a float, or an int
while read x; do
if [ "`echo $x | grep '\.'`" ]; then

• Pipe the line into grep.


else
• Use grep to search for a dot
• Must escape! Dot is a
fi metacharacter in grep.
done

© Alex Ufkes, 2022 22


Problem #2: Alex’s Solution

#!/bin/bash Next, we need to figure out if the


current line contains a float, or an int
while read x; do
if [ "`echo $x | grep '\.'`" ]; then

else
• If grep finds a dot, string is not
empty, and we have a float.
fi • If not, string is empty, test is false,
done we have an integer.

© Alex Ufkes, 2022 23


Problem #2: Alex’s Solution

#!/bin/bash
while read x; do
if [ "`echo $x | grep '\.'`" ]; then

else
If line contains an integer, all we
echo $x
do is print it. Done and done.
fi
done

© Alex Ufkes, 2022 24


Problem #2: Alex’s Solution

#!/bin/bash
while read x; do
if [ "`echo $x | grep '\.'`" ]; then
flt=`echo $x | sed -e "s/\./ + 0\./"`

else If line contains a float:


echo $x • Pipe into sed, perform substitution
fi • “.” replaced with “ + 0.”
done • 3.1415 becomes 3 + 0.1415
• Save in variable flt

© Alex Ufkes, 2022 25


Problem #2: Alex’s Solution

#!/bin/bash
while read x; do
if [ "`echo $x | grep '\.'`" ]; then
flt=`echo $x | sed -e "s/\./ + 0\./"`
echo "${flt} = $x"
else
echo $x • 3 + 0.1415 should be:
fi • 3 + 0.1415 = 3.1415
done • Simply use echo to add = 3.1415

© Alex Ufkes, 2022 26


© Alex Ufkes, 2022 27
Problem #2: Dr. Woit’s Solution

Same as my solution: grep for


#!/bin/bash dot, echo line as-is if not found
while read line ; do
if [ "$(echo $line | grep '\.' )" ] ; then
whole="$(echo $line | cut -d'.' -f1)"
fract="$(echo $line | cut -d'.' -f2)"
echo "$whole + 0.$fract = $line"
else
echo $line • Dr. Woit’s solution uses cut to extract whole and
fi fractional components.
done • Cut by field, using dot as a delimiter. Cool!
• Use echo to combine components for the output
© Alex Ufkes, 2022 28
© Alex Ufkes, 2022 29

You might also like