CSE 333 Lecture 5 - data structures & modules

Similar documents
CSE 333 Lecture 6 - data structures

CSE 333 Lecture 6 - data structures

Data Structures and Modules

Systems Programming and Computer Architecture ( )

Exercise Session 2 Simon Gerber

CSE 333 Lecture 7 - final C details

CSE 333 Midterm Exam 7/22/12

CSE 333 Lecture 9 - intro to C++

CSE 374 Programming Concepts & Tools

Final C Details. CSE 333 Autumn 2018

Exercise Session 2 Systems Programming and Computer Architecture

Kurt Schmidt. October 30, 2018

CSCI-243 Exam 1 Review February 22, 2015 Presented by the RIT Computer Science Community

CSci 4061 Introduction to Operating Systems. Programs in C/Unix

QUIZ. What are 3 differences between C and C++ const variables?

CSE 333. Lecture 9 - intro to C++ Hal Perkins Department of Computer Science & Engineering University of Washington

CSE 333 Midterm Exam 7/29/13

CSE 333 Midterm Exam July 24, Name UW ID#

Final C Details. CSE 333 Winter Teaching Assistants: Alexey Beall Renshu Gu Harshita Neti David Porter Forrest Timour Soumya Vasisht

CS61C : Machine Structures

CSE 333 Lecture 2 - arrays, memory, pointers

Midterm Exam Nov 8th, COMS W3157 Advanced Programming Columbia University Fall Instructor: Jae Woo Lee.

Ricardo Rocha. Department of Computer Science Faculty of Sciences University of Porto

Arrays and Memory Management

CSE 333 Lecture smart pointers

CS 326 Operating Systems C Programming. Greg Benson Department of Computer Science University of San Francisco

CS 220: Introduction to Parallel Computing. Beginning C. Lecture 2

Programs. Function main. C Refresher. CSCI 4061 Introduction to Operating Systems

CSE 333. Lecture 4 - malloc, free, struct, typedef. Hal Perkins Paul G. Allen School of Computer Science & Engineering University of Washington

Lecture 12 CSE July Today we ll cover the things that you still don t know that you need to know in order to do the assignment.

Programming. Lists, Stacks, Queues

Lab 5 Pointers and Arrays

CSE 374 Programming Concepts & Tools

CSE 303, Winter 2006, Final Examination 16 March Please do not turn the page until everyone is ready.

High-performance computing and programming Intro to C on Unix/Linux. Uppsala universitet

CSE 333 Lecture 2 Memory

CS3157: Advanced Programming. Outline

HW1 due Monday by 9:30am Assignment online, submission details to come

CSE 333 Lecture 4 - malloc, free, struct, typedef

Number Review. Lecture #3 More C intro, C Strings, Arrays, & Malloc Variables. Clarification about counting down

QUIZ. Source:

cs3157: another C lecture (mon-21-feb-2005) C pre-processor (3).

Intermediate Programming, Spring 2017*

Final CSE 131B Spring 2004

Final assignment: Hash map

CSE 303: Concepts and Tools for Software Development

Review: C Strings. A string in C is just an array of characters. Lecture #4 C Strings, Arrays, & Malloc

Deep C. Multifile projects Getting it running Data types Typecasting Memory management Pointers. CS-343 Operating Systems

COSC 2P91. Introduction Part Deux. Week 1b. Brock University. Brock University (Week 1b) Introduction Part Deux 1 / 14

Slide Set 9. for ENCM 335 in Fall Steve Norman, PhD, PEng

Lectures 5-6: Introduction to C

CSE 333 Autumn 2014 Midterm Key

CSE 333 Lecture 9 - storage

211: Computer Architecture Summer 2016

Lectures 5-6: Introduction to C

CS107, Lecture 9 C Generics Function Pointers

CpSc 1010, Fall 2014 Lab 10: Command-Line Parameters (Week of 10/27/2014)

CS61, Fall 2012 Section 2 Notes

