联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp

您当前位置:首页 >> C/C++编程C/C++编程

日期:2020-12-16 11:31

ECS 36A: Programming Assignment #8

Contents

1 Changelog 1

2 General Submission Details 1

3 Grading Breakdown 1

4 Submitting on Gradescope 2

4.1 Regarding Autograder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

4.1.1 Visible Test Cases’ Inputs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

5 Your Programming Tasks 3

5.1 Part #1: getProduct() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

5.2 Part #2: linearSearch() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

5.3 Part #3: Copy to Multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

5.4 Part #4: Run Steps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1 Changelog

You should always refer to the latest version of this document.

? v.1: Initial version.

? v.2: Fixed typo in the very last assertion in testLinearSearch().

? v.3: Autograder details.

2 General Submission Details

Partnering on this assignment is prohibited. If you have not already, you should read the section on

academic misconduct in the syllabus.

This assignment is due the night of Monday, December 14. Gradescope will say 12:30 AM on Tuesday, December 15, due

to the “grace period” (as described in the syllabus). Be careful about relying on the grace period for extra time; this could be

risky.

You should use the -Wall and -Werror flags when compiling. The autograder will use these flags when it compiles your

program.

3 Grading Breakdown

The autograder score will be out of 50 points. Each of the four parts is worth around 12.5 points.

?This content is protected and may not be shared, uploaded, or distributed.

1

4 Submitting on Gradescope

You should only submit prog8.c and the two shell scripts. You may be penalized for submitting additional files. You have

infinite submissions until the deadline.

During the 10/02 lecture, I talked about how to change the active submission, just in case that is something that you

find yourself wanting to do.

4.1 Regarding Autograder

Your output must match mine exactly.

There is a description about how to interpret some of the autograder error messages in the directions for the previous

two programming assignments. I will not repeat that description here.

4.1.1 Visible Test Cases’ Inputs

Parts #1 and #2: See test_getProduct.c and test_linearSearch.c on Canvas. (These are different from the testGetProduct.c

and testLinearSearch.c files used in the examples below.)

Part #3:

Case #1:

1 ./ cp_mult . sh hi

2 echo $?

Case #2:

1 mkdir d1 d2 d3 d4

2 echo -e "123\ n45 \ n78 " > vals2 . txt

3 ./ cp_mult . sh vals2 . txt d4 d1 d3 d2

4 echo -e "=== retval ==="

5 echo $?

6 echo -e "=== d4 / vals2 . txt ==="

7 cat d4 / vals2 . txt

8 echo -e "=== d1 / vals2 . txt ==="

9 cat d1 / vals2 . txt

10 echo -e "=== d3 / vals2 . txt ==="

11 cat d3 / vals2 . txt

12 echo -e "=== d2 / vals2 . txt ==="

13 cat d2 / vals2 . txt

Case #3:

1 mkdir foo goo bar

2 echo -e " blah \ nblah \ nblah \ nblah " > foo / vals3 . txt

3 ./ cp_mult . sh foo / vals3 . txt goo / vals3 . txt bar / vals3 . txt

4 echo -e "=== foo / vals3 . txt ==="

5 cat foo / vals3 . txt

6 echo -e "=== goo / vals3 . txt ==="

7 cat goo / vals3 . txt

8 echo -e "=== bar / vals3 . txt ==="

9 cat bar / vals3 . txt

Part #4:

Case #1:

1 echo " old contents to overwrite " > blah . txt

2 ./ run_steps . sh echo 18 27 3 blah . txt

3 cat blah . txt

Case #2:

1 chmod +x do_math . sh

2 ./ run_steps . sh ./ do_math . sh -30 50 10 math_output . txt

3 cat math_output . txt

do_math.sh: (available on Canvas)

1 #!/ bin / bash

2

3 echo " Add 2: "$ (( $1 + 2) )

4 echo " Subtract 1: "$ (( $1 - 1) )

Case #3:

2

1 gcc - Wall - Werror foo .c -o foo

2 ./ run_steps . sh ./ foo 35 115 15 the_output . txt

3 cat the_output . txt

foo.c: (available on Canvas)

1 # include < stdio .h >

2 # include < stdlib .h >

3

4 int main ( int argc , char * argv [])

