ISD Quizzes and Tests

Lakukan tugas rumah & ujian kamu dengan baik sekarang menggunakan Quizwiz!

Given the code in Appendix A, indicate whether the function(s) called on each line is a member or non-member function. If it is a function that has been declared in the provided header, which function is involved (see numbering in Appendix A); int main () { Floog v(1, 2, 3, 4); // #1 int i = 10; float f = 6.02; (v ** f); // #2 (i ** v); // #3 (f ** -v); // #4 (v ** v); // #5 std::cout << v << std::endl; // #6 return 0; } Appendix A class Floog { public: explicit Floog(const float a=0, const float b=0, const float c=0, const float d=0); // Constructor ~Floog() = default; Floog operator**(const Floog &rhs) const noexcept; //Op #1 Floog operator**(const int rhs) const noexcept; //Op #2 Floog operator**(const float rhs) const noexcept; //Op #3 Floog operator-() const noexcept; //Op #4 friend std::ostream &operator<<(std::ostream &, const Floog &) noexcept; private: float a, b, c, d; };

#1: Member, constructor #2: Member, operator #3 #3: Not member #4: member operator #4, and non-member operator*(for a float and a floog) #5: member, operator #1 #6: Non-member friend function, operator #5

Basic C++ Exception Handling (4)

-Is to allow error handling logic to exist out of band from the main logic of a function. -Ensures that destructors are run as the stack unwinds - ensuring that resources are freed -Is the primary error handling mechanism for C++ programs -Decreases complexity compared to imperatively checking for errors and manually handling them

std::remove_copy_if expects four parameters. The first two are the input begin and end iterators (aka source iterators). The third is the output iterator. The fourth is a unary function/functor that outputs false when the iterated value should be copied to the output iterator, and true if the value should not be copied. What is the output of the following code: std::vector<int> vect1; std::ostream_iterator<int> output(std::cout, " "); vect1.push_back(1); vect1.push_back(2); vect1.push_back(3); vect1.push_back(4); vect1.push_back(5); std::copy(vect1.begin(),, vect1.end(), output); std::cout << std::endl; std::vector<int> vect2(3, 99); std::remove_copy_if(vect1.begin(), vect1.end(), back_inserter(vect2), std::not_fn(std::bind(std::greater<>(), std::placeholders::_1, 3))); std::copy(vect2.begin(), vect2.end(), output);

1 2 3 4 5 99 99 99 4 5

Name and describe in detail each of the four parts of a lambda function: [A](B) -> C { D };

A is the capture block. Allows the function to import external variables into the local scope of the function. Can capture by reference or by copy. B is the input parameters. Same as for regular functions C is the return type. Can allow the compiler to infer the return type, but you can force a specific return type by putting the type here. D is the function body. Implementation of the function. Return what is needed.

What is meant by an STL "adaptive" or "adaptor" container? Name two example. b) What else uses the concept of adaptors within the STL? Name two specific examples of these other adaptations.

A) An adaptive container just alters (or "adapts") the behavior of one of the first-class containers in order to provide a different interface (set of behaviors). The three implemented in the STL are std::stack (stack), std::queue (queue), and std::priority_queue (heap) B) The concept of adaptation is also used with iterators and algorithms/functions/functors. Iterator adapters we discussed in class would include back_inserter() and ostream_iterator(). Algorithm/function/functor adapters discussed in class include bind/bind1st/bind2nd, not_fn, not1/not2, mem_fn, mem_fun/ptr_fun/mem_fun_ref.

Given the code in Appendix B, which version of the underlined method is called in each of these cases (if there is an error, note the error instead): A) Vehicle * a = new Car("George"); a->model(); B) Aircraft * b = new Helicopter(); b->setProp("name", "value"); C) const Car c("Betsy"); c.model(); D) Vehicle * d = new Car("George"); d->setProp("test", 42);

A) calls Car::model() B) Code does not compile. Helicopter is an abstract class and thus you cannot directly call its constructor. C) In fact, this code will not compile. model() is a non-const method and thus cannot be called on a const object. D) calls Vehicle::setProp(const std::string&, const int)

