START OF WEEK 1 of C If do these two, will get C highlighting for code in this file: :se syntax=c :colorscheme koehler (peachpuff and default are also not bad) Could also do :se filetype=c (or :se ft=c) <<< FILE TIMESTAMP >>> -The up to date file is: /usr/courses/cps393/dwoit/courseNotes/ -If you are viewing your own copy, check it is up to date -If you are viewing from a link in the Course Outline, be aware it may be outdated. <<>> -use command-line Linux via terminal session on CS test machine -edit on local machine with vim (or nano, gedit, emacs) -YOU MUST BE USED TO working command-line on moons since you must do so for tests/exams. (Test machines all have a moon image.) <<< Why learn C? >>> -Widespread usage -see article "The World is ... Powered by C Programming" https://www.toptal.com/c/after-all-these-years-the-world-is-still-powered-by-c-programming -among most popular programming languages according to ieee, tiobe etc https://www.tiobe.com/tiobe-index/ https://spectrum.ieee.org/top-programming-languages/ note Python outranks C, but Python is basically a front-end for C anyway! -Numerous jobs require C/C++/Linux -IEEE: C has most jobs for mobile development, (2nd most jobs overall). https://spectrum.ieee.org/top-programming-languages/ e.g., from Google: https://careers.google.com/jobs/results/134266830907679430 android games https://careers.google.com/jobs/results/75519189055349446 software developer -Many companies/facilities use C: YouTube, Netflix, Tumblr, Google/Cloud/AppEngine (memcached), Google Android, Facebook, Twitter, Amazon, Tesla Autopilot, ... Instagram (redis, memcached, sourcecode in Python and C, ), Pinterest, AirBnB, Tinder, Hulu (redis), Reditt, Wikipedia/Wikimedia, Wikia, SourceForge, Digg, Microsoft Azure, IBM Bluemix, etc. [some wikipedia/Memcached Nov23]. -Linux kernel is entirely in C (checked git repository Sep 2023) [https://github.com/torvalds/linux] There are some C++ files (under tools and scripts/kconfig) but NOT part of kernel. Minimal capability for Rust was added in Linux 6.1 -C is lowest-level *portable* language Low - no/little abstraction from machine details High - strong abstraction from machine details No standard "ordering" of high-level languages, but... high <--------------------------------------------->low Python Java Ada C Assembler R, Go, Pascal Machine Scala Fortran Language Ruby, VB C++ -Programming Languages have 2 top-level categories: -Imperative and Declarative, each with 2 paradigms: -Imperative: Procedural and OO -Declarative: Functional and Logical -Some languages mix it up somewhat: -Go has some OO ideas, but is not OO language -Lisp Object System incorporates OO into original Lisp -Scala is true hybrid OO and functional -C uses Procedural paradigm Procedural: main building-block is *variables/functions* step-by-step process involving explicit storage of data into variables to solve problem OO: main b-b is *objects/message-passes* Functional: main building block is *functions/fn composition* Logical: main building-block is numbers/atoms/variables and predicates (assertions) <<< Compare C to Java >>> 1. Similarities - end statements with ; - same primitive data types (except no boolean in C) - very similar in both: if, for, while, do-while, switch - C functions look like Java static methods - a basic (single-file) C pgm looks like a Java pgm where all methods are static - comments 2. Differences - no OO/classes, no exception facilities - program structure is different (see below) - no references. Instead, C has pointers (addresses) - no boolean. Instead, C considers false to be 0, true to be !0 - do IO differently - no documentation generator (like javadoc) <<< Structure of C Pgms--simplified >>> Pgm comments Includes Constant definitions Function Prototypes Global variable definitions Functions (main and others) DW shows simple C program e.g., /*Source: sample1.c Purpose: to show how printf works Input: None Output: a line stating the lucky number */ #include //for printf #include //for exit #define LUCKY 723 //macro int main(void) { printf("The lucky number is %d\n",LUCKY); printf("The %s number is %d\n", "lucky", LUCKY); exit(0) ; //same as return(0) here } Does? DW shows includes (<> and "") printf formatters and special characters #include -a preprocessor directive -preprocessor replaces with file contents *then* compiles -stdio.h is library function containing printf's definition #include -for exit's definition. Note return(0) is built-in. Needs no library. -exit quits whole program (even if called from a function), whereas return passes control back to caller -exit sets $? in shell -standard path, likely /usr/include/ (type stdio.h) "lib.h" -current dir (may use any absolute/relative pathname) #define LUCKY 723 -preprocessor directive -LUCKY is an object-like macro -replaces *all* LUCKY with 723 *before* compile -performance, easy global changes, sharing, readability (but typically use a variable instead.) int main(void) -required. Execution begins here printf("The lucky number is %d\n",LUCKY); -similar to Java: System.out.printf("The lucky number is: %d%n", LUCKY); -newline is \n (not %n) printf(format-string, arguments); ^ ^ | | | to replace format specifiers in format-string | | regular chars (letters, digits) escape sequence \n -newline \t -tab \a -alert (bell) \" -double quote " , etc format specifiers %d -decimal integer (%i is same) %c -character %s -string %f -floating point %lf -double (long floating point) e.g., printf("my \a %s has %f fleas\n","dog",12.45); Note: printf RETURNs an int specifying the number of chars printed usually ignored <<< Compiling and Running >>> To run pgm: gcc filename.c ./a.out or: gcc -o filename filename.c ./filename Note: if current dir in path, don't need ./ <<< Man Pages For C >>> -section 3 of the manual. -e.g., man 3 printf #shows C's printf function from stdio.h man stdio.h #shows all its types, macros, function prototypes man stdio #brief description of macros, functions HMWK: What is the output of the following program? //source: a.c #include int main(void) { printf("*\n**\n"); printf("***\n****"); printf("\n***"); printf("**\n******\n"); return 0 ; } DW shows errors/warnings Fix the following program so that it does what the comments say it will. Note that errors can be BEFORE the line it complains about. /*Source: b.c (and bfix.c) Purpose: to calculate the area of a rectangle with given length and width Input: none Output: length, width, and area of rectangle */ #include ; #define LENGTH 36 #define WIDTH 92 int main(void); printf("Length: %d, Width: %c, Area: %d\n", LENGTH,WIDTH,LENGTH*WIDTH); return 0; } Most of following is similar to Java... << Variable Types >> -declare before use -amount of storage for a type is machine-dependent, unlike Java where all primitive types have a predefined size, e.g., int always 4 bytes. TYPE USUAL SIZE RANGE (signed) FORMAT SPECIFIER char 1 byte -128...127 %c short int 2 bytes -32,768...32,767 %hd int 4 bytes (or 2) -2,147,483,648...2,147,483,647 %d or %i long int 4 bytes (or 8) -2,147,483,648...2,147,483,647 %ld float 4 bytes 3.4E-38 ... 3.4E+38 %f double 8 bytes 1.7E-308 ... 1.7E+308 %lf etc #include //Program to print number of bytes of C types // sizeof returns number of size_t bytes, which uses %zu //Source: typeSize.c int main (void) { printf("char is %zu bytes\n", sizeof(char)); printf("int is %zu bytes\n", sizeof(int)); printf("long int is %zu bytes\n", sizeof(long int)); printf("short int is %zu bytes\n", sizeof(short int)); printf("float is %zu bytes\n", sizeof(float)); printf("double is %zu bytes\n", sizeof(double)); printf("long double is %zu bytes\n", sizeof(long double)); printf("unsigned char is %zu bytes\n", sizeof(unsigned char)); return 0; } MODIFIERS: signed, unsigned, short, long short applies to integer only long applies to integer or double signed, unsigned apply to char or integer only unsigned char range 0...255 unsigned short int 0...65,535 As a variable, you do: double xx = 3.9876; As a constant, you do: #define xx 3.9876 (taken as double unless suffix) #define xx 3.9876L (taken as long double) L is double (if has decimal) or long int (if no decimal) U is unsigned. So #define x 44UL makes it unsigned long int /*source: sample2.c*/ /*program comments go here*/ #include int main(void) { char initial1, initial2; /*first initial, last initial*/ int year; /*CS year (1-4) */ printf("Input first and last initial and your year (sep. space):"); scanf("%c %c %d", &initial1, &initial2, &year); printf("\nHello %c%c from year %d\n",initial1,initial2,year); return 0; } Does? scanf: reads input from keyboard & stores in variables same formats as printf REMEMBER THE AMPERSANDS!! some tricky things. e.g., -when running above pgm, can enter multiple white-space, but not before first char, so this input is OK A B 32 but this is not A B 32 -if had "%c%c%d" then NO white-space is OK, must enter: AB32 <<< Intro to Macros >>> -already saw object-like macro #define LUCKY 123 -some macros are pre-defined (1st 3 are strings): __FILE__ __DATE__ __TIME__ __LINE__ printf("this source file is named %s\n",__FILE__); printf("current line number is %d\n",__LINE__); -also function-like macros #define ADD(x,y) x+y -then later printf("%d", ADD(3,2)); //expands to printf("%d", 3+2); -use parentheses for precedence issues, e.g., #define SQUARE(x) x * x means z=SQUARE(v+3); expands to: z=v+3 * v+3; which gives wrong answer (since 3 * v is done first) so do: #define SQUARE(x) (x) * (x) -may see more about macros later << Assignment in C >> age=3; initial1='D'; << Arithmetic Operations >> + - * / % var=age*2+1; 4%2 is 0 4%3 is 1 << Increment/Decrement >> i=i+1; i++ or ++i -used then inc; inc then used i=i-1; i-- or --i -" "dec; dec " " e.g. /*Purpose: to sum numbers from i to i+3 */ /*Source: sample3.c*/ #include int main(void) { int i; /*starting number */ int sum; /*sum of i to i+3 */ printf("Enter starting number: "); scanf("%d",&i); sum=0; sum=sum + i++; sum=sum + i++; sum=sum + i++; sum=sum + i; printf("Sum from %d to %d is: %d\n", i-3,i,sum); return 0 ; } e.g., i=1; j=i++; printf("%d %d",i,j); i=1; j=++i; printf("%d %d",i,j); int a,b=0,c=0; a=++b + c--; printf("%d %d %d",a,b,c); //check your answers against sample3a.c <<< Implicit Type Conversion >>> char < int < float < double (like automatic widening casting in Java) /*Purpose: to read in an integer, and print out one-third of its value Input: an integer Output: one-third of the integer Source: sample4.c */ #include int main(void) { int i; /*the integer*/ printf("Enter the integer: "); scanf("%d", &i); /*compute*/ printf("One-third: %f\n", i/3.0); printf("One-third: %d\n", i/3); //printf("One-third: %.0f\n", i/3.0); //printf rounds return 0 ; } <<< Type casts >>> are explicit type conversions (like explicit casting in Java) float f = 2.8; printf("%d", (int)f); //truncates int i = 4; double result; result= i*(double)8; //if result needs to be double or result= (double) (i*8); //if result needs to be double Note: put (double) in correct place: int i=4; x= i/(double)8; //x gets 0.5 y= (double) (i/8); //y gets 0.0 why? HMWK: re-write the program above that sums the numbers from i to (i+3) using only 1 scanf and 2 printf calls, and no assignment statements. DW shows function prototypes <<< Functions >>> 1. *declare* a function before use in file (function prototype) (similar to Java signature) 2. *define* a fn somewhere in pgm (maybe even different file) (the function code) e.g., /*Purpose: to compute half of an number *Input: an number to half *Output: half of the input number *sample5.c */ #include float half(float a); int main(void) { float num,hf; /*number to half, and its half*/ printf("Enter number: "); scanf("%f", &num); hf = half(num); printf("Half of %.2f is %.2f\n",num,hf); return 0; } float half(float a) { return (a/2); } NOTE: return ENDS function. Will be the LAST EXECUTED STATEMENT It is as if "square(num)" is REPLACED by what function square returns. Note: sample8.c makes function square and squares a double Implicit Function Declaration: -if forget declaration, gcc uses a default one -with return and argument types all int Try: -delete declaration line above -compile it Declaration and Definition together: -put definition before main (in place of prototype) No Return Value: -functions may return nothing (type void) -used for their "side-effects" (like Java) /*Source: sample7.c*/ #include void out (char c); void bell(void); int main(void) { out('A'); bell(); return 0 ; } void out(char c) { printf("%c\n",c); return; //optional } void bell(void) { printf("\a"); } << Library Functions >> -e.g., scanf, printf -include the appropriate .h file (has the declarations) e.g., #include -the definitions usually automatically linked in by gcc upon compile, e.g., gcc file.c -math.h contains mathmatical functions and constants (macros) -SOME gcc do not automatically link it in even when #include is in code, so must explicitly request: gcc file.c -lm -But our gcc DOES automatically link it, so don`t need -lm -man pages give type of functions` return values and arguments e.g., for whole library: man math.h man stdio.h man stdio //for brief descriptions e.g., for specific function: man sin man scanf man 3 printf #include #include /*sample6.c may need: gcc sample6.c -lm */ int main(void) { double answer; answer = sin(0.2); printf("%lf is sin of 0.2\n",answer); printf("%lf is Pi\n",M_PI); return 0; } man math.h (for all functions, macros, etc) man sin (for a specific function) DW shows type casts in function calls << Type Casts in Function Calls >> -sqrt function in math.h -takes a double argument and returns a double -arguments are up-converted to double if necessary int i=5; double result; result = sqrt(i); // int 5 converted to double first -consider: double x = sqrt(1/2); printf("%lf\n",x); Why does this print 0.000000 on moons? To get 0.707107 printed could do x=sqrt(1/(double)2)); << Returning/Exiting Functions >> 1. return statement Passes control (and return value, if any) back to caller. Type of returned value must be same as type of function. See function out in sample7.c for return with no value. 2. falling off the end (of a void function) see function bell in sample7.c 3. exit statement Normally called from main, but could call from any function. WHOLE PROGRAM is terminated. Control passed back to caller of whole program (usually shell). Shell variable $? is assigned the exit value. From main, can use return instead of exit. << Parameter Passing >> -Parameters passed by *value* (like Java) -a *copy* of parameter's value is passed to function -function can modify local value, it but does not affect the value outside of fn /*Source: sample9.c*/ #include void f(int i); int main(void) { int i=0; printf("%d",i); f(i); printf("%d",i); printf("\n"); return 0 ; } void f(int i) { printf("%d",i); i=1; printf("%d",i); } Output? DW shows local and global scope <<< Scope of Variables >>> 1. local declared in a function referenced within that function exist only while function is executing 1.a. static, as in: static int i; i retains its value from one call of function to next call 2. global declared *outside* any function can be referenced/modified by any function (below point of declaration) in file -A local definition overrides a global -Global and static initialized to 0 by compiler /*Source: sample10.c*/ #include void f(void); int i,k; int main(void) { int j=0; i=10;k=10; /*global*/ f(); printf("%d %d\n",i,k); return 0 ; } void f(void) { int i=20; k=5; // printf("%d",j); /*error*/ } -Adv: share data among fns -Dis: use memory throughout entire pgm side-effects (accidental modification by some fn) HMWK: A function called "pow" is available in math.h. Read about it in man page and use it to write a program to do the following: /*Purpose: to compute the maximum sized unsigned integer that could be stored in a given number of bits Input: an integer, b, representing a number of bits Output: a line stating the maximum unsigned decimal integer that could be represented with b bits Example: Input: 4 Output: Max unsigned decimal int that could be represented with 4 bits is 15 */ Hint: (2 to the power 4) - 1 is 15 Write a function called "me" which takes no arguments and has no return value, but has the side-effect of printing out your name and address. Test it by calling it in a program. DW shows separate compilation <<< Separate Files/Compilation >>> -Program code may be in multiple files. -Can compile each file separately, and later link all into one program. /*Source: prog.c */ #include #include "myfuncs.h" int main(void) { double d=19.54; outchar('A'); outchar('B'); outchar(G); outchar('\n'); printf("%lf\n",doubleDog(d)); return 0 ; } /*Source: myfuncs.c */ #include #include "myfuncs.h" void outchar(char c) { printf("%c %c ",c,G); } double doubleDog (double d) { return(d*2.0); } /*Source: myfuncs.h */ #define G 'v' void outchar(char c); double doubleDog(double d); Compile all source: gcc prog.c myfuncs.c Can compile 1 or more into object code first: gcc -c myfuncs.c gcc -c prog.c Then create executable by: gcc prog.o myfuncs.o or gcc prog.c myfuncs.o or gcc prog.o myfuncs.c DO NOT DO: gcc ... myfuncs.h //WRONG!! //already in prog.c via include DW shows Makefiles <<< Makefiles >>> Lots of good documentation online. e.g., https://web.mit.edu/gnu/doc/html/make_2.html Note it compiles with cc, but we use gcc. Using a Makefile: make prog where file Makefile in this dir is: ---------------------------------------- prog: prog.o myfuncs.o gcc -o prog prog.o myfuncs.o prog.o: prog.c myfuncs.h gcc -c prog.c myfuncs.o: myfuncs.c myfuncs.h gcc -c myfuncs.c ---------------------------------------- Or, could do just: make myfuncs.o if that's all you wanted. A makefile consists of a number of rules. Each rule is made up of a target, dependencies, and commands. target is the part before the : dependencies are after the : command(s) are after a TAB under a target: dependencies line In Linux shell, you can do: make x where x is any target in the makefile named Makefile. make looks at the dependencies for x. If they are files and they don't exist, or have been updated since the last time the target was created, then the commands are executed. However, before the commands are executed, it checks for each dependency, d, as a target. If it finds it, it implicitly does all "make d" first before "make x" To use a file other than Makefile (e.g., mf): make -f mf prog make -f mf etc If no *.o files existed, make prog would do all 3 lines in the Makefile: gcc -c prog.c gcc -c myfuncs.c gcc -o prog prog.o myfuncs.o If you type make with no argument, it does the first target in the makefile (prog in our case) If a target, t, has no dependencies, its command is always run when you do "make t" If make is not in your path, do "whereis make" to find out where it is, and add that dir to your path. Or run it directly. e.g., if you found it was in /usr/bin, then run it as: /usr/bin/make prog.o Makefiles also have "default/implicit rules". One such rule is that it knows that to make file x.o it must do $CC -c x.c where $CC is your environment variable for the C compiler (see below). Since make has default rules, you don't need rules with exact form: prog.o: prog.c $CC -c prog.c prog : prog.o $CC -o prog prog.o Note that in our case we cannot omit the following rule because it does not correcpond to the make default rule: prog.o: prog.c myfuncs.h gcc -c prog.c Note that myfuncs.c depends on myfuncs.h *not* for the prototype, but for the #define directive. However, prog.c depends on myfuncs.h for the function prototype (for doubleDog, since outchar could default). $CC above is an environment variable. Prof`s is set to "gcc", but yours might be a different compiler, like "cc". If that's the case, you should change it to gcc before using any default make rules. (Change it in your .profile or .bash_profile and re-login, or set it in the shell before using default make rules, as in CC=gcc, or set it at the top of your Makefile file, as in CC=gcc) Makefile2 has rule "clean" which cleans up object code. Run it by: make -f Makefile2 clean Makefile1 has rule "veryclean" and different "clean" rule. It also demonstrates using a variable DW shows getchar/putchar <<< Reading and Writing Characters >>> getchar(); reads in one char from stdin putchar(); prints out one char from stdout /*Source: sample11.c*/ #include int main(void) { char c; c=getchar(); /*read in 1 char*/ printf("you entered a %c\n",c); printf("In case you missed that, it was a: "); putchar(c); putchar('\n'); printf("char %c has ASCII code %d\n",c,c); //see below printf("char %c+1 is %c \n",c,c+1); return 0 ; } Chars are represented by their ASCII codes int 0-127. e.g.: A is 65 Z is 90 n is 110 c=getchar(); if (c <= 'Z' && c >= 'A') printf("%c is upper case",c); c='B'; printf("char %c has ASCII code %d",c,c); Note: extended ASCII is 0-255 but most later ones not printable on terminal WARNING: getchar returns the actual ENTER-key character too! Why? getchar() has buffered input as if reads do not happen until enter pressed e.g., see sample11A.c <<< Program Control Statements >>> They are like Java (if, if-else, for, while, do-while, switch, break, continue, etc) except no Boolean type (see below) << If Statement >> if (a < 7) printf("yes"); if (a < 7) { printf("yes "); printf("it is\n"); } if (a < 7 && b != 5) a=a+1; else { a=a+b; printf("%d",a); } Relational Operators: > >= < <= == != 2 operands each evaluate to int 0 when false; int 1 when true Logical Operators: && and (short-circuit) || or (short-circuit) ! not Note: C does not have a Boolean type in C, any non-0 (int) value is "true" 0 is "false" if C is assigning true, it is set to 1 e.g.: !5 is 0 (false) !!5 is 1 (true) Can nest ifs if (i != 0) if (i != 1) if (i != 2) if (i != 3) if (i != 4) if (i != 5) if (i != 6) if (i != 7) if (i != 8) if (i != 9) printf("%d is not a digit\n",i); else binds with nearest "else-less" if above it if (i != 0) if (i > 0) printf("\a"); else printf("\a\a\a"); The else binds to which if? No "elseif" but can do "else if" if (c >= '0' && c <= '9') printf("digit"); else if (c >= 'a' && c <= 'z') printf("lower case letter"); else if (c >= 'A' && c <= 'Z') printf("upper case letter"); else printf("not alphanumeric"); /*Source: fact.c Purpose: function fact(long n) computes n! Input argument: n an integer Output: n! an integer Note: a program using fact.c must include fact.h */ long fact(long n) { if (n == 0) return(1); else return (n*fact(n-1)); } /*Source: fact.h Purpose: header file for fact.c */ long fact(long n); Ifs good for checking for *valid input* e.g., what should fact check about n? DW shows fprintf and checking exit's value in shell /*Source: dimcheck.c Purpose: compute the floor space of a room Input: int length, width (length & width of room) Output: the square footage (integer) of room Exit: 0 if good dimensions; 1 otherwise */ #include #include int GetDim(void); int main(void) { int dim1, /*one dimension of room */ dim2, /*another dim of room */ ExitCode; /*code to exit with 0=good*/ /*initialize ExitCode to good value*/ ExitCode=0; /*read in dimensions*/ dim1 = GetDim(); dim2 = GetDim(); /*check for valid input*/ if ((dim1 <= 0) || (dim2 <= 0) ) { /*invalid dims*/ fprintf(stderr,"Input error. Expected 2 positive integers.\n"); ExitCode=1; } else printf("Floor Space is %d\n",dim1*dim2); exit(ExitCode); } int GetDim(void) { int dim; /*dimension */ int sret; //scanf return value printf("Enter a dimension (pos. int.): "); sret=scanf ("%d",&dim); if (sret != 1) return(-1); else return (dim); } Note: echo $? in shell displays a pgms's exit status HMWK: Here is a file called math2.c which contains functions for factorial and fibonacci /*Source: math2.c Purpose: source code for factorial and fibonacci functions */ long fact(long n) { if (n == 0) return(1); else return (n*fact(n-1)); } long fibonacci(long n) { if (n == 0) return (0); else if (n == 1) return (1); else return (fibonacci(n-1) + fibonacci(n-2)); } Write file math2.h, a header file for math2.c Write a program evaluate.c which prompts the user to enter a 0 or a 1. If 0 entered, calculate fact(n) where n is prompted for and read in. If 1 entered, calculate fibonacci(n), where n is prompted for and read in. Make sure your program does error checking on all input. Your program should exit with 0 if successful; with 1 if user didn't enter a "0 or 1"; and with 2 if the user entered an invalid (including negative) value for "n". << For loop >> for (i=0; i<=9; i++) { printf("%d",i); printf("\n"); } Output? DW shows srand, rand, time (note: man 2 time ; man 3 rand) /* Source: rand.c Purpose: generate MaxNum random integers Input: integer MaxNum (max number of rand nos to generate) Output: MaxNum random integers Exit: 0 if successful; 1 if improper user input (not +ve int) */ #include #include #include int main(void) { int MaxNum, /*number of random nos to generate */ i, /*index */ RandNo, /*a random number */ ExitCode=0; /*value to exit program with */ srand(time(NULL)); //seed with fairly unique number //srand(12345); //rand output always the same printf("How many rand nos to generate? "); if (((scanf("%d",&MaxNum)) != 1) || (MaxNum <0)) ExitCode=1; else for (i=1; i <= MaxNum; i++) { RandNo=rand(); printf("Random No %d is %d\n",i,RandNo); //RandNo=(rand()%6); //for 0 to 5 //c = (char) (rand() % 128); //for character } exit(ExitCode); } man getchar shows return value is int man putchar shows argument/return values are ints char c; for (c='a'; c<='z'; c++) putchar(c); for (c=getchar(); c!='X'; c=getchar()); printf("Thanks for finally inputting an X!! \n"); for ( ; ;) ; /*infinite loop*/ for (c='A'; c<='Z'; ) { putchar(c); c=c+2; } HMWK: write a program that prints out the extended ASCII character set. Use a for loop from 0 to 255, printing the index as a char in each loop. << While loop >> char c; c=getchar(); while (c != 'X') c=getchar(); printf("Thanks for finally inputting an X!! \n"); //same as above char c; while ( (c=getchar()) != 'X'); printf("Thanks for finally inputting an X!!"); //macro EOF (end-of-file) is 0. scanf returns EOF //when the input ends (file or stdin). For user //input, use ^d to send EOF in shell float x; char y; while ( scanf("%f %c",&x,&y) != EOF ) printf("%f\t%c\n",x,y) ; << break and continue >> Inside a loop, break; //stops loop and exits loop continue; //stops this iteration of loop starts //the next loop iteration << Switch Statement >> Like Java, but can only switch on int or char switch(c) { case 'a': printf("a vowel"); break; case 'e': printf("a vowel"); break; case 'i': printf("a vowel"); break; case 'o': printf("a vowel"); break; case 'u': printf("a vowel"); break; default: printf("non-vowel"); } == //source switch.c switch(c) { /*falls thru with no break*/ case 'a': case 'e': case 'i': case 'o': case 'u': printf("vowel"); break; default: printf("non-vowel"); } switch(i) { case 1: putchar('H'); case 2: putchar('E'); case 3: putchar('L'); case 4: putchar('L'); case 5: putchar('O'); default: putchar('\a'); } If i is 1? If i is 3? HMWK: (1) Write a program which reads in a character, and prints whether the character is a vowel or non-vowel. It must work for any case, e.g., 'a' and 'A' are both vowels. You should not have separate cases for upper and lower case vowels. Do this by converting the character to lower case before the switch. Use function "tolower" which is in ctype.h (for usage see tolower man page.) For non-letter (a-z,A-Z) characters, print an appropriate error message. Remember exit codes. (2) Modify your program to read in any number of characters and report, after each read, whether it is a vowel. You should stop processing characters when a '%' is input. You should always remind the user that a '%' will stop the program. DW shows ctype.h functions (ignore locale ones) DW shows isdigit returns 0 (false) or non-zero (true) DW shows char '9' is NOT same as int 9 << ctype.h >> Functions in ctype.h are toupper, tolower, isdigit, etc: digit - '0' converts char 0,1, ... 9 to int 0,1, ... 9 remember printf("%d %c", 'B','B'); => 66 B printf("%d %c", '9','9'); => 57 9 ASCII decimal code for '0' is 48 '1' is 49 '9' is 57 so if digit is '5' then digit-'0' evals to 53-48 = 5 /*Function: MakeInt() Source: MakeInt.c Purpose: to convert a sequence of digits to its integer value Input: a sequence of digit CHARACTERS, e.g., 325 Output: the integer 325 (three hundred and twenty five) */ #include #include int MakeInt() { int num=0, /*final integer value */ digit; /*digit that is read in*/ digit=getchar(); for( ; isdigit(digit); digit=getchar()) { num=num*10; num=num+ (digit - '0'); } return (num); } HMWK: (2) create a a program to display, at top of screen: ------------------------------------------------------ Welcome to the calculator program! Please choose the operation you desire by entering the appropriate number: 1. addition 2. subtraction 3. multiplication 4. division 5. absolute value 6. exit Your choice: ------------------------------------------------------ Note that you can clear screen using the C system command from stdlib.h, as in: system("clear"); //(system executes any linux command). The program will re-display this until user enters correct input. Then the program will prompt for necessary operands, calculate and display the result. The program will repeat the above until the user enters choice 6 (exit program). Use a separate function for each operation. Exit main with appropriate code. (3) Design and implement a program to print a table of squares, cubes and quatrics for numbers 1 to N, where N is input by user. Use functions for each of square, cube and quatric, and reuse square where possible. The table would look like: Number Square Cube Quatric ------ ------ ----- ------- 1 1 1 1 2 4 8 16 3 9 27 81 (4) This program will read in ints and print them out until 0 entered. Try entering 99a and see what happens? /*TryScan.c*/ #include int main(void) { int j,i=1; char c; while (i!=0) { scanf("%d",&i); printf("i is %d\n",i); } exit(1); } Fix it. Could try: adding line while ((c=getchar())!='\n'); after the scanf line, or fflush(stdin); which doesn't work on all systems, or j=scanf... and then after if (j!=1) {fprintf(stderr,"BAD"); exit(0);} (5) Fix fact(long n) so that it is robust: returns -1 when called with negative input. Then test: /*Source: testfact.c Purpose: driver to test factorial function in fact.c */ #include #include #include "math2.h" void test(int TestNumber, long result, long answer ); int main(void) { test(1,fact(0),1); /*boundary*/ test(2,fact(1),1); /*boundary*/ test(3,fact(2),2); /*boundary*/ test(4,fact(7),5040); /*interior*/ test(5,fact(-1),-1); /*error and boundary*/ test(6,fact(-3),-1); /*error*/ exit(0); } void test(int TestNo, long result, long answer) { if (result != answer) printf("Test %d failed\n",TestNo); } (6) Write test drivers for the square function and for the fibonacci function. What input would you use to test the program for computing floor space we did previously?