450 likes | 626 Vues
CS50 SECTION: WEEK 2. Kenny Yu, kennyyu@college.harvard.edu. Introduction. Kenny Yu, Quincy House Computer Science kennyyu@college.harvard.edu Office Hours: Leverett Dining Hall, Tuesday 9pm-12am. Announcements. Watch Problem Set 2’s walkthrough online
E N D
CS50 SECTION: WEEK 2 Kenny Yu, kennyyu@college.harvard.edu
Introduction • Kenny Yu, Quincy House Computer Sciencekennyyu@college.harvard.edu Office Hours: Leverett Dining Hall, Tuesday 9pm-12am
Announcements • Watch Problem Set 2’s walkthrough online • Expect Problem Set 0 feedback and scores back by Friday 9/23 • Expect Problem Set 1 feedback and scores back by Monday 9/26
Resources • Office hours (https://www.cs50.net/ohs) • Lecture videos, slides, source code, and notes (https://www.cs50.net/lectures) • Manuals, FAQs, other resources (http://manual.cs50.net) • Bulletin Board (http://help.cs50.net) • Post Questions here, extremely fast response times! • Google Moderator [this section only] • http://goo.gl/mod/fHvl • You can post questions, vote up questions, answer questions. I’ll also be answering section and topic-related questions there • Can post questions anonymously! (but still need to sign in with a gmail/college account) • My resources (https://cloud.cs50.net/~kennyyu/section/)
Agenda • Functions • Call Stack • Scope • Arrays • Strings • Command line arguments • Crypto • Fun Fun Fun
Functions in C • Functions take inputs, does something with them, and (optionally) produces some output f arg1, arg2, … argN f(arg1, arg2, …argN)
Functions: Why Use Them? • Organization: we can group (“encapsulate”) pieces of logic into one logical unit with a descriptive name; allows us to organize our code and break a big problem into small chunks • Resuability: instead of duplicating the same code over and over, we can write the code once, encapsulate it in a function, and use it anywhere; If we ever want to change the logic of the function, we only need to change it in one place
Functions: Syntax <return type> <func name>(<arg1 type> <arg1>, <arg2 type> <arg2>, …) { // implementation return <return type>; } Return Types: int, char, char * (string), float, ... Arguments: int x, char *argv[], float max, ... Example: int square(int num) { return num*num; }
Functions: void return types Functions with void return types do not return anything. void do_something(int num) { for (int i = 0; i < num; i++) printf(“ohai world\n”); }
Functions: void arguments Functions can also take no arguments, in which void is optionally written in // same as int main() { ... } int main(void) { printf(“ohai world\n”); return 0; }
Calling Functions int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; } int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); }
Calling Functions int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; // when the first return is reached, everything return b; // else after it is ignored } int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); }
The Call Stack • The call stack is a data structure used to manage function calls • A stack is first-in-last-out (think of lunch trays) • When a function gets called, a stack frame for that function gets pushed onto the top of the stack. • When a function returns, the stack frame for that function is popped off the top of the stack
Stack Frames int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; } int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); } main’s locals main’s parameters None
Stack Frames int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; } int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); } main’s locals int x = 5 Int y = 6 main’s parameters None
Stack Frames int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; } int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); } max()’s locals max()’s parameters int a = 5 Int b = 6 main’s locals int x = 5 Int y = 6 main’s parameters None max creates its own local copies of x and y and store them in a and b. max CANNOT change main’s local values of x and y with this implementation
Stack Frames int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; } int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); } max()’s locals int cmp = -1 max()’s parameters int a = 5 Int b = 6 main’s locals int x = 5 Int y = 6 main’s parameters None
Stack Frames int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; } int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); } max()’s locals int cmp = -1 max()’s parameters int a = 5 Int b = 6 Return 6 main’s locals int x = 5 Int y = 6 main’s parameters None
Stack Frames int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; } int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); } main’s locals int x = 5 Int y = 6 int z = 6 main’s parameters None
Stack Frames int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; } int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); }
Function Headers A function header is a function’s declaration without the body: Example: int max(int a, int b); Warning: A function must be declared (but not necessarily defined) before it can be used.
This won’t work: int main(void) { int x = 5; int y = 6; int z = max(x,y); // max is undeclared here printf(“max: %d\n”, z); } int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; }
Fix int max(int a, int b); // we declare max here and define it below int main(void) { int x = 5; int y = 6; int z = max(x,y); printf(“max: %d\n”, z); } int max(int a, int b) { int cmp = a - b; if (cmp > 0) return a; return b; }
A Note on Style: Function Headers • For small pieces of code, you should put all the function headers at the beginning of the file after all the #include’s and #define’s • For larger pieces of code involving larger files, it is best to make header files (.h files) that contain type definitions, struct definitions, function headers, and other things that will be shared between files. (More on this in the coming weeks.)
A Note on Style: “Magic” Numbers void mystery(int n) { if (n < 0) return; int foo = (int) ((float) n / 80); for (int i = 0; i < foo; i++) { printf(“*”); } } What is 80?
A Note on Style: “Magic” Numbers void mystery(int n) { if (n < 0) return; int foo = (int) ((float) n / 80); for (int i = 0; i < foo; i++) { printf(“*”); } } What is 80? The length of the terminal window.
A Note on Style: “Magic” Numbers void mystery(int n) { if (n < 0) return; int foo = (int) ((float) n / 80); for (int i = 0; i < foo; i++) { printf(“*”); } } What is 80? The length of the terminal window. But what if you were looking at the this code for the first time?
A Note on Style: “Magic” Numbers void mystery(int n) { if (n < 0) return; int foo = (int) ((float) n / 80); for (int i = 0; i < foo; i++) { printf(“*”); } } What is 80? The length of the terminal window. But what if you were looking at the this code for the first time? What if we decided to make the terminal window 90? In how many places would you need to change your code to fix the 80 and make it 90?
A Note on Style: “Magic” Numbers #include <stdio.h> #include <stdlib.h> #define WINDOW_LENGTH 80 void mystery(int n) { if (n < 0) return; int foo = (int) ((float) n / WINDOW_LENGTH); for (int i = 0; i < foo; i++) { printf(“*”); } }
A Note on Style: “Magic” Numbers #include <stdio.h> #include <stdlib.h> #define WINDOW_LENGTH 80 void mystery(int n) { if (n < 0) return; int foo = (int) ((float) n / WINDOW_LENGTH); for (int i = 0; i < foo; i++) { printf(“*”); } } We can use the C preprocessor directive #define NAME VALUE to define constants. When your program is compiled, the compiler literally does a copy and paste--in this case, every occurrence of WINDOW_LENGTH is replaced with 80.
Variable Scope • The scope of a variable is the part of a piece of code where that variable is defined. • Anything within the same set of curly braces is within the same scope • If a variable is declared within a scope with a variable with the same name as a variable declared in a broader scope that contains the inner scope, then it is impossible to access the broader-scoped variable until the inner-scope is exited • Global variables are declared outside all curly braces; it’s scope is the entire program
Where is the scope of cmp? int max(int a, int b) { int cmp = a – b; if (cmp > 0) return a; return b; }
Where is the scope of i? x? int fun4(int num) { int sum = 0; for (int i = 0; i < 10; i++) { int x = i * i; sum += x; } return sum; }
Where is the scope of x? int fun4(int num) { int x = 0; for (int i = 0; i < 10; i++) { int x = i * i; x += 1; } return x; }
Arrays • An array is a contiguous block of memory that holds values of the same type (think Science Center mailboxes) • If we have 100 values, we don’t need to declare 100 variables; just declare an array • Allows for easy iterating over data int int int int int
Array Syntax • Declare an array with: <type> <array name>[<size>]; int mailboxes[5]; ? ? ? ? ? 0 1 2 3 4
Array Syntax • Set an array element using <array name>[<index>] = <value>; mailboxes[0] = 51; mailboxes[1] = 50; mailboxes[2] = 61; mailboxes[3] = 121; mailboxes[4] = 124; Or do it all at once: mailboxes = {51, 50, 61, 121, 124}; 51 50 61 121 124 0 1 2 3 4
Iterating over Arrays Array indices range from 0 to (size – 1) WARNING: Do not attempt to access memory beyond the array’s bounds!!!!! You will get bad bad bad errors. int mailboxes[5]; mailboxes = {51, 50, 61, 121, 124}; for (int i = 0; i < 5; i++) { printf(“%d\n”, mailboxes[i]); }
Multidimensional Arrays We can make a multidimensional array by making arrays of arrays. char tictactoe[3][3] = {{‘X’,’O’,’X’}, {‘X’,’O’,’O’}, {‘X’,’X’,’O’}}; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { printf(“%c”, tictactoe[i][j]); } }
Strings are really arrays of chars • Strings must terminate with the last character being the nill character ‘\0’, ASCII value == 0 • We can access individual characters using array notation // string == char *, more on this in a few weeks string s = “this is cs50.”; char c = s[5]; // c == ‘i’ ‘t’ ‘h’ ‘i’ ‘s’ ‘ ‘ ‘i’ ‘s’ ‘ ‘ ‘c’ ‘s’ ‘5’ ‘0’ ‘.’ ‘\0’
Iterating Over a string string s = “this is cs50.”; // using strlen library function for (int i = 0, n = strlen(s); i < n; i++) { printf(“%c”, s[i]); } // using the fact that ‘\0’ evaluates to false for (int i = 0; s[i]; i++) { printf(“%c”, s[i]); }
Command Line Arguments When you run a program on the command line, you can also provide it with arguments $ ./prog arg1 arg2 … argN To use these command line arguments, use the argc and string argv[] arguments in the main function. argc stands for argument count, and argv stands for argument vector NOTE: argc is always equal to the number of command line arguments (number of strings followed by the program name). argv[0] is always the program name itself int main(int argc, string argv[]) { for (int i = 0; i < argc; i++) { printf(“%s\n”, argv[i]); } } // prints out “./prog”, “arg1”, “arg2”, ..., “argn”
Caesar Cipher • We are given a rotation key K and a string S to encrypt • We rotate each character S[i] by shifting the character K places to the right. • Key = 6:
Vigenere Cipher Instead of one key, we are given multiple keys. We now rotate each i-th character S[i] by the i-th key K[i] Treat A as 0 Key = “abcdf” => keys = [0,1,2,3,5] String = “cheese” => “cighie” S[0] = ‘c’ => ‘c’ + K[0] => ‘c’ + 0 => ‘c’ S[1] = ‘h’ => ‘h’ + K[1] => ‘h’ + 1 => ‘i’ S[2] = ‘e’ => ‘e’ + K[2] => ‘e’ + 2 => ‘g’ S[3] = ‘e’ => ‘e’ + K[3] => ‘e’ + 3 => ‘h’ S[4] = ‘s’ => ‘s’ + K[4] => ‘s’ + 5 => ‘x’ S[5] = ‘e’ => ‘e’ + K[0] => ‘e’ + 0 => ‘e’
Fun Fun Fun Goto: http://collabedit.com/u245w