5 {

6 int num = atoi ( argv [1]) ;

7 if ( num < 50)

8 printf (" Less than 50.\ n ") ;

9 else if (50 <= num && num <= 100)

10 printf (" Between 50 and 100 ( inclusive ) .\ n ") ;

11 else

12 printf (" Greater than 100.\ n ") ;

13 }

5 Your Programming Tasks

In this assignment, you will implement two C functions and two shell scripts. The two C functions go in a file named

prog8.c, and each of the names of the shell scripts is given in the respective part.

Your program should have no memory leaks.

Below is a list of headers that you are allowed to include in prog8.c. You may not need all of these.

? prog8.h

? <stdio.h>

? <stdlib.h>

? <stdbool.h>

? <ctype.h>

? <string.h>

? <limits.h>

? <assert.h>

5.1 Part #1: getProduct()

In prog8.c, implement a recursive function called getProduct() that takes as arguments an array of integers and the length

of this array. This function should return the product of this array’s values.

No input validation is necessary. (I want you to focus on learning recursion.) Thus:

? arr, as initially provided, will never be NULL. (Depending on your base case(s), it may become NULL.)

? arrLen, as initially provided, is always correct. (When performing a recursive call, be careful to not make arrLen become

incorrect.)

You are not allowed to use a loop for this part, since you must use recursion in a meaningful way. Your

approach should check and potentially act on the first element and then recurse on the rest of the array (i.e. the second

element onwards).

Here is what an implementation of getProduct() would look like if pointer arithmetic were not used. The index would have

to be an argument. You are not allowed to do this, since you are forced to use pointer arithmetic due to the fact that the

two parameters are set (in prog8.h) and you cannot change them. However, this should give you a good starting point.

1 int getProduct ( int * arr , int arrLen , int index )

2 {

3 if ( index == arrLen - 1)

4 return arr [ index ];

5 else

6 return arr [ index ] * getProduct ( arr , arrLen , index + 1) ;

7 }

Cautionary Tip: Be careful about using the prefix/postfix operators. If used improperly, you can encounter a compiler

error message that says something about sequencing. Here is an example to illustrate the concept. The error occurs because

in the line int b = a + ++a;, it is unclear if the left hand side of the addition (i.e. a) should be the old value of a (i.e. 3)

or the new value of a (i.e. 4). With the appropriate compiler flags, this triggers a compiler error. Without these flags, gcc

3

simply makes an assumption about which value of a to use, which is bad, because this is undefined behavior and potentially

inconsistent across different platforms.

1 $ cat main .c

2 # include < stdio .h >

3

4 int main ()

5 {

6 int a = 3;

7 int b = a + ++ a;

8 printf ("% d\n ", b);

9 }

10 $ gcc - Wall - Werror main . c

11 main .c: In function ’main ’:

12 main .c :6:17: error : operation on ’a ’ may be undefined [- Werror = sequence - point ]

13 int b = a + ++ a;

14 ^~~

15 cc1 : all warnings being treated as errors

16 $ gcc main .c

17 $ ./ a. out

18 8

19 $

Below are the test cases that I provide to you on Canvas. assert() takes as argument a boolean (usually a boolean

experssion) and crashes if the expression is false, reporting a diagnostic message if that occurs.

1 $ cat testGetProduct .c

2 # include " prog8 .h"

3

4 # include < assert .h >

5 # include < stdio .h >

6

7 void testGetProduct ( void )

8 {

9 {

10 int arr [] = {5 , 8, 3, -1};

11 assert ( getProduct ( arr , 4) == -120) ;

12 }

13 {

14 int arr [] = { -7 , 14 , -2};

15 assert ( getProduct ( arr , 3) == 196) ;

16 }

17 {

18 int arr [] = {5 , 15 , 0, 100 , -3};

19 assert ( getProduct ( arr , 5) == 0) ;

20 }

21 {

22 int arr [] = {2};

23 assert ( getProduct ( arr , 1) == 2) ;

24 }

25 {

26 int arr [] = {27 , 15 , 3 , 14 , 0 , -5, 2, 0};

27 assert ( getProduct ( arr , 8) == 0) ;

28 // Can " lie " about the array size .

29 assert ( getProduct ( arr , 4) == 27 * 15 * 3 * 14) ;

30 assert ( getProduct ( arr , 2) == 27 * 15) ;

31 assert ( getProduct ( arr , 1) == 27) ;

32 // Demonstrating some pointer arithmetic .

33 assert ( getProduct ( arr + 1, 1) == 15) ;

34 assert ( getProduct ( arr + 1, 2) == 45) ;

35 assert ( getProduct ( arr + 1, 3) == 45 * 14) ;

36 assert ( getProduct ( arr + 5, 2) == -10) ;

37 }

38 fprintf ( stderr , "%s(): All test cases passed !\n", __FUNCTION__ ) ;

39 }

