Due Date: Monday, April 26, 2021.
In this exercise we'll generate a file containing a number of random numbers between 0 and a limit given by the user, and also create a function that can input numbers from such a file. This could be used, for example, to test a sorting function on a set of arrays of various sizes.
Create a script called hw13.py. In this script, write a function starting with the header:
def generateNumbers(filename, size, limit):
that generates size number of random integer numbers and stores them in a text file with the name given by the parameter filename. The numbers in the file should be between 0 and the limit.
Detailed guidelines:
Start by specifying the Python interpreter, and then adding an import statement for the module random. Then add a section '__main__' like we did before. Then before that section add a function with the above header.
In this function, start by calling the function open with the first parameter being the filename, and the second parameter being "w" (write mode) and assigning the result to a variable fout:
fout = open(filename, "w")
This will open a file in writing mode and store a reference to it
in the variable fout. Let's start by writing the number of
random numbers that we'll store in the file. This can be done with the
instruction:
fout.writelines("%d\n" %(size))
This is a syntax that can be used to convert any number of values to a string. The expression within the parenthesis preceded by the % replaces the expression %d (stands for decimal) in the string. Any other characters will appear in the string as they are. Other types of values can be converted with %f for simple real numbers, %g for the scientific format, and %s for strings.
The next thing we'll do is write the numbers to the file, 20 per
line. First, declare a variable called strOut and initialize
it as an empty string (as in, ""). Then add a for
loop using the range function with size as parameter
(going from 0 to size-1). Inside the loop, generate a random
integer between 0 and limit using the
function randint and store it in a variable
called n. Then add the value of n to the string in
the variable strOut with the following instruction:
strOut = "%s %d" %(strOut, n)
What this is doing is creating a string by replacing the %s with the first expression in the parenthesis (strOut) and the %d with the second one (n). So it converts n to a string, adds it to the previous content of strOut, and then assigns the result back to strOut.
Then we want to write this out to a file once we reach 20 numbers. We can use the control variable for the loop (let's call it i) for this purpose. We could simply check if i%20 is equal to 0, but then this would print the first number on a line by itself. What we can do instead, is to check if (i+1)%20 is equal to 0. Add a conditional after that line above, still inside the loop, checking for this condition. If the condition is true, then do two things: first, write the string strOut to the file with an instruction similar to the writelines from before, where instead of %d you'll have %s and instead of size you'd have strOut. Then still inside the conditional, make strOut be an empty string again.
At this point you can close both the conditional and the loop. Note that most of the time, after the loop, the variable strOut will contain some numbers that have not been written to the file yet, unless the count of numbers is a multiple of 20 precisely. To take care of them, after the loop, repeat the instruction writing strOut to the file. Then close the file with fout.close().
In the main section, add a call to this function for testing purposes with whatever file name you want and whatever values you want for the size and the limit. Go back to the terminal, make the script executable, and test it to see that everything works.
If you look at the generated file, it should look fine except for the fact that a space is added at the beginning of each line. To avoid that, go back to the function and add a conditional before assigning the value to strOut inside the loop, testing if strOut is an empty string (strOut == ""). Copy the assignment instruction, and on the positive case remove the %s and the space after it, and also remove the strOut from inside the parenthesis. Then add an else: after it and have the old assignment instruction go under it.
Make the script take 3 arguments as positional parameters and use them as the parameters in a function call for the function defined at point a.
Detailed guidelines:
Add an import statement for the module sys. Then in
the '__main__' section, add a conditional checking that the
size of argv is at least 4 (1 for the name of the script, 3
for the parameters). If it is not, then print a message saying that
the script should be called with the file name, the count of numbers
in the file, and the limit for the random numbers. On the else, use
argv[1] as the file name, convert argv[2]
and argv[3] to integers using the function int that
we've seen in Lab 13, and then call this
function with those values. You can store them in local variables if
it makes it easier, or do the conversion directly in the function
call. Save the script and run it to see that it works. This time the
command will look something like this:
hw13.py test50.txt 50 100
Add a second function with the header
def readFile(filename):
that reverses the process of the function written for a). The function should read in numbers from a file similar to the one created at point a, and store them in an array that it returns.
Detailed guidelines:
In the same script before the main, add an import statement for the module string, then add a function with the above header. We're going to assume that the format of the file is identical to the files we create with the function generateNumbers.
Start by opening a file in a similar way to the first function
(generateNumbers), but where the second parameter
is "r" instead of "w" and store its reference in a
variable called fin. Then read the line containing the size
of the file with the instruction
line = fin.readline()
This line contains the number as a string, and the '\n' character. Convert it to an integer using the int function (the '\n' will not cause a problem at this point), and store it in a variable called size. Add another variable called result and initialize it as an empty array.
Then add a while loop with the continuation condition being that the length of the array result is less than size. Inside the loop start by repeating the instruction reading a line from the file and storing it in the variable line. Then call the function split (from the string module) with the first parameter being the line, and the second parameter being " " (a string containing a single space) and store the result in a variable called numbers. The result will be an array of all the numbers on that line, as strings, and one empty string at the end.
After that add a for loop (inside the while loop)
with a control variable n going through the sequence
numbers. In this loop, test if n is not empty with a
simple test:
if n:
If that is the case, then append to the array result the value
of n converted to an integer. Then you can close both loops
and then close the file. Finally, you can return the result.
Go back to the main section and add a call to this function readFile in the else case after the call to the function generateNumbers and use the same argument for the filename. Then print the result and verify that the content of the array matches the file.
Upload to Canvas: the file hw13.py and a file generated by the script.