Dana Vrajitoru
C151 Multi-User Operating Systems

C151 Homework 13

Due Date: Monday, April 26, 2021.

Ex. 1. File Operations

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.

a. Saving data to a file

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.

b. Using positional parameters

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

c. Reading data from a file

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.

Homework Submission

Upload to Canvas: the file hw13.py and a file generated by the script.