40

41 int main ()

42 {

43 testGetProduct () ;

44 }

45 $ gcc - Wall - Werror -g testGetProduct . c prog8 .c -o testGetProduct

46 $ ./ testGetProduct

47 testGetProduct () : All test cases passed !

48 $

4

5.2 Part #2: linearSearch()

In prog8.c, implement a recursive function called linearSearch() that takes as arguments an array of integers, the length

of this array, and a target integer. This function should return true (i.e. a non-zero integer) if the array contains the target

and false (i.e. zero) otherwise.

No input validation is necessary. (I want you to focus on learning recursion.) Thus:

? arr, as initially provided, will never be NULL.

? arrLen, as initially provided, is always correct.

You are not allowed to use a loop for this part, since you must use recursion in a meaningful way.

Below are the test cases that I provide to you on Canvas.

1 $ cat testLinearSearch . c

2 # include " prog8 .h"

3

4 # include < assert .h >

5 # include < stdio .h >

6

7 void testLinearSearch ( void )

8 {

9 {

10 int arr [] = {5 , 8, 3, -1};

11 assert ( linearSearch ( arr , 4, 8) );

12 assert (! linearSearch ( arr , 4, -7) );

13 assert ( linearSearch ( arr , 4, -1) ) ;

14 assert (! linearSearch ( arr , 4, 50) );

15 }

16 {

17 int arr [] = { -5 , -2 , 2 , -2, 3 , 4 , 1};

18 assert ( linearSearch ( arr , 7, -2) ) ;

19 assert ( linearSearch ( arr , 7, -5) ) ;

20 assert (! linearSearch ( arr , 7, 14) );

21 assert (! linearSearch ( arr , 7, 20) );

22 // Again , we can " lie " about the length .

23 assert (! linearSearch ( arr + 1 , 6 , -5) );

24 assert ( linearSearch ( arr + 1, 6, -2) );

25 assert ( linearSearch ( arr + 1, 6, 2) );

26 assert (! linearSearch ( arr + 3 , 4 , 2) );

27 }

28 fprintf ( stderr , "%s(): All test cases passed !\n", __FUNCTION__ ) ;

29 }

30

31 int main ()

32 {

33 testLinearSearch () ;

34 }

35 $ gcc - Wall - Werror -g testLinearSearch .c prog8 .c -o testLinearSearch

36 $ ./ testLinearSearch

37 testLinearSearch () : All test cases passed !

38 $

5.3 Part #3: Copy to Multiple

Filename: cp_mult.sh

Motivation: Recall that the cp command can be used to copy multiple files into a destination directory, but it cannot be

used to copy one file into multiple destinations. You will write a script that does that.

Write a shell script that takes as argument a regular file (i.e. never a directory) and a list of destinations. The script

should copy the file into each of the given destinations. If not enough arguments are provided, then a usage message should

be printed and the script should return 1 (with exit 1); otherwise, the script should return 0. Note that just like cp, cp_mult.sh

can be used to make multiple copies of a file in the same directory.

Below are some examples of how your script should behave.

1 $ ls d1

2 $ ls d2

3 $ cat vals . txt

4 5

5 18

6 3

7 7

5

8 $ ./ cp_mult . sh vals . txt d1 d2

9 $ echo $?

10 0

11 $ cat vals . txt

12 5

13 18

14 3

15 7

16 $ ls d1

17 vals . txt

18 $ ls d2

19 vals . txt

20 $ ./ cp_mult . sh

21 Usage : ./ cp_mult . sh [ src ] [ dest1 ] ...

22 $ echo $?

23 1

24 $ ./ cp_mult . sh vals . txt