Which statements are completely true? A) The Expression Tree application has two distinct run-time configurations B) The Expression Tree application can perform only plus, minus, times, negate and divide math operations C) The Expression Tree application supports the use of variables in expressions D) Use of patterns in the Expression Tree app. is intended to make it execute faster E) The Composite Pattern describes the structure to build a linked-list data structure F) The "Component" entity in the Composite Pattern is the root class of the pattern G) Leaf nodes can only contain other Leaf nodes in the Composite Pattern I) Adding a new type of Composite node implies creating a new class J) Composite_Binary_Node must inherit from Composite_Unary_Node

A, C, F, I, J

Which statements are completely true about the Singleton pattern: A) There are only two classes involved in the Singleton Pattern B) The "static" keyword is fundamental to implementing the Singleton pattern in C++ C) A singleton is globally available at any other point in a program D) A singleton's value is publicly readable and writable like a global variable E) Making a class into a singleton is complex and irreversible

B, C

Note which statements are completely true about Design Patterns: A) Design patterns describe a set of computational steps necessary to solve a problem B) Design patterns involve a "micro-architecture" or society of class instances C) Design patterns are language specific and not very portable D) Design patterns involve classes and the relationships between instance of these classes E) Design patterns are completely beneficial and do not have draw backs F) Design patterns provide common names for recurring problems and their solution G) Design patterns aid in making code reusable, extensible, understandable and maintainable H) Design patterns are an expression of design reuse I) Design paterns reduce the amount of code we have to write J) Design patterns are fun and should be used all the time

B, D, F, G, H

What is the result of the following program (choose one)? #include <iostream> #include <string> class Point { private: int x, y; public: Point (int xval=0, int yval=0) : x(xval), y(yval) {} // default copy ctor, assignment operator, and destructor are sufficient std::string toString() const { return "(" + std::to_string(x) + "," + std::to_string(y) + ")"; } Point operator+ (const Point &rhs) const { return Point(x+rhs.x, y+rhs.y); } }; int main() { Point p1(3,4); p1 = p1+2.5; std::cout << "p1 = " << p1.toString() << std::endl; return 0; } a. This code fails to compile b. This code fails at runtime with an exception c. This code prints "p1 = (5,4)" d. This code prints "p1 = (5.5, 4)" e. None of the above

C

Given the classes in Appendix B, draw the vtables for Vehicle, Car, Aircraft and Helicopter. Your tables should clearly indicate where each vtable entry points. Make it clear if the class is abstract or not, and if the method is pure virtual or not. Assume the provided code compiles correctly.

Check Exam Question 7

Explain the general relationships between STL containers, STL iterators, and STL algorithms.

Containers contain the data itself. Iterators allow access to elements within a container, but only point to where the data is in the container. Algorithms interact only with iterators to perform operations on containers. only iterator is well explained here.

Note which are correct and which are incorrect: A. Input iterators allow you to read data from a container B. Input iterators allow you to write data to a container C. Output iterators allow you to read data from a container D. Output iterators allow you to write data to a container E. All STL containers support both input and output iterators F. All STL containers support both forward and backward iterators G. All STL containers support random access iterators H. STL containers only support methods that have O(1) execution I. STL sequential containers are faster than associative containers J. Using the STL should reduce the amount of code needing to be written

Correct: A, D, E, F, J

Given the following code, provide a complete implementation of either a Functor or a Lambda function such that you get this as output: 3 3 3 3 1 1 2 3 5 8 13 21 34 55. This is four three's followed by the first 10 values of the Fibonacci sequence. There are many possible solutions - but you are not allowed to hard-code the output. Obviously, a functor would be defined outside of main while a lambda would be inline. You may add (but not remove) code in the spaces between these lines of code. int main(int argc, char ****argv) { std::vector<int> vecA(10, 1); std::vector<int> vecC(4, 3); std::transform(vecA.begin(), vecA.end(), vecC.begin(), std::back_inserter(vecC), **CALLED FROM HERE**); std::copy(vecC.begin(), vecC.end(), output); }

FUNCTOR: template<typename T> class Fibonacci { public: Fibonacci() : valA(1), valB(1) {} T operator() (const T &a, const T &b) { uint32_t ret = valA; valA = valB; valB += ret; return ret; } private: uint32_t valA, valB; }; LAMBDA: uint32_t valA=1, valB=1; std::transform(vecA.begin(), vecA.end(), vecC.begin(), std::back_inserter(vecC), [&valA, &valB](auto &a, auto &b){ uint32_t ret = valA; valA = valB; valB += ret; return ret; });