Computer Science 2500 Computer Organization Rensselaer Polytechnic Institute Spring Topic Notes: C and Unix Overview

C BOOTCAMP DAY 2. CS3600, Northeastern University. Alan Mislove. Slides adapted from Anandha Gopalan s CS132 course at Univ.

Program Translation. text. text. binary. binary. C program (p1.c) Compiler (gcc -S) Asm code (p1.s) Assembler (gcc or as) Object code (p1.

ch = argv[i][++j]; /* why does ++j but j++ does not? */

CSE 333 Midterm Exam Sample Solution 5/10/13

CSE 333 Midterm Exam Sample Solution 7/28/14

Recitation 2/18/2012

CSE 333 Lecture smart pointers

CSE 333 Midterm Exam Sample Solution 7/29/13

CMSC 341 Lecture 2 Dynamic Memory and Pointers

Programming in C. Pointers and Arrays

CS 61c: Great Ideas in Computer Architecture

BIL 104E Introduction to Scientific and Engineering Computing. Lecture 14

UNIVERSITY OF NEBRASKA AT OMAHA Computer Science 4500/8506 Operating Systems Fall Programming Assignment 1 (updated 9/16/2017)

C Review. MaxMSP Developers Workshop Summer 2009 CNMAT

CSE 333 Midterm Exam July 24, 2017 Sample Solution

CSC258: Computer Organization. Functions and the Compiler Tool Chain

Hello, World! in C. Johann Myrkraverk Oskarsson October 23, The Quintessential Example Program 1. I Printing Text 2. II The Main Function 3

Week 5, continued. This is CS50. Harvard University. Fall Cheng Gong

CSE 333 Midterm Exam 5/10/13

Lab 4: Tracery Recursion in C with Linked Lists

Systems Programming and Computer Architecture ( )

Announcements. CSCI 334: Principles of Programming Languages. Lecture 18: C/C++ Announcements. Announcements. Instructor: Dan Barowy

ECE 250 / CS 250 Computer Architecture. C to Binary: Memory & Data Representations. Benjamin Lee

CS 237 Meeting 19 10/24/12

CSE 333 Lecture 3 - arrays, memory, pointers

Computer Programming. The greatest gift you can give another is the purity of your attention. Richard Moss

Programming. Projects with Multiple Files

CSE 374 Final Exam 3/15/17 Sample Solution. Question 1. (8 points) Suppose we have the following two statements in a C program:

Slide Set 3. for ENCM 339 Fall 2017 Section 01. Steve Norman, PhD, PEng

CS349/SE382 A1 C Programming Tutorial

G52CPP C++ Programming Lecture 3. Dr Jason Atkin

COMP26912: Algorithms and Imperative Programming

Slide Set 1. for ENCM 339 Fall Steve Norman, PhD, PEng. Electrical & Computer Engineering Schulich School of Engineering University of Calgary

EMBEDDED SYSTEMS PROGRAMMING Language Basics

ELEC 377 C Programming Tutorial. ELEC Operating Systems

Lecture Notes on Generic Data Structures

CSE 374 Programming Concepts & Tools. Brandon Myers Winter 2015 C: Linked list, casts, the rest of the preprocessor (Thanks to Hal Perkins)

CSE 333. Lecture 11 - constructor insanity. Hal Perkins Paul G. Allen School of Computer Science & Engineering University of Washington

CE221 Programming in C++ Part 1 Introduction

C PROGRAMMING Lecture 5. 1st semester

speller.c dictionary contains valid words, one per line 1. calls load on the dictionary file

Transcription:

CSE 333 Lecture 5 - data structures & modules Hal Perkins Department of Computer Science & Engineering University of Washington

Administrivia HW1 out now, due in 2 weeks minus ε. Start early and make steady progress - Yes, you can use up to 2 late days on it - No, you don t want to New exercise (#4) posted, due before class Friday

Today s topics: - implementing data structures in C - multi-file C programs - brief intro to the C preprocessor

Let s build a simple linked list You ve seen a linked list in CSE143 - each node in a linked list contains: some element as its payload a pointer to the next node in the linked list - the last node in the list contains a NULL pointer (or some other indication that it is the last node) element Z element Y element X head

Linked list node Let s represent a linked list node with a struct - and, for now, assume each element is an int #include <stdio.h> int element; Node; n1 element 1 next Node n1, n2; n2.element = 2; n2.next = NULL; n1.element = 1; n1.next = &n2; n2 element next 2 NULL manual_list.c

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; (main) list NULL return n; Node *list = NULL; list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; (main) list NULL return n; Node *list = NULL; list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; (main) list (Push) head NULL (Push) e 1 (Push) n??? NULL Node *list = NULL; list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head NULL NULL (Push) e 1 (Push) n element next?????? list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head NULL NULL (Push) e 1 (Push) n element next?????? list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head NULL NULL (Push) e 1 (Push) n element next 1??? list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head NULL NULL (Push) e 1 (Push) n element next 1 NULL list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head NULL (Push) e 1 (Push) n element next 1 NULL list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; (main) list Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; element next 1 NULL list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head (Push) e 2 (Push) n??? element next 1 NULL list = Push(list, 1); list = Push(list, 2);

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head (Push) e 2 (Push) n element next 1 NULL list = Push(list, 1); list = Push(list, 2); element next??????

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head (Push) e 2 (Push) n element next 1 NULL list = Push(list, 1); list = Push(list, 2); element next??????

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head (Push) e 2 (Push) n element next 1 NULL list = Push(list, 1); list = Push(list, 2); element next 2???

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head (Push) e 2 (Push) n element next 1 NULL list = Push(list, 1); list = Push(list, 2); element 2 next

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; (main) list (Push) head (Push) e 2 (Push) n element next 1 NULL list = Push(list, 1); list = Push(list, 2); element 2 next

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; (main) list Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; element next 1 NULL list = Push(list, 1); list = Push(list, 2); element 2 next

Push onto list push_list.c #include <stdio.h> #include <stdlib.h> #include <assert.h> int element; Node; Node *Push(Node *head, int e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; Node *list = NULL; a (benign) leak!! try running with valgrind: bash$ gcc -o push_list -g -Wall push_list.c bash$ valgrind --leak-check=full./push_list why is this leak not a serious problem? element next 1 NULL list = Push(list, 1); list = Push(list, 2); element 2 next

A generic linked list Previously, our linked list elements were of type int - what if we want to let our customer decide the element type? - idea: let them push a generic pointer -- i.e., a (void *) void *element; Node; Node *Push(Node *head, void *e) { Node *n = (Node *) malloc(sizeof(node)); assert(n!= NULL); // crashes if false n->element = e; n->next = head; return n; element next element next NULL

Using a generic linked list To use it, customers will need to use type casting - convert their data type to a (void *) before pushing - convert from a (void *) back to their data type when accessing void *element; Node; manual_list_void.c Node *Push(Node *head, void *e); // assume last slide s code char *hello = "Hi there!"; char *goodbye = "Bye bye."; Node *list = NULL; list = Push(list, (void *) hello); list = Push(list, (void *) goodbye); printf("payload: '%s'\n", (char *) ((list->next)->element) );

Using a generic linked list Results in: (main) list (main) goodbye (main) hello element B y e b y e. \0 next element H i t h e r e! \0 next NULL

Multi-file C programs Let s create a linked list module - a module is a self-contained piece of an overall program has externally visible functions that customers can invoke has externally visible typedefs, and perhaps global variables, that customers can use may have internal functions, typedefs, global variables that customers should not look at - the module s interface is its set of public functions, typedefs, and global variables

Modularity The degree to which components of a system can be separated and recombined main program - loose coupling and separation of concerns linked list hash table - modules can be developed independently - modules can be re-used in different projects

C header files header: a C file whose only purpose is to be #include d - generally a filename with the.h extension - holds the variables, types, and function prototype declarations that make up the interface to a module the main idea - every name.c intended to be a module has a name.h - name.h declares the interface to that module - other modules that want to use name will #include name.h and they should assume as little as possible about the implementation in name.c

C module conventions Most C projects adhere to the following rules: -.h files never contain definitions, only declarations -.c files never contain prototype declarations for functions that are intended to be exported through the module interface those function prototype declarations belong in the.h file - never #include a.c file -- only #include.h files - #include all of the headers you reference, even if another header (accidentally) includes some of them - any.c file with an associated.h file should be able to be compiled into a.o file

#include and the C preprocessor The C preprocessor (cpp) transforms your source code before the compiler runs - transforms your original C source code into transformed C source code - processes the directives it finds in your code (#something) #include "ll.h" -- replaces with post-processed content of ll.h #define PI 3.1415 -- defines a symbol, replaces later occurrences and there are several others we ll see soon... - run on your behalf by gcc during compilation

Example Let s manually run the preprocessor on cpp_example.c: cpp is the preprocessor #define BAR 2 + FOO typedef long long int verylong; #define FOO 1 #include "cpp_example.h" cpp_example.h int x = FOO; // a comment int y = BAR; verylong z = FOO + BAR; cpp_example.c -P suppresses some extra debugging annotations (can also use gcc -E) bash$ cpp -P cpp_example.c out.c bash$ cat out.c typedef long long int verylong; int x = 1; int y = 2 + 1; verylong z = 1 + 2 + 1;

Program that uses a linked list #include <stdlib.h> #include <assert.h> #include "ll.h" Node *Push(Node *head, void *element) {... implementation here... void *element; Node; Node *Push(Node *head, void *element); ll.c #include "ll.h" int main(int argc, char **argv) { Node *list = NULL; char *hi = hello ; char *bye = goodbye ; list = Push(list, hi); list = Push(list, bye); example_ll_customer.c ll.h

Compiling the program Four steps: - compile example_ll_customer.c into an object file - compile ll.c into an object file - link ll.o, example_ll_customer.o into an executable - test, debug, rinse, repeat bash$ gcc -Wall -g -o example_ll_customer.o -c example_ll_customer.c bash$ gcc -Wall -g -o ll.o -c ll.c bash$ gcc -o example_ll_customer -g ll.o example_ll_customer.o bash$ bash$./example_ll_customer Payload: 'yo!' Payload: 'goodbye' Payload: 'hello' bash$ valgrind --leak-check=full./example_customer...etc.

Where do the comments go? If a function is declared in a header file (.h) and defined in a C file (.c) - The header needs full documentation. It is the public specification. - No need to cut/paste the comment in the C file Don t want two copies that can get out of sync But help the reader with a specified in foo.h comment on the code If a function has a prototype and implementation in the same C file - One school: full comment on the prototype at the top of the file, no comment (or declared above ) on code (e.g., project code is like this) - Another: prototype is for the compiler, doesn t need a comment; put the comments with the code to keep them together (my preference)

Exercise 1 Extend the linked list program we covered in class: - add a function that returns the number of elements in a list - implement a program that builds a list of lists i.e., it builds a linked list but each element in the list is a (different) linked list - bonus: design and implement a Pop function removes an element from the head of the list make sure your linked list code, and customers code that uses it, contains no memory leaks

Exercise 2 Implement and test a binary search tree - http://en.wikipedia.org/wiki/binary_search_tree don t worry about making it balanced - implement key insert( ) and lookup( ) functions bonus: implement a key delete( ) function - implement it as a C module bst.c, bst.h - implement test_bst.c contains main( ), tests out your BST

Exercise 3 Implement a Complex number module - complex.c, complex.h - includes a typedef to define a complex number a + bi, where a and b are doubles - includes functions to: add, subtract, multiply, and divide complex numbers - implement a test driver in test_complex.c contains main( )

See you on Friday!