25 Usage : ./ cp_mult . sh [ src ] [ dest1 ] ...

26 $ ls *. txt

27 vals . txt

28 $ ./ cp_mult . sh vals . txt vals2 . txt vals3 . txt vals4 . txt

29 $ cat vals2 . txt

30 5

31 18

32 3

33 7

34 $ cat vals3 . txt

35 5

36 18

37 3

38 7

39 $ cat vals4 . txt

40 5

41 18

42 3

43 7

44 $

5.4 Part #4: Run Steps

Filename: run_steps.sh

Motivation: As a happy undergraduate student, I encountered several situations in which I had to run an executable

multiple times with different command-line arguments and collect the output of each of those runs. As you can hopefully

imagine, doing this manually (i.e. typing each line into the terminal) would have been annoying; you can save time on such

a task by writing a script like the one you will write for this part.

Write a script that takes five arguments:

? A command to run (which could be an executable compiled with gcc). Note that it must be the exact command needed

to run it, not just the executable’s name (which is why you see ./test in the example instead of test).

? A start integer A.

? An end integer B.

? A step integer S.

? An output file.

The script should perform a series of runs of the given command. The first run should have A be passed as argument to

the command to run. In the next run, A + S should be passed. After that, A + 2S, then A + 3S, then A + 4S, and so on,

until the value passed would exceed B. Each run’s results should be logged into the output file. You may not assume this

output file exists, and its old contents should be overwritten.

The script assumes that the executable only takes an integer as its only command-line argument. If not enough arguments

are provided, then a usage message should be printed and the script should return 1 (with exit 1); otherwise, the script should

return 0.

Below are some examples of how your script should behave.

1 $ cat test .c

2 # include < stdio .h >

3

4 int main ( int argc , char * argv [])

5 {

6

6 printf (" Provided : %s \n", argv [1]) ;

7 }

8 $ gcc - Wall - Werror test . c -o test

9 $ ./ run_steps . sh ./ test 10 100 5 output1 . txt

10 $ cat output1 . txt

11 === 10 ===

12 Provided : 10

13 === 15 ===

14 Provided : 15

15 === 20 ===

16 Provided : 20

17 === 25 ===

18 Provided : 25

19 === 30 ===

20 Provided : 30

21 === 35 ===

22 Provided : 35

23 === 40 ===

24 Provided : 40

25 === 45 ===

26 Provided : 45

27 === 50 ===

28 Provided : 50

29 === 55 ===

30 Provided : 55

31 === 60 ===

32 Provided : 60

33 === 65 ===

34 Provided : 65

35 === 70 ===

36 Provided : 70

37 === 75 ===

38 Provided : 75

39 === 80 ===

40 Provided : 80

41 === 85 ===

42 Provided : 85

43 === 90 ===

44 Provided : 90

45 === 95 ===

46 Provided : 95

47 === 100 ===

48 Provided : 100

49 $ ./ run_steps . sh ./ test 50 80 10 output2 . txt

50 $ cat output2 . txt

51 === 50 ===

52 Provided : 50

53 === 60 ===

54 Provided : 60

55 === 70 ===

56 Provided : 70

57 === 80 ===

58 Provided : 80

59 $ cat test2 .c

60 # include < stdio .h >

61 # include < stdlib .h >

62

63 int main ( int argc , char * argv [])

64 {

65 int num = atoi ( argv [1]) ;

66 if ( num < 100)

67 printf (" Less than 100.\ n ") ;

68 else

69 printf (" Greater than or equal to 100.\ n ") ;

70 }

71 $ gcc - Wall - Werror test2 .c -o test2

72 $ ./ run_steps . sh ./ test2 97 104 2 output3 . txt

73 $ echo $?

74 0

75 $ cat output3 . txt

76 === 97 ===

77 Less than 100.

78 === 99 ===

79 Less than 100.

7

80 === 101 ===

81 Greater than or equal to 100.

82 === 103 ===

83 Greater than or equal to 100.

84 $ ./ run_steps . sh ./ test2 97 104

85 Usage : ./ run_steps . sh [ executable ] [ start ] [ end ] [ step ] [ outfile ]

86 $ echo $?

87 1

88 $

8


版权所有:编程辅导网 2021 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。 站长地图

python代写
微信客服:codinghelp