Name each of the three categories of STL iterators and for each list which methods are mandatory:

Forward iterators need to implement the two increment (operator++) methods Bidirectional iterators need to implement forward iterator methods and decrement (operator--) methods Random-access iterators need to implement bidirectional iterator methods and operator[ ]

Which one of the following statements is most true: I) Templated classes reduce the amount of code that is compiled into an executable II) There are no restrictions on what classes can be passed to class templates parameters III) Templates are easier to debug because they have less code IV) Compilation of templates requires more work from the compiler

IV

Describe in detail the advantages and disadvantages of the Interpreter pattern?

Interpreter is great for use on small/simple languages. There is a simple 1:1 relationship between classes and grammar rules for the language. This structure means it is easy to maintain and extend. The most significant downside to the Interpreter pattern is that there tends to be lots of classes. This becomes an issue as the complexity of the language and grammar rules grow. You should not use the Interpreter pattern for large/complex languages.

See the Iterator Pattern diagram in Appendix A. Provide a one sentence description of each class shown:

Iterator: Abstract interface class that defines the expected behavior of any iterator Concrete Iterator: Container-specific iterator implementation that implements the abstract iterator interface Aggregate: Abstract interface class that defines how to get an iterator from a container Concrete Aggregate: Container implementation that has methods for getting an appropriate concrete iterator

