程序代写案例-209H1S

欢迎使用51辅导,51作业君孵化低价透明的学长辅导平台,服务保持优质,平均费用压低50%以上! 51fudao.top
April 2018 Final Examination — Solutions CSC 209H1S
Question 1. [8 marks]
Each code snippet below contains a problem. Briefly state what the problem is and then modify the code to address
the problem. Make minimal changes so that the code works as intended. The code snippets in each part of this
question are independent of each other.
Part (a) [2 marks]
struct thing {
struct thing *next;
};
struct thing *a = malloc(sizeof(struct thing));
a->next = malloc(sizeof(struct thing));
free(a);
free(a->next);
Problem
Attempting to access a->next after a has already been
freed.
Solution
free(a->next);
free(a);
Part (b) [2 marks]
char *return_s() {
char *s = "hello world";
return s;
}
int main() {
char *r = return_s();
free(r);
}
Problem
r in main() is not on the heap, so it cannot be
freed.
Solution
Make return_s() use malloc, or don't
call free(r) in main.
Total Pages = 19 Page 1
CSC 209H1S Final Examination — Solutions April 2018
Part (c) [2 marks]
int fd[2];
int res = fork(); // error-checking is not shown, but that is not the problem
pipe(fd);
if (res == 0) {
close(fd[0]);
} else if (res > 0) {
close(fd[1]);
}
Problem
The pipe is not shared by the two processes. At
present, they each have a separate pipe. Instead the
pipe call has to be moved above the fork call.
Solution
int fd[2];
pipe(fd);
int res = fork();
...
Part (d) [2 marks]
int *make_list() {
int list[3] = {1, 2, 3};
return list;
}
int main() {
int *l = make_list();
int i;
for (i = 0; i < 3; i++) {
printf("%d\n", l[i]);
}
return 0;
}
Problem
list in make list() is memory on the stack.
Solution
Modify the function to make use
of dynamic memory instead.
Total Pages = 19 Page 2
April 2018 Final Examination — Solutions CSC 209H1S
Question 2. [8 marks]
Each code snippet below contains a problem. Briefly state what the problem is and then modify the code to address
the problem. Make minimal changes so that the code works as intended. The code snippets in each part of this
question are independent of each other.
Part (a) [2 marks]
struct animal {
char *name;
};
struct animal dog;
dog->name = "Fish";
Problem
dog is not a pointer, so we can’t use -> to get
its name value.
Solution
dog.name = "Fish";
Part (b) [2 marks]
char *s = "hey";
s[1] = 'a';
printf("%s", s); //print "hay"
Problem
Can’t mutate a string literal.
Solution
char s[] = "hey";
s[1] = 'a';
printf("%s", s); //print "hay"
Part (c) [2 marks]
char *word = malloc(6 * sizeof(char));
word = "hello";
Problem
Memory leak.
Assigning the string literal "hello" to word causes you
to lose your only reference to the memory originally
allocated to the variable.
Solution
char *word = malloc(6 * sizeof(char));
strncpy(word, "hello", 6);
Part (d) [2 marks]
int *a;
*a = 3;
Total Pages = 19 Page 3
CSC 209H1S Final Examination — Solutions April 2018
Problem
a is not initialized and does not have memory
assigned to it.
Solution
int *a = malloc(sizeof(int));
*a = 3;
----- OR -----
int *a, b = 3;
a = &b;
Total Pages = 19 Page 4
April 2018 Final Examination — Solutions CSC 209H1S
Question 3. [9 marks]
Match each term below to the description that best describes it. (Functions are indicated with parentheses.) Note
that some descriptions will not be used and each description should be used at most once.
I socket() D bind() K listen() M accept() O connect()
J endianness G htons() X port R dup2() L select()
U pipe C errno Y wait() E sigaction() A zombie
A. a process that has completed execution, but is still waiting for its parent to accept its termination status
B. an active process whose parent has finished or terminated before it
C. an integer variable that is set by certain functions
D. assigns a name / address to a socket
E. changes action taken by a process on receipt of a specific signal
F. chooses a client to connect to
G. converts values from host to network byte order
H. converts values from network to host byte order
I. creates an endpoint for communication and returns a descriptor
J. describes byte order
K. establishes a queue for connections
L. examines descriptor sets to see if any are ready for reading, writing, etc.
M. gets a connection from the queue
N. gets data from a server
O. initiates a connection from the client
P. initiates a connection from the server
Q. listens for new activity on one existing client
R. makes a copy of an open file descriptor
S. monitors the activity of a signal
T. object that allows bidirectional data flow
U. object that allows unidirectional data flow
V. raises a signal
W. specifies a file descriptor to examine
X. specifies which process to interact with on a server
Y. suspends execution until a child has terminated
Z. suspends execution until all children have terminated
Total Pages = 19 Page 5
CSC 209H1S Final Examination — Solutions April 2018
Question 4. [6 marks]
Consider the following code.
/* Precondition: strlen(orig) == strlen(new) */
void change_airline(char** flights, int size, char *orig, char *new){
for (int i = 0; i < size; i++) {
if (strncmp(flights[i], orig, strlen(orig)) == 0) {
strncpy(flights[i], new, strlen(orig));
}
}
}
int main(int argc, char**argv) {
char first[8] = {'A', 'C', ' ', '1', '2', '3', '4', '\0'};
char *flights[3];
flights[0] = first;
flights[1] = malloc(sizeof(char) * 8);
strcpy(flights[1], "AC 5555");
flights[2] = "WS 9876";
change_airline(flights, 3, "AC", "UN");
/* HERE */
for (int i=0; i < 3; i++) {
printf("%s\n", flights[i]);
}
return 0;
}
Part (a) [1 mark]
The code above runs without error. What does it print to stdout?
UN 1234
UN 5555
WS 9876
Total Pages = 19 Page 6
April 2018 Final Examination — Solutions CSC 209H1S
Part (b) [5 marks]
Complete the memory model diagram to reflect the state of memory at the point in the program marked by the
comment HERE.
Section Address Value Label
Read-only 0x100
0x104
0x108
0x10c
0x110
0x114
0x118
0x11c
...
...
Heap 0x23c
0x240
0x244
0x248
0x24c
0x250
0x254
0x258
0x25c
...
...
Stack
0x454
0x458
0x45c
0x460
0x464
0x468
0x46c
0x470
0x474
0x478
0x47c
0x480
0x484
0x488
0x48c
0x490
0x494
0x498
0x49c
Total Pages = 19 Page 7
CSC 209H1S Final Examination — Solutions April 2018
Question 5. [8 marks]
Part (a) [5 marks]
The sum ith integers program takes an integer i and one or more binary file names as arguments. Each binary
file contains a sequence of integers, and the program prints to stdout the sum of all the ith integers in each file.
For example, if you have files that contain binary representations for these numbers:
file1
-----------
1 2 3 4 5 6
file2
-----------
3 -2 400 384
file3
------------
8 21 8 0 ...
sum ith integers 0 file1 file2 file3 would print 12. (12 is the sum of 1, 3, and 8, the integers at position 0
of file1, file2, and file3, respectively.) sum ith integers 2 file1 file2 would print 403.
You may assume that the user calls the program with valid arguments, the each file exists, is readable and contains
enough integers, and that the files were created on the same machine as the one that will run your program. You
should not assume that integers are 4 bytes long.
Write C code to implement the sum ith integers program as specified above.
int main(int argc, char **argv) {
if (argc < 3) {
fprintf(stderr,"Usage: sum_ith_integers i filename[s]\n");
exit(1);
}
int sum = 0;
int i;
int offset = strtol(argv[1], NULL, 10);
for (i = 2; i < argc; i++) {
FILE *fp = fopen(argv[i], "rb"); // "r" is fine too, b is optional
fseek(fp, offset * sizeof(int), SEEK_SET);
int val;
fread(&val, sizeof(int), 1, fp);
sum += val;
}
printf("%d\n", sum);
return 0;
}
Total Pages = 19 Page 8
April 2018 Final Examination — Solutions CSC 209H1S
Part (b) [2 marks]
Why did we need the assumption that the files were created on the same machine as the one running the program?
Give two reasons.
The following may differ between machines:
• sizeof(int)
• endianness
Part (c) [1 mark]
The program prints the result, but could have been designed to return the result instead. What is the advantage of
printing rather than returning the result?
If the result is printed, the return value (exit code) can be used to indicate whether the program terminated successfuly
or due to some sort of error.
Total Pages = 19 Page 9
CSC 209H1S Final Examination — Solutions April 2018
Question 6. [9 marks]
Consider the following struct definition:
struct town {
int population;
char name[MAXNAME+1];
};
Part (a) [4 marks]
Write a function grow that will triple the population of a town represented by a struct town and append “-city”
to the name. If this would cause the population to exceed the value stored in the pre-defined constant MAXINT, set
the population to MAXINT. If there is not enough room for the new name, do not change it at all. If you encounter
only one of these problems return 1, both of these problems return 2, and otherwise return 0.
int grow(struct town *t) {
int result = 0;
if (t->population * 3 > MAXINT) {
t->population = MAXINT;
result = 1;
} else {
t->population *= 3;
}
if (strlen(t->name) + 5 <= MAXNAME) {
strcat(t->name, "-city");
} else {
result = 1;
}
return result;
}
Total Pages = 19 Page 10
April 2018 Final Examination — Solutions CSC 209H1S
Part (b) [5 marks]
Write the main function for a program that will read a town name from the first command-line argument, a population
from the second argument, create a struct to represent this town and then call grow on the struct. Do not use any
dynamically-allocated memory. If the original name provided by the user is too long, just truncate it to take what
will fit safely in the struct. You may assume that the propulation provided by the user is less than MAXINT.
You may assume that the user enters exactly two arguments and that the second one is an integer.
int main(int argc, char **argv) {
struct town t;
// ok to have MAXNAME + 1 here, just gets overwritten below
strncpy(t.name, argv[1], MAXNAME);
t.name[MAXNAME] = '\0';
t.population = strtol(argv[2], NULL, 0);
// also fine to just have grow(&t); and not save return value
int result = grow(&t);
return 0;
}
Total Pages = 19 Page 11
CSC 209H1S Final Examination — Solutions April 2018
Question 7. [5 marks]
Consider the following code:
int main(int argc, char **argv) {
int i;
int pid;
for (i = 1; i < argc; i++) {
pid = fork();
if (pid == 0) {
int n = 0;
int j;
for (j = 0; j < strlen(argv[i]); j++) {
if (argv[i][j] == 'a') {
n++;
}
}
exit(n);
}
}
for (i = 1; i < argc; i++) {
int status;
wait(&status);
if (WIFEXITED(status)) {
printf("%d ", WEXITSTATUS(status));
}
}
printf("***\n");
return 0;
}
Part (a) [1 mark]
Briefly describe what the program does.
Prints the number of times the character ’a’ appears in each commandline argument, followed by ***.
Part (b) [1 mark]
List all possible outputs generated by the program if it is compiled as do something and run like so:
./do something orange blue aardvark
1 0 3 ***
1 3 0 ***
0 1 3 ***
0 3 1 ***
3 1 0 ***
3 0 1 ***
Total Pages = 19 Page 12
April 2018 Final Examination — Solutions CSC 209H1S
Part (c) [3 marks]
Make changes to this copy of the original program so that the same number of processes are forked, but the order
of the output is guaranteed to match the order of the input. Also, change it so that the output now goes to stderr
instead of stdout.
int main(int argc, char **argv) {
int i;
int pid;
for (i = 1; i < argc; i++) {
pid = fork();
if (pid == 0) {
int n = 0;
int j;
for (j = 0; j < strlen(argv[i]); j++) {
if (argv[i][j] == 'a') {
n++;
}
}
exit(n);
} else if (pid > 0) {
int status;
wait(&status);
if (WIFEXITED(status)) {
fprintf(stderr, "%d\n", WEXITSTATUS(status));
}
}
}
fprintf(stderr, "***\n");
return 0;
}
Total Pages = 19 Page 13
CSC 209H1S Final Examination — Solutions April 2018
Question 8. [9 marks]
Write a program in which the parent process forks a single child, and there is a pipe set up between the two processes
that the child will use to write to the parent.
The child process should have a SIGUSR1 signal handler that writes the integer 1 into the pipe whenever SIGUSR1 is
received.
The parent process should keep track of the number of times 1 has been read from the pipe. Whenever it reads a 1,
the parent prints the updated count to standard output.
The program should continue to run indefinitely. You do not need to perform error checking for system calls, but
you should close unneeded pipe ends.
Part (a) [8 marks]
Write the program as described above.
int fd[2];
int write_val = 1;
void send_one(int signal) {
write(fd[1], &write_val, sizeof(int));
}
int main() {
pipe(fd);
int pid = fork();
if (pid == 0) {
close(fd[0]);
struct sigaction sa;
sa.sa_handler = send_one;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);
while (1);
} else if (pid > 0) {
close(fd[1]);
int count = 0;
while (1) {
// Read from the pipe:
int num = 0;
int num_read = read(fd[0], &num, sizeof(int));
if (num_read == sizeof(int) && num == 1) {
count++;
printf("%d\n", count);
}
}
}
return 0;
}
Total Pages = 19 Page 14
April 2018 Final Examination — Solutions CSC 209H1S
Part (b) [1 mark]
Assume the program has begun execution, and the child’s pid is 21483. Write a shell command to send the SIGUSR1
signal to the child process.
kill -USR1 21483
Total Pages = 19 Page 15
CSC 209H1S Final Examination — Solutions April 2018
Question 9. [5 marks]
Consider the man page of an imaginary system call office_hours. Type ps_set is a defined type, similar to type
fd_set that you used with select.
OFFICE_HOURS(2) BSD System Calls Manual OFFICE_HOURS(2)
NAME
PS_CLR, PS_ISSET, PS_SET, PS_ZERO, office_hours
SYNOPSIS
void PS_CLR(ps, ps_set *psset);
int PS_ISSET(ps, ps_set *psset);
void PS_SET(ps, ps_set *psset);
void PS_ZERO(ps_set *psset);
int officehours(ps_set *prof, struct timeval window);
DESCRIPTION
office_hours() examines the schedules for the professors in the
professor set prof to see which have office hours scheduled within the
given window from the current time. office_hours() replaces the
professor set with the subset of professors who have office hours
in the given window.
RETURN VALUE
office_hours() returns the number of professors from the ps_set
who have office hours in the window, or -1 if an error occurs.
If office_hours() returns with an error, the descriptor sets will be
unmodified and the global variable errno will be set to indicate the error.
Suppose that (like file descriptors), professors are represented by small integers and there are professors defined as
follows:
#define MICHELLE 1
#define ANDREW 2
#define JEN 3
#define ALAN 4
... (there are more)
You are only interested in office hours held by Jen or Michelle in the next 5 hours. Finish the program on the next
page, so that it calls office_hours and then prints either the message "Jen has office hours" or the message
"Michelle has office hours" or both messages as appropriate.
Demonstrate that you know how to properly check for errors on a system call by writing the code to give the
conventional behaviour if office_hours fails.
int main() {
struct timeval window;
window.interval = 5 * 60;
Total Pages = 19 Page 16
April 2018 Final Examination — Solutions CSC 209H1S
// set up first argument to office_hours
ps_set profs;
PS_ZERO(&profs);
PS_SET(MICHELLE, &profs);
PS_SET(JEN, &profs);
// call office_hours
if (office_hours(&profs, window) == -1) {
perror("office_hours");
exit(1);
}
// print the appropriate message
if (PS_ISSET(JEN, &profs)) {
printf("Jen has office hours\n");
}
if (PS_ISSET(MICHELLE, &profs)) {
printf("Michelle has office hours\n");
}
return 0;
}
Total Pages = 19 Page 17
CSC 209H1S Final Examination — Solutions April 2018
Question 10. [9 marks]
Part (a) [7 marks]
Suppose that students in your course have been submitting an executable named myprog.c and for each student, the
path to each student’s file is /209repos//myprog.c where is replaced by the student’s UTORID.
Your current directory contains the following 200 files: test1.in ... test100.in and expected1.out ... expected100.out
where expected*.out is the output that should be printed to stdout from a correct implementation of myprog.c
when called with redirected input from test*.in. The current directory contains other files, but none that end in
.out or .in.
On the next page, write a shell program that takes a single UTORID as a command-line argument and does the
following:
• creates a new subdirectory named the same as the UTORID from the command-line argument
• changes into that subdirectory
• copies the 100 test input files, the 100 expected output files, and the student’s submission into that subdirectory
• attempts to compile the student’s code into an executable named myprog
• if the compilation is successful:
– awards the student 5 marks for compiling successfully
– runs the student’s submission on each of the 100 tests producing actual*.out.
– awards 1 additional mark for each test where the student’s actual output is identical to the expected
output.
– prints to stdout, the UTORID and the total marks the student earned
• if the student is not successful:
– prints to stdout, the UTORID and a message that the code did not compile
• changes back to the original directory
Your program should not print anything other than what is listed here. In particular, it should not print compilation
messages or any other output about individual files matching or not. Note that gcc returns 0 when compilation is
successful and a non-zero value otherwise. Complete Part (a) on the next page.
Part (b) [1 mark]
Suppose your program from Part (a) is called myscript.sh. Give the command to set its permissions so that anyone
can read it or run it but nobody can change it.
chmod myscript 555 (or many variations)
Part (c) [1 mark]
Suppose your script has been run on many UTORIDs and the current directory now contains many subdirectories
with files. Give a single shell command that from your current directory will set the permissions on all the student
output files (those called actual*.out) so that nobody can execute or change any of the files, but TAs (who are
members of the group) can copy the files. Accounts that are not members of the group should not be able to copy
the files. No directory permissions need to be changed.
chmod 440 */actual*.out OR chmod 040 */actual*.out
Total Pages = 19 Page 18
April 2018 Final Examination — Solutions CSC 209H1S
utorid=$1
mkdir $utorid
cd $utorid
cp ../*.in .
cp ../*.out .
cp /209/repos/$utorid/myprog.c
# other options for redirection to /dev/null
if gcc -Wall -std=gnu99 -o myprog myprog.c > /dev/null 2 /dev/null
then
points=5
for i in `seq 1 100`
do
./myprog < test$i.in > actual$i.out
if ! diff actual$i.out expected$i.out >/dev/null
then
points=`expr $points + 1`
fi
done
echo $utorid $points
else
echo $utorid did not compile
fi
cd ..
Write your script for Part (a) here.
Total Pages = 19 Page 19 End of Solutions

欢迎咨询51作业君
51作业君

Email:51zuoyejun

@gmail.com

添加客服微信: abby12468