The code below is taken from the templatized version of our Stack. Clearly this assignment operator is attempting to perform a deep copy of the Stack. What lines could an exception be thrown on? And, if an exception is thrown on that line, describe if anything "bad" will happen as a result? Finally, what level of exception safety is achieved in this code? template <typename T> Stack<T> & Stack<T>::operator=(const Stack<T> &rhs) { size = rhs.size; //#1 stackTop = rhs.stackTop; //#2 T *temp = new T[size]; //#3 std::swap(stack, temp); //#4 for (uint32_t i = 0; i < stackTop; i++) { //#5 stack[i] = rhs.stack[i]; //#6 } //#7 delete[ ] temp; //#8 return *this; //#9 }

Line 1 incorrect: All arithmetic operations on primitive types - no possible exceptions Line 2 incorrect: All arithmetic operations on primitive types - no possible exceptions Line 3 incorrect: Out of memory on new could throw - size and stackTop have changed so stack is not coherent applied rubric item Line 4 incorrect: std::swap is considered exception safe - no possible exceptions applied rubric item Line 5 incorrect: All arithmetic operations on primitive types - no possible exceptions unapplied rubric item Line 6 incorrect: Possible exception since assignment could be calling a function depending on type of T. Exception would leak memory from old stack (swapped into temp), stack would have a corrupted set of values unapplied rubric item Line 7 incorrect: No possible exceptions applied rubric item Line 8 incorrect: Delete is considered exception safe - no possible exceptions unapplied rubric item Line 9 incorrect: Returning a value is exception safe applied rubric item Overall exception safety: no guarantee

Name and describe the purpose and properties of the different types of memory allocation. Where in the overall memory footprint of the application do they reside? Give an example of each.

Memory that is allocated for variables during compile time and resides within the static/data segment of overall memory. It can not be deallocated, but it is not necessarily immutable (i.e. const). All variables that are declared with the static keyword or that are declared outside of all functions are statically allocated. All compiled code is also loaded into the static memory segment. Ex: static int a = 7; Memory that is allocated to local variables that are part of a block scope. These variables are managed by the runtime and will be automatically destroyed when the block scope is left. All automatic variables reside in the Stack portion of the overall application memory footprint. Ex: { int a = 7; } Memory that is explicitly allocated by program code during the execution of the application. The memory is solely managed by the application code and must be "manually" deleted. The memory is allocated using the new keyword and cleaned up using the delete keyword. Dynamic variables reside in the heap segment of application memory. int * a = new int;

Name and describe the three "legs of the STL stool" as described in class? Why are they important? (i.e. Why do we both making a distinction between the three?) How does the term "generic programming" apply to the STL?

Name and describe the three "legs of the STL stool" as described in class? Containers: the templated data structures that actually hold values Iterators: closely related, and specific to each type of container. Iterators manage traversal through containers. Algorithms: computational methods that execute using iterators to perform useful functions on data contained in containers Why are they important? (i.e. Why do we both making a distinction between the three?) Makes each more reusable and extensible. Most importantly, executing algorithms via iterators allows for algorithms to become agnostic to the type and structure of the containers (see below about generic programming). How does the term "generic programming" apply to the STL? Generic in STL applies to both STL containers' ability to hold values of any type (generic to type), but also the STL algorithms' ability to operate on container of any structure (generic to structure).

What is the primary function of using the Builder pattern in the Expression Tree application (i.e. what does it do)?

The builder pattern is needed to translate from one representation (Symbols) to the other (Component_Nodes).

Underline the methods that are required to be an STL compatible input and output iterator: const operator*, non-const operator**, operator/, copy constructor, operator&, operator^, operator=, operator==, operator!=, operator@, operator#, operator%, pre-increment operator++, post=increment operator++, post-increment operator**

The following should be underlined: const operator* non-const operator* copy constructor operator= operator== operator!= pre-increment operator++ post-increment operator++

Which of the following are true statements about exception safety: A. Strongly exceptioon safe code means that when an exception is thrown, by the time the exception handler begins running, no variables were ever changed B. RAII uses local variables to only prevent memory leaks C. Copy-and-swap should only be used if RAII is not possible D. Copy-and-swap can be used together with RAII E. All code should be made to level 3 - strongly exception safe F. If you do not know otherwise, assume that a function will throw an exception G. Writing exception safe code does not necessarily require writing more code H. Simply changing the order of line of code can impact exception safety I. Exceptions can be thrown from any function, so always be paranoid

Not A. Strong exception safety says that the objects are in their original state, not that there were no changes. Not B. RAII can also be used to manage other resources such as a mutex lock Not C/D. These two can be used together to obtain strong exception safety Not E. It is not always possible to obtain level 3. Yes F. Yes G. Sometimes we only need to rearrange the code. Yes H. Not I. Some functions are "noexcept"

Provide a complete templatized functor, CountVals. See Appendix A for how it will be used. The primary idea is that it is initialized with a value - the "benchmark" value. Then for each invocation of its function operator it is passed an STL-compliant container that contains values of the same type as the benchmark value. Your functor should count and return the number of times the benchmark value appears in the container it was passed. The expected output for the two sample cases is in the comments of Appendix A. The bnechmark value's type supports operator==. Appendix A: Check Quiz 5 Back

One possible solution: template <typename AT, typename ST> class CountVals { public: explicit CountVals(const ST &val) : benchmark(val) {} uint32_t operator()(const AT &item) { uint32_t num = 0; for (auto c : item) if (c == benchmark) ++num; return num; // Alternate (bonus) implementation return std::count(item.begin(), item.end(), benchmark); } private: ST benchmark; };

Name each of the four associative containers discussed, and provide one sentence that summarizes their unique properties relative ot the other associative containers:

SET stores unique keys in sorted order MULTISET stores keys (possibly duplicated) in sorted order MAP stores unique keys in sorted order, and some value is associated with each key MULTIMAP stores keys (possibly duplicated) in sorted order, and some value is associated with each key

In the Expression Tree application, what is the point of the Symbol class and its hierachy of derived classes? What advantage does this approach give us, and what would we potentially give up if our Interpreter directly generated the ExpressionTree data structure?

Separation of Symbols from Component_nodes allows these two portions of the application to evolve separately. Also simplifies the creation of the Component_Node tree and centralizes the logic for translating Symbols to Component_Nodes.

Check the class diagram for the Observer pattern. Describe the purpose of each of these four classes. And, describe the key methods needed for each (don't worry about the names of the methods).

Subject Allows Observers to register (or subscribe) to data they are interested in. Maintains a list (or set or vector) of observers and "register" and "unregister" methods for Observers to call. Also has a "notify" method that calls the "update" method on each registered Observer. ConcreteSubject Instances of this class have the data that is of interest to all of the observers. All they have to do is derive from Subject and call its "notify" method when the data of interest changes. Observer: Abstract class that provides a base class for all ConcreteObservers. Any Observer can "register" and "unregister" itself with any Subject. Must provide pure virtual "update" method (see ConcreteObserver). ConcreteObserver: Inherit from Observer. All Observers must have an "update" method that will be called when the Subject "notifies" its Observers that its data has changed. The particular type of ConcreteObserver then processes the data change appropriately.

In one sentence, what is the primary problem that the Iterator pattern is trying to solve?

The iterator pattern is meant to decouple algorithms from the containers over which they operate, making the algorithms generic to the data's structure.

True or False Proper use of try...catch blocks prevents your program from failing You must have at least one catch blocks for each try If used, the default catch block (i.e. catch (...) ) should be last Thrown exceptions must be derived from std::exception try...catch blocks should be used liberally and enclose most code

True or False Proper use of try...catch blocks prevents your program from failing *F* You must have at least one catch blocks for each try *T* If used, the default catch block (i.e. catch (...) ) should be last *T* Thrown exceptions must be derived from std::exception *F* try...catch blocks should be used liberally and enclose most code *F*

True or False Semantically, operator** must always define the multiplication operation Overloading operator= and operator** also overloads operator**= The "arity" of an operator can not be changed by overloading it If not overloaded, compilers will supply operator& and operator= If in expression a + b, a is a built-in type and b is a user-defined type, the operator+ overload must be a non-member friend function

True or False Semantically, operator** must always define the multiplication operation *F* Overloading operator= and operator** also overloads operator**= *F* The "arity" of an operator can not be changed by overloading it *T* If not overloaded, compilers will supply operator& and operator= *F* If in expression a + b, a is a built-in type and b is a user-defined type, the operator+ overload must be a non-member friend function *F*

Under what types of use cases is a vector superior to a dequeue or a list? Under what types of use cases is a deque superior to a vector or a list? Under what types of use cases is a list superior to a vector or a deque?

Under what types of use cases is a vector superior to a dequeue or a list? Best at random access into data using indexes and pointer arithmetic. Under what types of use cases is a deque superior to a vector or a list? Also good at random access, but allows for efficient append/remove from both front and back. Under what types of use cases is a list superior to a vector or a deque? Excellent if lots of data manipulation, addition, removal, concatenation and splitting. Not good at random access.

Describe template specialization? Give a concrete example of when you would use specialization.

Version of a template class method or stand-alone function that is explicitly for a specific set of template parameter values. template <> Stack<float> & Stack<float>::operator=(const Stack &rhs)

Describe in detail the differences and similarities between the Composite and Interpreter patterns.

Very similar structure - the Interpreter is really a specialized version of the Composite pattern. Both have a recursive hierarchy of objects. Both have terminal and non-terminal derived classes unapplied rubric item Interpreter takes an input (string) and emits objects Interpreter has a context

When is it wise to use the Adapter pattern and when is it not?

We use the Adapter Pattern when we have existing code (legacy or otherwise) that we want to wrap and expose with a different interface. E.g. taking vectors and making them look and feel like stacks. This allows us to change (or adapt) their client-facing behavior without changing the existing classes themselves. This is not the best pattern to choose if you have the flexibility of modifying the adapter classes. Look to the bridge if you want to vary the implementation (adaptee) while keeping the interface (adaptor) unchanged.

Whrite a lambda expression in the code below. As a result of some simple calculations, the output from the last two statements should be: -5 -2.5 0 2.5 5 8.75 11.25 13.75 270 : 8 int main() { int sum = 0.0; uint32_t count = 0; std::vector<int> dataA = {-50, -40, -30, -20, -10, 10, 20, 30}; std::vector<int> dataB = {10, 20, 30, 40, 50, 60, 70, 80}; std::vector<double> data C; std::transform(dataA.begin(), dataA.end(), dataB.begin(), std::back_inserter(dataC), /* Write lambda here */

[&sum, &count](const int A, const int B) -> float { ++count; sum+= A; sum += B; float combine = (A + B) / 8; return combine; });

Given the following code, how many template classes of each class A, B and C were generated and compiled into the program? What were the template parameters for each? template <typename T> class A{ ...}; template <typename T, int = 0> class B{ ... }; template<typename T, typename T2> class C{ ...}; int main() { A<string> var1(); B<int> var3(); B<int, 0> var5(); B<int, 6> var6(); C<string, double> var8(); C<A<int>, B<int, 6>> var10(); ... }

var1(): one A template class (A<string>) var3(): one B template class with the default parameter (B<int, 0>) var6(): one B template class (B<int, 6>) var8(): one C template class (C<string, double>) var10(): one C template class (C<A<int>,B<int,6>>) var10(): one A template class (A<int>) var5 reuses B<int, 0> template class generated for var3 var10 reuses B<int, 6> template class generated for var6 unapplied rubric item Final result: 2 template classes for each class template, for a grand total of 6.

Provide the output generated by the following program. The std::replace_if() algorithm passes the iterated value through if the predicate (3rd param) returns false, and replaces the value with the 4th param if the predicate returns true. #include <iostream> #include <iterator> #include <vector> int main() { std::vector<int> vec(10); std::ostream_iterator<int> output (std::count, ":"); std::fill(vec.begin(), vec.end(), 8); std::cout << "vec: " << std::endl; std::copy(vec.begin(), vec.end(), output); std::cout << std::endl; int index = 2; std::transform(vec.begin(), vec.end(), vec.begin(), [&index](auto i) { return i + index++ * 2; }); std::cout << "vec1: " << std::endl; std::copy(vec.begin(), vec.end(), output); std::cout << std::endl; std::replace_if(vec.begin(), vec.end(), [index](int i) { return i >= index + 7; }, 99); std::cout << "vec2: " << std::endl; std::copy(vec.begin(), vec.end(), output); std::cout << std::endl; return 0; } // end main

vec: 8:8:8:8:8:8:8:8:8:8: vec1: 12:14:16:18:20:22:24:26:28:30: vec2: 12:14:16:18:99:99:99:99:99:99:

Some of functions above are not shown in the header in Appendix A, provide the complete signature, ignoring return type, for those functioons that are missing (do not implement them):

const int operator**(const Floog & rhs); const operator**(const Floog&rhs);

For each line of Code in the table below, answer yes or no if the *Data* or the *Pointer* are const. int const ** consts = {-1, 1, 21, 33}; char ** const bob = "Bob's your uncle"; char const * thisIsAPointer; const char * const foo = "string";

int const ** consts = {-1, 1, 21, 33}; N Y char ** const bob = "Bob's your uncle"; Y N char const * thisIsAPointer; N Y const char * const foo = "string"; N Y

Using the notional class definition of a templated Stack on the last page (i.e. these are the only methods you have, and that they are all well defined and implemented), write the full implementation of a specialized version of a const method called min. It takes no parameters and simply returns the smallest value in the stack. Your version should be specialized for std::string and return

template <> uint32_t Stack<std::string>::min() const { uint32_t len = 0; for (uint32_t i = 0; i < stackTop; ++i) { len = stack[i].length() > len ? stack[i].length() : len; } return len; }

Rewrite the above method to achieve the highest possible level of exception safety. You may not invoke the copy constructor. What level of exception safety did you achieve?

template <typename T> Stack<T> & Stack<T>::operator=(const Stack<T> &rhs) { if (this != &rhs) { uint32_t newSize = rhs.size; std::unique_ptr<T[]> newBuffer = new T[newSize]; for (uint32_t i = 0; i < newSize; ++i) newBuffer[i] = rhs.stack[i]; std::swap(stack, newBuffer); stackTop = rhs.top; size = newSize; } return *this; }

Using the reference headers at back, write the complete declaration of the method or function that would be needed to execute each of the following lines of code. *x* is always of type *Stack*, *y* is always of type *Foo*, and *z* is always of type *int*. Make it clear if it is a method or function, template or non-template, const or non-const. I am not interested in the return type. x / y y *= z z * x

x / y template<typename T> stack<T>::operator/(const Foo &rhs); y *= z Foo::operator*=(const int &rhs); z * x template<typename T> operator*(const int &lhs, const stack<T>&rhs);

Describe three of the potential pitfalls in implementing the Observer pattern. And, how might you mitigate each?

• Dangling references/difficulty - Use C++ smart pointers, particularly strong_ptr/weak_ptr to manage observer/subject lifecycle. • Update overhead --Leverage push vs. pull model. --Allow observers to specify filters that influence updates that are provided to them. (pushes overhead to the subject). --Provide hints to observers as to what has changed, observers make decisions to pull data (pushes overhead to the observer) • Unknown update topology (loops) - limit roles to being either observers or subjects, but not both • Repeating an observer so that it is notified twice - use a std::set


Set pelajaran terkait

MGT 4150 Final Review Chapters 8-12

View Set

Introduction to Networking Mod 7 Network Architecture Quiz

View Set

NURS 3280 Final Exam vSim Questions

View Set

Chapter 9 One-Sample & Two- Sample Independent Sample t Tests

View Set