├── Appendix ├── bstr_hello.c ├── bstr_split.c └── bstr_trim.c ├── Chapter01 ├── comments.c ├── hello1.c └── hello2.c ├── Chapter02 ├── hello.c ├── hello2.c ├── hello3.c ├── hello4.c ├── hello5.c ├── hello6.c ├── hello7.c ├── hello_nowhitespace.c ├── hello_whitespace.c ├── main.c ├── main2.c └── printingEscapeSquences.c ├── Chapter03 ├── sizes_ranges1.c └── sizes_ranges2.c ├── Chapter04 ├── inchesToFeet.c ├── printDistance1.c └── printDistance2.c ├── Chapter05 ├── calcLength.c ├── casting.c ├── convertDigitToInt.c ├── convertTemperature.c ├── convertTemperature_NoNo.c ├── convertUpperLower.c ├── logical.c ├── prefixpostix.c ├── printLength.c └── truncRounding.c ├── Chapter06 ├── calc.c ├── leapYear1.c ├── leapYear2.c ├── leapYear3.c └── temp.c ├── Chapter07 ├── gauss_bruteforce.c ├── gauss_goto.c ├── gauss_loops.c ├── gauss_loops2.c └── primes.c ├── Chapter08 ├── shapes.c └── shapes2.c ├── Chapter09 ├── card.c ├── card2.c └── card3.c ├── Chapter10 ├── card.h ├── card4.c └── card5.c ├── Chapter11 ├── array1.c ├── array2.c ├── array3.c └── array3.h ├── Chapter12 ├── arraysND.c └── arraysND.h ├── Chapter13 ├── pointers1.c ├── pointers2.c ├── pointers3.c └── pointers4.c ├── Chapter14 ├── arrayOfPointers.c ├── arrays_pointers.c ├── arrays_pointers_funcs.c └── syarra_sretniop.c ├── Chapter15 ├── greet.c ├── printASCII_version1.c ├── printASCII_version2.c ├── printASCII_version3.c ├── printASCIIwithControl.c ├── printASCIIwithControlAndEscape.c ├── printExtendedASCII.c ├── saferStringOps.c ├── showChar.c └── simpleStrings.c ├── Chapter16 ├── carddeck.c ├── carddeck_0.c ├── carddeck_1a.c ├── carddeck_1b.c ├── carddeck_1c.c ├── carddeck_2a.c ├── carddeck_2b.c └── carddeck_3.c ├── Chapter17 └── heading.c ├── Chapter18 └── linkedlisttester.c ├── Chapter19 ├── character_string.c ├── double.c ├── signedInt.c └── unsignedInt.c ├── Chapter20 ├── example_getopt_long.c ├── example_gnu_getopts_long.c └── showArgs.c ├── Chapter21 ├── flush.c ├── internalFormatting.c ├── nameSorter.c ├── read2Numbers.c ├── read2NumbersUsingResult.c ├── readChar.c ├── readDate.c ├── readScanSet.c ├── readString.c ├── readString2.c ├── readWidth.c └── usingAtoi.c ├── Chapter22 ├── open_close_argv.c ├── open_close_fgetstr.c └── open_close_string.c ├── Chapter23 ├── createUnsorted.c ├── getoptFiles.c ├── nameList.c ├── nameList.h ├── sortNames.c └── test_trimStr.c ├── Chapter24 ├── card.c ├── card.h ├── carddeck.c ├── dealer.c ├── dealer.h ├── deck.c ├── deck.h ├── hand.c └── hand.h ├── Chapter25 ├── circle.c └── trig.c ├── LICENSE └── README.md /Appendix/bstr_hello.c: -------------------------------------------------------------------------------- 1 | // bstr_hello.c 2 | // Appendix 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to use bstrlib in "Hello, world!" 6 | // 7 | // Download bstrlib sources from 8 | // http://bstring.sourceforge.net 9 | // or 10 | // https://github.com/websnarf/bstrlib 11 | // 12 | // Dependencies: 13 | // 14 | // bstrlib.h 15 | // bstrlib.c 16 | // 17 | // Compile with: 18 | // 19 | // cc bstr_hello.c bstrlib.c -o bstr_hello -Wall -Werror -std=c11 20 | // 21 | 22 | #include 23 | #include "bstrlib.h" 24 | 25 | int main( void ) { 26 | bstring b = bfromcstr ("Hello, World!"); 27 | puts( (char*)b->data ); 28 | } 29 | -------------------------------------------------------------------------------- /Appendix/bstr_split.c: -------------------------------------------------------------------------------- 1 | // bstr_split.c 2 | // Appendix 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to split words into a 6 | // bstrList and print them out. 7 | // 8 | // Download bstrlib sources from 9 | // http://bstring.sourceforge.net 10 | // or 11 | // https://github.com/websnarf/bstrlib 12 | // 13 | // Dependencies: 14 | // 15 | // bstrlib.h 16 | // bstrlib.c 17 | // 18 | // Compile with: 19 | // 20 | // cc bstr_split.c bstrlib.c -o bstr_hello -Wall -Werror -std=c11 21 | // 22 | 23 | #include 24 | #include "bstrlib.h" 25 | 26 | int main( void ) { 27 | bstring b = bfromcstr( "Hello, World and my Grandma, too!" ); 28 | puts( (char*)b->data ); 29 | 30 | struct bstrList *blist = bsplit( b , ' ' ); 31 | 32 | printf( "num %d\n" , blist->qty ); 33 | for( int i=0 ; iqty ; i++ ) { 34 | printf( "%d: %s\n" , i , bstr2cstr( blist->entry[i] , '_' ) ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Appendix/bstr_trim.c: -------------------------------------------------------------------------------- 1 | // bstr_trim.c 2 | // Appendix 3 | // Learn C Programming 4 | // 5 | // Compare trimStr we created in Chapter 23 to 6 | // trim function available in bstrlib. 7 | // 8 | // Download bstrlib sources from 9 | // http://bstring.sourceforge.net 10 | // or 11 | // https://github.com/websnarf/bstrlib 12 | // 13 | // Dependencies: 14 | // 15 | // bstrlib.h 16 | // bstrlib.c 17 | // 18 | // Compile with: 19 | // 20 | // cc bstr_trim.c bstrlib.c -o bstr_trim -Wall -Werror -std=c11 21 | // 22 | #include 23 | #include 24 | #include 25 | #include "bstrlib.h" 26 | 27 | int CTrimStr( char* pCStr ); 28 | int BTrimStr( bstring b ); 29 | 30 | void testTrim( int testNum , char* pString ); 31 | 32 | int main( void ) { 33 | testTrim( 1 , "Hello, World!\n" ); 34 | testTrim( 2 , "Box of frogs \t \n" ); 35 | testTrim( 3 , " \t Bag of hammers" ); 36 | testTrim( 4 , "\t\t Sack of ferrets\t\t " ); 37 | testTrim( 5 , " \t\n\v\t\r " ); 38 | testTrim( 6 , "" ); 39 | testTrim( 7 , "Goodbye, World!" ); 40 | } 41 | 42 | 43 | void testTrim( int testNum , char* pInputString ) 44 | { 45 | size_t len; 46 | char testString[ strlen( pInputString ) + 1]; 47 | 48 | strcpy( testString , pInputString ); 49 | fprintf( stderr , "%1d. original: \"%s\" [len:%d]\n" , testNum, testString , 50 | (int)strlen( pInputString ) ); 51 | 52 | strcpy( testString , pInputString ); 53 | len = CTrimStr( testString ); 54 | fprintf( stderr , " CTrimStr: \"%s\" [len:%d]\n" , testString , (int)len ) ; 55 | 56 | bstring b = bfromcstr( pInputString ); 57 | len = BTrimStr( b ); 58 | fprintf( stderr , " BTrimStr: \"%s\" [len:%d]\n\n" , (char*)b->data , (int)len ); 59 | } 60 | 61 | 62 | int CTrimStr( char* pCStr ) 63 | { 64 | size_t first , last , lenIn , lenOut ; 65 | first = last = lenIn = lenOut = 0; 66 | 67 | lenIn = strlen( pCStr ); // 68 | char tmpStr[ lenIn+1 ]; // Create working copy. 69 | strcpy( tmpStr , pCStr ); // 70 | char* pTmp = tmpStr; // pTmp may change in Left Trim segment. 71 | 72 | // Left Trim 73 | // Find 1st non-whitespace char; pStr will point to that. 74 | while( isspace( pTmp[ first ] ) ) 75 | first++; 76 | pTmp += first; 77 | 78 | lenOut = strlen( pTmp ); // Get new length after Left Trim. 79 | if( lenOut ) { // Check for empty string. 80 | // e.g. " " trimmed to nothing. 81 | // Right Trim 82 | // Find 1st non-whitespace char & set NUL character there. 83 | last = lenOut-1; // off-by-1 adjustment. 84 | while( isspace( pTmp[ last ] ) ) 85 | last--; 86 | pTmp[ last+1 ] = '\0'; // Terminate trimmed string. 87 | } 88 | lenOut = strlen( pTmp ); // Length of trimmed string. 89 | if( lenIn != lenOut ) // Did we change anything? 90 | strcpy( pCStr , pTmp ); // Yes, copy trimmed string back. 91 | return lenOut; 92 | } 93 | 94 | int BTrimStr( bstring b ) { 95 | btrimws( b ); 96 | return b->slen; 97 | } 98 | 99 | 100 | -------------------------------------------------------------------------------- /Chapter01/comments.c: -------------------------------------------------------------------------------- 1 | 2 | // comments.c 3 | // Chapter 01 4 | // Learn C Programming 5 | // 6 | // Compile with: 7 | // 8 | // cc comments.c 9 | // 10 | 11 | /* (1) A single-line C-style comment. */ 12 | 13 | /* (2) A multi-line 14 | C-style comment. */ 15 | 16 | /* 17 | * (3) A very common way to 18 | * format a multi-line 19 | * C-Style comment. 20 | */ 21 | 22 | /* (4) C-style comments can appear almost anywhere. */ 23 | 24 | /*5*/ printf( /* say hello */ "Hello, world!\n"); 25 | 26 | /*6*/ printf( "Hello, world!\n" ); /* yay! */ 27 | 28 | // (7) A C++ style comment (terminated by End-of-Line). 29 | 30 | printf( "Hello, world!\n" ); // (8) Say hello; yay! 31 | 32 | // 33 | // (9) A more common way 34 | // of commenting with multi-line 35 | // C++ style comments. 36 | // 37 | 38 | // (10) Anything can appear after //, even /* ... */ and 39 | // more // after the first // but they will be 40 | // ignored because they are all in the comment. 41 | -------------------------------------------------------------------------------- /Chapter01/hello1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf( "Hello, world!\n" ); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /Chapter01/hello2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hello2.c 3 | * My first C program with comments. 4 | * by 5 | * created // 6 | * 7 | * compile with: 8 | * 9 | * cc hello2.c 10 | */ 11 | 12 | #include 13 | 14 | int main() 15 | { 16 | printf( "Hello, world!\n" ); 17 | return 0; 18 | } 19 | 20 | /* eof */ 21 | -------------------------------------------------------------------------------- /Chapter02/hello.c: -------------------------------------------------------------------------------- 1 | // hello.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Simple "Hello, world!" program. 6 | // 7 | // compile with: 8 | // 9 | // cc hello.c 10 | 11 | #include 12 | 13 | int main() 14 | { 15 | printf( "Hello, world!\n" ); 16 | return 0; 17 | } 18 | 19 | // 20 | -------------------------------------------------------------------------------- /Chapter02/hello2.c: -------------------------------------------------------------------------------- 1 | // hello2.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Using a simple function that simply prints 2 characters. 6 | // 7 | // 8 | // Compile with: 9 | // 10 | // cc hello2.c -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | 16 | void printComma() 17 | { 18 | printf( ", " ); 19 | return; 20 | } 21 | 22 | int main() 23 | { 24 | printf( "Hello" ); 25 | printComma(); 26 | printf( "world!\n" ); 27 | return 0; 28 | } 29 | 30 | // 31 | -------------------------------------------------------------------------------- /Chapter02/hello3.c: -------------------------------------------------------------------------------- 1 | // hello3.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Using two functions, one function that takes no parameters, 6 | // and one function that takes a string parameter. 7 | // 8 | // 9 | // Compile with: 10 | // 11 | // cc hello3.c -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | 17 | void printComma() 18 | { 19 | printf( ", " ); 20 | } 21 | 22 | void printWord( char* word ) 23 | { 24 | printf( "%s" , word ); 25 | } 26 | 27 | int main() 28 | { 29 | printWord( "Hello" ); 30 | printComma(); 31 | printWord( "world" ); 32 | printf( "!\n" ); 33 | 34 | return 0; 35 | } 36 | 37 | // 38 | -------------------------------------------------------------------------------- /Chapter02/hello4.c: -------------------------------------------------------------------------------- 1 | // hello4.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Now we have 3 functions. 6 | // 1st with no parameters. 7 | // 2nd with 1 string parameter. 8 | // 3rd with 2 string parameters. 9 | // Pay attention to how they are called. 10 | // 11 | // Compile with: 12 | // 13 | // cc hello4.c -Wall -Werror -std=c11 14 | // 15 | 16 | 17 | #include 18 | 19 | void printComma() 20 | { 21 | printf( ", " ); 22 | } 23 | 24 | void printWord( char* word ) 25 | { 26 | printf( "%s" , word ); 27 | } 28 | 29 | void printGreeting( char* greeting , char* addressee ) 30 | { 31 | printWord( greeting ); 32 | printComma(); 33 | printWord( addressee ); 34 | printf( "!\n" ); 35 | } 36 | 37 | int main() 38 | { 39 | printGreeting( "Hello" , "world" ); 40 | printGreeting( "Good day" , "Your Royal Highness" ); 41 | printGreeting( "Howdy" , "John Q. and Jane P. Doe" ); 42 | printGreeting( "Hey" , "Moe, Larry, and Curly" ); 43 | 44 | return 0; 45 | } 46 | 47 | // 48 | -------------------------------------------------------------------------------- /Chapter02/hello5.c: -------------------------------------------------------------------------------- 1 | // hello5.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Cutting back our functions to just 1 that takes 2 string parameters. 6 | // 7 | // Compile with: 8 | // 9 | // cc hello5.c -Wall -Werror -std=c11 10 | // 11 | 12 | 13 | #include 14 | 15 | void printGreeting( char* greeting , char* addressee ) 16 | { 17 | printf( "%s, %s!\n" , greeting , addressee ); 18 | } 19 | 20 | int main() 21 | { 22 | printGreeting( "Hello" , "world" ); 23 | printGreeting( "Good day" , "Your Royal Highness" ); 24 | printGreeting( "Howdy" , "John Q. and Jane P. Doe" ); 25 | printGreeting( "Hey" , "Moe, Larry, and Curly" ); 26 | 27 | return 0; 28 | } 29 | 30 | // 31 | -------------------------------------------------------------------------------- /Chapter02/hello6.c: -------------------------------------------------------------------------------- 1 | // hello6.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Breaking our program into a bunch of small functions. 6 | // 7 | // Compile with: 8 | // 9 | // cc hello6.c -Wall -Werror -std=c11 10 | // 11 | 12 | 13 | #include 14 | 15 | void printAGreeting( char* greeting ) 16 | { 17 | printf( "%s" , greeting ); 18 | } 19 | 20 | void printAComma( void ) 21 | { 22 | printf( ", " ); 23 | } 24 | 25 | void printAnAddressee( char* aName ) 26 | { 27 | printf( "%s" , aName ); 28 | } 29 | 30 | void printANewLine() 31 | { 32 | printf( "\n" ); 33 | } 34 | 35 | void printGreeting( char* aGreeting , char* aName ) 36 | { 37 | printAGreeting( aGreeting ); 38 | printAComma(); 39 | printAnAddressee( aName ); 40 | printANewLine(); 41 | } 42 | 43 | int main() 44 | { 45 | printGreeting( "Hi" , "Bub" ); 46 | 47 | return 0; 48 | } 49 | 50 | // 51 | -------------------------------------------------------------------------------- /Chapter02/hello7.c: -------------------------------------------------------------------------------- 1 | // hello7.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Using function prototypes to call our functions in any 6 | // order (before the compiler processes the function body). 7 | // Sometimes this is called "top-down" function implementation. 8 | // 9 | // Compile with: 10 | // 11 | // cc hello7.c -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | 17 | // function prototypes 18 | 19 | void printGreeting( char* aGreeting , char* aName ); 20 | void printAGreeting( char* greeting ); 21 | void printAnAddressee( char* aName ); 22 | void printAComma( void ); 23 | void printANewLine( void ); 24 | 25 | 26 | int main() 27 | { 28 | printGreeting( "Hi" , "Bub" ); 29 | 30 | return 0; 31 | } 32 | 33 | void printGreeting( char* aGreeting , char* aName ) 34 | { 35 | printAGreeting( aGreeting ); 36 | printAComma(); 37 | printAnAddressee( aName ); 38 | printANewLine(); 39 | } 40 | 41 | void printAGreeting( char* greeting ) 42 | { 43 | printf( "%s" , greeting ); 44 | } 45 | 46 | void printAnAddressee( char* aName ) 47 | { 48 | printf( "%s" , aName ); 49 | } 50 | 51 | void printAComma( void ) 52 | { 53 | printf( ", " ); 54 | } 55 | 56 | void printANewLine() 57 | { 58 | printf( "\n" ); 59 | } 60 | 61 | // 62 | -------------------------------------------------------------------------------- /Chapter02/hello_nowhitespace.c: -------------------------------------------------------------------------------- 1 | // hello_nowhitespace.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // We're saving spaces but so what? 6 | // This is really bad programming style. 7 | // 8 | // Compile with: 9 | // 10 | // cc hello_nowhitespace.c -Wall -Werror -std=c11 11 | // 12 | 13 | #include 14 | int main(){printf("Hello, world!\n");} 15 | -------------------------------------------------------------------------------- /Chapter02/hello_whitespace.c: -------------------------------------------------------------------------------- 1 | // hello_whitespace.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Whitespace gone wild! 6 | // Just because you can do a thing does 7 | // mean that you must to that thing. 8 | // 9 | // Don't do what you see here, either. 10 | // 11 | // Compile with: 12 | // 13 | // cc hello_whitespace.c -Wall -Werror -std=c11 14 | // 15 | 16 | # include 17 | 18 | 19 | int 20 | main 21 | ( 22 | ) 23 | { 24 | 25 | printf 26 | 27 | ( 28 | 29 | "Hello, world!\n" 30 | 31 | ) 32 | ; 33 | 34 | return 35 | 0 36 | ; 37 | 38 | } 39 | 40 | // 41 | 42 | -------------------------------------------------------------------------------- /Chapter02/main.c: -------------------------------------------------------------------------------- 1 | // main.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // The very minimal and useless C program. 6 | // We do this only for illustrative purpose, no other. 7 | // 8 | // Compile with: 9 | // 10 | // cc main.c -Wall -Werror -std=c11 11 | // 12 | 13 | int main( void ) 14 | { 15 | return 0; 16 | } 17 | 18 | // 19 | -------------------------------------------------------------------------------- /Chapter02/main2.c: -------------------------------------------------------------------------------- 1 | // main2.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Adding a simple function. 6 | // The program still does nothing. 7 | // 8 | // Compile with: 9 | // 10 | // cc main2.c -Wall -Werror -std=c11 11 | // 12 | 13 | void printComma() 14 | { 15 | 16 | // ... means 0 or more statements could go here. 17 | 18 | return; 19 | } 20 | 21 | int main() 22 | { 23 | 24 | // ... means 0 or more statements could go here. 25 | 26 | return 0; 27 | } 28 | 29 | // 30 | -------------------------------------------------------------------------------- /Chapter02/printingEscapeSquences.c: -------------------------------------------------------------------------------- 1 | // printingEscapeSequences.c 2 | // Chapter 2 3 | // Learn C Programming 4 | // 5 | // Demonstrate how escape sequences appear both 6 | // in the source code and on the console. 7 | // 8 | // Compile with: 9 | // 10 | // cc printingEscapeSequences.c -Wall -Werror -std=c11 11 | // 12 | 13 | #include 14 | 15 | int main( void ) 16 | { 17 | printf( "Hello, world without a new line" ); 18 | printf( "Hello, world with a new line\n" ); 19 | printf( "A string with \"quoted text\" inside of it\n\n" ); 20 | 21 | printf( "Tabbed\tColumn\tHeadings\n" ); 22 | printf( "The\tquick\tbrown\n" ); 23 | printf( "fox\tjumps\tover\n" ); 24 | printf( "the\tlazy\tdog.\n\n" ); 25 | 26 | printf( "A line of text that\nspans three lines\nand completes the line\n\n" ); 27 | 28 | return 0; 29 | } 30 | 31 | // 32 | -------------------------------------------------------------------------------- /Chapter03/sizes_ranges1.c: -------------------------------------------------------------------------------- 1 | // sizes_ranges1.c 2 | // Chapter 3 3 | // Learn C Programming 4 | // 5 | // Print out the sizes and ranges for each of C's data types. 6 | // Save this program and run it on various computer systems you may find 7 | // yourself working on to confirm and verify the system's limits. 8 | // 9 | // Compile with: 10 | // 11 | // cc sizes_ranges1.c -Wall -Werror -std=c11 12 | // 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | // function prototypes 20 | // 21 | void printSizes( void ); 22 | 23 | 24 | int main( void ) 25 | { 26 | printSizes(); 27 | 28 | return 0; 29 | } 30 | 31 | // function to print the # of bytes for each of C11's data types 32 | // 33 | void printSizes( void ) 34 | { 35 | printf( "Size of C data types\n\n" ); 36 | printf( "Type Bytes\n\n" ); 37 | printf( "char %lu\n" , sizeof( char ) ); 38 | printf( "int8_t %lu\n" , sizeof( int8_t ) ); 39 | printf( "unsigned char %lu\n" , sizeof( unsigned char ) ); 40 | printf( "uint8_t %lu\n" , sizeof( uint8_t ) ); 41 | printf( "short %lu\n" , sizeof( short ) ); 42 | printf( "int16_t %lu\n" , sizeof( int16_t ) ); 43 | printf( "uint16t %lu\n" , sizeof( uint16_t ) ); 44 | printf( "int %lu\n" , sizeof( int ) ); 45 | printf( "unsigned %lu\n" , sizeof( unsigned ) ); 46 | printf( "long %lu\n" , sizeof( long ) ); 47 | printf( "unsigned long %lu\n" , sizeof( unsigned long ) ); 48 | printf( "int32_t %lu\n" , sizeof( int32_t ) ); 49 | printf( "uint32_t %lu\n" , sizeof( uint32_t ) ); 50 | printf( "long long %lu\n" , sizeof( long long ) ); 51 | printf( "int64_t %lu\n" , sizeof( int64_t ) ); 52 | printf( "unsigned long long %lu\n" , sizeof( unsigned long long ) ); 53 | printf( "uint64_t %lu\n" , sizeof( uint64_t ) ); 54 | printf( "\n" ); 55 | printf( "float %lu\n" , sizeof( float ) ); 56 | printf( "double %lu\n" , sizeof( double ) ); 57 | printf( "long double %lu\n" , sizeof( long double ) ); 58 | printf( "\n" ); 59 | printf( "bool %lu\n" , sizeof( bool ) ); 60 | printf( "_Bool %lu\n" , sizeof( _Bool ) ); 61 | printf( "\n" ); 62 | } 63 | 64 | /* eof */ 65 | 66 | -------------------------------------------------------------------------------- /Chapter03/sizes_ranges2.c: -------------------------------------------------------------------------------- 1 | // sizes_ranges2.c 2 | // Chapter 3 3 | // Learn C Programming 4 | // 5 | // Print out the sizes and ranges for each of C's data types. 6 | // Save this program and run it on various computer systems you may find 7 | // yourself working on to confirm and verify the system's limits. 8 | // 9 | // Compile with: 10 | // 11 | // cc sizes_ranges2.c -Wall -Werror -std=c11 12 | // 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | // function prototypes 22 | // 23 | void printSizes( void ); 24 | void printRanges( void ); 25 | 26 | 27 | int main( void ) 28 | { 29 | printSizes(); 30 | printRanges(); 31 | 32 | return 0; 33 | } 34 | 35 | // A Function to print the # of bytes for each of C11's data types. 36 | // The fixed-width integer types are defined in stdint.h 37 | // 38 | void printSizes( void ) 39 | { 40 | printf( "Size of C data types\n\n" ); 41 | printf( "Type Bytes\n\n" ); 42 | printf( "char %lu\n" , sizeof( char ) ); 43 | printf( "int8_t %lu\n" , sizeof( int8_t ) ); 44 | printf( "unsigned char %lu\n" , sizeof( unsigned char ) ); 45 | printf( "uint8_t %lu\n" , sizeof( uint8_t ) ); 46 | printf( "short %lu\n" , sizeof( short ) ); 47 | printf( "int16_t %lu\n" , sizeof( int16_t ) ); 48 | printf( "uint16_t %lu\n" , sizeof( uint16_t ) ); 49 | printf( "int %lu\n" , sizeof( int ) ); 50 | printf( "unsigned %lu\n" , sizeof( unsigned ) ); 51 | printf( "long %lu\n" , sizeof( long ) ); 52 | printf( "unsigned long %lu\n" , sizeof( unsigned long ) ); 53 | printf( "int32_t %lu\n" , sizeof( int32_t ) ); 54 | printf( "uint32_t %lu\n" , sizeof( uint32_t ) ); 55 | printf( "long long %lu\n" , sizeof( long long ) ); 56 | printf( "int64_t %lu\n" , sizeof( int64_t ) ); 57 | printf( "unsigned long long %lu\n" , sizeof( unsigned long long ) ); 58 | printf( "uint64_t %lu\n" , sizeof( uint64_t ) ); 59 | printf( "\n" ); 60 | printf( "float %lu\n" , sizeof( float ) ); 61 | printf( "double %lu\n" , sizeof( double ) ); 62 | printf( "long double %lu\n" , sizeof( long double ) ); 63 | printf( "\n" ); 64 | printf( "bool %lu\n" , sizeof( bool ) ); 65 | printf( "_Bool %lu\n" , sizeof( _Bool ) ); 66 | printf( "\n" ); 67 | } 68 | 69 | 70 | // For each type, print its min and max values for our system. 71 | // These are defined in limits.h and float.h 72 | // 73 | void printRanges( void ) 74 | { 75 | printf( "Ranges for integer data types in C\n\n" ); 76 | printf( "int8_t %20d %20d\n" , SCHAR_MIN , SCHAR_MAX ); 77 | printf( "int16_t %20d %20d\n" , SHRT_MIN , SHRT_MAX ); 78 | printf( "int32_t %20d %20d\n" , INT_MIN , INT_MAX ); 79 | printf( "int64_t %20lld %20lld\n" , LLONG_MIN , LLONG_MAX ); 80 | printf( "uint8_t %20d %20d\n" , 0 , UCHAR_MAX ); 81 | printf( "uint16_t %20d %20d\n" , 0 , USHRT_MAX ); 82 | printf( "uint32_t %20d %20u\n" , 0 , UINT_MAX ); 83 | printf( "uint64_t %20d %20llu\n" , 0 , ULLONG_MAX ); 84 | printf( "\n" ); 85 | printf( "Ranges for real number data types in C\n\n" ); 86 | printf( "flaot %14.7g %14.7g\n" , FLT_MIN , FLT_MAX ); 87 | printf( "double %14.7g %14.7g\n" , DBL_MIN , DBL_MAX ); 88 | printf( "long double %14.7Lg %14.7Lg\n" , LDBL_MIN , LDBL_MAX ); 89 | printf( "\n" ); 90 | } 91 | 92 | /* eof */ 93 | 94 | -------------------------------------------------------------------------------- /Chapter04/inchesToFeet.c: -------------------------------------------------------------------------------- 1 | // inchesToFeet.c 2 | // Chapter 4: Using Variables and Assignment 3 | // Learn C Programming 4 | // 5 | // A function which demonstrates assignment via 6 | // return value. 7 | // 8 | // There are 2 assignments. 9 | // 1 to the function expression and the 2nd to 10 | // the variable feet via the = operator. 11 | // 12 | // Compile with: 13 | // 14 | // cc inchesToFeet.c -Wall -Werror -std=c11 15 | // 16 | 17 | #include 18 | 19 | double inchesToFeet( double ); 20 | 21 | int main( void ) 22 | { 23 | double inches = 1024.0; 24 | double feet = 0.0; 25 | 26 | feet = inchesToFeet( inches ); 27 | printf( "%12.3g inches is equal to %12.3g feet\n" , inches , feet ); 28 | 29 | return 0; 30 | } 31 | 32 | // Given inches, convert this to feet. 33 | // 34 | double inchesToFeet( double someInches ) 35 | { 36 | double someFeet = someInches / 12.0; 37 | return someFeet; 38 | } 39 | 40 | // 41 | -------------------------------------------------------------------------------- /Chapter04/printDistance1.c: -------------------------------------------------------------------------------- 1 | // printDistance1.c 2 | // Chapter 4: Using Variables and Assignment 3 | // Learn C Programming 4 | // 5 | // A function that demonstrates the use of 6 | // assignment via actual parameters and 7 | // explicit assignment inside the function. 8 | // 9 | // Compile with: 10 | // 11 | // cc printDistance1.c -Wall -Werror -std=c11 12 | // 13 | 14 | #include 15 | 16 | // Function prototypes. 17 | void printDistance( double ); 18 | 19 | int main( void ) 20 | { 21 | double feet = 5280.0; 22 | printDistance( feet ); 23 | printf( "feet = %12.3g\n" , feet ); 24 | return 0; 25 | } 26 | 27 | // Given feet, print the distance in feet and yards. 28 | // 29 | void printDistance( double f ) 30 | { 31 | printf( "The distance in feet is %12.3g\n" , f ); 32 | f = f / 3.0 ; 33 | printf( "The distance in yards is %12.3g\n" , f ); 34 | } 35 | 36 | // 37 | 38 | -------------------------------------------------------------------------------- /Chapter04/printDistance2.c: -------------------------------------------------------------------------------- 1 | // printDistance2.c 2 | // Chapter 4: Using Variables and Assignment 3 | // Learn C Programming 4 | // 5 | // A better function that demonstrates the use of 6 | // assignment via actual parameters and 7 | // explicit assignment inside the function. 8 | // 9 | // This one is better because 10 | // 1) actual parameter name is meaningful of its use, and 11 | // 2) local variable yards is explicitly declared so its 12 | // value and use are clear. 13 | // 14 | // Compile with: 15 | // 16 | // cc printDistance2.c -Wall -Werror -std=c11 17 | // 18 | 19 | #include 20 | 21 | // Function prototypes. 22 | void printDistance( double ); 23 | 24 | int main( void ) 25 | { 26 | double feet = 5280.0; 27 | printDistance( feet ); 28 | printf( "feet = %12.3g\n" , feet ); 29 | return 0; 30 | } 31 | 32 | // Given feet, print the distance in feet and yards. 33 | // 34 | void printDistance( double feet ) 35 | { 36 | double yards = feet / 3.0; 37 | 38 | printf( "The distance in feet is %12.3g\n" , feet ); 39 | printf( "The distance in yards is %12.3g\n" , yards ); 40 | } 41 | 42 | // 43 | 44 | -------------------------------------------------------------------------------- /Chapter05/calcLength.c: -------------------------------------------------------------------------------- 1 | // calcLength.c 2 | // Chapter 5 3 | // Learn C Programming 4 | // 5 | // Program to demonstrate a complex expression 6 | // two different ways. 7 | // First compute the value with a complex expression. 8 | // Then compute the value again with a sequence of simple expressions. 9 | // 10 | // Compile with: 11 | // 12 | // cc calcLength.c -o calcLength -Wall -Werror -std=c11 13 | // 14 | 15 | 16 | #include 17 | 18 | 19 | int feetToInches( double feet ) 20 | { 21 | int inches = feet * 12; 22 | return inches; 23 | } 24 | 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | int aValue = 8; 29 | int aLength = 0; 30 | 31 | // 3 additions in 1 statement (a complex statement) 32 | // 33 | aLength = 5 + aValue + feetToInches( 3.5 ); 34 | printf( "Calculated length = %d\n" , aLength ); 35 | 36 | // 3 additions in 3 statements accumulated in the variable aLength; 37 | // 38 | aLength = 5; 39 | aLength = aLength + aValue; 40 | aLength = aLength + feetToInches( 3.5 ); 41 | printf( "Calculated length = %d\n" , aLength ); 42 | } 43 | -------------------------------------------------------------------------------- /Chapter05/casting.c: -------------------------------------------------------------------------------- 1 | // casting.c 2 | // Chapter 5 3 | // Learn C Programming 4 | // 5 | // Program to demonstrate casting 6 | // for predictable results. 7 | // 8 | // Compile with: 9 | // 10 | // cc casting.c -o casting -Wall -Werror -std=c11 11 | // 12 | 13 | #include 14 | 15 | int main( void ) 16 | { 17 | int numerator = 33; 18 | int denominator = 5; 19 | double result; 20 | 21 | 22 | result = numerator / denominator; 23 | printf( "Truncation: %d / %d = %.2g\n" , numerator , denominator , result ); 24 | 25 | result = (double) numerator / denominator; 26 | printf( "No truncation: %.2f / %d = %.2f\n" , (double)numerator , denominator , result ); 27 | 28 | result = numerator / (double)denominator; 29 | printf( " %d / %.2f = %.2f\n" , numerator , (double)denominator , result ); 30 | 31 | return 0; 32 | } 33 | 34 | // eof 35 | -------------------------------------------------------------------------------- /Chapter05/convertDigitToInt.c: -------------------------------------------------------------------------------- 1 | // convertDigitToInt.c 2 | // Chapter 5 3 | // Learn C Programming 4 | // 5 | // Program to convert digit characters to their 6 | // numerical values and add them together (operations on 7 | // characters). 8 | // 9 | // Compile with: 10 | // 11 | // cc convertDigitToInt.c -o convertDigitToInt -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | 16 | #include 17 | 18 | int main( void ) { 19 | char digit5 = '5'; 20 | char digit8 = '8'; 21 | 22 | int sumDigits = digit5 + digit8; 23 | printf( "digit5 + digit8 = '5' + '8' = %d (oh, dear!)\n" , 24 | sumDigits ); 25 | 26 | char value5 = digit5 - '0'; // get the numerical value of '5' 27 | char value8 = digit8 - '0'; // get the numerical value of '8' 28 | sumDigits = value5 + value8; 29 | printf( "value5 + value8 = 5 + 8 = %d\n" , 30 | sumDigits ); 31 | } 32 | 33 | // eof 34 | -------------------------------------------------------------------------------- /Chapter05/convertTemperature.c: -------------------------------------------------------------------------------- 1 | // convertTemperature.c 2 | // Chapter 5 3 | // Learn C Programming 4 | // 5 | // Program to convert temperature values 6 | // to and from Celsius and Fahrenheit. 7 | // 8 | // Note how we test our functions's correct 9 | // calculations. 10 | // 11 | // Compile with: 12 | // 13 | // cc convertTemperature.c -o convertTemperature -Wall -Werror -std=c11 14 | // 15 | 16 | 17 | #include 18 | 19 | double celsiusToFahrenheit( double degreesC ); 20 | double fahrenheitToCelsius( double degreesF ); 21 | 22 | int main( void ) 23 | { 24 | int c = 0; 25 | int f = 32; 26 | printf( "%4d Celsius is %4d Fahrenheit\n" , c , (int)celsiusToFahrenheit( c ) ); 27 | printf( "%4d Fahrenheit is %4d Celsius\n\n" , f , (int)fahrenheitToCelsius( f ) ); 28 | 29 | c = 100; 30 | f = 212; 31 | printf( "%4d Celsius is %4d Fahrenheit\n" , c , (int)celsiusToFahrenheit( c ) ); 32 | printf( "%4d Fahrenheit is %4d Celsius\n\n" , f , (int)fahrenheitToCelsius( f ) ); 33 | 34 | c = f = 50; 35 | printf( "%4d Celsius is %4d Fahrenheit\n" , c , (int)celsiusToFahrenheit( c ) ); 36 | printf( "%4d Fahrenheit is %4d Celsius\n\n" , f , (int)fahrenheitToCelsius( f ) ); 37 | return 0; 38 | } 39 | 40 | 41 | double celsiusToFahrenheit( double degreesC ) 42 | { 43 | double degreesF = (degreesC * 9.0 / 5.0 ) + 32; 44 | return degreesF; 45 | } 46 | 47 | 48 | double fahrenheitToCelsius( double degreesF ) 49 | { 50 | double degreesC = (degreesF - 32 ) * 5.0 / 9.0 ; 51 | return degreesC; 52 | } 53 | 54 | // eof 55 | -------------------------------------------------------------------------------- /Chapter05/convertTemperature_NoNo.c: -------------------------------------------------------------------------------- 1 | // convertTempertature_NoNo.c 2 | // Chapter 5 3 | // Learn C Programming 4 | // 5 | // Demonstrate what happens with the C compiler 6 | // when we declare multiple functions of the same 7 | // name but with different parameter and return 8 | // types. 9 | // 10 | // Compile with: 11 | // 12 | // cc convertTemperature_NoNo.c -o convertTemperature_NoNo -Wall -Werror -std=c11 13 | // 14 | 15 | 16 | #include 17 | 18 | double celsiusToFahrenheit( double degreesC ); 19 | double fahrenheitToCelcius( double degreesF ); 20 | 21 | int celsiusToFahrenheit( int degreesC ); 22 | int fahrenheitToCelcius( int degreesF ); 23 | 24 | double celsiusToFahrenheit( int degreesC ); 25 | double fahrenheitToCelcius( int degreesF ); 26 | 27 | int celsiusToFahrenheit( double degreesC ); 28 | int fahrenheitToCelcius( double degreesF ); 29 | 30 | 31 | int main( void ) 32 | { 33 | // It doesn't matter what happens here. We 34 | // need to see if the compiler will recognize 35 | // multiple versions of the same functions. 36 | return 0; 37 | } 38 | 39 | double celsiusToFahrenheit( double degreesC ) 40 | { 41 | double degreesF = (degreesC * 9.0 / 5.0 ) + 32; 42 | return degreesF; 43 | } 44 | double fahrenheitToCelcius( double degreesF ) 45 | { 46 | double degreesC = (degreesF - 32 ) * 5.0 / 9.0 ; 47 | return degreesC; 48 | } 49 | 50 | 51 | int celsiusToFahrenheit( int degreesC ) 52 | { 53 | int degreesF = (degreesC * 9 / 5 ) + 32; 54 | return degreesF; 55 | } 56 | int fahrenheitToCelcius( int degreesF ) 57 | { 58 | int degreesC = (degreesF - 32 ) * 5 / 9; 59 | return degreesC; 60 | } 61 | 62 | 63 | double celsiusToFahrenheit( int degreesC ) 64 | { 65 | double degreesF = (degreesC * 9.0 / 5.0 ) + 32; 66 | return degreesF; 67 | } 68 | double fahrenheitToCelcius( int degreesF ) 69 | { 70 | double degreesC = (degreesF - 32 ) * 5.0 / 9.0 ; 71 | return degreesC; 72 | } 73 | 74 | 75 | int celsiusToFahrenheit( double degreesC ) 76 | { 77 | int degreesF = (degreesC * 9 / 5 ) + 32; 78 | return degreesF; 79 | } 80 | int fahrenheitToCelcius( double degreesF ) 81 | { 82 | int degreesC = (degreesF - 32 ) * 5 / 9; 83 | return degreesC; 84 | } 85 | 86 | // eof 87 | -------------------------------------------------------------------------------- /Chapter05/convertUpperLower.c: -------------------------------------------------------------------------------- 1 | // convertUpperLower.c 2 | // Chapter 5 3 | // Learn C Programming 4 | // 5 | // Program to convert a lower case letter to upper case 6 | // and an upper case letter to lower case (operations on 7 | // characters). 8 | // 9 | // Compile with: 10 | // 11 | // cc convertUpperLower.c -o convertUpperLower -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | 17 | int main( void ) 18 | { 19 | char lowerChar = 'b'; 20 | char upperChar = 'M'; 21 | 22 | char anUpper = lowerChar - 32; 23 | char aLower = upperChar + 32; 24 | 25 | printf( "Lower case '%c' can be changed to upper case '%c'\n" , 26 | lowerChar , anUpper ); 27 | printf( "Upper case '%c' can be changed to lower case '%c'\n" , 28 | upperChar , aLower ); 29 | } 30 | 31 | // eof 32 | -------------------------------------------------------------------------------- /Chapter05/logical.c: -------------------------------------------------------------------------------- 1 | // logical.c 2 | // Chapter 5 3 | // Learn C Programming 4 | // 5 | // Program to print out logical operagtor 6 | // "truth" tables for !!, &&, and ! 7 | // 8 | // Compile with: 9 | // 10 | // cc logical.c -o logical -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | #include 16 | 17 | 18 | void printLogicalAND( bool z, bool o ); 19 | void printLogicalOR( bool z, bool o ); 20 | void printLogicalNOT( bool z, bool o ); 21 | 22 | 23 | int main( void ) 24 | { 25 | bool one = 1; 26 | bool zero = 0; 27 | 28 | printLogicalAND( zero , one ); 29 | printLogicalOR( zero , one ); 30 | printLogicalNOT( zero , one ); 31 | 32 | return 0; 33 | } 34 | 35 | void printLogicalAND( bool z, bool o ) 36 | { 37 | bool zero_zero = z && z ; 38 | bool zero_one = z && o ; 39 | bool one_zero = o && z ; 40 | bool one_one = o && o ; 41 | 42 | printf( "AND | %1d | %1d\n" , z , o ); 43 | printf( " %1d | %1d | %1d\n" , z, zero_zero , zero_one ); 44 | printf( " %1d | %1d | %1d\n\n" , o , zero_one , one_one ); 45 | printf( "\n" ); 46 | } 47 | 48 | void printLogicalOR( bool z, bool o ) 49 | { 50 | bool zero_zero = z || z ; 51 | bool zero_one = z || o ; 52 | bool one_zero = o || z ; 53 | bool one_one = o || o ; 54 | 55 | printf( "OR | %1d | %1d\n" , z , o ); 56 | printf( " %1d | %1d | %1d\n" , z , zero_zero , zero_one ); 57 | printf( " %1d | %1d | %1d\n\n" , o , zero_one , one_one ); 58 | } 59 | 60 | void printLogicalNOT( bool z, bool o ) 61 | { 62 | bool not_zero = !z ; 63 | bool not_one = !o ; 64 | 65 | printf( "NOT \n" ); 66 | printf( " %1d | %1d \n" , z , not_zero ); 67 | printf( " %1d | %1d \n\n" , o , not_one ); 68 | } 69 | 70 | // eof 71 | -------------------------------------------------------------------------------- /Chapter05/prefixpostix.c: -------------------------------------------------------------------------------- 1 | // prefixpostfix.c 2 | // Chapter 5: Exploring Operators and Expressions 3 | // Learn C Programming 4 | // 5 | // A program to illustrate when the prefix and postfix 6 | // increment operator changes the value of a variable. 7 | // 8 | // Confusion or doubt can be removed by making the 9 | // incrementation its own statement. 10 | // 11 | // Compile with: 12 | // 13 | // cc prefixpostfix.c -o prefixpostfix -Wall -Werror -std=c11 14 | // 15 | 16 | #include 17 | 18 | int main( void ) 19 | { 20 | int aValue = 5; 21 | 22 | // Demonstrate prefix incrementation. 23 | 24 | printf( "Initial: %d\n" , aValue ); 25 | printf( " Prefix: %d\n" , ++aValue ); // Prefix incrementation. 26 | printf( " Final: %d\n\n" , aValue ); 27 | 28 | // Reset aValue. 29 | 30 | aValue = 5; 31 | 32 | // Demonstrate postfix incrementation. 33 | 34 | printf( "Initial: %d\n" , aValue ); 35 | printf( "Postfix: %d\n" , aValue++ ); // Postfix incrementation. 36 | printf( " Final: %d\n\n" , aValue ); 37 | 38 | // A more predictable result: increment in isolation. 39 | aValue = 5; 40 | ++aValue; 41 | printf( "++aValue (alone) == %d\n" , aValue ); 42 | 43 | aValue = 5; 44 | aValue++; 45 | printf( "aValue++ (alone) == %d\n" , aValue ); 46 | 47 | return 0; 48 | } 49 | 50 | // 51 | 52 | -------------------------------------------------------------------------------- /Chapter05/printLength.c: -------------------------------------------------------------------------------- 1 | // printLength.c 2 | // Chapter 5 3 | // Learn C Programming 4 | // 5 | // Program to print a length in given meters as well as 6 | // in feed (converted from meters). Consideration must be 7 | // given to values effectively 1.0 feet but which will never 8 | // be exactly 1.0 feet -- they'll be more like 1.0000000987 feet, 9 | // or 1.0 for any practical purpose. 10 | // We consider 1.0 feet within 4 significant digits. 11 | // 12 | // Compile with: 13 | // 14 | // cc printLength.c -o printLength -Wall -Werror -std=c11 15 | // 16 | 17 | 18 | #include 19 | 20 | void printLength( double meters ); 21 | 22 | int main( void ) { 23 | printLength( 0.0 ); 24 | printLength( 1.0 ); 25 | printLength( 12.0 / 39.67 ); 26 | printLength( 2.5 ); 27 | } 28 | 29 | void printLength( double meters ) { 30 | double feet = meters * 39.67 / 12.0; 31 | printf( "Length = %f meter%c\n" , 32 | meters, 33 | meters == 1.0 ? ' ' : 's' ); 34 | printf( "Length = %f %s\n\n" , 35 | feet, 36 | 0.99995 < feet && feet < 1.00005 ? "foot" : "feet" ); 37 | } 38 | -------------------------------------------------------------------------------- /Chapter05/truncRounding.c: -------------------------------------------------------------------------------- 1 | // truncRounding.c 2 | // Chapter 5 3 | // Learn C Programming 4 | // 5 | // Program to demonstrate implicit type conversions: 6 | // truncation and rounding to/from long int and from/to double. 7 | // 8 | // Compile with: 9 | // 10 | // cc truncRounding.c -o truncRounding -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | 16 | void doubleFunc( double dbl ); 17 | void longIntFunc( long int li ); 18 | 19 | int main( void ) 20 | { 21 | float floatValue = 58.73; 22 | short int intValue = 13; 23 | 24 | longIntFunc( intValue ); 25 | longIntFunc( floatValue ); // possible truncation 26 | 27 | doubleFunc( floatValue ); 28 | doubleFunc( intValue ); 29 | 30 | return 0; 31 | } 32 | 33 | void doubleFunc( double dbl ) 34 | { 35 | printf( "doubleFunc %.2f\n" , dbl ); 36 | } 37 | 38 | void longIntFunc( long int li ) 39 | { 40 | printf( "longIntFunc %ld\n" , li ); 41 | } 42 | 43 | // eof 44 | 45 | -------------------------------------------------------------------------------- /Chapter06/calc.c: -------------------------------------------------------------------------------- 1 | // calc.c 2 | // Chapter 6 3 | // Learn C Programming 4 | // 5 | // Build a simple calculator using a function with 6 | // a switch statement. 7 | // 8 | // Compile with: 9 | // 10 | // cc calc.c -o calc -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | #include 16 | 17 | 18 | double calc( double operand1, double operand2 , char operator ); 19 | 20 | 21 | int main( void ) 22 | { 23 | calc( 1.0 , 2.0 , '+' ); 24 | calc( 10.0 , 7.0 , '-' ); 25 | calc( 4.0 , 2.3 , '*' ); 26 | calc( 5.0 , 0.0 , '/' ); 27 | calc( 5.0 , 2.0 , '%' ); 28 | calc( 1.0 , 2.0 , '?' ); 29 | 30 | return 0; 31 | } 32 | 33 | 34 | double calc( double operand1 , double operand2 , char operator ) 35 | { 36 | double result = 0.0; 37 | 38 | printf( "%g %c %g = " , operand1 , operator , operand2 ); 39 | switch( operator ) 40 | { 41 | case '+': 42 | result = operand1 + operand2; 43 | break; 44 | case '-': 45 | result = operand1 - operand2; 46 | break; 47 | case '*': 48 | result = operand1 * operand2; 49 | break; 50 | case '/': 51 | if( operand2 == 0.0 ) 52 | { 53 | printf( "*** ERROR *** division by %g is undefined.\n" , operand2 ); 54 | return result; 55 | } else { 56 | result = operand1 / operand2; 57 | } 58 | break; 59 | case '%': 60 | // Remaindering: assume operations on integers (cast first). 61 | result = (int) operand1 % (int) operand2; 62 | break; 63 | default: 64 | printf( "*** ERROR *** unknown operator; operator must be + - * / or %%\n" ); 65 | return result; 66 | break; 67 | } 68 | printf( "%g\n" , result ); 69 | return result; 70 | } 71 | 72 | // eof 73 | 74 | -------------------------------------------------------------------------------- /Chapter06/leapYear1.c: -------------------------------------------------------------------------------- 1 | // leapYear1.c 2 | // Chapter 6 3 | // Learn C Programming 4 | // 5 | // Our first pass at a leap year program. 6 | // In this version, we use "fall through" logic 7 | // using return to end the evaluation. 8 | // 9 | // Compile with: 10 | // 11 | // cc leapYear1.c -o leapYear1 -Wall -Werror -std=c11 12 | // 13 | 14 | #include 15 | #include 16 | 17 | bool isLeapYear( int ); 18 | 19 | int main( void ) 20 | { 21 | int year; 22 | 23 | printf( "Determine if a year is a leap year or not.\n\n" ); 24 | printf( "Enter year: "); 25 | scanf( "%d" , &year ); 26 | 27 | // A simple version. 28 | // 29 | if( isLeapYear( year ) ) 30 | printf( "%d year is a leap year\n" , year ); 31 | else 32 | printf( "%d year is not a leap year \n" , year ); 33 | 34 | // A more C-like version. 35 | printf( "%d year is%sa leap year\n" , year , isLeapYear( year ) ? " " : " not " ); 36 | 37 | return 0; 38 | } 39 | 40 | bool isLeapYear( int year ) 41 | { 42 | // Leap years not part of Gregorian calendar until after 1752. 43 | // Is year before 1751? 44 | // Yes: return false. 45 | // No: "fall through" to next condition. 46 | // 47 | if( year < 1751 ) return false; 48 | 49 | // Is year an multiple of 4? (remainder will be 0) 50 | // Yes: return true. 51 | // No: "fall through" and return false. 52 | // 53 | if( (year % 4) == 0 ) return true; 54 | 55 | return false; 56 | } 57 | 58 | // eof 59 | -------------------------------------------------------------------------------- /Chapter06/leapYear2.c: -------------------------------------------------------------------------------- 1 | // leapYear2.c 2 | // Chapter 6 3 | // Learn C Programming 4 | // 5 | // Our second pass at a leap year program. 6 | // In this version, we use "if/else if/else" logic. 7 | // Note: in if/else logic, only one of each condition is 8 | // evaluated. Once the condition is met, execution 9 | // resumes at the end of the complex statement. 10 | // Compile with: 11 | // 12 | // cc leapYear2.c -o leapYear2 -Wall -Werror -std=c11 13 | // 14 | 15 | 16 | #include 17 | #include 18 | 19 | 20 | bool isLeapYear( int ); 21 | 22 | 23 | int main( void ) 24 | { 25 | int year; 26 | 27 | printf( "Determine if a year is a leap year or not.\n\n" ); 28 | printf( "Enter year: "); 29 | scanf( "%d" , &year ); 30 | 31 | // A more C-like version. 32 | printf( "%d year is%sa leap year\n" , year , isLeapYear( year ) ? " " : " not " ); 33 | 34 | return 0; 35 | } 36 | 37 | 38 | // isLeapYear logic conforms to algorithm given in 39 | // https://en.wikipedia.org/wiki/Leap_year. 40 | // 41 | bool isLeapYear( int year ) 42 | { 43 | bool isLeap = false; 44 | 45 | // Leap years not part of Gregorian calendar until after 1752. 46 | // 47 | if( year < 1751 ) // Is is before leap years known. 48 | isLeap = false; 49 | else if( (year % 4 ) != 0 ) // Year is not a multiple of 4. 50 | isLeap = false; 51 | else if( ( year % 400 ) == 0 ) // Year is a multiple of 400. 52 | isLeap = true; 53 | else if( (year % 100) == 0 ) // Year is multiple of 100. 54 | isLeap = false; 55 | else 56 | isLeap = true; // Year is a multiple of 4 (other conditions 400 years, 100 years) 57 | // already considered. 58 | return isLeap; 59 | } 60 | 61 | // eof 62 | -------------------------------------------------------------------------------- /Chapter06/leapYear3.c: -------------------------------------------------------------------------------- 1 | // leapYear3.c 2 | // Chapter 6 3 | // Learn C Programming 4 | // 5 | // Our third `pass at a leap year program. 6 | // In this version, we use nested if statements. 7 | // 8 | // Compile with: 9 | // 10 | // cc leapYear.c -o leapYear3 -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | #include 16 | 17 | 18 | bool isLeapYear( int ); 19 | 20 | 21 | int main( void ) 22 | { 23 | int year; 24 | 25 | printf( "Determine if a year is a leap year or not.\n\n" ); 26 | printf( "Enter year: "); 27 | scanf( "%d" , &year ); 28 | 29 | // A more C-like version. 30 | printf( "%d year is%sa leap year\n" , year , isLeapYear( year ) ? " " : " not " ); 31 | 32 | return 0; 33 | } 34 | 35 | 36 | bool isLeapYear( int year ) 37 | { 38 | bool isLeap = false; 39 | 40 | // Leap years not part of Gregorian calendar until after 1752. 41 | // 42 | if( year < 1751 ) // Is is before leap years known. 43 | isLeap = false; 44 | else if( (year % 4 ) != 0 ) // Year is not a multiple of 4. 45 | isLeap = false; 46 | else // Year is a multiple of 4. 47 | { 48 | if( (year % 400 ) == 0 ) 49 | isLeap = true; 50 | else if( (year % 100 ) == 0 ) 51 | isLeap = false; 52 | else 53 | isLeap = true; 54 | } 55 | return isLeap; 56 | } 57 | 58 | // eof 59 | -------------------------------------------------------------------------------- /Chapter06/temp.c: -------------------------------------------------------------------------------- 1 | // temp.c 2 | // Chapter 6 3 | // Learn C Programming 4 | // 5 | // Use multiple or chained if else statements to 6 | // convert from a range of values into a specific 7 | // message or unit. 8 | // 9 | // Compile with: 10 | // 11 | // cc temp.c -o temp -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | #include 17 | 18 | 19 | void describeTemp( double degreesF ); 20 | 21 | 22 | int main( void ) 23 | { 24 | describeTemp( 100.0 ); 25 | describeTemp( 85.0 ); 26 | describeTemp( 70.0 ); 27 | describeTemp( 55.0 ); 28 | describeTemp( 40.0 ); 29 | describeTemp( 25.0 ); 30 | describeTemp( 10.0 ); 31 | describeTemp( -5.0 ); 32 | return 0; 33 | } 34 | 35 | 36 | void describeTemp( double degreesF ) 37 | { 38 | char * message; 39 | 40 | if( degreesF >= 100.0 ) message = "hot! Stay in the shade."; 41 | else if( degreesF >= 80.0 ) message = "perfect weather for swimming."; 42 | else if( degreesF >= 60.0 ) message = "very comfortable."; 43 | else if( degreesF >= 40.0 ) message = "chilly."; 44 | else if( degreesF >= 20.0 ) message = "freezing, but good skiing weather."; 45 | else message = "way too cold to do much of anything!" ; 46 | printf( "%g°F is %s\n" , degreesF , message ); 47 | } 48 | 49 | // eof 50 | 51 | -------------------------------------------------------------------------------- /Chapter07/gauss_bruteforce.c: -------------------------------------------------------------------------------- 1 | // gauss_bruteforce.c 2 | // Chapter 7 3 | // Learn C Programming 4 | // 5 | // Demonstrate looping: 6 | // 1. A rather ugly brute-force method. 7 | // 2. A 2nd ugly brute-force method. 8 | // 3. Gauss's single line calculation. 9 | // 10 | // As you can see, we go from the ridiculous to the 11 | // sublime. 12 | // 13 | // Compile with: 14 | // 15 | // cc gauss_bruteforce.c -o gauss_bruteforce -Wall -Werror -std=c11 16 | // 17 | 18 | #include 19 | #include 20 | 21 | int sum100bruteForce( void ); 22 | int sum100bruteForce2( void ); 23 | int sumNviaGauss( int N ); 24 | 25 | int main( void ) 26 | { 27 | int n = 100; 28 | printf( "The sum of 1..100 = %d (via brute force)\n" , sum100bruteForce() ); 29 | printf( "The sum of 1..100 = %d (via brute force2)\n" , sum100bruteForce2() ); 30 | printf( "The sum of 1..%d = %d (via Gaussian insight)\n" , n , sumNviaGauss( n ) ); 31 | 32 | return 0; 33 | } 34 | 35 | 36 | int sum100bruteForce( void ) 37 | { 38 | int sum = 0; 39 | sum = 1; 40 | sum += 2; 41 | sum += 3; 42 | sum += 4; 43 | sum += 5; 44 | sum += 6; 45 | sum += 7; 46 | sum += 8; 47 | sum += 9; 48 | sum += 10; 49 | 50 | sum += 11; 51 | sum += 12; 52 | sum += 13; 53 | sum += 14; 54 | sum += 15; 55 | sum += 16; 56 | sum += 17; 57 | sum += 18; 58 | sum += 19; 59 | sum += 20; 60 | 61 | sum += 21; 62 | sum += 22; 63 | sum += 23; 64 | sum += 24; 65 | sum += 25; 66 | sum += 26; 67 | sum += 27; 68 | sum += 28; 69 | sum += 29; 70 | sum += 30; 71 | 72 | sum += 31; 73 | sum += 32; 74 | sum += 33; 75 | sum += 34; 76 | sum += 35; 77 | sum += 36; 78 | sum += 37; 79 | sum += 38; 80 | sum += 39; 81 | sum += 40; 82 | 83 | sum += 41; 84 | sum += 42; 85 | sum += 43; 86 | sum += 44; 87 | sum += 45; 88 | sum += 46; 89 | sum += 47; 90 | sum += 48; 91 | sum += 49; 92 | sum += 50; 93 | 94 | sum += 51; 95 | sum += 52; 96 | sum += 53; 97 | sum += 54; 98 | sum += 55; 99 | sum += 56; 100 | sum += 57; 101 | sum += 58; 102 | sum += 59; 103 | sum += 60; 104 | 105 | sum += 61; 106 | sum += 62; 107 | sum += 63; 108 | sum += 64; 109 | sum += 65; 110 | sum += 66; 111 | sum += 67; 112 | sum += 68; 113 | sum += 69; 114 | sum += 70; 115 | 116 | sum += 71; 117 | sum += 72; 118 | sum += 73; 119 | sum += 74; 120 | sum += 75; 121 | sum += 76; 122 | sum += 77; 123 | sum += 78; 124 | sum += 79; 125 | 126 | sum += 80; 127 | sum += 81; 128 | sum += 82; 129 | sum += 83; 130 | sum += 84; 131 | sum += 85; 132 | sum += 86; 133 | sum += 87; 134 | sum += 88; 135 | sum += 89; 136 | sum += 90; 137 | 138 | sum += 91; 139 | sum += 92; 140 | sum += 93; 141 | sum += 94; 142 | sum += 95; 143 | sum += 96; 144 | sum += 97; 145 | sum += 98; 146 | sum += 99; 147 | sum += 100; 148 | 149 | return sum; 150 | } 151 | 152 | 153 | int sum100bruteForce2( void ) 154 | { 155 | int sum = 0; 156 | int num = 1; 157 | sum = num; 158 | sum += ++num; 159 | sum += ++num; 160 | sum += ++num; 161 | sum += ++num; 162 | sum += ++num; 163 | sum += ++num; 164 | sum += ++num; 165 | sum += ++num; 166 | sum += ++num; // 10 167 | 168 | sum += ++num; 169 | sum += ++num; 170 | sum += ++num; 171 | sum += ++num; 172 | sum += ++num; 173 | sum += ++num; 174 | sum += ++num; 175 | sum += ++num; 176 | sum += ++num; 177 | sum += ++num; // 20 178 | 179 | sum += ++num; 180 | sum += ++num; 181 | sum += ++num; 182 | sum += ++num; 183 | sum += ++num; 184 | sum += ++num; 185 | sum += ++num; 186 | sum += ++num; 187 | sum += ++num; 188 | sum += ++num; // 30 189 | 190 | sum += ++num; 191 | sum += ++num; 192 | sum += ++num; 193 | sum += ++num; 194 | sum += ++num; 195 | sum += ++num; 196 | sum += ++num; 197 | sum += ++num; 198 | sum += ++num; 199 | sum += ++num; // 40 200 | 201 | sum += ++num; 202 | sum += ++num; 203 | sum += ++num; 204 | sum += ++num; 205 | sum += ++num; 206 | sum += ++num; 207 | sum += ++num; 208 | sum += ++num; 209 | sum += ++num; 210 | sum += ++num; // 50 211 | 212 | sum += ++num; 213 | sum += ++num; 214 | sum += ++num; 215 | sum += ++num; 216 | sum += ++num; 217 | sum += ++num; 218 | sum += ++num; 219 | sum += ++num; 220 | sum += ++num; 221 | sum += ++num; // 60 222 | 223 | sum += ++num; 224 | sum += ++num; 225 | sum += ++num; 226 | sum += ++num; 227 | sum += ++num; 228 | sum += ++num; 229 | sum += ++num; 230 | sum += ++num; 231 | sum += ++num; 232 | sum += ++num; // 70 233 | 234 | sum += ++num; 235 | sum += ++num; 236 | sum += ++num; 237 | sum += ++num; 238 | sum += ++num; 239 | sum += ++num; 240 | sum += ++num; 241 | sum += ++num; 242 | sum += ++num; 243 | sum += ++num; // 80 244 | 245 | sum += ++num; 246 | sum += ++num; 247 | sum += ++num; 248 | sum += ++num; 249 | sum += ++num; 250 | sum += ++num; 251 | sum += ++num; 252 | sum += ++num; 253 | sum += ++num; 254 | sum += ++num; // 90 255 | 256 | sum += ++num; 257 | sum += ++num; 258 | sum += ++num; 259 | sum += ++num; 260 | sum += ++num; 261 | sum += ++num; 262 | sum += ++num; 263 | sum += ++num; 264 | sum += ++num; 265 | sum += ++num; // 100 266 | 267 | return sum; 268 | } 269 | 270 | 271 | // The brilliant mathematician Gauss solved the tedious 272 | // "busy work" problem of adding the numbers 1 to 100 with the 273 | // following simple equation when he was in elementary school. 274 | // 275 | // See http://mathcentral.uregina.ca/QQ/database/QQ.02.06/jo1.html 276 | // and https://trans4mind.com/personal_development/mathematics/series/sumNaturalNumbers.htm 277 | // for delightful explanations. 278 | // 279 | int sumNviaGauss( int N ) 280 | { 281 | int sum = 0; 282 | sum = N * ( N+1 ) / 2; 283 | return sum; 284 | } 285 | 286 | 287 | // eof 288 | -------------------------------------------------------------------------------- /Chapter07/gauss_goto.c: -------------------------------------------------------------------------------- 1 | // gauss_goto.c 2 | // Chapter 7 3 | // Learn C Programming 4 | // 5 | // Demonstrate counter-controlled looping with goto 6 | // 1. Do ... while() goto loop 7 | // 2. While() ... goto loop 8 | // 3. For() ... goto loop 9 | // 10 | // For each goto loop function, the corresponding C statement function 11 | // is included for comparison. 12 | // 13 | // Compile with: 14 | // 15 | // cc gauss_goto.c -o gauss_goto -Wall -Werror -std=c11 16 | // 17 | 18 | #include 19 | #include 20 | 21 | int sumNviaWhile( int N ); 22 | int sumNviaGoto_While( int N ); 23 | 24 | int sumNviaDoWhile( int N ); 25 | int sumNviaGoto_Do( int N ); 26 | 27 | int sumNviaGoto_For( int N ); 28 | int sumNviaFor( int N ); 29 | 30 | 31 | int main( void ) 32 | { 33 | int n = 100; 34 | printf( "The sum of 1..%d = %d (via do-like goto loop)\n" , n , sumNviaGoto_Do( n ) ); 35 | printf( "The sum of 1..%d = %d (via while-like goto loop)\n" , n , sumNviaGoto_While( n ) ); 36 | printf( "The sum of 1..%d = %d (via for-like goto loop)\n" , n , sumNviaGoto_For( n ) ); 37 | 38 | return 0; 39 | } 40 | 41 | 42 | // ------------ DoWhile and Goto_Do 43 | 44 | int sumNviaDoWhile( int N ) 45 | { 46 | int sum = 0; 47 | int num = 0; 48 | 49 | do 50 | { 51 | sum += (num+1); // Off-by-one: shift 0..99 to 1..100. 52 | num++; 53 | } while ( num < N ); // num: 0..99 (100 is not less than 100). 54 | 55 | return sum; 56 | } 57 | 58 | 59 | int sumNviaGoto_Do( int N ) 60 | { 61 | int sum = 0; 62 | int num = 0; 63 | 64 | begin_loop: 65 | 66 | sum += (num+1); 67 | num++; 68 | 69 | if( num < N ) goto begin_loop; // loop! 70 | // else fall-through out of loop. 71 | 72 | end_loop: 73 | 74 | return sum; 75 | } 76 | 77 | 78 | // ------------ While and Goto_While 79 | 80 | int sumNviaWhile( int N ) 81 | { 82 | int sum = 0; 83 | int num = 0; 84 | 85 | while( num < N ) // num: 0..99 (100 is not less than 100) 86 | { 87 | sum += (num+1); // Off-by-one: shift 0..99 to 1..100. 88 | num++; 89 | } 90 | 91 | return sum; 92 | } 93 | 94 | 95 | int sumNviaGoto_While( int N ) 96 | { 97 | int sum = 0; 98 | int num = 0; 99 | 100 | begin_loop: 101 | 102 | if( !(num < N) ) goto end_loop; 103 | 104 | sum += (num+1); 105 | num++; 106 | 107 | goto begin_loop; 108 | 109 | end_loop: 110 | 111 | return sum; 112 | } 113 | 114 | 115 | // ------------ For and Goto_For 116 | 117 | int sumNviaFor( int N ) 118 | { 119 | int sum = 0; 120 | for( int num = 0 ; num < N ; num++ ) // num: 0..99 (it's a C thing) 121 | { 122 | sum += (num+1); // Off-by-one: shift 0..99 to 1..100. 123 | } 124 | return sum; 125 | } 126 | 127 | 128 | int sumNviaGoto_For( int N) 129 | { 130 | int sum = 0; 131 | int num = 0; 132 | 133 | int i = 0; // initialize counter 134 | 135 | begin_loop: 136 | 137 | if( !(i < N) ) goto end_loop; // test condition 138 | 139 | sum += (num+1); 140 | num++; 141 | 142 | i++; // counter increment 143 | goto begin_loop; 144 | 145 | end_loop: 146 | 147 | return sum; 148 | } 149 | 150 | 151 | // eof 152 | -------------------------------------------------------------------------------- /Chapter07/gauss_loops.c: -------------------------------------------------------------------------------- 1 | // gauss_loops.c 2 | // Chapter 7 3 | // Learn C Programming 4 | // 5 | // Demonstrate looping: 6 | // 1. Counter-controlled looping with while(). 7 | // 2. Counter-controlled looping with for(). 8 | // 3. Counter-controlled looping with do...while(). 9 | // 10 | // Compile with: 11 | // 12 | // cc gauss_loops.c -o gauss_loops -Wall -Werror -std=c11 13 | // 14 | 15 | 16 | #include 17 | #include 18 | 19 | 20 | int sumNviaFor( int n ); 21 | int sumNviaWhile( int n ); 22 | int sumNviaDoWhile( int n ); 23 | int sumNviaGoto( int n ); 24 | 25 | 26 | int main( void ) 27 | { 28 | int n = 100; 29 | 30 | printf( "The sum of 1..%d = %d (via while() ... loop)\n" , n , sumNviaWhile( n ) ); 31 | printf( "The sum of 1..%d = %d (via for() ... loop)\n" , n , sumNviaFor( n ) ); 32 | printf( "The sum of 1..%d = %d (via do...while() loop)\n" , n , sumNviaDoWhile( n ) ); 33 | 34 | return 0; 35 | } 36 | 37 | 38 | int sumNviaWhile( int N ) 39 | { 40 | int sum = 0; 41 | 42 | int num = 0; 43 | while( num < N ) // num: 0..99 (100 is not less than 100) 44 | { 45 | sum += (num+1); // Off-by-one: shift 0..99 to 1..100. 46 | num++; 47 | } 48 | 49 | return sum; 50 | } 51 | 52 | 53 | int sumNviaFor( int N ) 54 | { 55 | int sum = 0; 56 | 57 | for( int num = 0 ; num < N ; num++ ) // num: 0..99 (it's a C thing) 58 | { 59 | sum += (num+1); // Off-by-one: shift 0..99 to 1..100. 60 | } 61 | 62 | return sum; 63 | } 64 | 65 | 66 | int sumNviaDoWhile( int N ) 67 | { 68 | int sum = 0; 69 | 70 | int num = 0; 71 | do { 72 | sum += (num+1); // Off-by-one: shift 0..99 to 1..100. 73 | num++; 74 | } while ( num < N ); // num: 0..99 (100 is not less than 100). 75 | 76 | return sum; 77 | } 78 | 79 | 80 | // eof 81 | -------------------------------------------------------------------------------- /Chapter07/gauss_loops2.c: -------------------------------------------------------------------------------- 1 | // gauss_loops2.c 2 | // Chapter 7 3 | // Learn C Programming 4 | // 5 | // Demonstrate looping with: 6 | // 1. Counter-controlled looping with while()... C idioms. 7 | // 1. Counter-controlled looping with for()... C idioms 8 | // 3. Counter-controlled looping with do...while() C idioms. 9 | // 10 | // The purpose here is to show looping with idiomatic C styles. 11 | // The minimum of local variables are used; the input parameter 12 | // is used/altered as appropriate. 13 | // 14 | // Note how it can sometimes be clearer to count down rather 15 | // than up. Remember to be certain for your loop ranges! 16 | // 17 | // Compile with: 18 | // 19 | // cc gauss_loops2.c -o gauss_loops2 -Wall -Werror -std=c11 20 | // 21 | 22 | 23 | #include 24 | #include 25 | 26 | 27 | int sumNviaFor2( int N ); 28 | int sumNviaWhile2( int N ); 29 | int sumNviaDoWhile2( int N ); 30 | 31 | 32 | int main( void ) 33 | { 34 | int n = 100; 35 | 36 | printf( "The sum of 1..%d = %d (via while() ... loop 2)\n" , n , sumNviaWhile2( n ) ); 37 | printf( "The sum of 1..%d = %d (via for() ... loop 2)\n" , n , sumNviaFor2( n ) ); 38 | printf( "The sum of 1..%d = %d (via do...while() loop 2)\n" , n , sumNviaDoWhile2( n ) ); 39 | 40 | return 0; 41 | } 42 | 43 | 44 | // a more C-like While() ... loop 45 | // 46 | int sumNviaWhile2( int N ) 47 | { 48 | int sum = 0; 49 | 50 | while( N ) // N: N down to 1 (stops at 0). 51 | { 52 | sum += N; 53 | N--; 54 | } 55 | 56 | return sum; 57 | } 58 | 59 | 60 | // A more C-like For() ... loop. 61 | // 62 | // The for conditions are presented each on their own line. 63 | // This is not really useful when these statements are simple 64 | // but can be clearer as the for conditions get more complicated 65 | // with multiple indexs, multiple relations, and/or multiple counter 66 | // increments. 67 | // 68 | int sumNviaFor2( int N ) 69 | { 70 | int sum = 0; 71 | 72 | for( int i = N ; // range: 100..1 73 | i > 0 ; // stops at 1. 74 | i-- 75 | ) 76 | { 77 | sum += i; // No off-by-one. 78 | } 79 | 80 | return sum; 81 | } 82 | 83 | 84 | // a more C-like Do ... While() 85 | // 86 | int sumNviaDoWhile2( int N ) 87 | { 88 | int sum = 0; 89 | 90 | do { 91 | sum += N; 92 | N--; 93 | } while ( N ); // range: N down to 1 (stops at 0). 94 | 95 | return sum; 96 | } 97 | 98 | 99 | // eof 100 | -------------------------------------------------------------------------------- /Chapter07/primes.c: -------------------------------------------------------------------------------- 1 | // primes.c 2 | // Chapter 7 3 | // Learn C Programming 4 | // 5 | // Demonstrate "refined goto": 6 | // 1. break 7 | // 2. continue 8 | // 9 | // Compile with: 10 | // 11 | // cc primes.c -o primes -Wall -Werror -std=c11 12 | // 13 | 14 | #include 15 | #include 16 | 17 | bool isPrime( int num ); 18 | 19 | int sumPrimes( int num ); 20 | int sumNonPrimes( int num ); 21 | 22 | int main( void ) 23 | { 24 | for( int i = 1 ; i < 8 ; i++ ) 25 | printf( "%d => %sprime\n", i , isPrime( i ) ? "" : "not " ); 26 | printf("\n"); 27 | 28 | printf( "Sum of prime numbers 1..100 = %d\n" , sumPrimes( 100 ) ); 29 | printf( "Sum of non-prime numbers 1..100 = %d\n" , sumNonPrimes( 100 ) ); 30 | return 0; 31 | } 32 | 33 | 34 | bool isPrime( int num ) 35 | { 36 | if( num == 1 ) return false; 37 | if( num == 2 ) return true; 38 | 39 | bool isPrime = true; // Make initial assumption that num is prime. 40 | 41 | for( int i = 2 ; i < num ; i++ ) 42 | { 43 | if( (num % i) == 0 ) // We found a divisor of num; num is not prime. 44 | { 45 | isPrime = false; 46 | break; // No need to keep checking; leave the loop. 47 | } 48 | } 49 | return isPrime; 50 | } 51 | 52 | int sumPrimes( int num ) 53 | { 54 | int sum = 0; 55 | for( int i = 1 ; i < (num+1) ; i++ ) 56 | { 57 | if( !isPrime( i ) ) continue; 58 | printf( "%d " , i); 59 | sum += i; 60 | } 61 | printf("\n"); 62 | return sum; 63 | } 64 | 65 | int sumNonPrimes( int num ) 66 | { 67 | int sum = 0; 68 | for( int i = 1 ; i < (num+1) ; i++ ) 69 | { 70 | if( isPrime( i ) ) continue; 71 | printf( "%d " , i); 72 | sum += i; 73 | } 74 | printf("\n"); 75 | return sum; 76 | } 77 | 78 | // eof 79 | 80 | -------------------------------------------------------------------------------- /Chapter08/shapes.c: -------------------------------------------------------------------------------- 1 | 2 | // shapes.c 3 | // Chapter 8 4 | // Learn C Programming 5 | // 6 | // Demonstrate defining and using enumerated types with 7 | // the switch statement. 8 | // 9 | // Compile with: 10 | // 11 | // cc shapes.c -o shapes -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | 17 | const char* nameTriangle = "triangle"; 18 | const char* nameSquare = "square"; 19 | const char* nameRectangle = "rectangle"; 20 | const char* nameTrapezoid = "trapezoid"; 21 | const char* namePentagon = "pentagon"; 22 | const char* nameHexagon = "hexagon"; 23 | const char* nameOctagon = "octagon"; 24 | const char* nameCircle = "circle"; 25 | const char* nameUnknown = "unknown"; 26 | 27 | enum shape 28 | { 29 | triangle, 30 | square, 31 | rectangle, 32 | trapezoid, 33 | pentagon, 34 | hexagon, 35 | octagon, 36 | circle 37 | }; 38 | 39 | void PrintShapeInfo( enum shape aShape ); 40 | const char* GetShapeName( enum shape aShape ); 41 | 42 | 43 | int main( void ) 44 | { 45 | PrintShapeInfo( triangle ); 46 | PrintShapeInfo( square ); 47 | PrintShapeInfo( rectangle ); 48 | PrintShapeInfo( trapezoid ); 49 | PrintShapeInfo( pentagon ); 50 | PrintShapeInfo( hexagon ); 51 | PrintShapeInfo( octagon ); 52 | PrintShapeInfo( circle ); 53 | return 0; 54 | } 55 | 56 | 57 | void PrintShapeInfo( enum shape aShape) 58 | { 59 | int nSides = 0; 60 | switch( aShape ) 61 | { 62 | case triangle: 63 | nSides = 3; 64 | break; 65 | case square: 66 | case rectangle: 67 | case trapezoid: 68 | nSides = 4; 69 | break; 70 | case circle: 71 | printf( "A circle has an infinite number of sides\n" ); 72 | return; 73 | break; 74 | default: 75 | printf( "UNKNOWN SHAPE TYPE\n" ); 76 | return; 77 | break; 78 | } 79 | printf( "A %s has %d sides\n" , GetShapeName( aShape) , nSides ); 80 | } 81 | 82 | const char* GetShapeName( enum shape aShape) 83 | { 84 | const char * name; 85 | switch( aShape ) 86 | { 87 | case triangle: name = nameTriangle; break; 88 | case square: name = nameSquare; break; 89 | case rectangle: name = nameRectangle; break; 90 | case trapezoid: name = nameTrapezoid; break; 91 | case pentagon: name = namePentagon; break; 92 | case hexagon: name = nameHexagon; break; 93 | case octagon: name = nameOctagon; break; 94 | case circle: name = nameCircle; break; 95 | default: name = nameUnknown; break; 96 | } 97 | return name; 98 | } 99 | 100 | // eof 101 | 102 | -------------------------------------------------------------------------------- /Chapter08/shapes2.c: -------------------------------------------------------------------------------- 1 | 2 | // shapes2.c 3 | // Chapter 8 4 | // Learn C Programming 5 | // 6 | // Demonstrate defining and using enumerated types with 7 | // the switch statement. 8 | // 9 | // Added code to handle all shape types. 10 | // 11 | // Compile with: 12 | // 13 | // cc shapes2.c -o shapes2 -Wall -Werror -std=c11 14 | // 15 | 16 | 17 | #include 18 | 19 | const char* nameTriangle = "triangle"; 20 | const char* nameSquare = "square"; 21 | const char* nameRectangle = "rectangle"; 22 | const char* nameTrapezoid = "trapezoid"; 23 | const char* namePentagon = "pentagon"; 24 | const char* nameHexagon = "hexagon"; 25 | const char* nameOctagon = "octagon"; 26 | const char* nameCircle = "circle"; 27 | const char* nameUnknown = "unknown"; 28 | 29 | enum shape 30 | { 31 | triangle, 32 | square, 33 | rectangle, 34 | trapezoid, 35 | pentagon, 36 | hexagon, 37 | octagon, 38 | circle 39 | }; 40 | 41 | void PrintShapeInfo( enum shape aShape ); 42 | const char* GetShapeName( enum shape aShape ); 43 | 44 | 45 | int main( void ) 46 | { 47 | PrintShapeInfo( triangle ); 48 | PrintShapeInfo( square ); 49 | PrintShapeInfo( rectangle ); 50 | PrintShapeInfo( trapezoid ); 51 | PrintShapeInfo( pentagon ); 52 | PrintShapeInfo( hexagon ); 53 | PrintShapeInfo( octagon ); 54 | PrintShapeInfo( circle ); 55 | return 0; 56 | } 57 | 58 | 59 | void PrintShapeInfo( enum shape aShape) 60 | { 61 | int nSides = 0; 62 | switch( aShape ) 63 | { 64 | case triangle: 65 | nSides = 3; 66 | break; 67 | case square: 68 | case rectangle: 69 | case trapezoid: 70 | nSides = 4; 71 | break; 72 | case pentagon: 73 | nSides = 5; 74 | break; 75 | case hexagon: 76 | nSides = 6; 77 | break; 78 | case octagon: 79 | nSides = 8; 80 | break; 81 | case circle: 82 | printf( "A circle has an infinite number of sides\n" ); 83 | return; 84 | break; 85 | default: 86 | printf( "UNKNOWN SHAPE TYPE\n" ); 87 | return; 88 | break; 89 | } 90 | printf( "A %s has %d sides\n" , GetShapeName( aShape) , nSides ); 91 | } 92 | 93 | const char* GetShapeName( enum shape aShape) 94 | { 95 | const char * name; 96 | switch( aShape ) 97 | { 98 | case triangle: name = nameTriangle; break; 99 | case square: name = nameSquare; break; 100 | case rectangle: name = nameRectangle; break; 101 | case trapezoid: name = nameTrapezoid; break; 102 | case pentagon: name = namePentagon; break; 103 | case hexagon: name = nameHexagon; break; 104 | case octagon: name = nameOctagon; break; 105 | case circle: name = nameCircle; break; 106 | default: name = nameUnknown; break; 107 | } 108 | return name; 109 | } 110 | 111 | // eof 112 | 113 | -------------------------------------------------------------------------------- /Chapter09/card.c: -------------------------------------------------------------------------------- 1 | // card.c 2 | // Chapter 9 3 | // Learn C Programming 4 | // 5 | // Demonstrate defining and using structured types. 6 | // 7 | // Compile with: 8 | // 9 | // cc card.c -o card -Wall -Werror -std=c11 10 | // 11 | 12 | 13 | #include 14 | #include 15 | 16 | 17 | enum Suit 18 | { 19 | club = 1, 20 | diamond, 21 | heart, 22 | spade 23 | }; 24 | 25 | enum Face 26 | { 27 | one = 1, 28 | two, 29 | three, 30 | four, 31 | five, 32 | six, 33 | seven, 34 | eight, 35 | nine, 36 | ten, 37 | jack, 38 | queen, 39 | king, 40 | ace 41 | }; 42 | 43 | struct Card 44 | { 45 | enum Suit suit; 46 | int suitValue; 47 | enum Face face; 48 | int faceValue; 49 | double d; 50 | bool isWild; 51 | }; 52 | 53 | int main( void ) 54 | { 55 | struct Card card; 56 | 57 | printf( " enum Suit is %lu bytes\n" , sizeof( enum Suit ) ); 58 | printf( " enum Face is %lu bytes\n" , sizeof( enum Face ) ); 59 | printf( " int is %lu bytes\n" , sizeof( int ) ); 60 | printf( " bool is %lu bytes\n" , sizeof( bool ) ); 61 | 62 | printf( "struct Card is %lu bytes\n" , sizeof( struct Card ) ); 63 | printf( " card is %lu bytes\n" , sizeof( card ) ); 64 | 65 | return 0; 66 | } 67 | 68 | // eof 69 | -------------------------------------------------------------------------------- /Chapter09/card2.c: -------------------------------------------------------------------------------- 1 | // card2.c 2 | // Chapter 9 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to access components of structures 6 | // and perform operations on structures with functions. 7 | // 8 | // Compile with: 9 | // 10 | // cc card2.c -o card2 -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | #include 16 | 17 | 18 | enum Suit 19 | { 20 | club = 1, 21 | diamond, 22 | heart, 23 | spade 24 | }; 25 | 26 | 27 | enum Face 28 | { 29 | one = 1, 30 | two, 31 | three, 32 | four, 33 | five, 34 | six, 35 | seven, 36 | eight, 37 | nine, 38 | ten, 39 | jack, 40 | queen, 41 | king, 42 | ace 43 | }; 44 | 45 | 46 | struct Card 47 | { 48 | enum Suit suit; 49 | int suitValue; 50 | enum Face face; 51 | int faceValue; 52 | bool isWild; 53 | }; 54 | 55 | 56 | bool isEqual( struct Card c1 , struct Card c2 ); 57 | int sumCards( struct Card c1 , struct Card c2 ); 58 | 59 | 60 | int main( void ) 61 | { 62 | struct Card card1 = { heart , (int) heart , king, (int)king , false }; 63 | 64 | struct Card card2 = card1; // card 2 is now identical to card 1 65 | 66 | struct Card card3 = {0}; 67 | card3.suit = spade; 68 | card3.suitValue = (int)spade; 69 | card3.face = ace; 70 | card3.faceValue = (int)ace; 71 | card3.isWild = true; 72 | 73 | bool cardsEqual = isEqual( card1 , card2 ); 74 | printf( "card1 is%s equal to card2\n" , cardsEqual? "" : " not" ); 75 | 76 | cardsEqual = isEqual( card2 , card3 ); 77 | printf( "card2 is%s equal to card3\n" , cardsEqual? "" : " not" ); 78 | 79 | printf( "The combined faceValue of card2(%d) + card3(%d) is %d\n" , 80 | card2.faceValue , 81 | card3.faceValue , 82 | sumCards( card2 , card3 ) ); 83 | 84 | return 0; 85 | } 86 | 87 | 88 | bool isEqual( struct Card c1 , struct Card c2 ) 89 | { 90 | if( c1.suit != c2.suit ) return false; 91 | if( c1.face != c2.face ) return false; 92 | if( c1.isWild != c2.isWild ) return false; 93 | return true; 94 | } 95 | 96 | 97 | int sumCards( struct Card c1 , struct Card c2 ) 98 | { 99 | int faceValue = c1.faceValue + c2.faceValue; 100 | return faceValue; 101 | } 102 | 103 | // eof 104 | 105 | -------------------------------------------------------------------------------- /Chapter09/card3.c: -------------------------------------------------------------------------------- 1 | // card3.c 2 | // Chapter 9 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to create a structure whose 6 | // components are other structures and then how 7 | // to access those sub-components. 8 | // 9 | // Compile with: 10 | // 11 | // cc card3.c -o card3 -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | #include 17 | 18 | 19 | enum Suit 20 | { 21 | club = 1, 22 | diamond, 23 | heart, 24 | spade 25 | }; 26 | 27 | enum Face 28 | { 29 | one = 1, 30 | two, 31 | three, 32 | four, 33 | five, 34 | six, 35 | seven, 36 | eight, 37 | nine, 38 | ten, 39 | jack, 40 | queen, 41 | king, 42 | ace 43 | }; 44 | 45 | 46 | struct Card 47 | { 48 | enum Suit suit; 49 | int suitValue; 50 | enum Face face; 51 | int faceValue; 52 | bool isWild; 53 | }; 54 | 55 | 56 | struct Hand 57 | { 58 | int cardsDealt; 59 | struct Card c1, c2, c3, c4, c5; 60 | }; 61 | 62 | 63 | struct Hand addCard( struct Hand oldHand , struct Card card ); 64 | void printHand( struct Hand h ); 65 | void printHand2( struct Hand h ); 66 | void printCard( struct Card c ); 67 | 68 | 69 | int main( void ) 70 | { 71 | struct Hand h = {0}; 72 | 73 | struct Card c1 = { spade , (int)spade , ten , (int)ten , false }; 74 | struct Card c2 = { heart , (int)heart , queen , (int)queen , false }; 75 | struct Card c3 = { diamond , (int)diamond , five , (int)ten , false }; 76 | struct Card c4 = { club , (int)club , ace , (int)ace , false }; 77 | struct Card c5 = { heart , (int)heart , jack , (int)jack , false }; 78 | struct Card c6 = { club , (int)club , two , (int)two , false }; 79 | 80 | h = addCard( h , c1 ); 81 | h = addCard( h , c2 ); 82 | h = addCard( h , c3 ); 83 | h = addCard( h , c4 ); 84 | h = addCard( h , c5 ); 85 | h = addCard( h , c6 ); 86 | 87 | printHand( h ); 88 | printf("\n"); 89 | printHand2( h ); 90 | 91 | return 0; 92 | } 93 | 94 | 95 | struct Hand addCard( struct Hand oldHand , struct Card card ) 96 | { 97 | struct Hand newHand = oldHand; 98 | switch( newHand.cardsDealt ) 99 | { 100 | case 0: 101 | newHand.c1 = card; newHand.cardsDealt++; break; 102 | case 1: 103 | newHand.c2 = card; newHand.cardsDealt++; break; 104 | case 2: 105 | newHand.c3 = card; newHand.cardsDealt++; break; 106 | case 3: 107 | newHand.c4 = card; newHand.cardsDealt++; break; 108 | case 4: 109 | newHand.c5 = card; newHand.cardsDealt++; break; 110 | default: 111 | // Hand is full, what to do now? 112 | // ERROR --> Ignore new card. 113 | newHand = oldHand; 114 | break; 115 | } 116 | return newHand; 117 | } 118 | 119 | void printHand( struct Hand h ) 120 | { 121 | for( int i = 1; i < h.cardsDealt+1 ; i++ ) // 1..5 122 | { 123 | struct Card c; 124 | switch( i ) 125 | { 126 | case 1: c = h.c1; break; 127 | case 2: c = h.c2; break; 128 | case 3: c = h.c3; break; 129 | case 4: c = h.c4; break; 130 | case 5: c = h.c5; break; 131 | default: return; break; 132 | } 133 | printCard( c ); 134 | } 135 | } 136 | 137 | 138 | void printHand2( struct Hand h ) 139 | { 140 | int dealt = h.cardsDealt; 141 | if( dealt == 0 ) return; 142 | printCard( h.c1 ); if( dealt == 1 ) return; 143 | printCard( h.c2 ); if( dealt == 2 ) return; 144 | printCard( h.c3 ); if( dealt == 3 ) return; 145 | printCard( h.c4 ); if( dealt == 4 ) return; 146 | printCard( h.c5 ); return; 147 | } 148 | 149 | 150 | // yet another version of printHand 151 | // 152 | void printHand3( struct Hand h ) 153 | { 154 | for( int i = 1; i < h.cardsDealt+1 ; i++ ) // 1..5 155 | { 156 | switch( i ) 157 | { 158 | case 1: printCard( h.c1 ); break; 159 | case 2: printCard( h.c2 ); break; 160 | case 3: printCard( h.c3 ); break; 161 | case 4: printCard( h.c4 ); break; 162 | case 5: printCard( h.c5 ); break; 163 | default: return; break; 164 | } 165 | } 166 | } 167 | 168 | 169 | void printCard( struct Card c ) 170 | { 171 | switch( c.face ) 172 | { 173 | case two: printf( " 2 " ); break; 174 | case three: printf( " 3 " ); break; 175 | case four: printf( " 4 " ); break; 176 | case five: printf( " 5 " ); break; 177 | case six: printf( " 6 " ); break; 178 | case seven: printf( " 7 " ); break; 179 | case eight: printf( " 8 " ); break; 180 | case nine: printf( " 9 " ); break; 181 | case ten: printf( " 10 " ); break; 182 | case jack: printf( " Jack " ); break; 183 | case queen: printf( "Queen " ); break; 184 | case king: printf( " King " ); break; 185 | case ace: printf( " Ace " ); break; 186 | default: printf( " ??? " ); break; 187 | } 188 | switch( c.suit ) 189 | { 190 | case spade: printf( "of Spades\n"); break; 191 | case heart: printf( "of Hearts\n"); break; 192 | case diamond: printf( "of Diamonds\n"); break; 193 | case club: printf( "of Clubs\n"); break; 194 | default: printf( "of ???s\n"); break; 195 | } 196 | } 197 | 198 | // eof 199 | -------------------------------------------------------------------------------- /Chapter10/card.h: -------------------------------------------------------------------------------- 1 | // card.h 2 | // Chapter 10 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to create header file of 6 | // typedefs, custom types, and function prototypes. 7 | // 8 | 9 | 10 | typedef enum 11 | { 12 | club = 1, 13 | diamond, 14 | heart, 15 | spade 16 | } Suit; 17 | 18 | 19 | typedef enum 20 | { 21 | one = 1, 22 | two, 23 | three, 24 | four, 25 | five, 26 | six, 27 | seven, 28 | eight, 29 | nine, 30 | ten, 31 | jack, 32 | queen, 33 | king, 34 | ace 35 | } Face; 36 | 37 | 38 | typedef struct 39 | { 40 | Suit suit; 41 | int suitValue; 42 | Face face; 43 | int faceValue; 44 | bool isWild; 45 | } Card; 46 | 47 | 48 | typedef struct 49 | { 50 | int cardsDealt; 51 | Card c1, c2, c3, c4, c5; 52 | } Hand; 53 | 54 | 55 | Hand addCard( Hand oldHand , Card card ); 56 | void printHand( Hand h ); 57 | void printHand2( Hand h ); 58 | void printCard( Card c ); 59 | 60 | 61 | // eof 62 | -------------------------------------------------------------------------------- /Chapter10/card4.c: -------------------------------------------------------------------------------- 1 | // card4.c 2 | // Chapter 10 3 | // Learn C Programming 4 | // 5 | // Demonstrate the use of typedef for 6 | // enums and structs. 7 | // 8 | // Compile with: 9 | // 10 | // cc card4.c -o card4 -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | #include 16 | 17 | 18 | typedef enum 19 | { 20 | club = 1, 21 | diamond, 22 | heart, 23 | spade 24 | } Suit; 25 | 26 | typedef enum 27 | { 28 | one = 1, 29 | two, 30 | three, 31 | four, 32 | five, 33 | six, 34 | seven, 35 | eight, 36 | nine, 37 | ten, 38 | jack, 39 | queen, 40 | king, 41 | ace 42 | } Face; 43 | 44 | 45 | typedef struct 46 | { 47 | Suit suit; 48 | int suitValue; 49 | Face face; 50 | int faceValue; 51 | bool isWild; 52 | } Card; 53 | 54 | 55 | typedef struct 56 | { 57 | int cardsDealt; 58 | Card c1, c2, c3, c4, c5; 59 | } Hand; 60 | 61 | 62 | Hand addCard( Hand oldHand , Card card ); 63 | void printHand( Hand h ); 64 | void printHand2( Hand h ); 65 | void printCard( Card c ); 66 | 67 | 68 | int main( void ) 69 | { 70 | Hand h = {0}; 71 | 72 | Card c1 = { spade , (int)spade , ten , (int)ten , false }; 73 | Card c2 = { heart , (int)heart , queen , (int)queen , false }; 74 | Card c3 = { diamond , (int)diamond , five , (int)ten , false }; 75 | Card c4 = { club , (int)club , ace , (int)ace , false }; 76 | Card c5 = { heart , (int)heart , jack , (int)jack , false }; 77 | Card c6 = { club , (int)club , two , (int)two , false }; 78 | 79 | h = addCard( h , c1 ); 80 | h = addCard( h , c2 ); 81 | h = addCard( h , c3 ); 82 | h = addCard( h , c4 ); 83 | h = addCard( h , c5 ); 84 | h = addCard( h , c6 ); 85 | 86 | printHand( h ); 87 | printf("\n"); 88 | printHand2( h ); 89 | 90 | return 0; 91 | } 92 | 93 | 94 | Hand addCard( Hand oldHand , Card card ) 95 | { 96 | Hand newHand = oldHand; 97 | switch( newHand.cardsDealt ) 98 | { 99 | case 0: 100 | newHand.c1 = card; newHand.cardsDealt++; break; 101 | case 1: 102 | newHand.c2 = card; newHand.cardsDealt++; break; 103 | case 2: 104 | newHand.c3 = card; newHand.cardsDealt++; break; 105 | case 3: 106 | newHand.c4 = card; newHand.cardsDealt++; break; 107 | case 4: 108 | newHand.c5 = card; newHand.cardsDealt++; break; 109 | default: 110 | // Hand is full, what to do now? 111 | // ERROR --> Ignore new card. 112 | newHand = oldHand; 113 | break; 114 | } 115 | return newHand; 116 | } 117 | 118 | void printHand( Hand h ) 119 | { 120 | for( int i = 1; i < h.cardsDealt+1 ; i++ ) // 1..5 121 | { 122 | Card c; 123 | switch( i ) 124 | { 125 | case 1: c = h.c1; break; 126 | case 2: c = h.c2; break; 127 | case 3: c = h.c3; break; 128 | case 4: c = h.c4; break; 129 | case 5: c = h.c5; break; 130 | default: return; break; 131 | } 132 | printCard( c ); 133 | } 134 | } 135 | 136 | 137 | void printHand2( Hand h ) 138 | { 139 | int dealt = h.cardsDealt; 140 | if( dealt == 0 ) return; 141 | printCard( h.c1 ); if( dealt == 1 ) return; 142 | printCard( h.c2 ); if( dealt == 2 ) return; 143 | printCard( h.c3 ); if( dealt == 3 ) return; 144 | printCard( h.c4 ); if( dealt == 4 ) return; 145 | printCard( h.c5 ); return; 146 | } 147 | 148 | 149 | // yet another version of printHand 150 | // 151 | void printHand3( Hand h ) 152 | { 153 | for( int i = 1; i < h.cardsDealt+1 ; i++ ) // 1..5 154 | { 155 | switch( i ) 156 | { 157 | case 1: printCard( h.c1 ); break; 158 | case 2: printCard( h.c2 ); break; 159 | case 3: printCard( h.c3 ); break; 160 | case 4: printCard( h.c4 ); break; 161 | case 5: printCard( h.c5 ); break; 162 | default: return; break; 163 | } 164 | ; 165 | } 166 | } 167 | 168 | 169 | void printCard( Card c ) 170 | { 171 | switch( c.face ) 172 | { 173 | case two: printf( " 2 " ); break; 174 | case three: printf( " 3 " ); break; 175 | case four: printf( " 4 " ); break; 176 | case five: printf( " 5 " ); break; 177 | case six: printf( " 6 " ); break; 178 | case seven: printf( " 7 " ); break; 179 | case eight: printf( " 8 " ); break; 180 | case nine: printf( " 9 " ); break; 181 | case ten: printf( " 10 " ); break; 182 | case jack: printf( " Jack " ); break; 183 | case queen: printf( "Queen " ); break; 184 | case king: printf( " King " ); break; 185 | case ace: printf( " Ace " ); break; 186 | default: printf( " ??? " ); break; 187 | } 188 | switch( c.suit ) 189 | { 190 | case spade: printf( "of Spades\n"); break; 191 | case heart: printf( "of Hearts\n"); break; 192 | case diamond: printf( "of Diamonds\n"); break; 193 | case club: printf( "of Clubs\n"); break; 194 | default: printf( "of ???s\n"); break; 195 | } 196 | } 197 | 198 | // eof 199 | -------------------------------------------------------------------------------- /Chapter10/card5.c: -------------------------------------------------------------------------------- 1 | // card5.c 2 | // Chapter 10 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to create source file with its 6 | // own header file of typedefs, custom types, and 7 | // function prototypes. 8 | // 9 | // Depends upon: 10 | // 11 | // card.h 12 | // 13 | // Compile with: 14 | // 15 | // cc card5.c -o card5 -Wall -Werror -std=c11 16 | // 17 | 18 | 19 | #include 20 | #include 21 | 22 | #include "card.h" 23 | 24 | 25 | int main( void ) 26 | { 27 | Hand h = {0}; 28 | 29 | Card c1 = { spade , (int)spade , ten , (int)ten , false }; 30 | Card c2 = { heart , (int)heart , queen , (int)queen , false }; 31 | Card c3 = { diamond , (int)diamond , five , (int)ten , false }; 32 | Card c4 = { club , (int)club , ace , (int)ace , false }; 33 | Card c5 = { heart , (int)heart , jack , (int)jack , false }; 34 | Card c6 = { club , (int)club , two , (int)two , false }; 35 | 36 | h = addCard( h , c1 ); 37 | h = addCard( h , c2 ); 38 | h = addCard( h , c3 ); 39 | h = addCard( h , c4 ); 40 | h = addCard( h , c5 ); 41 | h = addCard( h , c6 ); 42 | 43 | printHand( h ); 44 | printf("\n"); 45 | printHand2( h ); 46 | 47 | return 0; 48 | } 49 | 50 | 51 | Hand addCard( Hand oldHand , Card card ) 52 | { 53 | Hand newHand = oldHand; 54 | switch( newHand.cardsDealt ) 55 | { 56 | case 0: 57 | newHand.c1 = card; newHand.cardsDealt++; break; 58 | case 1: 59 | newHand.c2 = card; newHand.cardsDealt++; break; 60 | case 2: 61 | newHand.c3 = card; newHand.cardsDealt++; break; 62 | case 3: 63 | newHand.c4 = card; newHand.cardsDealt++; break; 64 | case 4: 65 | newHand.c5 = card; newHand.cardsDealt++; break; 66 | default: 67 | // Hand is full, what to do now? 68 | // ERROR --> Ignore new card. 69 | newHand = oldHand; 70 | break; 71 | } 72 | return newHand; 73 | } 74 | 75 | void printHand( Hand h ) 76 | { 77 | for( int i = 1; i < h.cardsDealt+1 ; i++ ) // 1..5 78 | { 79 | Card c; 80 | switch( i ) 81 | { 82 | case 1: c = h.c1; break; 83 | case 2: c = h.c2; break; 84 | case 3: c = h.c3; break; 85 | case 4: c = h.c4; break; 86 | case 5: c = h.c5; break; 87 | default: return; break; 88 | } 89 | printCard( c ); 90 | } 91 | } 92 | 93 | 94 | void printHand2( Hand h ) 95 | { 96 | int dealt = h.cardsDealt; 97 | if( dealt == 0 ) return; 98 | printCard( h.c1 ); if( dealt == 1 ) return; 99 | printCard( h.c2 ); if( dealt == 2 ) return; 100 | printCard( h.c3 ); if( dealt == 3 ) return; 101 | printCard( h.c4 ); if( dealt == 4 ) return; 102 | printCard( h.c5 ); return; 103 | } 104 | 105 | 106 | // yet another version of printHand 107 | // 108 | void printHand3( Hand h ) 109 | { 110 | for( int i = 1; i < h.cardsDealt+1 ; i++ ) // 1..5 111 | { 112 | switch( i ) 113 | { 114 | case 1: printCard( h.c1 ); break; 115 | case 2: printCard( h.c2 ); break; 116 | case 3: printCard( h.c3 ); break; 117 | case 4: printCard( h.c4 ); break; 118 | case 5: printCard( h.c5 ); break; 119 | default: return; break; 120 | } 121 | ; 122 | } 123 | } 124 | 125 | 126 | void printCard( Card c ) 127 | { 128 | switch( c.face ) 129 | { 130 | case two: printf( " 2 " ); break; 131 | case three: printf( " 3 " ); break; 132 | case four: printf( " 4 " ); break; 133 | case five: printf( " 5 " ); break; 134 | case six: printf( " 6 " ); break; 135 | case seven: printf( " 7 " ); break; 136 | case eight: printf( " 8 " ); break; 137 | case nine: printf( " 9 " ); break; 138 | case ten: printf( " 10 " ); break; 139 | case jack: printf( " Jack " ); break; 140 | case queen: printf( "Queen " ); break; 141 | case king: printf( " King " ); break; 142 | case ace: printf( " Ace " ); break; 143 | default: printf( " ??? " ); break; 144 | } 145 | switch( c.suit ) 146 | { 147 | case spade: printf( "of Spades\n"); break; 148 | case heart: printf( "of Hearts\n"); break; 149 | case diamond: printf( "of Diamonds\n"); break; 150 | case club: printf( "of Clubs\n"); break; 151 | default: printf( "of ???s\n"); break; 152 | } 153 | } 154 | 155 | // eof 156 | -------------------------------------------------------------------------------- /Chapter11/array1.c: -------------------------------------------------------------------------------- 1 | // array1.c 2 | // Chapter 11 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to declare and initialize 6 | // arrays. 7 | // 8 | // Compile with: 9 | // 10 | // cc array1.c -o array1 -Wall -Werror -std=c11 11 | // 12 | 13 | #include 14 | 15 | 16 | int main( void ) 17 | { 18 | int anArray[10] = {0}; // Initialize the whole thing to 0. 19 | 20 | int typeSize = sizeof( int ); 21 | int arraySize = sizeof( anArray ); 22 | int elementNum = arraySize / typeSize; 23 | 24 | printf( " sizeof(int) = %2d bytes\n" , typeSize ); 25 | printf( " sizeof(anArray) = %2d bytes\n" , arraySize ); 26 | printf( " anArray[] has %d elements\n\n" , elementNum ); 27 | 28 | // Dynamically allocate array size via initialization. 29 | 30 | float lengthArray[] = { 1.0 , 2.0 , 3.0 , 4.0 , 3.0 , 2.0 , 1.0 }; 31 | 32 | typeSize = sizeof( float ); 33 | arraySize = sizeof( lengthArray ); 34 | elementNum = arraySize / typeSize; 35 | 36 | printf( " sizeof(float) = %2d bytes\n" , typeSize ); 37 | printf( " sizeof(lengthArray) = %2d bytes\n" , arraySize ); 38 | printf( " lengthArray[] has %d elements\n" , elementNum ); 39 | } 40 | 41 | // eof 42 | -------------------------------------------------------------------------------- /Chapter11/array2.c: -------------------------------------------------------------------------------- 1 | // array2.c 2 | // Chapter 11 3 | // Learn C Programming 4 | // 5 | // Demonstrate arroy bounds issues. 6 | // 7 | // Compile with: 8 | // 9 | // cc array2.c -o array2 -Wall -Werror -std=c11 10 | // 11 | 12 | 13 | #include 14 | 15 | 16 | int main( void ) { 17 | int anArray[10] = {0}; // Initialize the whole thing to 0. 18 | int x, y , z; 19 | x = 11; 20 | y = 12; 21 | z = 13; 22 | 23 | // anArray[ 11 ] = 7; // Compiler error! 24 | anArray[ x] = 0; // No compiler error, but runtime error! 25 | } 26 | 27 | // eof 28 | -------------------------------------------------------------------------------- /Chapter11/array3.c: -------------------------------------------------------------------------------- 1 | // array3.c 2 | // Chapter 11 3 | // Learn C Programming 4 | // 5 | // Demonstrate using arrays in functions and 6 | // as parameters to functions. 7 | // 8 | // Depends upon: 9 | // 10 | // array3.h 11 | // 12 | // Compile with: 13 | // 14 | // cc array3.c -o array3 -lm -Wall -Werror -std=c11 15 | // 16 | // NOTE -lm switch to include libm.a (math library corresponding to math.h) 17 | // may not be required for all compilers/environments. 18 | // 19 | 20 | #include 21 | #include 22 | 23 | #include "array3.h" 24 | 25 | 26 | int main( void ) 27 | { 28 | int array1[] = { 3 , 4 , 6 , 8, 13 , 17 , 18 , 19 }; 29 | int array2[] = { 34 , 88 , 32 , 12 , 10 }; 30 | 31 | int size = sizeof( array1 ) / sizeof( int ); 32 | printf( "array1: range, mean, & standard deviation\n" ); 33 | printf( " range = [%d..%d]\n" , 34 | findMin( size , array1 ) , 35 | findMax( size , array1 ) ); 36 | printf( " mean = %g\n" , findMean( size , array1 ) ); 37 | printf( " std dev = %g\n\n", findStdDev( size , array1 ) ); 38 | 39 | 40 | size = sizeof( array2 ) / sizeof( int ); 41 | printf( "array2: range, mean, & standard deviation\n" ); 42 | printf( " range = [%d..%d]\n" , 43 | findMin( size , array2 ) , 44 | findMax( size , array2 ) ); 45 | printf( " mean = %g\n" , findMean( size , array2 ) ); 46 | printf( " std dev = %g\n\n", findStdDev( size , array2 ) ); 47 | } 48 | 49 | 50 | int findMin( int size , int a[] ) 51 | { 52 | int min = a[0]; 53 | for( int i = 1 ; i < size ; i++ ) 54 | if( a[i] < min ) min = a[i]; 55 | return min; 56 | } 57 | 58 | 59 | int findMax( int size , int a[] ) 60 | { 61 | int max = a[0]; 62 | for( int i = 1 ; i < size ; i++ ) 63 | if( a[i] > max ) max = a[i]; 64 | return max; 65 | } 66 | 67 | 68 | double findMean( int size , int a[] ) 69 | { 70 | double sum = 0.0; 71 | for( int i = 0 ; i < size ; i++ ) 72 | { 73 | sum += a[i]; 74 | } 75 | double mean = sum / size; 76 | return mean; 77 | } 78 | 79 | 80 | double findStdDev( int size , int a[] ) 81 | { 82 | // Compute variance. 83 | 84 | double mean = findMean( size , a ); 85 | double sum = 0.0; 86 | double variance = 0.0; 87 | 88 | for( int i = 0; i < size ; i++ ) 89 | { 90 | sum += pow( (a[i] - mean) , 2 ); 91 | } 92 | variance = sum / size; 93 | 94 | // Compute standard deviation from variance. 95 | 96 | double stdDev = sqrt( variance ); 97 | return stdDev; 98 | } 99 | 100 | // eof 101 | 102 | -------------------------------------------------------------------------------- /Chapter11/array3.h: -------------------------------------------------------------------------------- 1 | // array3.h 2 | // Chapter 11 3 | // Learn C Programming 4 | // 5 | // Header file for array3.c 6 | // 7 | 8 | // function prototypes 9 | 10 | int findMin( int size , int a[] ); 11 | int findMax( int size , int a[] ); 12 | 13 | double findMean( int size , int a[] ); 14 | double findStdDev( int size , int a[] ); 15 | 16 | 17 | // eof 18 | 19 | -------------------------------------------------------------------------------- /Chapter12/arraysND.c: -------------------------------------------------------------------------------- 1 | // arraysND.c 2 | // Chapter 12 3 | // Learn C Programming 4 | // 5 | // ND stands for N-dimensions. 6 | // 7 | // Demonstrate how to declare, initialize, and 8 | // manipulate 2D and 3D arrays. 9 | // 10 | // Pretty printing functions included which add 11 | // row and column headings (as array offsets). 12 | // 13 | // Depends upon: 14 | // 15 | // arraysND.h 16 | // 17 | // Compile with: 18 | // 19 | // cc arraysND.c -o arraysND -Wall -Werror -std=c11 20 | // 21 | 22 | 23 | #include 24 | #include 25 | #include "arraysND.h" 26 | 27 | int main( void ) 28 | { 29 | const int size1D = 5; 30 | const int size2D = 4; 31 | const int size3D = 3; 32 | 33 | bool pretty = true; 34 | 35 | int array2D[size2D][size1D]; 36 | int array3D[size3D][size2D][size1D]; 37 | 38 | int total = 0; 39 | 40 | initialize2DArray( size2D , size1D , array2D ); 41 | if( !pretty ) print2DArray( size2D , size1D , array2D ); 42 | else prettyPrint2DArray( size2D , size1D , array2D ); 43 | total = sum2DArray( size2D , size1D , array2D ); 44 | printf( "Total for array2D is %d\n\n" , total ); 45 | 46 | initialize3DArray( size3D , size2D , size1D , array3D ); 47 | if( !pretty) print3DArray( size3D , size2D , size1D , array3D ); 48 | else prettyPrint3DArray( size3D , size2D , size1D , array3D ); 49 | total = sum3DArray( size3D , size2D , size1D , array3D ); 50 | printf( "Total for array3D is %d\n\n" , total ); 51 | 52 | } 53 | 54 | 55 | void initialize2DArray( int row , int col , int array[row][col] ) 56 | { 57 | for( int j = 0 ; j < row ; j++ ) // j : 0..(row-1) 58 | { 59 | for( int i = 0; i < col ; i++ ) // i : 0..(col-1) 60 | { 61 | array[j][i] = (10*(j+1)) + (i+1); 62 | // array[j][i] = (10*j) + i; 63 | } 64 | } 65 | } 66 | 67 | 68 | void initialize3DArray( int z , int y , int x , int array[z][y][x] ) 69 | { 70 | for( int k = 0 ; k < z ; k++ ) // k : 0..(z-1) 71 | { 72 | for( int j = 0 ; j < y ; j++ ) // j : 0..(y-1) 73 | { 74 | for( int i = 0; i < x ; i++ ) // i : 0..(x-1) 75 | { 76 | array[k][j][i] = (100*(k+1)) + (10*(j+1)) + (i+1); 77 | // array[k][j][i] = (100*k) + (10*j) + i; 78 | } 79 | } 80 | } 81 | } 82 | 83 | 84 | void print2DArray( int row , int col , int array[row][col] ) 85 | { 86 | for( int j = 0 ; j < row ; j++ ) // j : 0..(row-1) 87 | { 88 | for( int i = 0; i < col ; i++ ) // i : 0..(col-1) 89 | { 90 | printf("%4d" , array[j][i]); 91 | } 92 | printf("\n"); 93 | } 94 | printf("\n"); 95 | } 96 | 97 | 98 | void prettyPrint2DArray( int row , int col , int array[row][col] ) 99 | { 100 | // Print column offsets as heading. 101 | printf(" "); 102 | for( int i = 0; i < col ; i++) printf(" [%1d]", i); 103 | printf("\n"); 104 | 105 | for( int j = 0 ; j < row ; j++ ) // j : 0..(row-1) 106 | { 107 | // Print row offset as lead-in. 108 | printf("[%1d]", j); 109 | 110 | for( int i = 0; i < col ; i++ ) // i : 0..(col-1) 111 | { 112 | printf("%4d" , array[j][i]); 113 | } 114 | printf("\n"); 115 | } 116 | printf("\n"); 117 | } 118 | 119 | 120 | void print3DArray( int z , int y , int x , int array[z][y][x] ) 121 | { 122 | for( int k = 0 ; k < z ; k++ ) // k : 0..(z-1) 123 | { 124 | for( int j = 0 ; j < y ; j++ ) // j : 0..(y-1) 125 | { 126 | for( int i = 0; i < x ; i++ ) // i : 0..(x-1) 127 | { 128 | printf("%4d" , array[k][j][i]); 129 | } 130 | printf("\n"); 131 | } 132 | printf("\n"); 133 | } 134 | } 135 | 136 | 137 | void prettyPrint3DArray( int z , int y , int x , int array[z][y][x] ) 138 | { 139 | for( int k = 0 ; k < z ; k++ ) // k : 0..(z-1) 140 | { 141 | // Print z offset as lead-in. 142 | printf("[%1d]", k ); 143 | // Print x offset as heading. 144 | printf(" "); 145 | for( int i = 0; i < x ; i++) printf(" [%1d]", i); 146 | printf("\n"); 147 | 148 | for( int j = 0 ; j < y ; j++ ) // j : 0..(y-1) 149 | { 150 | // Print y offset as lead-in. 151 | printf(" [%1d]", j); 152 | for( int i = 0; i < x ; i++ ) // i : 0..(x-1) 153 | { 154 | printf("%4d" , array[k][j][i]); 155 | } 156 | printf("\n"); 157 | } 158 | printf("\n"); 159 | } 160 | } 161 | 162 | 163 | int sum2DArray( int row , int col , int array[row][col] ) 164 | { 165 | int sum = 0; 166 | for( int j = 0 ; j < row ; j++ ) // j : 0..(row-1) 167 | { 168 | for( int i = 0; i < col ; i++ ) // i : 0..(col-1) 169 | { 170 | sum += array[j][i]; 171 | } 172 | } 173 | return sum; 174 | } 175 | 176 | 177 | int sum3DArray( int z , int y , int x , int array[z][y][x] ) 178 | { 179 | int sum = 0; 180 | for( int k = 0 ; k < z ; k++ ) // k : 0..(z-1) 181 | { 182 | for( int j = 0 ; j < y ; j++ ) // j : 0..(y-1) 183 | { 184 | for( int i = 0; i < x ; i++ ) // i : 0..(x-1) 185 | { 186 | sum += array[k][j][i]; 187 | } 188 | } 189 | } 190 | return sum; 191 | } 192 | 193 | 194 | // eof 195 | -------------------------------------------------------------------------------- /Chapter12/arraysND.h: -------------------------------------------------------------------------------- 1 | // arraysND.h 2 | // Chapter 12 3 | // Learn C Programming 4 | // 5 | // Header file for arraysND.c 6 | // 7 | 8 | 9 | // Function prototypes. 10 | 11 | void initialize2DArray( int row , int col , int array[row][col] ); 12 | void print2DArray( int row , int col , int array[row][col] ); 13 | void prettyPrint2DArray( int row , int col , int array[row][col] ); 14 | int sum2DArray( int row , int col , int array[row][col] ); 15 | 16 | void initialize3DArray( int z , int y , int x , int array[z][y][x] ); 17 | void print3DArray( int z , int y , int x , int array[z][y][x] ); 18 | void prettyPrint3DArray( int z , int y , int x , int array[z][y][x] ); 19 | int sum3DArray( int z , int y , int x , int array[z][y][x] ); 20 | 21 | // eof 22 | -------------------------------------------------------------------------------- /Chapter13/pointers1.c: -------------------------------------------------------------------------------- 1 | // pointers1.c 2 | // Chapter 13 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) declare a pointer to int 7 | // 2) get info about the pointer (its address, size) 8 | // 3) assign targets to the pointer 9 | // 4) print out info about the targets. 10 | // 11 | // Compile with: 12 | // 13 | // cc pointers1.c -o pointers1 -Wall -Werror -std=c11 14 | // 15 | 16 | #include 17 | 18 | int main( void ) 19 | { 20 | 21 | int height = 10; 22 | int width = 20; 23 | int length = 40; 24 | 25 | int* pDimension = NULL; 26 | 27 | printf( "\nValues:\n\n"); 28 | 29 | printf( " sizeof(int) = %2lu\n" , sizeof(int) ); 30 | printf( " sizeof(int*) = %2lu\n" , sizeof(int*) ); 31 | printf( " [height, width, length] = [%2d,%2d,%2d]\n\n" , 32 | height , width , length ); 33 | printf( " address of pDimension = %#lx\n" , 34 | (unsigned long)&pDimension ); 35 | 36 | printf( "\nUsing address of each named variables...\n\n"); 37 | 38 | pDimension = &height; 39 | printf( " address of height = %#lx, value at address = %2d\n" , 40 | (unsigned long)pDimension , *pDimension ); 41 | pDimension = &width; 42 | printf( " address of width = %#lx, value at address = %2d\n" , 43 | (unsigned long)pDimension , *pDimension ); 44 | pDimension = &length; 45 | printf( " address of length = %#lx, value at address = %2d\n" , 46 | (unsigned long)pDimension , *pDimension ); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /Chapter13/pointers2.c: -------------------------------------------------------------------------------- 1 | // pointers2.c 2 | // Chapter 13 3 | // Learn C Programming 4 | // 5 | // This program builds upon program pointers1.c 6 | // 7 | // Demonstrates how to use pointers in functions (parameters 8 | // and in function body). Also shows what "side effects" are. 9 | // 10 | // Specifically 11 | // 1) clean up printf() statements by moving them out of 12 | // main() and into functions. 13 | // 2) use pointers in fuction parameters 14 | // (copy the pointer value instead of copying the target value) 15 | // 3) use the function pointers to access targets 16 | // 4) demonstrate "side effects" by changing value of targets 17 | // (this changes them outside of the function) 18 | // 4) call the new functions with pointer variables. 19 | // 20 | // Compile with: 21 | // 22 | // cc pointers2.c -o pointers2 -Wall -Werror -std=c11 23 | // 24 | 25 | #include 26 | 27 | void showInfo( int height, int width , int length ) 28 | { 29 | printf( " sizeof(int) = %2lu\n" , sizeof(int) ); 30 | printf( " sizeof(int*) = %2lu\n" , sizeof(int*) ); 31 | printf( " [height, width, length] = [%2d,%2d,%2d]\n\n" , 32 | height , width , length ); 33 | } 34 | 35 | 36 | void showVariable( char* pId , int* pDim ) 37 | { 38 | printf( " address of %s = %#lx, value at address = %2d\n" , 39 | pId, 40 | (unsigned long)pDim , 41 | *pDim ); 42 | } 43 | 44 | int main( void ) 45 | { 46 | int height = 10; 47 | int width = 20; 48 | int length = 40; 49 | 50 | int* pDimension = NULL; 51 | char* pIdentifier = NULL; 52 | 53 | printf( "\nValues:\n\n"); 54 | 55 | showInfo( height , width , length ); 56 | 57 | printf( " address of pDimension = %#lx\n" , 58 | (unsigned long)&pDimension ); 59 | 60 | printf( "\nUsing address of each named variables...\n\n"); 61 | 62 | pIdentifier = "height"; 63 | pDimension = &height; 64 | showVariable( pIdentifier , pDimension ); 65 | pIdentifier = "width "; 66 | pDimension = &width; 67 | showVariable( pIdentifier , pDimension ); 68 | pIdentifier = "height"; 69 | pDimension = &length; 70 | showVariable( pIdentifier , pDimension ); 71 | } 72 | 73 | // eof 74 | 75 | -------------------------------------------------------------------------------- /Chapter13/pointers3.c: -------------------------------------------------------------------------------- 1 | // pointers3.c 2 | // Chapter 13 3 | // Learn C Programming 4 | // 5 | // This program builds on program pointers2.c 6 | // 7 | // Demonstrates how to use target addresses without 8 | // pointer variables. 9 | // 10 | // Specifically 11 | // 1) removes the pointer variables in main() 12 | // 2) call function with references w/o pointer variables. 13 | // 14 | // Compile with: 15 | // 16 | // cc pointers3.c -o pointers3 -Wall -Werror -std=c11 17 | // 18 | 19 | #include 20 | 21 | void showInfo( int height, int width , int length ) 22 | { 23 | printf( " sizeof(int) = %2lu\n" , sizeof(int) ); 24 | printf( " sizeof(int*) = %2lu\n" , sizeof(int*) ); 25 | printf( " [height, width, length] = [%2d,%2d,%2d]\n\n" , 26 | height , width , length ); 27 | } 28 | 29 | 30 | void showVariable( char* pId , int* pDim ) 31 | { 32 | printf( " address of %s = %#lx, value at address = %2d\n" , 33 | pId, 34 | (unsigned long)pDim , 35 | *pDim ); 36 | } 37 | 38 | int main( void ) 39 | { 40 | int height = 10; 41 | int width = 20; 42 | int length = 40; 43 | 44 | printf( "\nValues:\n\n"); 45 | 46 | showInfo( height , width , length ); 47 | 48 | printf( "\nUsing address of each named variables...\n\n"); 49 | 50 | showVariable( "height" , &height ); 51 | showVariable( "width " , &width ); 52 | showVariable( "length" , &length ); 53 | } 54 | 55 | // eof 56 | 57 | -------------------------------------------------------------------------------- /Chapter13/pointers4.c: -------------------------------------------------------------------------------- 1 | // pointers4.c 2 | // Chapter 13 3 | // Learn C Programming 4 | // 5 | // This program builds on program pointers2.c 6 | // and demonstrates double indirection in a function 7 | // parameter. 8 | // 9 | // Specifically 10 | // 1) modifies showInfo() to pass a pointer to a pointer 11 | // (double indirection) so the address of pDimension 12 | // can be properly accessed in the function. 13 | // 14 | // Compile with: 15 | // 16 | // cc pointers4.c -o pointers4 -Wall -Werror -std=c11 17 | // 18 | 19 | #include 20 | 21 | void showInfo( int height, int width , int length , int** ppDim ) 22 | { 23 | printf( " sizeof(int) = %2lu\n" , sizeof(int) ); 24 | printf( " sizeof(int*) = %2lu\n" , sizeof(int*) ); 25 | printf( " [height, width, length] = [%2d,%2d,%2d]\n\n" , 26 | height , width , length ); 27 | printf( " address of pDimension = %#lx\n" , 28 | (unsigned long)ppDim ); 29 | } 30 | 31 | 32 | void showVariable( char* pId , int* pDim ) 33 | { 34 | printf( " address of %s = %#lx, value at address = %2d\n" , 35 | pId, 36 | (unsigned long)pDim , 37 | *pDim ); 38 | } 39 | 40 | int main( void ) 41 | { 42 | int height = 10; 43 | int width = 20; 44 | int length = 40; 45 | 46 | int* pDimension = NULL; 47 | int** ppDimension = &pDimension; 48 | char* pIdentifier = NULL; 49 | 50 | printf( "\nValues:\n\n"); 51 | 52 | showInfo( height , width , length , ppDimension ); 53 | 54 | printf( "\nUsing address of each named variables...\n\n"); 55 | 56 | pIdentifier = "height"; 57 | pDimension = &height; 58 | showVariable( pIdentifier , pDimension ); 59 | pIdentifier = "width "; 60 | pDimension = &width; 61 | showVariable( pIdentifier , pDimension ); 62 | pIdentifier = "height"; 63 | pDimension = &length; 64 | showVariable( pIdentifier , pDimension ); 65 | } 66 | 67 | // eof 68 | -------------------------------------------------------------------------------- /Chapter14/arrayOfPointers.c: -------------------------------------------------------------------------------- 1 | // arrayOfPointers.c 2 | // Chapter 14 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) an array name is interchangeable with a pointer to the same address 7 | // 2) get info about the pointers and their values 8 | // 3) traverse the array using 3 methods: 9 | // a) using array notation incrementing index; 10 | // b) using pointer plus offset (pointer doesn't change); and 11 | // c) using incremented pointer (pointer changes). 12 | // 13 | // compile with: 14 | // 15 | // cc arrayOfPointers.c -o arrayOfPointers -Wall -Werror -std=c11 16 | // 17 | 18 | #include 19 | 20 | int main( void) 21 | { 22 | // Set everything up. 23 | 24 | // Standard 2D array. 25 | 26 | int arrayStd[3][5] = { { 11 , 12 , 13 , 14 , 15 } , 27 | { 21 , 22 , 23 , 24 , 25 } , 28 | { 31 , 32 , 33 , 34 , 35 } }; 29 | 30 | // Array of pointers. 31 | 32 | int* arrayPtr[3] = { NULL }; 33 | 34 | // Array sizes and pointer for pointer traversal. 35 | 36 | const int rows = 3; 37 | const int cols = 5; 38 | 39 | int* pInteger; 40 | 41 | // Sub-arrays. 42 | 43 | int array1[5] = { 11 , 12 , 13 , 14 , 15 }; 44 | int array2[5] = { 21 , 22 , 23 , 24 , 25 }; 45 | int array3[5] = { 31 , 32 , 33 , 34 , 35 }; 46 | 47 | arrayPtr[0] = array1; 48 | arrayPtr[1] = array2; 49 | arrayPtr[2] = array3; 50 | 51 | // Do traversals. 52 | 53 | printf( "Print both arrays using array notation, array[i][j].\n\n"); 54 | 55 | for( int i = 0 ; i < rows ; i++ ) 56 | { 57 | for( int j = 0 ; j < cols ; j++ ) 58 | { 59 | printf( " %2d" , arrayStd[i][j]); 60 | } 61 | printf( "\n" ); 62 | } 63 | printf("\n"); 64 | 65 | for( int i = 0 ; i < rows ; i++ ) 66 | { 67 | for( int j = 0 ; j < cols ; j++ ) 68 | { 69 | printf( " %2d" , arrayPtr[i][j]); 70 | } 71 | printf( "\n" ); 72 | } 73 | printf("\n"); 74 | 75 | 76 | printf( "Print both arrays using pointers, *pInteger++.\n\n"); 77 | 78 | pInteger = &(arrayStd[0][0]); 79 | for( int i = 0 ; i < rows ; i++ ) 80 | { 81 | for( int j = 0 ; j < cols ; j++ ) 82 | { 83 | printf( " %2d" , *pInteger++); 84 | } 85 | printf( "\n" ); 86 | } 87 | printf("\n"); 88 | 89 | // This line is here if you camment out "pInteger = arrayPtr[j];", below. 90 | // Otherwise, pInteger is reassigned with that statement and this one has no effect. 91 | 92 | pInteger = arrayPtr[0]; 93 | 94 | for( int i = 0 ; i < rows ; i++ ) 95 | { 96 | // pInteger = arrayPtr[i]; // Get the pointer to the correct sub-array. 97 | 98 | for( int j = 0 ; j < cols ; j++ ) 99 | { 100 | printf( " %2d" , *pInteger++); 101 | } 102 | printf( "\n" ); 103 | } 104 | printf("\n"); 105 | 106 | // Bonus: 107 | // 108 | // Traversing 2D array as a single array of row*col elements. 109 | // 110 | // printf("Because arrayStd is a contiguous block, we could also traverse\n"); 111 | // printf("it as if it was a 3x5, or 15-element, 1D array.\n\n"); 112 | // 113 | // pInteger = &(arrayStd[0][0]); 114 | // for( int i = 0 ; i < (rows*cols) ; i++) 115 | // { 116 | // printf( " %2d" , *pInteger++); 117 | // if( i%5 == 4 ) printf("\n"); 118 | // } 119 | // printf("\n"); 120 | 121 | } 122 | 123 | // eof 124 | -------------------------------------------------------------------------------- /Chapter14/arrays_pointers.c: -------------------------------------------------------------------------------- 1 | // arrays_pointers.c 2 | // Chapter 14 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) an array name is interchangeable with a pointer to the same address 7 | // 2) get info about the pointers and their values 8 | // 3) traverse the array using 3 methods: 9 | // a) using array notation incrementing index; 10 | // b) using pointer plus offset (pointer doesn't change); and 11 | // c) using incremented pointer (pointer changes). 12 | // 13 | // Compile with: 14 | // 15 | // cc arrays_pointers.c -o arrays_pointers -Wall -Werror -std=c11 16 | // 17 | 18 | #include 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | const int arraySize = 5; 23 | int array[5] = { 1 , 2 , 3 , 4 , 5 }; 24 | int* pArray1 = array; 25 | int* pArray2 = &(array[0]); 26 | 27 | printf("Pointer values (addresses) from initial assignments:\n\n"); 28 | 29 | printf( " address of array = %#lx, value at array = %d\n" , 30 | (unsigned long)array , 31 | *array ); 32 | printf( " address of &array[0] = %#lx, value at array[0] = %d\n" , 33 | (unsigned long)&array[0] , 34 | array[0] ); 35 | printf( " address of pArray1 = %#lx, value at pArray1 = %#lx\n" , 36 | (unsigned long)&pArray1 , 37 | (unsigned long) pArray1 ); 38 | printf( " address of pArray2 = %#lx, value at pArray2 = %#lx\n\n" , 39 | (unsigned long)&pArray2 , 40 | (unsigned long) pArray2 ); 41 | 42 | printf("\n(1) Array values using array notation (index is incremented):\n\n"); 43 | 44 | for( int i = 0; i < arraySize ; i++ ) 45 | printf( " &(array[%1d]) = %#lx, array[%1d] = %1d, i++\n", 46 | i , 47 | (unsigned long)&(array[i]), 48 | i , 49 | array[i] ); 50 | 51 | printf("\n(2) Array values using a pointer addition (offset is incremented):\n\n"); 52 | 53 | for( int i = 0 ; i < arraySize; i++ ) 54 | printf( " pArray2+%1d = %#lx, *(pArray2+%1d) = %1d, i++\n", 55 | i , (unsigned long)(pArray2+i) , 56 | i , *(pArray2+i) ); 57 | 58 | printf("\n(3) Array values using pointer referencing (pointer is incremented):\n\n"); 59 | 60 | for( int i = 0 ; i < arraySize ; i++ , pArray1++ ) 61 | printf( " pArray1 = %#lx, *pArray1 = %1d, pArray1++\n", 62 | (unsigned long)pArray1 , 63 | *pArray1 ); 64 | } 65 | 66 | /* eof */ 67 | -------------------------------------------------------------------------------- /Chapter14/arrays_pointers_funcs.c: -------------------------------------------------------------------------------- 1 | // arrays_pointers_funcs.c 2 | // Chapter 14 3 | // Learn C Programming 4 | // 5 | // This is a copy of arrays_pointers.c which spefically demonstrate how to 6 | // traverse the array using the array as a function parameter using 2 methods: 7 | // a) a function with the array name using array notation; 8 | // b) a function with a pointer to 1st element using pointer arithmetic; 9 | // c) a function with the array name using pointer arithmetic; and 10 | // d) a function with a pointer to 1st element using array notation; 11 | // 12 | // compile with: 13 | // 14 | // cc arrays_pointers_funcs.c -o arrays_pointers_funcs -Wall -Werror -std=c11 15 | // 16 | 17 | #include 18 | 19 | void traverse1( int size , int arr[] ); 20 | void traverse2( int size , int* pArr ); 21 | void traverse3( int size , int arr[] ); 22 | void traverse4( int size , int* pArr ); 23 | 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | const int arraySize = 5; 28 | int array[5] = { 10 , 20 , 30 , 40 , 50 }; 29 | 30 | printf("Pointer values (addresses) from initial assignments:\n\n"); 31 | 32 | printf( " address of array = %#lx, value at array = %d\n" , 33 | (unsigned long)array , 34 | *array ); 35 | printf( " address of &array[0] = %#lx, value at array[0] = %d\n" , 36 | (unsigned long)&array[0] , 37 | array[0] ); 38 | 39 | traverse1( arraySize , array ); 40 | traverse2( arraySize , array ); 41 | traverse3( arraySize , array ); 42 | traverse4( arraySize , array ); 43 | } 44 | 45 | // see printf() for function purpose. 46 | // 47 | void traverse1( int size , int arr[] ) 48 | { 49 | printf("\n(1) Function parameter is an array, using array notation:\n\n"); 50 | 51 | for( int i = 0; i < size ; i++ ) 52 | printf( " &(array[%1d]) = %#lx, array[%1d] = %1d, i++\n", 53 | i , 54 | (unsigned long)&(arr[i]), 55 | i , 56 | arr[i] ); 57 | } 58 | 59 | 60 | // see printf() for function purpose. 61 | // 62 | void traverse2( int size , int* pArr ) 63 | { 64 | printf("\n(2) Function parameter is a pointer, using pointer:\n\n"); 65 | 66 | for( int i = 0 ; i < size ; i++ , pArr++ ) 67 | printf( " pArr = %#lx, *pArr = %1d, pArr++\n", 68 | (unsigned long)pArr , 69 | *pArr ); 70 | } 71 | 72 | 73 | // see printf() for function purpose. 74 | // 75 | void traverse3( int size , int arr[] ) 76 | { 77 | printf("\n(3) Function parameter is an array, using pointer:\n\n"); 78 | 79 | for( int i = 0 ; i < size ; i++ , arr++ ) 80 | printf( " arr = %#lx, *arr = %1d, arr++\n", 81 | (unsigned long)arr , 82 | *arr ); 83 | } 84 | 85 | 86 | // see printf() for function purpose. 87 | // 88 | void traverse4( int size , int* pArr ) 89 | { 90 | printf("\n(4) Function parameter is a pointer, using array notation :\n\n"); 91 | 92 | for( int i = 0; i < size ; i++ ) 93 | printf( " &(pArr[%1d]) = %#lx, pArr[%1d] = %1d, i++\n", 94 | i , 95 | (unsigned long)&(pArr[i]), 96 | i , 97 | pArr[i] ); 98 | } 99 | 100 | /* eof */ 101 | -------------------------------------------------------------------------------- /Chapter14/syarra_sretniop.c: -------------------------------------------------------------------------------- 1 | // syarra_sretniop.c (this is a play on "arrays" and "pointers" reversed. 2 | // Chapter 14 3 | // Learn C Programming 4 | // 5 | // This is a copy of arrays_pointers.c which spefically demonstrate how to 6 | // traverse the array _in_reverse_ using 3 methods: 7 | // a) using array notation incrementing index; 8 | // b) using pointer plus offset (pointer doesn't change); and 9 | // c) using incremented pointer (pointer changes). 10 | // 11 | // compile with: 12 | // 13 | // cc syarra_sretniop.c -o syarra_sretniop -Wall -Werror -std=c11 14 | // 15 | 16 | #include 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | const int arraySize = 5; 21 | int array[5] = { 1 , 2 , 3 , 4 , 5 }; 22 | int* pArray1 = array; 23 | int* pArray2 = &(array[0]); 24 | 25 | printf("Pointer values (addresses) from initial assignments:\n\n"); 26 | 27 | printf( " address of array = %#lx, value at array = %d\n" , 28 | (unsigned long)array , 29 | *array ); 30 | printf( " address of &array[0] = %#lx, value at array[0] = %d\n" , 31 | (unsigned long)&array[0] , 32 | array[0] ); 33 | printf( " address of pArray1 = %#lx, value at pArray1 = %#lx\n" , 34 | (unsigned long)&pArray1 , 35 | (unsigned long) pArray1 ); 36 | printf( " address of pArray2 = %#lx, value at pArray2 = %#lx\n\n" , 37 | (unsigned long)&pArray2 , 38 | (unsigned long) pArray2 ); 39 | 40 | // In this loop, we count down from arraySize. 41 | // NOTE: because of the one-off issue, we can't use i, we have 42 | // to use an adjusted index, j. 43 | // 44 | printf("\n(1) Array values using array notation (index is decremented):\n\n"); 45 | 46 | for( int i = arraySize ; i > 0 ; i-- ) 47 | { 48 | int j = i-1; 49 | printf( " &(array[%1d]) = %#lx, array[%1d] = %1d, i++\n", 50 | j , 51 | (unsigned long)&(array[j]), 52 | j , 53 | array[j] ); 54 | } 55 | 56 | // In this loop, only the index variable needs to be changed to count down 57 | // from 4 (not 5 because of the one-off issue). We also need to adjust the 58 | // stop value to -1 becuase *(pArray2+0) is the 1st value in the array. 59 | // 60 | printf("\n(2) Array values using a pointer addition (offset is decremented):\n\n"); 61 | 62 | for( int i = arraySize-1 ; i > -1 ; i-- ) 63 | { 64 | printf( " pArray2+%1d = %#lx, *(pArray2+%1d) = %1d, i++\n", 65 | i , (unsigned long)(pArray2+i) , 66 | i , *(pArray2+i) ); 67 | } 68 | 69 | // In this loop, 70 | // a) the initialization expression has two operations -- 71 | // i is a counter from 0 72 | // pArray1 starts at the last element of the array 73 | // and 74 | // b) the incremention expression has two operations. 75 | // i is incremented 76 | // pArray1 is decremented from last to first elements. 77 | // 78 | printf("\n(3) Array values using pointer referencing (pointer is decremented):\n\n"); 79 | 80 | int i; 81 | for( pArray1 = &array[arraySize-1], i = 0 ; 82 | i < arraySize ; 83 | i++ , pArray1-- ) 84 | { 85 | printf( " pArray1 = %#lx, *pArray1 = %1d, pArray1++\n", 86 | (unsigned long)pArray1 , 87 | *pArray1 ); 88 | } 89 | } 90 | 91 | // eof 92 | -------------------------------------------------------------------------------- /Chapter15/greet.c: -------------------------------------------------------------------------------- 1 | // greet.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) use a string more than once 7 | // 2) manipulate each element of a string with while()... 8 | // 9 | // compile with: 10 | // 11 | // cc greet.c -o greet -Wall -Werror -std=c11 12 | // 13 | 14 | #include 15 | #include 16 | 17 | int main( void ) 18 | { 19 | char greeting[] = "hello, world!" ; 20 | printf( "%s\n" , greeting ); 21 | 22 | int i = 0; 23 | while( greeting[i] != '\0' ) { 24 | greeting[i] = toupper( greeting[i] ); 25 | i++; 26 | } 27 | printf( "%s\n" , greeting ); 28 | } 29 | 30 | // eof 31 | -------------------------------------------------------------------------------- /Chapter15/printASCII_version1.c: -------------------------------------------------------------------------------- 1 | // printASCII_version1.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) builds upon showChar.c 7 | // 2) print the ASCII values 32 through 64 8 | // 9 | // compile with: 10 | // 11 | // cc printASCII_version1.c -o printASCII_version1 -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | 17 | 18 | int main( void ) 19 | { 20 | char c2; 21 | for( int i = 32 ; i < 64 ; i++ ) 22 | { 23 | c2 = i; 24 | printf("%c %3d %#x\n" , c2 , c2 ,c2 ); 25 | } 26 | } 27 | 28 | // eof 29 | -------------------------------------------------------------------------------- /Chapter15/printASCII_version2.c: -------------------------------------------------------------------------------- 1 | // printASCII_version2.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) builds upon printASCII_version1.c 7 | // 2) print the ASCII values 32 through 127 -- but doesn't handle DEL character 8 | // 9 | // compile with: 10 | // 11 | // cc printASCII_version1.c -o printASCII_version1 -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | 17 | 18 | int main( void ) 19 | { 20 | char c1 , c2 , c3 , c4; 21 | 22 | printf("| Ch Dec Hex | Ch Dec Hex | Ch Dec Hex |\n" ); 23 | printf("|-------------|-------------|-------------|\n" ); 24 | 25 | for( int i = 0 ; i < 32; i++) 26 | { 27 | c1 = i; // <-- Not used yet (a dummy assignment for now). 28 | c2 = i+32; 29 | c3 = i+64; 30 | c4 = i+96; 31 | 32 | printf( "| %c %3d %#x | %c %3d %#x | %c %3d %#x |" , 33 | c2 , c2 , c2 , 34 | c3 , c3 , c3 , 35 | c4 , c4 , c4 ); 36 | printf( "\n" ); 37 | } // for 38 | } // main 39 | 40 | // eof 41 | -------------------------------------------------------------------------------- /Chapter15/printASCII_version3.c: -------------------------------------------------------------------------------- 1 | // printASCII_version3.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) builds upon printASCII_version2.c 7 | // 2) print the ASCII values 32 through 127 8 | // a) correctly handles DEL character. 9 | // 10 | // compile with: 11 | // 12 | // cc printASCII_version3.c -o printASCII_version3 -Wall -Werror -std=c11 13 | // 14 | 15 | 16 | #include 17 | 18 | 19 | int main( void ) 20 | { 21 | char c1 , c2 , c3 , c4; 22 | /* 23 | printf(" Table of 7-Bit ASCII and\n" ); 24 | printf(" Single-Byte UTF-8 Character Sets\n " ); 25 | printf(" (excluding control characters)\n\n" ); 26 | 27 | printf("| Printable Characaters (plus DEL) |\n" ); 28 | */ 29 | printf("| Ch Dec Hex | Ch Dec Hex | Ch Dec Hex |\n" ); 30 | printf("|-------------|-------------|-------------|\n" ); 31 | 32 | for( int i = 0 ; i < 32; i++) 33 | { 34 | c1 = i; // <-- Not used yet (a dummy assignment for now). 35 | c2 = i+32; 36 | c3 = i+64; 37 | c4 = i+96; 38 | 39 | if( c4 != 127 ) { 40 | printf("| %c %3d %#x | %c %3d %#x | %c %3d %#x | " , 41 | c2 , c2 , c2 , 42 | c3 , c3 , c3 , 43 | c4 , c4 , c4 ); 44 | } else { 45 | printf("| %c %3d %#x | %c %3d %#x |%s %3d %#x |" , 46 | c2 , c2 , c2 , 47 | c3 , c3 , c3 , 48 | "DEL" , c4 , c4 ); 49 | } 50 | printf( "\n" ); 51 | 52 | } // for 53 | } // main 54 | 55 | // eof 56 | -------------------------------------------------------------------------------- /Chapter15/printASCIIwithControl.c: -------------------------------------------------------------------------------- 1 | // printASCIIwithControl.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) builds upon printASCII_version3.c 7 | // 2) print the ASCII values 0 through 127 8 | // a) uses a lookup table to print control character mnemonics. 9 | // b) simplifies printf statements fron a single one to multiple statements. 10 | // 11 | // compile with: 12 | // 13 | // cc printASCIIwithControl.c -o printASCIIwithControl -Wall -Werror -std=c11 14 | // 15 | 16 | 17 | #include 18 | 19 | 20 | int main( void ) 21 | { 22 | char* ctrl[] = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", 23 | " BS", " HT", " LF", " VT", " FF", " CR", " SO", " SI", 24 | "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", 25 | "CAN", " EM", "SUB", "ESC", " FS", " GS", " RS", " US" }; 26 | char c1 , c2 , c3 , c4; 27 | 28 | printf(" Table of 7-Bit ASCII and \n"); 29 | printf(" Single-Byte UTF-8 Character Sets \n\n"); 30 | 31 | printf("|Control Character| Printable Characaters (except DEL) |\n" ); 32 | printf("|-----------------|-----------------------------------------|\n" ); 33 | printf("| SYM Ch Dec Hex | Ch Dec Hex | Ch Dec Hex | Ch Dec Hex |\n" ); 34 | printf("|-----------------|-------------|-------------|-------------|\n" ); 35 | 36 | for( int i = 0 ; i < 32; i++) 37 | { 38 | c1 = i; 39 | c2 = i+32; 40 | c3 = i+64; 41 | c4 = i+96; 42 | 43 | printf( "| %s ^%c %3d %#4x " , // 1st column 44 | ctrl[i] , c1+64 , c1 , c1 ); 45 | printf( "| %c %3d %#x " , // 2nd column 46 | c2 , c2 , c2 ); 47 | printf( "| %c %3d %#x " , // 3rd column 48 | c3 , c3 , c3 ); 49 | if( c4 != 127 ) { // 4th column 50 | printf( "| %c %3d %#x |\n" , 51 | c4 , c4 , c4 ); 52 | } else { 53 | printf( "|%s %3d %#x |\n" , 54 | "DEL" , c4 , c4 ); 55 | } 56 | } 57 | c1 = 0x7; 58 | printf("%c%c%c", c1 , c1 , c1); 59 | } // main 60 | 61 | // eof 62 | 63 | -------------------------------------------------------------------------------- /Chapter15/printASCIIwithControlAndEscape.c: -------------------------------------------------------------------------------- 1 | // printASCIIwithControlAndEscape.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) builds upon printASCIIwithControl.c 7 | // 2) print the ASCII values 0 through 127 8 | // a) uses a lookup table to print control character escape sequences. 9 | // 10 | // compile with: 11 | // 12 | // cc printASCIIwithControlAndEscape.c -o printASCIIwithControlAndEscape -Wall -Werror -std=c11 13 | // 14 | 15 | 16 | #include 17 | #include 18 | 19 | 20 | int main( void ) 21 | { 22 | char* ctrl[] = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL" , 23 | " BS", " HT", " LF", " VT", " FF", " CR", " SO", " SI" , 24 | "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB" , 25 | "CAN", " EM", "SUB", "ESC", " FS", " GS", " RS", " US" }; 26 | char format[] = { '0' , 0 , 0 , 0 , 0 , 0 , 0 , 'a' , 27 | 'b' , 't' , 'n' , 'v' , 'f' , 'r' , 0 , 0 , 28 | 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 29 | 0 , 0 , 0 , 'e' , 0 , 0 , 0 , 0 }; 30 | char c1 , c2 , c3 , c4; 31 | 32 | printf(" Table of 7-Bit ASCII and \n"); 33 | printf(" Single-Byte UTF-8 Character Sets \n\n"); 34 | 35 | printf("| Control Characters | Printable Characaters (except DEL) |\n" ); 36 | printf("|---------------------|-----------------------------------------|\n" ); 37 | printf("| SYM Fmt Ch Dec Hex | Ch Dec Hex | Ch Dec Hex | Ch Dec Hex |\n" ); 38 | printf("|---------------------|-------------|-------------|-------------|\n" ); 39 | 40 | for( int i = 0 ; i < 32; i++) 41 | { 42 | c1 = i; 43 | c2 = i+32; 44 | c3 = i+64; 45 | c4 = i+96; 46 | 47 | char fmtStr[] = " "; 48 | if( format[i] ) 49 | { 50 | fmtStr[1] = '\\'; 51 | fmtStr[2] = format[i]; 52 | } 53 | 54 | printf( "| %s %s ^%c %3d %#4x " , // 1st column 55 | ctrl[i] , fmtStr , c3 , c1 , c1 ); 56 | printf( "| %c %3d %#x " , // 2nd column 57 | c2 , c2 , c2 ); 58 | printf( "| %c %3d %#x " , // 3rd column 59 | c3 , c3 , c3 ); 60 | if( c4 != 127 ) { // 4th column 61 | printf( "| %c %3d %#x |\n" , 62 | c4 , c4 , c4 ); 63 | } else { 64 | printf( "|%s %3d %#x |\n" , 65 | "DEL" , c4 , c4 ); 66 | } 67 | } 68 | c1 = 0x7; 69 | printf("%c%c%c", c1 , c1 , c1); 70 | } 71 | 72 | // eof 73 | -------------------------------------------------------------------------------- /Chapter15/printExtendedASCII.c: -------------------------------------------------------------------------------- 1 | // printExtendedASCII.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) builds upon printASCII_version3.c 7 | // 2) print the ASCII values 32 through 255 8 | // 9 | // compile with: 10 | // 11 | // cc printExtendedASCII.c -o printExtendedASCII -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | /* 16 | * Extended ASCII table for Apple operating systems. 17 | * see 18 | */ 19 | 20 | 21 | #include 22 | 23 | 24 | int main( void ) 25 | { 26 | unsigned char c1 , c2 , c3 , c4 , c5 , c6 , c7 , c8 ; 27 | 28 | printf(" Table of 8-Bit ASCII, or\n" ); 29 | printf(" Vendor-specific Extended ASCII\n " ); 30 | printf(" (excluding control characters)\n\n" ); 31 | 32 | printf("| Printable Characaters (plus DEL) |\n" ); 33 | 34 | printf("| Ch Dec Hex | Ch Dec Hex | Ch Dec Hex | Ch Dec Hex | Ch Dec Hex | Ch Dec Hex | Ch Dec Hex |\n" ); 35 | printf("|-------------|-------------|-------------|-------------|-------------|-------------|-------------|\n" ); 36 | 37 | for( int i = 0 ; i < 32; i++) 38 | { 39 | c1 = i; // <-- Not used yet (a dummy assignment for now). 40 | c2 = i+32; 41 | c3 = i+64; 42 | c4 = i+96; 43 | c5 = i+128; // extended ASCII characters 44 | c6 = i+160; 45 | c7 = i+192; 46 | c8 = i+224; 47 | 48 | printf( "| %c %3d %#x " , 49 | c2 , c2 , c2 ); 50 | printf( "| %c %3d %#x " , 51 | c3 , c3 , c3 ); 52 | if( c4 == 127 ) { 53 | printf("|%s %3d %#x |" , 54 | "DEL" , c4 , c4 ); 55 | } else { 56 | printf("| %c %3d %#x |" , 57 | c4 , c4 , c4 ); 58 | } 59 | 60 | // Print extended ASCII for your your system. 61 | // 62 | printf(" %c %3d %#x | %c %3d %#x | %c %3d %#x | %c %3d %#x |" , 63 | c5 , c5 , c5 , 64 | c6 , c6 , c6 , 65 | c7 , c7 , c7 , 66 | c8 , c8 , c8 ); 67 | printf( "\n" ); 68 | } // for 69 | } // main 70 | 71 | // eof 72 | -------------------------------------------------------------------------------- /Chapter15/saferStringOps.c: -------------------------------------------------------------------------------- 1 | // saferStringOps.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) use a string more than once 7 | // 2) manipulate each element of a string with while()... 8 | // 9 | // compile with: 10 | // 11 | // cc saferStringOps.c -o saferStringOps -Wall -Werror -std=c11 12 | // 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | void myStringNCompare( char* s1 , char* s2 , int n); 19 | 20 | int main( void ) 21 | { 22 | char salutation[] = "hello"; 23 | char audience[] = "everybody"; 24 | printf( "%s, %s!\n", salutation , audience ); 25 | 26 | int lenSalutation = strlen( salutation ); 27 | int lenAudience = strlen( audience ); 28 | int lenGreeting1 = lenSalutation+lenAudience+1; 29 | char greeting1[lenGreeting1]; 30 | 31 | strncpy( greeting1 , salutation , lenSalutation ); 32 | strncat( greeting1 , audience , lenAudience ); 33 | printf( "%s\n" , greeting1 ); 34 | 35 | char greeting2[7] = {0}; 36 | strncpy( greeting2 , salutation , 3 ); 37 | strncat( greeting2 , audience , 3 ); 38 | printf( "%s\n" , greeting2 ); 39 | 40 | myStringNCompare( greeting1 , greeting2 , 7 ); 41 | 42 | myStringNCompare( greeting1 , greeting2 , 3 ); 43 | 44 | char* str1 = "abcde"; 45 | char* str2 = "aeiou"; 46 | char* str3 = "AEIOU"; 47 | 48 | myStringNCompare( str1 , str2 , 3 ); 49 | myStringNCompare( str2 , str3 , 5 ); 50 | } 51 | 52 | 53 | void myStringNCompare( char* s1 , char* s2 , int n) 54 | { 55 | int result = strncmp( s1 , s2 , n ); 56 | 57 | char* pResultStr; 58 | if( result < 0 ) pResultStr = "less than (come before)"; 59 | else if( result > 0 ) pResultStr = "greater than (come after)"; 60 | else pResultStr = "equal to"; 61 | printf( "First %d characters of %s are %s %s\n" , 62 | n, s1 , pResultStr , s2 ); 63 | } 64 | 65 | // eof 66 | -------------------------------------------------------------------------------- /Chapter15/showChar.c: -------------------------------------------------------------------------------- 1 | // showChar.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) create character variables 7 | // 2) assign character values as characters and as integer values 8 | // 3) print out an individual characer as 9 | // a) a character 10 | // b) its decimal value 11 | // c) its hexadecimal value 12 | // 13 | // compile with: cc showChar.c -o showChar -Wall -Werror -std=c11 14 | // 15 | 16 | 17 | #include 18 | 19 | 20 | void showChar( int ch ); 21 | 22 | int main( void ) 23 | { 24 | signed char aChar = 'A'; 25 | char c1 = 65 ; 26 | char c2 = 'a'; 27 | char c3 = 97 ; 28 | char c4 = '7'; 29 | unsigned char aByte = 7; 30 | 31 | showChar( aChar ); 32 | showChar( c1 ); 33 | showChar( c2 ); 34 | showChar( c3 ); 35 | showChar( c4 ); 36 | showChar( aByte ); 37 | } 38 | 39 | void showChar( int ch ) 40 | { 41 | printf( "ch = '%c' (%d) [%#x]\n" , ch , ch , ch ); 42 | } 43 | 44 | // eof 45 | -------------------------------------------------------------------------------- /Chapter15/simpleStrings.c: -------------------------------------------------------------------------------- 1 | // simpleStrings.c 2 | // Chapter 15 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) declare and initialize strings in various ways 7 | // 2) manipulate (change) a single characger within a string 8 | // 3) illustrate the difference between strings and string literals (constant) 9 | // 4) some experiments with strings: 10 | // a) try to modify a string literal 11 | // b) loop through string with for()... 12 | // c) loop through string with while()... 13 | // 14 | // compile with: 15 | // 16 | // cc simpleStrings.c -o simpleStrings -Wall -Werror -std=c11 17 | // 18 | 19 | 20 | #include // for printf() 21 | #include // for toupper() 22 | #include // for strlen() 23 | 24 | 25 | int main( void ) 26 | { 27 | char string0[8] = { 0 }; 28 | char string1[8] = { 'h' , 'e' , 'l' , 'l', 'o' , '\0' }; 29 | char string2[8] = "hello"; 30 | char string3[] = "hello"; 31 | char* string4 = "hello"; 32 | 33 | printf( "A) 0:\"%s\" 1:\"%s\" 2:\"%s\" 3:\"%s\" 4:\"%s\"\n\n" , 34 | string0 , string1 , string2 , string3 , string4 ); 35 | 36 | string0[0] = 'H'; 37 | string1[0] = 'H'; 38 | string2[0] = toupper( string0[0] ); 39 | string3[0] = toupper( string0[0] ); 40 | // string4[0] = 'H'; // Can't do this because its a pointer 41 | // to a literal string (constant). 42 | char* string5 = "Hello"; // assign pointer to new string. 43 | 44 | printf( "B) 0:\"%s\" 1:\"%s\" 2:\"%s\" 3:\"%s\" 4:\"%s\"\n\n" , 45 | string0 , string1 , string2 , string3 , string5 ); 46 | 47 | 48 | // EXPERIMENTS 49 | // 50 | // To do each experiment, change #if 0 to #if 1 and then build and run the 51 | // program. 52 | 53 | // Experiment 1: initialize an array with a string too long. 54 | // 55 | // This should cause compiler error; but it is useful to know what an error 56 | // of this kind looks like. 57 | // 58 | 59 | // Should fail. 60 | #if 0 61 | char string6[8] = "Ladies and Gentlemen"; 62 | 63 | // Will succeed. 64 | char string7[] = "Ladies and Gentlemen"; 65 | #endif 66 | 67 | 68 | // Experiment 2: convert string2 to all upper case using loop. 69 | 70 | #if 0 71 | int length = strlen( string2 ); 72 | for( int i = 0 ; i < length ; i++ ) 73 | { 74 | string2[i] = toupper( string2[i]); 75 | } 76 | printf( "E2) \"%s\" \n" , string2 ); 77 | #endif 78 | 79 | // Experiment 3: convert string3 to all upper case using loop. 80 | 81 | #if 0 82 | int i = 0; 83 | while( string7[i] != '\0' ) 84 | { 85 | string7[i] = toupper( string7[i]); 86 | i++; 87 | } 88 | printf( "E3) \"%s\" \n" , string7 ); 89 | #endif 90 | } 91 | 92 | // eof 93 | -------------------------------------------------------------------------------- /Chapter16/carddeck_0.c: -------------------------------------------------------------------------------- 1 | // carddeck0.c 2 | // Chapter 16 3 | // Learn C Programming 4 | // 5 | // Starting point (from Chapter 10, card4.c) for complex structures. 6 | // Modify it to reflect data structures and operations using arrays and 7 | // pointers. 8 | // 9 | // In carddeck_0.c, remove unneeded functions (we'll add them back later) 10 | // and demonstrate an array of structures. 11 | // 12 | // compile with: 13 | // 14 | // cc carddeck_0.c -o carddeck_0 -Wall -Werror =std=c11 15 | // 16 | 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | // ============================================ 24 | // Definitions related to a Card 25 | // 26 | // Card Suits 27 | // 28 | typedef enum 29 | { 30 | club = 1, 31 | diamond, 32 | heart, 33 | spade 34 | } Suit; 35 | 36 | typedef enum 37 | { 38 | one = 1, 39 | two, 40 | three, 41 | four, 42 | five, 43 | six, 44 | seven, 45 | eight, 46 | nine, 47 | ten, 48 | jack, 49 | queen, 50 | king, 51 | ace 52 | } Face; 53 | 54 | 55 | typedef struct 56 | { 57 | Suit suit; 58 | int suitValue; 59 | Face face; 60 | int faceValue; 61 | bool isWild; 62 | } Card; 63 | 64 | 65 | // Operations on a Card 66 | // 67 | void InitializeCard( Card* pCard , Suit s , Face f , bool w ); 68 | void PrintCard( Card* pCard ); 69 | void CardToString( Card* pCard , char pCardStr[20] ); 70 | 71 | // ============================================ 72 | // Definitions related to a Deck 73 | // 74 | // A Deck 75 | 76 | // For now, the deck will be declared as an array of Cards in main(). 77 | 78 | // operations on a Deck (array of cards) 79 | // 80 | void InitializeDeck( Card* pDeck ); 81 | void PrintDeck( Card* pDeck ); 82 | 83 | 84 | int main( void ) 85 | { 86 | Card aCard; 87 | InitializeCard( &aCard, diamond , seven , true ); 88 | PrintCard( &aCard ); 89 | printf( "\n" ); 90 | } 91 | 92 | 93 | // ============================================ 94 | // Operations on a Card 95 | // ============================================ 96 | 97 | 98 | void InitializeCard( Card* pCard, Suit s , Face f , bool w ) 99 | { 100 | pCard->suit = s; 101 | pCard->suitValue = (int)s; 102 | 103 | pCard->face = f; 104 | pCard->faceValue = (int)f; 105 | 106 | pCard->isWild = w; 107 | } 108 | 109 | 110 | void PrintCard( Card* pCard ) 111 | { 112 | char cardStr[20] = {0}; 113 | CardToString( pCard , cardStr ); 114 | printf( "%18s" , cardStr ); 115 | } 116 | 117 | 118 | void CardToString( Card* pCard , char pCardStr[20] ) 119 | { 120 | switch( pCard->face ) 121 | { 122 | case two: strcpy( pCardStr , " 2 " ); break; 123 | case three: strcpy( pCardStr , " 3 " ); break; 124 | case four: strcpy( pCardStr , " 4 " ); break; 125 | case five: strcpy( pCardStr , " 5 " ); break; 126 | case six: strcpy( pCardStr , " 6 " ); break; 127 | case seven: strcpy( pCardStr , " 7 " ); break; 128 | case eight: strcpy( pCardStr , " 8 " ); break; 129 | case nine: strcpy( pCardStr , " 9 " ); break; 130 | case ten: strcpy( pCardStr , " 10 " ); break; 131 | case jack: strcpy( pCardStr , " Jack " ); break; 132 | case queen: strcpy( pCardStr , "Queen " ); break; 133 | case king: strcpy( pCardStr , " King " ); break; 134 | case ace: strcpy( pCardStr , " Ace " ); break; 135 | default: strcpy( pCardStr , " ??? " ); break; 136 | } 137 | switch( pCard->suit ) 138 | { 139 | case spade: strcat( pCardStr , "of Spades "); break; 140 | case heart: strcat( pCardStr , "of Hearts "); break; 141 | case diamond: strcat( pCardStr , "of Diamonds"); break; 142 | case club: strcat( pCardStr , "of Clubs "); break; 143 | default: strcat( pCardStr , "of ???s "); break; 144 | } 145 | } 146 | 147 | 148 | // eof 149 | -------------------------------------------------------------------------------- /Chapter16/carddeck_1a.c: -------------------------------------------------------------------------------- 1 | // carddeck_1a.c 2 | // Chapter 16 3 | // Learn C Programming 4 | // 5 | // carddeck_1a.c builds upon carddeck_0.c. 6 | // In this version, we add an array of structures, called Deck 7 | // and some functions to manipulate the Deck array. 8 | // 9 | // compile with: 10 | // 11 | // cc carddeck_1a.c -o carddeck_1a -Wall -Werror =std=c11 12 | // 13 | 14 | 15 | #include 16 | #include 17 | #include // for strcpy() and strcat() 18 | 19 | 20 | // Useful constants (avoid "magic numbers" whose meaning is 21 | // sometimes vague and whose values may change). Use these instead 22 | // of literals; when you need to change these, they are applied 23 | // everywhere. 24 | // 25 | enum { 26 | kCardsInDeck = 52, // For now, 52 cards in a deck. This will change 27 | // depending upon the card game and the # of wild 28 | // cards, etc. 29 | kCardsInSuit = 13 // For now, kCardsInDeck / 4. This will change 30 | // depending upon the card game. 31 | }; 32 | 33 | const bool kWildCard = true; 34 | const bool kNotWildCard = false; 35 | 36 | 37 | // ============================================ 38 | // Definitions related to a Card 39 | // 40 | // Card Suits 41 | // 42 | typedef enum 43 | { 44 | club = 1, 45 | diamond, 46 | heart, 47 | spade 48 | } Suit; 49 | 50 | typedef enum 51 | { 52 | one = 1, 53 | two, 54 | three, 55 | four, 56 | five, 57 | six, 58 | seven, 59 | eight, 60 | nine, 61 | ten, 62 | jack, 63 | queen, 64 | king, 65 | ace 66 | } Face; 67 | 68 | 69 | typedef struct 70 | { 71 | Suit suit; 72 | int suitValue; 73 | Face face; 74 | int faceValue; 75 | bool isWild; 76 | } Card; 77 | 78 | 79 | // Operations on a Card 80 | // 81 | void InitializeCard( Card* pCard , Suit s , Face f , bool w ); 82 | void PrintCard( Card* pCard ); 83 | void CardToString( Card* pCard , char pCardStr[20] ); 84 | 85 | 86 | int main( void ) 87 | { 88 | Card deck[ kCardsInDeck ]; 89 | 90 | Card* aCard = &deck[3]; 91 | aCard->suit = spade; 92 | aCard->suitValue = (int)spade; 93 | aCard->face = five; 94 | aCard->faceValue = (int)five; 95 | aCard->isWild = kNotWildCard; 96 | 97 | PrintCard( &deck[3] ); 98 | printf( "\n" ); 99 | } 100 | 101 | 102 | // ============================================ 103 | // Operations on a Card 104 | // ============================================ 105 | 106 | 107 | void InitializeCard( Card* pCard, Suit s , Face f , bool w ) 108 | { 109 | pCard->suit = s; 110 | pCard->suitValue = (int)s; 111 | 112 | pCard->face = f; 113 | pCard->faceValue = (int)f; 114 | 115 | pCard->isWild = w; 116 | } 117 | 118 | 119 | void PrintCard( Card* pCard ) 120 | { 121 | char cardStr[20] = {0}; 122 | CardToString( pCard , cardStr ); 123 | printf( "%18s" , cardStr ); 124 | } 125 | 126 | 127 | void CardToString( Card* pCard , char pCardStr[20] ) 128 | { 129 | switch( pCard->face ) 130 | { 131 | case two: strcpy( pCardStr , " 2 " ); break; 132 | case three: strcpy( pCardStr , " 3 " ); break; 133 | case four: strcpy( pCardStr , " 4 " ); break; 134 | case five: strcpy( pCardStr , " 5 " ); break; 135 | case six: strcpy( pCardStr , " 6 " ); break; 136 | case seven: strcpy( pCardStr , " 7 " ); break; 137 | case eight: strcpy( pCardStr , " 8 " ); break; 138 | case nine: strcpy( pCardStr , " 9 " ); break; 139 | case ten: strcpy( pCardStr , " 10 " ); break; 140 | case jack: strcpy( pCardStr , " Jack " ); break; 141 | case queen: strcpy( pCardStr , "Queen " ); break; 142 | case king: strcpy( pCardStr , " King " ); break; 143 | case ace: strcpy( pCardStr , " Ace " ); break; 144 | default: strcpy( pCardStr , " ??? " ); break; 145 | } 146 | switch( pCard->suit ) 147 | { 148 | case spade: strcat( pCardStr , "of Spades "); break; 149 | case heart: strcat( pCardStr , "of Hearts "); break; 150 | case diamond: strcat( pCardStr , "of Diamonds"); break; 151 | case club: strcat( pCardStr , "of Clubs "); break; 152 | default: strcat( pCardStr , "of ???s "); break; 153 | } 154 | } 155 | 156 | // eof 157 | -------------------------------------------------------------------------------- /Chapter16/carddeck_1b.c: -------------------------------------------------------------------------------- 1 | // carddeck_1b.c 2 | // Chapter 16 3 | // Learn C Programming 4 | // 5 | // carddeck_1b.c builds upon carddeck_1a.c. 6 | // In this version, we add an array of structures, called Deck 7 | // and some functions to manipulate the Deck array. 8 | // 9 | // compile with: 10 | // 11 | // cc carddeck_1bc -o carddeck_1b -Wall -Werror =std=c11 12 | // 13 | 14 | 15 | #include 16 | #include 17 | #include // for strcpy() and strcat() 18 | 19 | 20 | // Useful constants (avoid "magic numbers" whose meaning is 21 | // sometimes vague and whose values may change). Use these instead 22 | // of literals; when you need to change these, they are applied 23 | // everywhere. 24 | // 25 | enum { 26 | kCardsInDeck = 52, // For now, 52 cards in a deck. This will change 27 | // depending upon the card game and the # of wild 28 | // cards, etc. 29 | kCardsInSuit = 13 // For now, kCardsInDeck / 4. This will change 30 | // depending upon the card game. 31 | }; 32 | 33 | const bool kWildCard = true; 34 | const bool kNotWildCard = false; 35 | 36 | 37 | // ============================================ 38 | // Definitions related to a Card 39 | // 40 | // Card Suits 41 | // 42 | typedef enum 43 | { 44 | club = 1, 45 | diamond, 46 | heart, 47 | spade 48 | } Suit; 49 | 50 | typedef enum 51 | { 52 | one = 1, 53 | two, 54 | three, 55 | four, 56 | five, 57 | six, 58 | seven, 59 | eight, 60 | nine, 61 | ten, 62 | jack, 63 | queen, 64 | king, 65 | ace 66 | } Face; 67 | 68 | 69 | typedef struct 70 | { 71 | Suit suit; 72 | int suitValue; 73 | Face face; 74 | int faceValue; 75 | bool isWild; 76 | } Card; 77 | 78 | 79 | // Operations on a Card 80 | // 81 | void InitializeCard( Card* pCard , Suit s , Face f , bool w ); 82 | void PrintCard( Card* pCard ); 83 | void CardToString( Card* pCard , char pCardStr[20] ); 84 | 85 | 86 | int main( void ) 87 | { 88 | Card deck[ kCardsInDeck ]; 89 | 90 | InitializeCard( &deck[3], spade , five , kNotWildCard ); 91 | PrintCard( &deck[3] ); 92 | printf( "\n" ); 93 | } 94 | 95 | 96 | // ============================================ 97 | // Operations on a Card 98 | // ============================================ 99 | 100 | 101 | void InitializeCard( Card* pCard, Suit s , Face f , bool w ) 102 | { 103 | pCard->suit = s; 104 | pCard->suitValue = (int)s; 105 | 106 | pCard->face = f; 107 | pCard->faceValue = (int)f; 108 | 109 | pCard->isWild = w; 110 | } 111 | 112 | 113 | void PrintCard( Card* pCard ) 114 | { 115 | char cardStr[20] = {0}; 116 | CardToString( pCard , cardStr ); 117 | printf( "%18s" , cardStr ); 118 | } 119 | 120 | 121 | void CardToString( Card* pCard , char pCardStr[20] ) 122 | { 123 | switch( pCard->face ) 124 | { 125 | case two: strcpy( pCardStr , " 2 " ); break; 126 | case three: strcpy( pCardStr , " 3 " ); break; 127 | case four: strcpy( pCardStr , " 4 " ); break; 128 | case five: strcpy( pCardStr , " 5 " ); break; 129 | case six: strcpy( pCardStr , " 6 " ); break; 130 | case seven: strcpy( pCardStr , " 7 " ); break; 131 | case eight: strcpy( pCardStr , " 8 " ); break; 132 | case nine: strcpy( pCardStr , " 9 " ); break; 133 | case ten: strcpy( pCardStr , " 10 " ); break; 134 | case jack: strcpy( pCardStr , " Jack " ); break; 135 | case queen: strcpy( pCardStr , "Queen " ); break; 136 | case king: strcpy( pCardStr , " King " ); break; 137 | case ace: strcpy( pCardStr , " Ace " ); break; 138 | default: strcpy( pCardStr , " ??? " ); break; 139 | } 140 | switch( pCard->suit ) 141 | { 142 | case spade: strcat( pCardStr , "of Spades "); break; 143 | case heart: strcat( pCardStr , "of Hearts "); break; 144 | case diamond: strcat( pCardStr , "of Diamonds"); break; 145 | case club: strcat( pCardStr , "of Clubs "); break; 146 | default: strcat( pCardStr , "of ???s "); break; 147 | } 148 | } 149 | 150 | // eof 151 | -------------------------------------------------------------------------------- /Chapter17/heading.c: -------------------------------------------------------------------------------- 1 | // heading.c 2 | // Chapter 18 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to use a static variable in 6 | // a function to print the next page number each time the 7 | // function is called. 8 | // 9 | // compile with: 10 | // 11 | // cc heading.c -o heading -Wall -Werror -std=c11 12 | // 13 | 14 | #include 15 | 16 | void printHeading( const char* aHeading ); 17 | 18 | int main( void ) { 19 | printHeading( "Title Page" ); 20 | printHeading( "Chapter 1 " ); 21 | printHeading( " " ); 22 | printHeading( " " ); 23 | printHeading( "Chapter 2 " ); 24 | printHeading( " " ); 25 | printHeading( "Conclusion" ); 26 | } 27 | 28 | void printHeading( const char* aHeading ) { 29 | /* static */ int pageNo = 1; 30 | printf( "%s \t Page %d\n" , aHeading , pageNo); 31 | pageNo++; 32 | } 33 | 34 | // eof 35 | -------------------------------------------------------------------------------- /Chapter19/character_string.c: -------------------------------------------------------------------------------- 1 | // character_string.c 2 | // Chapter 19 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) print a string using minimum field width, precision and alignment. 7 | // 2) print sub-strings with pointer arithmetic. 8 | // 3) print a character using minimum field width and alignment 9 | // 10 | // compile with: 11 | // 12 | // cc character_string.c -o character_string -Wall -Werror -std=c11 13 | // 14 | 15 | #include 16 | 17 | int main( void ) 18 | { 19 | char aChar = 'C' ; 20 | char* pStr = "Learn to program with C" ; 21 | 22 | printf( "String output\n" ); 23 | printf( " Specifier Formatted Value\n" ); 24 | printf( " %%s [%s] everything\n" , pStr ); 25 | printf( " %%30s [%30s] everything right-aligned, field=30\n" , pStr ); 26 | printf( " %%.10s [%.10s] truncated to first 10 characters\n" , pStr ); 27 | printf( " %%30.10s [%30.10s] only 10 chars right-aligned, field=30\n" , pStr ); 28 | printf( " %%-30.10s [%-30.10s] only 10 chars left-aligned, field=30\n\n" , pStr ); 29 | printf( " %%*.*s [%*.*s] use width & precision in argument list\n\n" , 30 , 10 , pStr ); 30 | 31 | printf( "Sub-string output\n" ); 32 | printf( " %%.7s [%.7s] 3rd word (using array offset)\n" , &pStr[9] ); 33 | printf( " %%.12s [%.12s] 3rd and 4th words (using pointer arithmetic)\n\n" , pStr + 9 ); 34 | 35 | printf( "Character output\n" ); 36 | printf( " %%c [%c] character\n" , aChar ); 37 | printf( " %%10c [%10c] character right-aligned, field=10\n" , aChar ); 38 | printf( " %%-10c [%-10c] character left-aligned, field=10\n\n" , aChar ); 39 | } 40 | 41 | // eof 42 | -------------------------------------------------------------------------------- /Chapter19/double.c: -------------------------------------------------------------------------------- 1 | // double.c 2 | // Chapter 19 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) print floating point in natural format nnnn.nnnn 7 | // 2) print floating point in scientific notation 8 | // 3) demonstrate G type conversion for optimal format of floating point 9 | // 10 | // compile with: 11 | // 12 | // cc double.c -o double -Wall -Werror -std=c11 13 | // 14 | 15 | #include 16 | 17 | int main( void ) 18 | { 19 | double aDouble = 987654321.987654321; 20 | 21 | printf( "Use of the %%f, %%e, and %%E format specifiers:\n" ); 22 | printf( " Specifier Formatted Value\n" ); 23 | printf( " %%f [%f] whatever\n" , aDouble ); 24 | printf( " %%.3f [%.3f] 3 decimal places\n" , aDouble ); 25 | printf( " %%.9f [%.8f] 8 decimal places\n" , aDouble ); 26 | printf( " %%.0f [%.0f] no decimal places\n" , aDouble ); 27 | printf( " %%#.0f [%#.0f] no decimal places, but decimal point\n" , aDouble ); 28 | printf( " %%15.3f [%15.3f] 3 decimals, 15 wide, left aligned]\n" , aDouble ); 29 | printf( " %%-15.3f [%-15.3f] 3 decimals, 15 wide, right aligned\n" , aDouble ); 30 | printf( " %%e [%e] using exponential notation\n" , aDouble ); 31 | printf( " %%E [%E] using EXPONENTIAL notation\n" , aDouble ); 32 | printf( " %%.3e [%.3e] exponent with 3 decimal places\n" , aDouble ); 33 | printf( " %%15.3e [%15.3e] exponent with 3 decimals, 15 wide\n" , aDouble ); 34 | printf( " %%015.3e [%015.3e] exponent with 3 decimals, 15 wide, 0-fill\n" , aDouble ); 35 | printf( " %% 15.3e [% 15.3e] exponent with 3 decimals, 15 wide, leave space for sign\n" , aDouble ); 36 | printf( " %%+15.3e [%+15.3e] exponent with 3 decimals, 15 wide, show sign\n" , aDouble ); 37 | printf( " %%+015.3e [%+015.3e] exponent with 3 decimals, 15 wide, show sign, 0-fill\n" , aDouble ); 38 | printf( " %%.0e [%.0e] exponent with no decimals\n" , aDouble ); 39 | printf( " %%15.0e [%15.0e] exponent 15 wide, no decimals\n\n" , aDouble ); 40 | 41 | printf( " %%a [%a] hexidecimal version of double, exponent=2^p\n" , aDouble ); 42 | printf( " %%A [%A] HEXIDECIMAL version of double, exponent=2^P\n\n" , aDouble ); 43 | 44 | printf( "Use of the %%g, and %%G format specifiers:\n" ); 45 | printf( " Specifier %%18.12g %%18.3g" ); 46 | printf( " %%18.3G %%18g\n" ); 47 | double k = aDouble * 1e-15; 48 | for( int i = 0 ; i < 10 ; i++, k *= 1000 ) 49 | printf( " [%18.12g] [%18.3g] [%18.3G] [%18g]\n" , 50 | k , k , k , k ); 51 | } 52 | 53 | // eof 54 | -------------------------------------------------------------------------------- /Chapter19/signedInt.c: -------------------------------------------------------------------------------- 1 | // signedInt.c 2 | // Chapter 19 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) print signed values using minimum field, precision, and alignment 7 | // 2) print 64-bit values (long long int) 8 | // 3) explore powers of 2 and powers of 9 9 | // 10 | // compile with: 11 | // 12 | // cc signedInt.c -o signedInt -Wall -Werror -std=c11 13 | // 14 | 15 | #include 16 | 17 | int main( void ) 18 | { 19 | int smallInt = 12; 20 | int largeInt = 0x7fffffff; // int32 max 21 | int negativeInt = -smallInt; 22 | unsigned anUnsigned = 130; 23 | 24 | long long int reallyLargeInt = 0x7fffffffffffffff; // int64 max 25 | 26 | printf( " Signed Printf \n" ); 27 | printf( " Name right left zero right left\n" ); 28 | printf( " aligned aligned filled minimum minimum whatever\n" ); 29 | printf( " Specifier %%10d %%-10d %%-.10d %%10.3d %%-10.3d %%d\n" ); 30 | printf( " [%10d] [%-10d] [%-.10d] [%10.3d] [%-10.3d] [%d]\n" , 31 | smallInt , smallInt , smallInt , smallInt , smallInt , smallInt ); 32 | printf( " [%10d] [%-10d] [%-.10d] [%10.3d] [%-10.3d] [%d]\n" , 33 | largeInt , largeInt , largeInt , largeInt , largeInt , largeInt ); 34 | printf( " [%10d] [%-10d] [%-.10d] [%10.3d] [%-10.3d] [%d]\n" , 35 | anUnsigned , anUnsigned , anUnsigned , anUnsigned , anUnsigned , anUnsigned ); 36 | printf( " [%10d] [%-10d] [%-.10d] [%10.3d] [%-10.3d] [%d]\n\n" , 37 | negativeInt , negativeInt , negativeInt , negativeInt , negativeInt , negativeInt ); 38 | 39 | printf( " Specifier %%20lld %%-20lld %%-.20lld\n" ); 40 | printf( " [%20lld] [%-20lld] [%-.20lld]\n" , 41 | reallyLargeInt , reallyLargeInt , reallyLargeInt ); 42 | printf( " %%20.3lld %%-20.3lld %%lld\n" ); 43 | printf( " [%20.3lld] [%-20.3lld] [%lld]\n\n" , 44 | reallyLargeInt , reallyLargeInt , reallyLargeInt ); 45 | 46 | 47 | printf( "Powers of 2: 2^0, 2^2, 2^4, 2^6, 2^8 , 2^10\n" ); 48 | int k = 1; 49 | for( int i = 0 ; i < 6 ; i++ , k<<=2 ) 50 | { 51 | printf( " [%6d] [%-6d] [%-.6d] [%6.3d] [%-6.3d] [%d]\n" , 52 | k , k , k , k , k , k ); 53 | } 54 | printf( "\nPowers of 9: 9^1, 9^2, 9^3, 9^4\n" ); 55 | k = 9; 56 | for( int i = 0 ; i < 5 ; i++ , k*=9 ) 57 | { 58 | printf( " [%6d] [%-6d] [%-.6d] [%6.3d] [%-6.3d] [%d]\n" , 59 | k , k , k , k , k , k ); 60 | } 61 | } 62 | 63 | // eof 64 | -------------------------------------------------------------------------------- /Chapter19/unsignedInt.c: -------------------------------------------------------------------------------- 1 | // unsignedInt.c 2 | // Chapter 19 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) print unsigned values in octal, decimal, and hexadecimal 7 | // 2) see what happens when you print negative numbers as unsigned values 8 | // 3) explore powers of 2 and powers of 9 9 | // 4) print out pointer values. 10 | // 11 | // compile with: 12 | // 13 | // cc unsignedInt.c -o unsignedInt -Wall -Werror -std=c11 14 | // 15 | 16 | #include 17 | 18 | int main( void ) 19 | { 20 | int smallInt = 12; 21 | int largeInt = (1024*1024*3)+(1024*2)+512+128+64+32+16+8+4+2+1; 22 | int negativeInt = -smallInt; 23 | unsigned anUnsigned = 130; 24 | 25 | printf( " Unsigned Printf \n" ); 26 | printf( " Base Base-8 Base-10 Base-16 BASE-16\n" ); 27 | printf( " Name octal unsigned hexadeximal HEXIDECIMAL\n" ); 28 | printf( " Specifier %%12o %%12u %%12x %%12X \n" ); 29 | printf( " [%12o] [%12u] [%12x] [%12X]\n" , 30 | smallInt , smallInt , smallInt , smallInt ); 31 | printf( " [%12o] [%12u] [%12x] [%12X]\n" , 32 | largeInt , largeInt , largeInt , largeInt ); 33 | printf( " [%12o] [%12u] [%12x] [%12X]\n\n" , 34 | anUnsigned , anUnsigned , anUnsigned , anUnsigned ); 35 | 36 | printf( " Specifier %%#o %%#u %%#x %%#X\n"); 37 | printf( " [%#12o] [%12u] [%#12x] [%#12X]\n" , 38 | smallInt , smallInt , smallInt , smallInt ); 39 | printf( " [%#12o] [%12u] [%#12x] [%#12X]\n" , 40 | largeInt , largeInt , largeInt , largeInt ); 41 | printf( " [%#12o] [%12u] [%#12x] [%#12X]\n\n" , 42 | anUnsigned , anUnsigned , anUnsigned , anUnsigned ); 43 | 44 | printf( " Negative Numbers as Unsigned:\n" ); 45 | printf( " -0 [%12o] [%12u] [%12x] [%12X]\n" , 46 | -0 , -0 , -0 , -0 ); 47 | printf( " -1 [%12o] [%12u] [%12x] [%12X]\n" , 48 | -1 , -1 , -1 , -1 ); 49 | printf( " -2 [%12o] [%12u] [%12x] [%12X]\n" , 50 | -2 , -2 , -2 , -2 ); 51 | printf( " -12 [%12o] [%12u] [%12x] [%12X]\n\n" , 52 | negativeInt , negativeInt , negativeInt , negativeInt ); 53 | 54 | 55 | printf( "Powers of 2: 2^0, 2^2, 2^4, 2^6, 2^8 , 2^10\n" ); 56 | int k = 1; 57 | for( int i = 0 ; i < 6 ; i++ , k<<=2 ) 58 | { 59 | printf( " [%#12o] [%12u] [%#12x] [%#12X]\n" , 60 | k , k , k , k ); 61 | } 62 | printf( "\nPowers of 9: 9^1, 9^2, 9^3, 9^4\n" ); 63 | printf( " Specifier %%o %%u %%x %%X \n" ); 64 | k = 9; 65 | for( int i = 0 ; i < 5 ; i++ , k*=9 ) 66 | { 67 | printf( " [%#12o] [%12u] [%#12x] [%#12X]\n" , 68 | k , k , k , k ); 69 | } 70 | 71 | printf( "\nPointer Output\n" ); 72 | printf( " %%p [%p] pointer\n" , &smallInt ); 73 | printf( " %%#lx [%#lx] using hex\n\n" , (unsigned long)&smallInt ); 74 | } 75 | 76 | // eof 77 | 78 | 79 | -------------------------------------------------------------------------------- /Chapter20/example_getopt_long.c: -------------------------------------------------------------------------------- 1 | // example_getopt_long.c 2 | // Chapter 20 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // * retrieve arguments entered on the command line with the C Standard 7 | // Library routine getopts_long(). 8 | // 9 | // compile with: 10 | // 11 | // cc example_getopt_long.c -o example_getopt_long -Wall -Werror -std=c11 12 | // 13 | // sample inputs; 14 | // 15 | // example_getopt_long -t "There and Back" -a "Bilbo Baggins" 16 | // example_getopt_long --author "Jeff Szuhay --title "Hello, world!" 17 | // example_getopt_long -a -t 18 | // example_getopt_long -b -c 19 | // 20 | 21 | #include 22 | #include 23 | 24 | 25 | static struct option long_options[] = { 26 | {"title", required_argument, NULL, 't'}, 27 | {"author", required_argument, NULL, 'a'}, 28 | {NULL, 0, NULL, 0} 29 | }; 30 | 31 | typedef struct _book { 32 | char* title; 33 | char* author; 34 | } Book; 35 | 36 | 37 | int main(int argc, char *argv[]) { 38 | char ch; 39 | Book b; 40 | 41 | while( (ch = getopt_long( argc , argv , "t:a:" , long_options, NULL ) ) != -1 ) { 42 | switch (ch) { 43 | case 't': 44 | b.title = optarg; 45 | break; 46 | case 'a': 47 | b.author = optarg; 48 | break; 49 | default: 50 | printf( "\nUsage: %s -title 'title' -author 'name'\n\n" , argv[0] ); 51 | return 1; 52 | break; 53 | } 54 | } 55 | if( b.title ) printf( "Title is [%s]\n" , b.title ); 56 | if( b.author ) printf( "Author is [%s]\n" , b.author ); 57 | if( optind < argc ) { 58 | printf( "non-option ARGV-elements: " ); 59 | while( optind < argc ) 60 | printf( "%s ", argv[ optind++ ] ); 61 | printf( "\n" ); 62 | } 63 | } 64 | 65 | // eof 66 | -------------------------------------------------------------------------------- /Chapter20/example_gnu_getopts_long.c: -------------------------------------------------------------------------------- 1 | // example_gnu_getopts_long.c 2 | // Chapter 20 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // * retrieve arguments entered on the command line using the C Standard 7 | // Library routine getopt_long(). 8 | // * use flag arguments with no parameters 9 | // * use required arguments 10 | // * use optional arguments with default setting (can be set to something else. 11 | // 12 | // compile with: 13 | // 14 | // cc example_gnu_getopts_long.c -o showArgs -Wall -Werror -std=c11 15 | // 16 | // Sample inputs: 17 | // 18 | // example_gnu_getopts_long --verbose -a -b --num=3 --size=10 --delete=Bye-bye \ 19 | // -c Hello -f AFile.dat Red Green Blue 20 | // (try others yourself) 21 | // 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | /* Flag set by ‘--verbose’. */ 28 | static int verbose_flag; 29 | static int num_flag; 30 | 31 | static struct option long_options[] = 32 | { 33 | /* These options set a flag. */ 34 | {"verbose", no_argument, &verbose_flag, 1}, 35 | {"brief", no_argument, &verbose_flag, 0}, 36 | /* These options don’t set a flag. 37 | We distinguish them by their indices. */ 38 | {"add", no_argument, 0, 'a'}, 39 | {"append", no_argument, 0, 'b'}, 40 | {"delete", required_argument, 0, 'd'}, 41 | {"create", required_argument, 0, 'c'}, 42 | {"file", required_argument, 0, 'f'}, 43 | {"number", optional_argument, &num_flag, 1}, 44 | {"size", optional_argument, 0 , 's'}, 45 | {0, 0, 0, 0} 46 | }; 47 | 48 | int main (int argc, char **argv) 49 | { 50 | int c; 51 | 52 | while (1) { 53 | /* getopt_long stores the option index here. */ 54 | int option_index = 0; 55 | 56 | c = getopt_long (argc, argv, "abc:d:f:s:", 57 | long_options, &option_index); 58 | 59 | /* Detect the end of the options. */ 60 | if (c == -1) 61 | break; 62 | 63 | switch (c) { 64 | case 0: 65 | /* If this option set a flag, do nothing else now. */ 66 | // if (long_options[option_index].flag != 0) 67 | // break; 68 | printf ("option %s", long_options[option_index].name); 69 | if( optarg ) 70 | printf (" with arg %s", optarg); 71 | printf( "\n" ); 72 | break; 73 | 74 | case 'a': 75 | puts ("Option -a"); 76 | break; 77 | 78 | case 'b': 79 | puts ("Option -b"); 80 | break; 81 | 82 | case 'n': 83 | printf( "Option -n"); 84 | if( optarg ) printf( " with value %s" , optarg ); 85 | printf( "\n" ); 86 | break; 87 | 88 | case 'c': 89 | printf ("Option -c with value `%s'\n", optarg); 90 | break; 91 | 92 | case 'd': 93 | printf ("Option -d with value `%s'\n", optarg); 94 | break; 95 | 96 | case 'f': 97 | printf ("Option -f with value `%s'\n", optarg); 98 | break; 99 | 100 | case 's': 101 | printf( "Option -s"); 102 | if( optarg ) printf( " with value %s" , optarg ); 103 | printf( "\n" ); 104 | break; 105 | 106 | case '?': 107 | /* getopt_long already printed an error message. */ 108 | break; 109 | 110 | default: 111 | abort (); 112 | } 113 | } 114 | 115 | /* Instead of reporting ‘--verbose’ 116 | and ‘--brief’ as they are encountered, 117 | we report the final status resulting from them. */ 118 | if (verbose_flag) 119 | puts ("verbose flag is set"); 120 | 121 | /* Print any remaining command line arguments (not options). */ 122 | if (optind < argc) 123 | { 124 | printf ("non-option ARGV-elements: "); 125 | while (optind < argc) 126 | printf ("%s ", argv[optind++]); 127 | putchar ('\n'); 128 | } 129 | 130 | exit (0); 131 | } 132 | 133 | // eof 134 | -------------------------------------------------------------------------------- /Chapter20/showArgs.c: -------------------------------------------------------------------------------- 1 | // showArgs.c 2 | // Chapter 20 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // * retrieve arguments entered on the command line 7 | // 8 | // compile with: 9 | // 10 | // cc showArgs.c -o showArgs -Wall -Werror -std=c11 11 | // 12 | 13 | #include 14 | 15 | int main(int argc, char *argv[]) 16 | { 17 | // argc will never be 0. 18 | // program name is always argv[0] 19 | 20 | if( argc == 1 ) { 21 | printf( " No arguments given on command line.\n" ); 22 | printf( " usage: %s ... \n\n" , argv[0] ); 23 | return 0; 24 | } 25 | 26 | printf( "argument count = [%d]\n" , argc ); 27 | for( int i = 0 ; i < argc ; i++ ) { 28 | if( i == 0 ) 29 | printf( "executable = [%s]\n" , argv[i] ); 30 | else 31 | printf( "argument %d = [%s]\n" , i , argv[i] ); 32 | } 33 | printf( "\n" ); 34 | } 35 | 36 | // eof 37 | -------------------------------------------------------------------------------- /Chapter21/flush.c: -------------------------------------------------------------------------------- 1 | // flush.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate input buffering works in 6 | // "cooked mode" of console i/o. 7 | // Final output is flushed with \n or when program ends. 8 | // 9 | // compile with: 10 | // 11 | // cc flush.c -o flush -Wall -Werror -std=c11 12 | // 13 | 14 | #include // For printf() 15 | #include // For sleep() 16 | 17 | int main( void ) { 18 | printf( "You'll see this immediately.\nNow count to 5 slowly.\n"); 19 | printf( "Then, this appears ... "); 20 | sleep( 5 ); 21 | printf( "when the buffer is finally flushed.\n" ); 22 | } 23 | 24 | // eof 25 | 26 | -------------------------------------------------------------------------------- /Chapter21/internalFormatting.c: -------------------------------------------------------------------------------- 1 | // internalFormatting.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to perform internal data conversion 6 | // using sscanf() and sprintf(). 7 | // This program is very similar to read2NumbersUsingResult.c whichg 8 | // uses scanf(). 9 | // 10 | // compile with: 11 | // 12 | // cc internalFormatting.c -o internalFormatting -Wall -Werror -std=c11 13 | // 14 | 15 | 16 | #include 17 | #include 18 | 19 | const int bufferSize = 80; 20 | 21 | int main( void ) 22 | { 23 | int anInteger = -1; 24 | double aDouble = -1.0; 25 | int numScanned = 0 , numPrinted = 0; 26 | 27 | char sIn[] = "1234 5678.9012"; 28 | char sOut[ bufferSize ]; 29 | memset( sOut , 0 , bufferSize ); 30 | 31 | printf("Using sscanf() on [%s]\n" , sIn ); 32 | numScanned = sscanf( sIn , "%d%lf" , &anInteger , &aDouble ); 33 | printf( "sscanf() was able to assign %d values.\n" , numScanned ); 34 | printf( "1. integer: %d\n" , anInteger ); 35 | printf( "2. double: %lf\n\n" , aDouble ); 36 | 37 | puts( "Using sprintf() to format values to string buffer:" ); 38 | numPrinted = sprintf( sOut , "integer=[%d] double=[%9.4lf]" , anInteger , aDouble ); 39 | printf( "%d characters in output string \"%s\"\n" , numPrinted , sOut ); 40 | } 41 | -------------------------------------------------------------------------------- /Chapter21/nameSorter.c: -------------------------------------------------------------------------------- 1 | // nameSorter.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrates a simple "insertion sort" using an array. 6 | // Input and output is primarily done with fgets() and fputs(). 7 | // 8 | // compile with: 9 | // 10 | // cc nameSorter.c -o nameSorter -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | const int listMax = 100; 19 | const int stringMax = 80; 20 | 21 | typedef char string [ stringMax ]; 22 | 23 | void addName( string* names , string newOne , int* listSize ); 24 | void printNames( string* names , int listSize ); 25 | 26 | void removeNewline( string s ) { 27 | int len = strlen( s ); 28 | s[ len-1 ] = '\0'; 29 | } 30 | 31 | int main( void ) { 32 | string newName; 33 | string nameList[ listMax ]; 34 | int numNames = 0; 35 | 36 | while( printf( "Name: %d: ", numNames+1 ), 37 | fgets( newName , stringMax , stdin ), 38 | removeNewline( newName ) , 39 | strlen( newName ) > 0 ) 40 | addName( nameList , newName , &numNames ); 41 | 42 | printNames( nameList , numNames ); 43 | } 44 | 45 | void addName( string* names , string newName , int* pNumEntries ) { 46 | if( *pNumEntries >= listMax ) { 47 | puts( "List is full!" ); 48 | return; /* the array is full */ 49 | } else { 50 | int k = 0; /* k is position in list to insert newName. */ 51 | bool found = false; /* When found is true, newName goes before an existing 52 | name in the list. */ 53 | 54 | /* Scan through list looking for existing name that newName should come 55 | before. If not found, k is the end of the list. */ 56 | while( !found && k < *pNumEntries ) 57 | found = (strcmp( newName, names[ k++ ] ) < 0); 58 | 59 | if( found ) { 60 | /* Move k back one place to insert newName at k-th position.*/ 61 | k-- ; 62 | /* Move each exising name back in the list, making a space newName */ 63 | for( int j = *pNumEntries ; j > k ; j-- ) { 64 | strcpy( names[ j ] , names[ j-1 ] ); 65 | } 66 | } 67 | /* Insert new string in list at k-th position. */ 68 | strcpy( names[ k ] , newName ); 69 | (*pNumEntries)++; 70 | } 71 | return; 72 | } 73 | 74 | void printNames( string *names , int numEntries ) 75 | { 76 | printf("\nNumber of Entries: %d\n\n" , numEntries ); 77 | for( int i = 0 ; i < numEntries ; i++ ) { 78 | fputs( names[i] , stdout ); 79 | fputc( '\n' , stdout ); 80 | } 81 | } 82 | 83 | // eof 84 | -------------------------------------------------------------------------------- /Chapter21/read2Numbers.c: -------------------------------------------------------------------------------- 1 | // read2Numbers.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to read an integer and a double 6 | // using scanf() and %d and %lf format specifiers. 7 | // 8 | // compile with: 9 | // 10 | // cc read2Numbers.c -o read2Numbers -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | 16 | // Test Input 17 | // * 5 cases are given. 18 | // * Each test ends with the final . 19 | // * Notice how whitespace is important or ignored. 20 | // * Notice how non-numbers terminate number parsing. 21 | // 22 | // 1234 5678.9012 23 | // 24 | // 25 | // 1234 26 | // 5678.9012 27 | // 28 | // 1234.5678 29 | // 30 | // 1234 hello 5678.9012 31 | // 32 | // hello 1234 5678.9012 33 | // 34 | 35 | 36 | int main( void ) 37 | { 38 | int anInteger = -1; 39 | double aDouble = -1.0; 40 | 41 | printf( "Enter an integer and a decimal number: " ); 42 | scanf( "%d%lf" , &anInteger , &aDouble ); 43 | printf( "1. integer: %d\n" , anInteger ); 44 | printf( "2. double: %lf\n\n" , aDouble ); 45 | } 46 | 47 | // eof 48 | -------------------------------------------------------------------------------- /Chapter21/read2NumbersUsingResult.c: -------------------------------------------------------------------------------- 1 | // read2NumbersUsingResult.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to use the result of scanf() 6 | // to determine how many values were correctly converted. 7 | // 8 | // compile with: 9 | // 10 | // cc read2NumbersUsingResult.c -o read2NumbersUsingResult -Wall -Werror -std=c11 11 | // 12 | 13 | #include 14 | 15 | // Test input (5 cases): 16 | // 17 | // 1. 1234 5678.9012 18 | // 2. 19 | // 1234 20 | // 5678.9012 21 | // 3. 1234.5678 22 | // 4. 1234 hello 5678.9012 23 | // 5. 24 | // 25 | 26 | int main( void ) { 27 | int anInteger = -1; 28 | double aDouble = -1.0; 29 | int numScanned = 0; 30 | 31 | printf( "Enter an integer and a decimal number: " ); 32 | 33 | numScanned = scanf( "%d%lf" , &anInteger , &aDouble ); 34 | 35 | printf( "scanf() was able to assign %d values.\n" , numScanned ); 36 | if( numScanned > 0 ) printf( "1. integer: %d\n" , anInteger ); 37 | if( numScanned > 1 ) printf( "2. double: %lf\n" , aDouble ); 38 | printf( "\n" ); 39 | } 40 | 41 | // eof 42 | -------------------------------------------------------------------------------- /Chapter21/readChar.c: -------------------------------------------------------------------------------- 1 | // readChar.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to read a character between 2 integers 6 | // without and with a space in the format specifier. 7 | // 8 | // compile with: 9 | // 10 | // cc readChar.c -o readChar -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | 16 | 17 | // test inputs: 18 | // 19 | // 123m 456 20 | // 123 m456 21 | // 123 w 456 22 | // 23 | 24 | 25 | int main( void ) 26 | { 27 | char aChar; 28 | int anInt1, anInt2; 29 | int numScanned; 30 | 31 | printf( "1st: Enter : " ); 32 | numScanned = scanf( "%d%c%d" , &anInt1 , &aChar , &anInt2 ); 33 | printf( "Values scanned = %d. Character selected: [%c]\n" , 34 | numScanned , aChar ); 35 | 36 | printf( "2nd: Enter : " ); 37 | numScanned = scanf( "%d %c%d" , &anInt1 , &aChar , &anInt2 ); 38 | printf( "Values scanned = %d. Character selected: [%c]\n\n" , 39 | numScanned , aChar ); 40 | } 41 | 42 | // eof 43 | -------------------------------------------------------------------------------- /Chapter21/readDate.c: -------------------------------------------------------------------------------- 1 | // readDate.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to use field width specifiers 6 | // to read data elements with the non-assighnment operater 7 | // to parse characters between date elements. 8 | // 9 | // compile with: 10 | // 11 | // cc readDate.c -o readDate -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | 17 | 18 | // Test Inputs: 19 | // 20 | // 01x01x2020 21 | // 22 | // 02 02 2021 23 | // 24 | // 12^25^2019 25 | // 26 | // 9!30!2019 27 | // 28 | // 12x 5y2020 29 | // 30 | // 7/4/2019 31 | // 32 | // x 33 | 34 | 35 | int main( void ) 36 | { 37 | int year , month , day; 38 | int numScanned; 39 | while( printf("Enter mm*dd*yyyy (any other character to quit): "), 40 | numScanned = scanf( "%2d%*c%2d%*c%4d" , &month , &day , &year ) , 41 | numScanned > 0 ) 42 | printf( "%d.%d.%d\n\n" , month , day , year ); 43 | printf( "\nDone\n" ); 44 | } 45 | 46 | // eof 47 | -------------------------------------------------------------------------------- /Chapter21/readScanSet.c: -------------------------------------------------------------------------------- 1 | // readScanSet.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to use a scan set to limit 6 | // character inputs. 7 | // 8 | // compile with: 9 | // 10 | // cc readScanSet.c -o readScanSet -Wall -Werror -std=c11 11 | // 12 | 13 | #include 14 | 15 | // Test inputs: 16 | // 17 | // aayyeeuuiioo 18 | // 19 | // aeimwouy 20 | // 21 | // a e i o u y 22 | // 23 | 24 | const int bufferSize = 80; 25 | 26 | int main( void ) 27 | { 28 | char stringBuffer[ bufferSize ]; 29 | printf( "Enter only vowels: " ); 30 | scanf( "%[aeiouy]" , stringBuffer ); 31 | printf( "Processed string: [%s]\n\n" , stringBuffer ); 32 | } 33 | 34 | // eof 35 | 36 | -------------------------------------------------------------------------------- /Chapter21/readString.c: -------------------------------------------------------------------------------- 1 | // readString.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to read a string with scanf(). 6 | // Compare to readString2.c 7 | // 8 | // compile with: 9 | // 10 | // cc readString.c -o readString -Wall -Werror -std=c11 11 | // 12 | 13 | 14 | #include 15 | 16 | 17 | // Test inputs: 18 | // 19 | // Anything up to the white space 20 | // 21 | // Every_thing%before;any:white'space\(will%be read into an array.) 22 | // 23 | // Skipping initial white space. 24 | // 25 | 26 | const int bufferSize = 80; 27 | 28 | int main( void ) 29 | { 30 | char stringBuffer[ bufferSize ]; 31 | 32 | printf( "Enter a string: " ); 33 | scanf( "%s" , stringBuffer ); 34 | printf( "Processed string: [%s]\n\n" , stringBuffer ); 35 | } 36 | 37 | // eof 38 | -------------------------------------------------------------------------------- /Chapter21/readString2.c: -------------------------------------------------------------------------------- 1 | // readString2.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to read and write a string with 6 | // gets() and puts(). 7 | // Compare this program to readString.c 8 | // 9 | // compile with: 10 | // 11 | // cc readString2.c -o readString2 -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | 17 | const int bufferSize = 80; 18 | 19 | int main( void ) 20 | { 21 | char stringBuffer[ bufferSize ]; 22 | 23 | printf( "Enter a string: " ); 24 | gets( stringBuffer ); 25 | puts( "You entered: " ); 26 | puts( stringBuffer ); 27 | } 28 | 29 | // eof 30 | -------------------------------------------------------------------------------- /Chapter21/readWidth.c: -------------------------------------------------------------------------------- 1 | // readWidth.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to use the field with specifier 6 | // to read data elements (1st approximation). 7 | // See also readDAte.c for a better solution. 8 | // 9 | // compile with: 10 | // 11 | // cc readWidth.c -o readWidth -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | 17 | 18 | // Test inputs: 19 | // 20 | // 01012020 21 | // 22 | // 02 02 2021 23 | // 24 | // 12252019 25 | // 26 | // 9302019 27 | // 28 | // 12 52020 29 | // 30 | // 7/4/2019 31 | // 32 | 33 | 34 | int main( void ) 35 | { 36 | int year , month , day; 37 | int numScanned; 38 | while( printf("Enter mmddyyyy (any other character to quit): "), 39 | numScanned = scanf( "%2d%2d%4d" , &month , &day , &year ) , 40 | numScanned > 0 ) 41 | printf( "%d/%d/%d\n\n" , month , day , year ); 42 | printf( "\nDone\n" ); 43 | } 44 | 45 | // eof 46 | -------------------------------------------------------------------------------- /Chapter21/usingAtoi.c: -------------------------------------------------------------------------------- 1 | // usingAtoi.c 2 | // Chapter 21 3 | // Learn C Programming 4 | // 5 | // compile with: 6 | // 7 | // cc usingAtoi.c -o usingAtoi -Wall -Werror -std=c11 8 | // 9 | 10 | 11 | #include 12 | #include 13 | 14 | 15 | int main( void ) 16 | { 17 | int anInteger = -1; 18 | double aDouble = -1.0; 19 | 20 | char sInteger[] = "1234" ; 21 | char sDouble[] = "5678.9012"; 22 | 23 | printf("As strings: integer=\"%s\" double=\"%s\"\n" , 24 | sInteger , sDouble ); 25 | anInteger = atoi( sInteger ); 26 | aDouble = atof( sDouble ); 27 | printf("As values: integer=[%d] double=[%lf]\n\n" , 28 | anInteger , aDouble ); 29 | } 30 | 31 | // eof 32 | -------------------------------------------------------------------------------- /Chapter22/open_close_argv.c: -------------------------------------------------------------------------------- 1 | // open_close_argv.c 2 | // Chapter 22 3 | // Learn C Programming 4 | // 5 | // Builds on open_close_fgetstr.c 6 | // Demonstrate how to use argc and argv to get 7 | // input and output filenames from command line. 8 | // 9 | // compile with: 10 | // 11 | // cc open_close_argv.c -o open_close_argv -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | #include // for errno 19 | 20 | 21 | void usage( char* cmd ) { 22 | fprintf( stderr , "usage: %s inputFileName outputFileName\n" , cmd ); 23 | exit( 0 ); 24 | } 25 | 26 | 27 | int main( int argc, char *argv[] ) { 28 | FILE* inputFile = NULL; 29 | FILE* outputFile = NULL; 30 | 31 | if( argc != 3 ) usage( argv[0] ); 32 | 33 | if( NULL == ( inputFile = fopen( argv[1] , "r") ) ) { 34 | fprintf( stderr, "input file: %s: %s\n", argv[1], strerror(errno)); 35 | exit( 1 ); 36 | } 37 | fprintf( stderr , "%s opened for reading.\n" , argv[1] ); 38 | 39 | if( NULL == ( outputFile = fopen( argv[2] , "w" ) ) ) { 40 | fprintf( stderr, "output file: %s: %s\n", argv[2], strerror(errno)); 41 | exit( 1 ); 42 | } 43 | fprintf( stderr , "%s opened for writing.\n" , argv[2] ); 44 | 45 | fprintf( stderr , "Do work here.\n" ); 46 | 47 | fprintf( stderr , "Closing files.\n" ); 48 | fclose( inputFile ); 49 | fflush( outputFile ); 50 | fclose( outputFile ); 51 | } 52 | 53 | // eof 54 | -------------------------------------------------------------------------------- /Chapter22/open_close_fgetstr.c: -------------------------------------------------------------------------------- 1 | // open_close_fgetstr.c 2 | // Chapter 22 3 | // Learn C Programming 4 | // 5 | // Builds on open_close_string.c 6 | // Demonstrate how to get filenames for input and output 7 | // via prompt. 8 | // 9 | // compile with: 10 | // 11 | // cc open_close_fgetstr.c -o open_close_fgetstr -Wall -Werror -std=c11 12 | // 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | #include // for errno 19 | 20 | 21 | int main(int argc, char *argv[]) { 22 | FILE* inputFile; 23 | FILE* outputFile; 24 | 25 | char inputFilename[80] = {0}; 26 | char outputFilename[80] = {0}; 27 | 28 | fprintf( stdout , "Enter name of input file: " ); 29 | fscanf( stdin , "%80s" , inputFilename ); 30 | inputFile = fopen( inputFilename , "r" ); 31 | if( NULL == inputFile ) { 32 | fprintf( stderr, "input file: %s: %s\n", inputFilename , strerror( errno ) ); 33 | exit( 1 ); 34 | } 35 | 36 | fprintf( stdout , "Enter name of output file: " ); 37 | fscanf( stdin , "%80s" , outputFilename ); 38 | outputFile = fopen( outputFilename , "w" ); 39 | if( NULL == outputFile ) { 40 | fprintf( stderr, "input file: %s: %s\n", outputFilename , strerror( errno ) ); 41 | exit( 1 ); 42 | } 43 | 44 | fprintf( stdout , "\"%s\" opened for reading.\n" , inputFilename ); 45 | fprintf( stdout , "\"%s\" opened for writing.\n" , outputFilename ); 46 | fprintf( stderr , "Do work here.\n" ); 47 | 48 | fprintf( stderr , "Closing files.\n" ); 49 | fclose( inputFile ); 50 | fflush( outputFile ); 51 | fclose( outputFile ); 52 | } 53 | 54 | // eof 55 | 56 | -------------------------------------------------------------------------------- /Chapter22/open_close_string.c: -------------------------------------------------------------------------------- 1 | // open_close_string.c 2 | // Chapter 22 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to 6 | // 1) open a file for reading, 7 | // 2) open a file for writing 8 | // 3) close input file 9 | // 4) flush output file before closing 10 | // 5) close output file. 11 | // 6) use of errno and strerror() function. 12 | // 13 | // compile with: 14 | // 15 | // cc open_close_string.c -o open_close_string -Wall -Werror -std=c11 16 | // 17 | 18 | 19 | #include 20 | #include // for exit 21 | #include 22 | #include // for errno 23 | 24 | 25 | int main( void ) { 26 | FILE* inputFile; 27 | FILE* outputFile; 28 | 29 | char inputFilename[] = "./input.data"; 30 | char outputFilename[] = "./output.data"; 31 | 32 | inputFile = fopen( inputFilename , "r" ); 33 | if( NULL == inputFile ) { 34 | fprintf( stderr, "input file: %s: %s\n", inputFilename , strerror( errno ) ); 35 | exit( 1 ); 36 | } 37 | 38 | outputFile = fopen( outputFilename , "w" ); 39 | if( NULL == outputFile ) { 40 | fprintf( stderr, "input file: %s: %s\n", outputFilename , strerror( errno ) ); 41 | exit( 1 ); 42 | } 43 | 44 | // Files now open for reading and writing. 45 | 46 | fprintf( stdout , "\"%s\" opened for reading.\n" , inputFilename ); 47 | fprintf( stdout , "\"%s\" opened for writing.\n" , outputFilename ); 48 | 49 | fprintf( stderr , "Do work here.\n" ); 50 | 51 | fprintf( stderr , "Closing files.\n" ); 52 | fclose( inputFile ); 53 | fflush( outputFile ); 54 | fclose( outputFile ); 55 | } 56 | 57 | // eof 58 | 59 | -------------------------------------------------------------------------------- /Chapter23/createUnsorted.c: -------------------------------------------------------------------------------- 1 | // createUnsorted.c 2 | // Chapter 23 3 | // Learn C Programming 4 | // 5 | // This program builds upon getoptFiles.c 6 | // 7 | // Demonstrate how to use fgets() and fputs() in a *useful* way, 8 | // removing and adding '\n' as needed to each. 9 | // 10 | // compile with: 11 | // 12 | // cc createUnsorted.c -o createUnsorted -Wall -Werror -std=c11 13 | // 14 | 15 | #include 16 | #include 17 | #include 18 | #include // for getopt 19 | #include // for errno 20 | #include 21 | 22 | const int stringMax = 80; 23 | 24 | void usage( char* cmd ); 25 | int getName( FILE* inFileDesc , char* ppStr ); 26 | void putName( char* pStr , FILE* outFileDesc ); 27 | int trimStr( char* pStr ); 28 | 29 | 30 | int main(int argc, char *argv[]) { 31 | int ch; 32 | FILE* inputFile = NULL; 33 | FILE* outputFile = NULL; 34 | 35 | while( ( ch = getopt( argc , argv , "i:o:h" ) ) != -1 ) { 36 | switch (ch) { 37 | case 'i': 38 | if( NULL == ( inputFile = fopen( optarg , "r") ) ) { 39 | fprintf( stderr, "input file \"%s\": %s\n", optarg, strerror(errno)); 40 | exit( EXIT_FAILURE ); 41 | } 42 | fprintf( stderr , "Using \"%s\" for input.\n" , optarg ); 43 | break; 44 | case 'o': 45 | if( NULL == ( outputFile = fopen( optarg , "a" ) ) ) { 46 | fprintf( stderr, "output file \"%s\": %s\n", optarg, strerror(errno)); 47 | exit( EXIT_FAILURE ); 48 | } 49 | fprintf( stderr , "Using \"%s\": for output.\n" , optarg ); 50 | break; 51 | case '?': 52 | case 'h': 53 | default: 54 | usage( argv[0] ); 55 | break; 56 | } 57 | } 58 | 59 | if( !inputFile ) { 60 | inputFile = stdin; 61 | fprintf( stderr , "Using stdin for input.\n" ); 62 | } 63 | 64 | if( !outputFile ) { 65 | outputFile = stdout; 66 | fprintf( stderr , "Using stdout for output.\n" ); 67 | } 68 | 69 | char nameBuffer[ stringMax ]; 70 | 71 | while( getName( inputFile , nameBuffer ) ) { 72 | putName( nameBuffer , outputFile ); 73 | } 74 | 75 | fprintf( stderr , "Closing files.\n" ); 76 | fclose( inputFile ); 77 | fflush( outputFile ); 78 | fclose( outputFile ); 79 | } 80 | 81 | 82 | void usage( char* cmd ) 83 | { 84 | fprintf( stderr , "usage: %s [-i inputFileName] [-o outputFileName]\n" , cmd ); 85 | fprintf( stderr , " If -i inputFileName is not given, stdin is used.\n" ); 86 | fprintf( stderr , " If -o outputFileName is not given stdout is used.\n\n" ); 87 | exit( 0 ); 88 | } 89 | 90 | 91 | // getName -- Read nameString (a full line) 92 | // If input is from stdin, give prompt. 93 | // Trim excess whitespace before and after string 94 | // (including which fgets() preserves). 95 | // parametrs: 96 | // inFileDesc - input stream 97 | // nameStr - array of characters allocated by caller 98 | // returns: 99 | // length of nameStr. 0, or empty string, means end of input. 100 | // 101 | int getName( FILE* inFileDesc , char* pStr ) { 102 | static int numNames = 0; 103 | int len; 104 | 105 | memset( pStr , 0 , stringMax ); 106 | 107 | if( stdin == inFileDesc ) 108 | fprintf( stdout , "Name %d: ", numNames+1 ); 109 | 110 | fgets( pStr , stringMax , inFileDesc ); 111 | 112 | len = trimStr( pStr ); 113 | 114 | if( len ) numNames++; 115 | return len; 116 | } 117 | 118 | 119 | // putName - write nameString, appending 120 | // 121 | void putName( char* pStr , FILE* outFileDesc ) { 122 | fputs( pStr , outFileDesc ); 123 | fputc( '\n' , outFileDesc ); 124 | } 125 | 126 | 127 | // trimStr - Trims beginning and end of a string. 128 | // Creates a working copy of string, trims that, 129 | // and copies the trimmed string back to original. 130 | // 131 | // Because a trimmed string will always be the same 132 | // or fewer characters than the original, the only 133 | // side effect of this function is the modifiction of 134 | // the original string in place. 135 | // 136 | // Parameter: 137 | // pString - pointer of string to be trimmed/modified. 138 | // Returns: 139 | // The length of the string after trimming. 140 | // 141 | int trimStr( char* pString ) 142 | { 143 | size_t first , last , lenIn , lenOut ; 144 | first = last = lenIn = lenOut = 0; 145 | 146 | lenIn = strlen( pString ); 147 | char tmpStr[ lenIn+1 ]; // Create working copy. 148 | strcpy( tmpStr , pString ); // 149 | char* pTmp = tmpStr; // pTmp may change in Left Trim segment. 150 | 151 | // Left Trim 152 | // Find 1st non-whitespace char; pStr will point to that. 153 | while( isspace( pTmp[ first ] ) ) 154 | first++; 155 | pTmp += first; 156 | 157 | lenOut = strlen( pTmp ); // Get new length after Left Trim. 158 | if( lenOut ) { // Check for empty string. 159 | // e.g. " " trimmed to nothing. 160 | // Right Trim 161 | // Find 1st non-whitespace char & set NUL character there. 162 | last = lenOut-1; // off-by-1 adjustment. 163 | while( isspace( pTmp[ last ] ) ) 164 | last--; 165 | pTmp[ last+1 ] = '\0'; // Terminate trimmed string. 166 | } 167 | lenOut = strlen( pTmp ); // Length of trimmed string. 168 | if( lenIn != lenOut ) // Did we change anything? 169 | strcpy( pString , pTmp ); // Yes, copy trimmed string back. 170 | return lenOut; 171 | } 172 | 173 | // eof 174 | -------------------------------------------------------------------------------- /Chapter23/getoptFiles.c: -------------------------------------------------------------------------------- 1 | // getoptFiles.c 2 | // Chapter 23 3 | // Learn C Programming 4 | // 5 | // Demonstrate how to use getopt() to 6 | // 1) open an input file or use stdin 7 | // 2) open an output file or use stdout 8 | // 9 | // This is a "template" program in that it can be used 10 | // as the starting point for any number of different kinds 11 | // of file-processing programs. 12 | // 13 | // compile with: 14 | // 15 | // cc getoptFiles.c -o getoptFiles -Wall -Werror -std=c11 16 | // 17 | 18 | #include 19 | #include 20 | #include 21 | #include // for getopt 22 | #include // for errno 23 | 24 | 25 | void usage( char* cmd ) 26 | { 27 | fprintf( stderr , "usage: %s [-i inputFileName] [-o outputFileName]\n" , cmd ); 28 | fprintf( stderr , " If -i inputFileName is not given, stdin is used.\n" ); 29 | fprintf( stderr , " If -o outputFileName is not given stdout is used.\n\n" ); 30 | exit( 0 ); 31 | } 32 | 33 | 34 | int main(int argc, char *argv[]) { 35 | 36 | int ch; 37 | FILE* inputFile = NULL; 38 | FILE* outputFile = NULL; 39 | 40 | while( ( ch = getopt( argc , argv , "i:o:h" ) ) != -1 ) { 41 | switch (ch) { 42 | case 'i': 43 | if( NULL == ( inputFile = fopen( optarg , "r") ) ) { 44 | fprintf( stderr, "input file \"%s\": %s\n", optarg, strerror(errno)); 45 | exit( EXIT_FAILURE ); 46 | } 47 | fprintf( stderr , "Using \"%s\" for input.\n" , optarg ); 48 | break; 49 | case 'o': 50 | if( NULL == ( outputFile = fopen( optarg , "a" ) ) ) { 51 | fprintf( stderr, "output file \"%s\": %s\n", optarg, strerror(errno)); 52 | exit( EXIT_FAILURE ); 53 | } 54 | fprintf( stderr , "Using \"%s\": for output.\n" , optarg ); 55 | break; 56 | case '?': 57 | case 'h': 58 | default: 59 | usage( argv[0] ); 60 | break; 61 | } 62 | } 63 | 64 | if( !inputFile ) { 65 | inputFile = stdin; 66 | fprintf( stderr , "Using stdin for input.\n" ); 67 | } 68 | 69 | if( !outputFile ) { 70 | outputFile = stdout; 71 | fprintf( stderr , "Using stdout for output.\n" ); 72 | } 73 | 74 | fprintf( stderr , "Do work here.\n" ); 75 | 76 | fprintf( stderr , "Closing files.\n" ); 77 | fclose( inputFile ); 78 | fflush( outputFile ); 79 | fclose( outputFile ); 80 | } 81 | 82 | // eof 83 | -------------------------------------------------------------------------------- /Chapter23/nameList.c: -------------------------------------------------------------------------------- 1 | // nameList.c 2 | // Chapter 23 3 | // Learn C Programming 4 | // 5 | // A family of singly-linked list routines to 6 | // perform insertion sort. 7 | // 8 | // Do not compile alone. No main(). Part of sortNames.c 9 | // 10 | 11 | #include "nameList.h" 12 | 13 | 14 | NameList* CreateNameList( void ) { 15 | NameList* pNL = (NameList*)calloc( 1 , sizeof( NameList )); 16 | if( pNL == NULL ) OutOfStorage(); 17 | return pNL; 18 | } 19 | 20 | 21 | ListNode* CreateListNode( char* pNameToAdd ) { 22 | ListNode* pNewNode = (ListNode*)calloc( 1 , sizeof( ListNode ) ); 23 | if( pNewNode == NULL ) OutOfStorage(); 24 | pNewNode->pData = (char*)calloc(1, strlen(pNameToAdd)+1 ); 25 | if( pNewNode->pData == NULL ) OutOfStorage(); 26 | strcpy( pNewNode->pData , pNameToAdd ); 27 | return pNewNode; 28 | } 29 | 30 | 31 | void AddName( NameList* pNames , char* pNameToAdd ) { 32 | ListNode* pNewName = CreateListNode( pNameToAdd ); 33 | 34 | if( IsEmpty( pNames ) ) { // Empty list. Insert as 1st item. 35 | pNames->pFirstNode = pNewName; 36 | (pNames->nodeCount)++; 37 | return; 38 | } 39 | 40 | (pNames->nodeCount)++; 41 | ListNode* curr; 42 | ListNode* prev; 43 | curr = prev = pNames->pFirstNode; 44 | while( curr ) { 45 | // Perform string comparison here. 46 | if( strcmp( pNewName->pData , curr->pData ) < 0 ) { 47 | // Found insertion point before an existing name. 48 | if( curr == pNames->pFirstNode) { // New names comes before all. Insert at front 49 | pNames->pFirstNode = pNewName; 50 | pNewName->pNext = curr; 51 | } else { // Insert somewhere in middle 52 | prev->pNext = pNewName; 53 | pNewName->pNext = curr; 54 | } 55 | return; 56 | } 57 | prev = curr; // Adjust pointers for next iteration. 58 | curr = prev->pNext; 59 | } 60 | prev->pNext = pNewName; // New name comes after all. Insert at end. 61 | } 62 | 63 | 64 | void PrintNames( FILE * outputDesc , NameList* pNames ) { 65 | ListNode* curr = pNames->pFirstNode; 66 | while( curr ) { 67 | fputs( curr->pData , outputDesc ); 68 | fputc( '\n' , outputDesc ); 69 | curr = curr->pNext; 70 | } 71 | } 72 | 73 | 74 | void DeleteNames( NameList* pNames ) { 75 | while( pNames->pFirstNode ) { 76 | ListNode* temp = pNames->pFirstNode; 77 | pNames->pFirstNode = pNames->pFirstNode->pNext; 78 | free( temp->pData ); 79 | free( temp ); 80 | } 81 | } 82 | 83 | bool IsEmpty( NameList* pNames ) { 84 | return pNames->nodeCount==0; 85 | } 86 | 87 | 88 | void OutOfStorage( void ) { 89 | fprintf( stderr , "### FATAL RUNTIME ERROR ### No Memory Available" ); 90 | exit( EXIT_FAILURE ); 91 | } 92 | 93 | // eof 94 | -------------------------------------------------------------------------------- /Chapter23/nameList.h: -------------------------------------------------------------------------------- 1 | // nameList.h 2 | // Chapter 23 3 | // Learn C Programming 4 | // 5 | // Header file for nameList.c 6 | // 7 | 8 | #ifndef _SORT_NAMES_H_ 9 | #define _SORT_NAMES_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef char ListData; 17 | 18 | typedef struct _Node ListNode; 19 | typedef struct _Node { 20 | ListNode* pNext; 21 | ListData* pData; 22 | } ListNode; 23 | 24 | typedef struct { 25 | ListNode* pFirstNode; 26 | int nodeCount; 27 | } NameList; 28 | 29 | NameList* CreateNameList(); 30 | ListNode* CreateListNode( char* pNameToAdd ); 31 | void AddName( NameList* pNames , char* pNameToAdd ); 32 | void DeleteNames( NameList* pNames ); 33 | bool IsEmpty( NameList* pNames ); 34 | void PrintNames( FILE* outputDesc , NameList* pNames ); 35 | 36 | void OutOfStorage( void ); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /Chapter23/sortNames.c: -------------------------------------------------------------------------------- 1 | // sortNames.c 2 | // Chapter 23 3 | // Learn C Programming 4 | // 5 | // This program builds upon createUnsorted.c 6 | // 7 | // Adds sorting of input lines into a singly-linked 8 | // list with insertion-sort approach. 9 | // 10 | // Dependencies: 11 | // nameList.h 12 | // nameList.c 13 | // 14 | // Compile with: 15 | // 16 | // cc sortNames.c nameList.c -o sortNames -Wall -Werror -std=c11 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include // for getopt 23 | #include // for errno 24 | #include 25 | 26 | #include "nameList.h" 27 | 28 | 29 | const int stringMax = 80; 30 | 31 | 32 | void usage( char * cmd ); 33 | int getName( FILE* inFileDesc , char* ppStr ); 34 | void putName( char* pStr , FILE* outFileDesc ); 35 | int trimStr( char* pStr ); 36 | 37 | 38 | int main(int argc, char *argv[]) { 39 | int ch; 40 | FILE* inputFile = NULL; 41 | FILE* outputFile = NULL; 42 | 43 | while( ( ch = getopt( argc , argv , "i:o:h" ) ) != -1 ) { 44 | switch (ch) { 45 | case 'i': 46 | if( NULL == ( inputFile = fopen( optarg , "r") ) ) { 47 | fprintf( stderr, "input file \"%s\": %s\n", optarg, strerror(errno)); 48 | exit( EXIT_FAILURE ); 49 | } 50 | fprintf( stderr , "Using \"%s\" for input.\n" , optarg ); 51 | break; 52 | case 'o': 53 | if( NULL == ( outputFile = fopen( optarg , "w" ) ) ) { 54 | fprintf( stderr, "output file \"%s\": %s\n", optarg, strerror(errno)); 55 | exit( EXIT_FAILURE ); 56 | } 57 | fprintf( stderr , "Using \"%s\": for output.\n" , optarg ); 58 | break; 59 | case '?': 60 | case 'h': 61 | default: 62 | usage( argv[0] ); 63 | break; 64 | } 65 | } 66 | 67 | if( !inputFile ) { 68 | inputFile = stdin; 69 | fprintf( stderr , "Using stdin for input.\n" ); 70 | } 71 | 72 | if( !outputFile ) { 73 | outputFile = stdout; 74 | fprintf( stderr , "Using stdout for output.\n" ); 75 | } 76 | 77 | char nameBuffer[ stringMax ]; 78 | NameList nameList = {0}; 79 | 80 | while( getName( inputFile , nameBuffer ) ) { 81 | AddName( &nameList , nameBuffer ); 82 | } 83 | 84 | PrintNames( outputFile , &nameList ); 85 | DeleteNames( &nameList ); 86 | 87 | fprintf( stderr , "Closing files.\n" ); 88 | fclose( inputFile ); 89 | fflush( outputFile ); 90 | fclose( outputFile ); 91 | } 92 | 93 | 94 | void usage( char* cmd ) 95 | { 96 | fprintf( stderr , "usage: %s [-i inputFileName] [-o outputFileName]\n" , cmd ); 97 | fprintf( stderr , " If -i inputFileName is not given, stdin is used.\n" ); 98 | fprintf( stderr , " If -o outputFileName is not given stdout is used.\n\n" ); 99 | exit( 0 ); 100 | } 101 | 102 | 103 | // getName -- Read nameString (a full line) 104 | // If input is from stdin, give prompt. 105 | // Trim excess whitespace before and after string 106 | // (including which fgets() preserves). 107 | // parametrs: 108 | // inFileDesc - input stream 109 | // nameStr - array of characters allocated by caller 110 | // returns: 111 | // length of nameStr. 0, or empty string, means end of input. 112 | // 113 | int getName( FILE* inFileDesc , char* pStr ) { 114 | static int numNames = 0; 115 | int len; 116 | 117 | memset( pStr , 0 , stringMax ); 118 | 119 | if( stdin == inFileDesc ) 120 | fprintf( stdout , "Name %d: ", numNames+1 ); 121 | 122 | fgets( pStr , stringMax , inFileDesc ); 123 | 124 | len = trimStr( pStr ); 125 | 126 | if( len ) numNames++; 127 | return len; 128 | } 129 | 130 | 131 | // putName - write nameString, appending 132 | // 133 | void putName( char* pStr , FILE* outFileDesc ) { 134 | fputs( pStr , outFileDesc ); 135 | fputc( '\n' , outFileDesc ); 136 | } 137 | 138 | 139 | // trimStr - Trims beginning and end of a string. 140 | // Creates a working copy of string, trims that, 141 | // and copies the trimmed string back to original. 142 | // 143 | // Because a trimmed string will always be the same 144 | // or fewer characters than the original, the only 145 | // side effect of this function is the modifiction of 146 | // the original string in place. 147 | // 148 | // Parameter: 149 | // pString - pointer of string to be trimmed/modified. 150 | // Returns: 151 | // The length of the string after trimming. 152 | // 153 | int trimStr( char* pString ) 154 | { 155 | size_t first , last , lenIn , lenOut ; 156 | first = last = lenIn = lenOut = 0; 157 | 158 | lenIn = strlen( pString ); 159 | char tmpStr[ lenIn+1 ]; // Create working copy. 160 | strcpy( tmpStr , pString ); // 161 | char* pTmp = tmpStr; // pTmp may change in Left Trim segment. 162 | 163 | // Left Trim 164 | // Find 1st non-whitespace char; pStr will point to that. 165 | while( isspace( pTmp[ first ] ) ) 166 | first++; 167 | pTmp += first; 168 | 169 | lenOut = strlen( pTmp ); // Get new length after Left Trim. 170 | if( lenOut ) { // Check for empty string. 171 | // e.g. " " trimmed to nothing. 172 | // Right Trim 173 | // Find 1st non-whitespace char & set NUL character there. 174 | last = lenOut-1; // off-by-1 adjustment. 175 | while( isspace( pTmp[ last ] ) ) 176 | last--; 177 | pTmp[ last+1 ] = '\0'; // Terminate trimmed string. 178 | } 179 | lenOut = strlen( pTmp ); // Length of trimmed string. 180 | if( lenIn != lenOut ) // Did we change anything? 181 | strcpy( pString , pTmp ); // Yes, copy trimmed string back. 182 | return lenOut; 183 | } 184 | 185 | // eof 186 | -------------------------------------------------------------------------------- /Chapter23/test_trimStr.c: -------------------------------------------------------------------------------- 1 | // test_trim.c 2 | // Chapter 23 3 | // Learn C Programming 4 | // 5 | // This program tests the trimStr() and trimStrInPlace() 6 | // functions. 7 | // 8 | // trimStr() returns a pointer to the beginning of the trimmed string, 9 | // modifying the original string. 10 | // 11 | // trimStrInPlace() (1) copies the trimmed string back to the original 12 | // string using same pointer and (2) returns length of the 13 | // trimmed string. 14 | // THIS IS PREFERRED FUNCTION TO USE. 15 | // 16 | // Compile with: 17 | // 18 | // cc test_trim.c -o test_trim -Wall -Werror -std=c11 19 | // 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | char* trimStr( char* pString ); 26 | int trimStrInPlace( char* pString ); 27 | 28 | void testTrim( int testNum , char* pString ); 29 | 30 | int main( void ) { 31 | 32 | testTrim( 1 , "Hello, World!\n" ); 33 | testTrim( 2 , "Box of frogs \t \n" ); 34 | testTrim( 3 , " \t Bag of hammers" ); 35 | testTrim( 4 , "\t\t Sack of ferrets\t\t " ); 36 | testTrim( 5 , " \t\n\v\t\r " ); 37 | testTrim( 6 , "" ); 38 | testTrim( 7 , "Goodbye, World!" ); 39 | } 40 | 41 | // trimStr - Trims beginning and end of a string. 42 | // Pointer to beginning of input string may be 43 | // modified; therefore, return value is essential. 44 | // 45 | // Parameter: 46 | // pString - pointer to string to be trimmed. 47 | // Returns: 48 | // A pointer to the beginning of the trimmed string. 49 | // 50 | char* trimStr( char* pString ) 51 | { 52 | size_t first , last , len ; 53 | first = last = len = 0; 54 | 55 | // Left Trim 56 | // Find 1st non-whitespace char; pStr will point to that. 57 | while( isspace( pString[ first ] ) ) 58 | first++; 59 | pString += first; 60 | 61 | len = strlen( pString ); // Get new length after Left Trim. 62 | if( len ) { // Check for empty string. e.g. " " trimmed to nothing. 63 | // Right Trim 64 | // Find 1st non-whitespace char & set NUL character there. 65 | last = len-1; // off-by-1 adjustment. 66 | while( isspace( pString[ last ] ) ) 67 | last--; 68 | pString[ last+1 ] = 0; // Terminate trimmed string. 69 | } 70 | return pString; 71 | } 72 | 73 | 74 | // trimStrInPlace - Trims beginning and end of a string. 75 | // Creates a working copy of string, trims that, 76 | // and copies the trimmed string back to original. 77 | // 78 | // Because a trimmed string will always be the same 79 | // or fewer characters than the original, the only 80 | // side effect of this function is the modifiction of 81 | // the original string in place. 82 | // 83 | // Parameter: 84 | // pString - pointer of string to be trimmed/modified. 85 | // Returns: 86 | // The length of the string after trimming. 87 | // 88 | int trimStrInPlace( char* pString ) 89 | { 90 | size_t first , last , lenIn , lenOut ; 91 | first = last = lenIn = lenOut = 0; 92 | 93 | lenIn = strlen( pString ); // 94 | char tmpStr[ lenIn+1 ]; // Create working copy. 95 | strcpy( tmpStr , pString ); // 96 | char* pTmp = tmpStr; // pTmp may change in Left Trim segment. 97 | 98 | // Left Trim 99 | // Find 1st non-whitespace char; pStr will point to that. 100 | while( isspace( pTmp[ first ] ) ) 101 | first++; 102 | pTmp += first; 103 | 104 | lenOut = strlen( pTmp ); // Get new length after Left Trim. 105 | if( lenOut ) { // Check for empty string. e.g. " " trimmed to nothing. 106 | // Right Trim 107 | // Find 1st non-whitespace char & set NUL character there. 108 | last = lenOut-1; // off-by-1 adjustment. 109 | while( isspace( pTmp[ last ] ) ) 110 | last--; 111 | pTmp[ last+1 ] = '\0'; // Terminate trimmed string. 112 | } 113 | lenOut = strlen( pTmp ); // Length of trimmed string. 114 | if( lenIn != lenOut ) // Did we change anything? 115 | strcpy( pString , pTmp ); // Copy trimmed string back to input string. 116 | return lenOut; 117 | } 118 | 119 | 120 | void testTrim( int testNum , char* pString ) 121 | { 122 | size_t len; 123 | char testString[ strlen( pString ) + 1]; 124 | char* pTest; 125 | 126 | strcpy( testString , pString ); 127 | fprintf( stderr , "%1d. original: \"%s\" [len:%d]\n" , testNum, testString , (int)strlen(pString) ); 128 | pTest = trimStr( testString ); 129 | fprintf( stderr , " trimStr: \"%s\" [len:%d]\n" , pTest , (int)strlen( pTest )); 130 | 131 | strcpy( testString , pString ); 132 | len = trimStrInPlace( testString ); 133 | fprintf( stderr , " trimStr2: \"%s\" [len:%d]\n\n" , testString , (int)len ) ; 134 | } 135 | 136 | // eof 137 | -------------------------------------------------------------------------------- /Chapter24/card.c: -------------------------------------------------------------------------------- 1 | // card.c 2 | // Chapter 24 3 | // Learn C Programming 4 | // 5 | // To compile: 6 | // see main program source file: dealer.c 7 | // 8 | 9 | 10 | #include "dealer.h" 11 | 12 | 13 | // ============================================ 14 | // Operations on a Card 15 | // ============================================ 16 | 17 | 18 | void InitializeCard( Card* pCard, Suit s , Face f , bool w ) { 19 | pCard->suit = s; 20 | pCard->suitValue = (int)s; 21 | 22 | pCard->face = f; 23 | pCard->faceValue = (int)f; 24 | 25 | pCard->isWild = w; 26 | } 27 | 28 | 29 | void PrintCard( Card* pCard ) { 30 | char cardStr[20] = {0}; 31 | CardToString( pCard , cardStr ); 32 | printf( "%18s" , cardStr ); 33 | } 34 | 35 | 36 | void CardToString( Card* pCard , char pCardStr[20] ) { 37 | switch( pCard->face ) { 38 | case two: strcpy( pCardStr , " 2 " ); break; 39 | case three: strcpy( pCardStr , " 3 " ); break; 40 | case four: strcpy( pCardStr , " 4 " ); break; 41 | case five: strcpy( pCardStr , " 5 " ); break; 42 | case six: strcpy( pCardStr , " 6 " ); break; 43 | case seven: strcpy( pCardStr , " 7 " ); break; 44 | case eight: strcpy( pCardStr , " 8 " ); break; 45 | case nine: strcpy( pCardStr , " 9 " ); break; 46 | case ten: strcpy( pCardStr , " 10 " ); break; 47 | case jack: strcpy( pCardStr , " Jack " ); break; 48 | case queen: strcpy( pCardStr , "Queen " ); break; 49 | case king: strcpy( pCardStr , " King " ); break; 50 | case ace: strcpy( pCardStr , " Ace " ); break; 51 | default: strcpy( pCardStr , " ??? " ); break; 52 | } 53 | switch( pCard->suit ) { 54 | case spade: strcat( pCardStr , "of Spades "); break; 55 | case heart: strcat( pCardStr , "of Hearts "); break; 56 | case diamond: strcat( pCardStr , "of Diamonds"); break; 57 | case club: strcat( pCardStr , "of Clubs "); break; 58 | default: strcat( pCardStr , "of ???s "); break; 59 | } 60 | } 61 | 62 | // eof 63 | -------------------------------------------------------------------------------- /Chapter24/card.h: -------------------------------------------------------------------------------- 1 | // card.h 2 | // Chapter 24 3 | // Learn C Programming 4 | // 5 | // Header file for card.c 6 | // 7 | 8 | #ifndef _CARD_H_ 9 | #define _CARD_H_ 10 | 11 | enum { 12 | kNotWildCard = 0, 13 | kWildCard = 1, 14 | kCardsInSuit = 13 15 | }; 16 | 17 | // 18 | // Card Suits 19 | // 20 | typedef enum { 21 | club = 1, 22 | diamond, 23 | heart, 24 | spade 25 | } Suit; 26 | 27 | // 28 | // Card Faces 29 | // 30 | typedef enum { 31 | one = 1, 32 | two , 33 | three , 34 | four , 35 | five , 36 | six , 37 | seven , 38 | eight , 39 | nine , 40 | ten , 41 | jack , 42 | queen , 43 | king , 44 | ace 45 | } Face; 46 | 47 | 48 | // 49 | // A Card 50 | // 51 | typedef struct { 52 | Suit suit; 53 | int suitValue; 54 | Face face; 55 | int faceValue; 56 | bool isWild; 57 | } Card; 58 | 59 | // 60 | // Operations on a Card 61 | // 62 | void InitializeCard( Card* pCard , Suit s , Face f , bool w ); 63 | void PrintCard( Card* pCard ); 64 | void CardToString( Card* pCard , char pCardStr[20] ); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /Chapter24/dealer.c: -------------------------------------------------------------------------------- 1 | // dealer.c 2 | // Chapter 24 3 | // Learn C Programming 4 | // 5 | // Demonstrate 6 | // 1) how to group data structures and functions that 7 | // manipulate them into .c/.h pairs. 8 | // 2) use a common header file for all source files. 9 | // 3) use preprocessor directives to eliminate redundant include file preprocessing 10 | // 4) build a multi-file program 11 | // 12 | // Dependencies: 13 | // 14 | // card.h card.c 15 | // hand.h hand.c 16 | // deck.h deck.c 17 | // 18 | // Compile with: 19 | // 20 | // cc dealer.c card.c hand.c deck.c -o dealer -Wall -Werror -std=c11 21 | // 22 | 23 | #include "dealer.h" 24 | 25 | int main( void ) { 26 | Deck deck; 27 | Deck* pDeck = &deck; 28 | 29 | InitializeDeck( pDeck ); 30 | PrintDeck( pDeck ); 31 | 32 | ShuffleDeck( pDeck ); 33 | PrintDeck( pDeck ); 34 | 35 | Hand h1 , h2 , h3 , h4; 36 | 37 | Hand* hands[] = { &h1 , &h2 , &h3 , &h4 }; 38 | 39 | for( int i = 0 ; i < kNumHands ; i++ ) { 40 | InitializeHand( hands[i] ); 41 | } 42 | 43 | for( int i = 0 ; i < kCardsInHand ; i++ ) { 44 | for( int j = 0 ; j < kNumHands ; j++ ) { 45 | AddCardToHand( hands[j] , DealCardFromDeck( pDeck ) ); 46 | } 47 | } 48 | PrintAllHands( hands ); 49 | PrintDeck( pDeck ); 50 | 51 | return 0; 52 | } 53 | 54 | // eof 55 | 56 | -------------------------------------------------------------------------------- /Chapter24/dealer.h: -------------------------------------------------------------------------------- 1 | // dealer.h 2 | // Chapter 24 3 | // Learn C Programming 4 | // 5 | // Header file for dealer.c and common to 6 | // other source files: card.c, hand.c, and deck.c 7 | // 8 | 9 | #include // for Boolean 10 | #include // for printf() 11 | #include // for strcpy() and strcat() 12 | #include // for rand() and srand() 13 | #include // for date(). 14 | 15 | #include "card.h" 16 | #include "hand.h" 17 | #include "deck.h" 18 | 19 | // eof 20 | -------------------------------------------------------------------------------- /Chapter24/deck.c: -------------------------------------------------------------------------------- 1 | // deck.c 2 | // Chapter 24 3 | // Learn C Programming 4 | // 5 | // To compile: 6 | // see main program source file: dealer.c 7 | // 8 | 9 | 10 | #include "dealer.h" 11 | 12 | 13 | // ============================================ 14 | // Operations on a Deck of Cards 15 | // ============================================ 16 | 17 | 18 | void InitializeDeck( Deck* pDeck ) { 19 | Face f[kCardsInSuit] = { two , three , four , five , six , seven , 20 | eight , nine , ten , jack , queen , king , ace }; 21 | Card* pC; 22 | for( int i = 0 ; i < kCardsInSuit ; i++ ) { 23 | pC = &(pDeck->ordered[ i + (0*kCardsInSuit) ]); 24 | InitializeCard( pC , spade , f[i], kNotWildCard ); 25 | 26 | pC = &(pDeck->ordered[ i + (1*kCardsInSuit) ]); 27 | InitializeCard( pC , heart , f[i], kNotWildCard ); 28 | 29 | pC = &(pDeck->ordered[ i + (2*kCardsInSuit) ]); 30 | InitializeCard( pC , diamond , f[i], kNotWildCard ); 31 | 32 | pC = &(pDeck->ordered[ i + (3*kCardsInSuit) ]); 33 | InitializeCard( pC , club , f[i], kNotWildCard ); 34 | } 35 | 36 | for( int i = 0 ; i < kCardsInDeck ; i++ ) { 37 | pDeck->shuffled[i] = &(pDeck->ordered[i]); 38 | } 39 | 40 | pDeck->bIsShuffled = false; 41 | pDeck->numDealt = 0; 42 | } 43 | 44 | 45 | void ShuffleDeck( Deck* pDeck ) { 46 | long randIndex; 47 | #if 1 48 | srand( 8*1024*1024 ); // Just some number (8 megabits for giggles) 49 | // The actual number doesn't matter (could be 1). 50 | // this is handy for reproducibility and verifying 51 | // your program as you developt it. 52 | #else 53 | srand( time(NULL) ); // Seed our PRNG using time() function. Because time() 54 | // ever increases, we'll get a different series each time 55 | // we run the program. 56 | #endif 57 | Card* pTmpCard; 58 | 59 | // Now, walk through the shuffled array, swapping the pointer 60 | // at a random card index in shuffuled with the pointer at the 61 | // current card index. 62 | // 63 | for( int thisIndex = 0 ; thisIndex < kCardsInDeck ; thisIndex++ ) { 64 | // get a random index 65 | randIndex = rand() % kCardsInDeck; // get next random number between 0..52 66 | 67 | // swap card pointers between thisIndex and randIndex 68 | pTmpCard = pDeck->shuffled[ thisIndex ]; 69 | pDeck->shuffled[ thisIndex ] = pDeck->shuffled[ randIndex ]; 70 | pDeck->shuffled[ randIndex ] = pTmpCard; 71 | } 72 | pDeck->bIsShuffled = true; 73 | } 74 | 75 | 76 | Card* DealCardFromDeck( Deck* pDeck ) { 77 | Card* pCard = pDeck->shuffled[ pDeck->numDealt ]; 78 | pDeck->shuffled[ pDeck->numDealt ] = NULL; 79 | pDeck->numDealt++; 80 | return pCard; 81 | } 82 | 83 | 84 | void PrintDeck( Deck* pDeck ) { 85 | printf( "%d cards in the deck\n" , 86 | kCardsInDeck ); 87 | printf( "Deck %s shuffled\n", 88 | pDeck->bIsShuffled ? "is" : "is not" ); 89 | printf( "%d cards dealt into %d hands\n" , 90 | pDeck->numDealt , kNumHands ); 91 | 92 | if( pDeck->bIsShuffled == true ) { // Deck is shuffled. 93 | if( pDeck->numDealt > 0 ) { 94 | printf( "The remaining shuffled deck:\n" ); 95 | } else { 96 | printf( "The full shuffled deck:\n"); 97 | } 98 | 99 | for( int i = pDeck->numDealt , j = 0 ; i < kCardsInDeck ; i++ , j++ ) { 100 | printf( "(%2d)" , i+1 ); 101 | PrintCard( pDeck->shuffled[ i ] ); 102 | if( j == 3 ) { 103 | printf( "\n" ); 104 | j = -1; 105 | } else { 106 | printf( "\t"); 107 | } 108 | } 109 | } else { // Deck is not shuffled. 110 | printf( "The ordered deck: \n" ); 111 | for( int i = 0 ; i < kCardsInSuit ; i++ ) { 112 | int index = i + (0*kCardsInSuit); 113 | printf( "(%2d)" , index+1 ); 114 | PrintCard( &(pDeck->ordered[ index ] ) ); 115 | 116 | index = i + (1*kCardsInSuit); 117 | printf( " (%2d)" , index+1 ); 118 | PrintCard( &(pDeck->ordered[ index ] ) ); 119 | 120 | index = i + (2*kCardsInSuit); 121 | printf( " (%2d)" , index+1 ); 122 | PrintCard( &(pDeck->ordered[ i + (2*kCardsInSuit) ] ) ); 123 | 124 | index = i + (3*kCardsInSuit); 125 | printf( " (%2d)" , index+1 ); 126 | PrintCard( &(pDeck->ordered[ index ] ) ); 127 | printf( "\n" ); 128 | } 129 | } 130 | printf( "\n\n" ); 131 | } 132 | 133 | // eof 134 | -------------------------------------------------------------------------------- /Chapter24/deck.h: -------------------------------------------------------------------------------- 1 | // deck.h 2 | // Chapter 24 3 | // Learn C Programming 4 | // 5 | // Header file for deck.c 6 | // 7 | 8 | 9 | #ifndef _DECK_H_ 10 | #define _DECK_H_ 11 | 12 | #include "card.h" 13 | 14 | enum { 15 | kCardsInDeck = 52 16 | }; 17 | 18 | 19 | // 20 | // A Deck 21 | // 22 | typedef struct { 23 | Card ordered[ kCardsInDeck ]; 24 | Card* shuffled[ kCardsInDeck ]; 25 | int numDealt; 26 | bool bIsShuffled; 27 | } Deck; 28 | 29 | 30 | // 31 | // Operations on a Deck of Cards 32 | // 33 | void InitializeDeck( Deck* pDeck ); 34 | void ShuffleDeck( Deck* pDeck ); 35 | Card* DealCardFromDeck( Deck* pDeck ); 36 | void PrintDeck( Deck* pDeck ); 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /Chapter24/hand.c: -------------------------------------------------------------------------------- 1 | // hand.c 2 | // Chapter 24 3 | // Learn C Programming 4 | // 5 | // To compile: 6 | // see main program source file: dealer.c 7 | // 8 | 9 | 10 | #include "dealer.h" 11 | 12 | 13 | // ============================================ 14 | // Operations on a Hand 15 | // ============================================ 16 | 17 | 18 | void InitializeHand( Hand* pHand ) { 19 | pHand->cardsDealt = 0; 20 | for( int i = 0; i < kCardsInHand ; i++ ) { 21 | pHand->hand[i] = NULL; 22 | } 23 | } 24 | 25 | 26 | void AddCardToHand( Hand* pHand , Card* pCard ) { 27 | if( pHand->cardsDealt == kCardsInHand ) return; 28 | 29 | pHand->hand[ pHand->cardsDealt ] = pCard; 30 | pHand->cardsDealt++; 31 | } 32 | 33 | 34 | void PrintHand( Hand* pHand , char* pLeadStr ) { 35 | for( int i = 0; i < kCardsInHand ; i++ ) { // 1..5 36 | Card* pCard = pHand->hand[i]; 37 | printf("%s" , pLeadStr ); 38 | PrintCard( pCard ); 39 | printf("\n"); 40 | } 41 | } 42 | 43 | 44 | void PrintAllHands( Hand* hands[ kNumHands ] ) { 45 | printf( " Hand 1: \n"); 46 | PrintHand( hands[ 0 ] , " " ); 47 | 48 | printf( "Hand 2: \n"); 49 | PrintHand( hands[ 1 ], " " ); 50 | 51 | printf( " Hand 3: \n"); 52 | PrintHand( hands[ 2 ], " " ); 53 | 54 | printf( " Hand 4: \n" ); 55 | PrintHand( hands[ 3 ] , " " ); 56 | printf( "\n" ); 57 | } 58 | 59 | // eof 60 | -------------------------------------------------------------------------------- /Chapter24/hand.h: -------------------------------------------------------------------------------- 1 | // hand.h 2 | // Chapter 24 3 | // Learn C Programming 4 | // 5 | // Header file for hand.c 6 | // 7 | 8 | 9 | #ifndef _HAND_H_ 10 | #define _HAND_H_ 11 | 12 | #include "card.h" 13 | 14 | enum { 15 | kCardsInHand = 5, 16 | kNumHands = 4 17 | }; 18 | 19 | 20 | // 21 | // A Hand 22 | // 23 | typedef struct { 24 | int cardsDealt; 25 | Card* hand[ kCardsInHand ]; 26 | } Hand; 27 | 28 | // 29 | // Operations on a Hand 30 | // 31 | void InitializeHand( Hand* pHand ); 32 | void AddCardToHand( Hand* pHand , Card* pCard ); 33 | void PrintHand( Hand* pHand , char* pLeadStr ); 34 | void PrintAllHands( Hand* hands[ kNumHands ] ); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /Chapter25/circle.c: -------------------------------------------------------------------------------- 1 | // circle.c 2 | // Chapter 25 3 | // Learn C Programming 4 | // 5 | // Demonstrate various types of scope: 6 | // 1. local scope 7 | // 2. static scope 8 | // 3. function prototype scope 9 | // 4. external / file scope 10 | // 5. global / multi-file scope 11 | // 12 | // NOTE: no header file is employed to show what the source file 13 | // looks like after preprocessing. 14 | // 15 | // Dependencies: 16 | // 17 | // trig.c 18 | // 19 | // Compile with: 20 | // 21 | // cc circle.c trig.c -o cirle -Wall -Werror -std=c18 22 | // 23 | 24 | #include 25 | 26 | // === trig.h 27 | double circle_circumference( double diameter ); 28 | double circle_area( double radius ); 29 | double circle_volume( double radius ); 30 | 31 | extern const long double global_Pi; 32 | // === 33 | 34 | static const double unit_circle_radius = 1.0; 35 | 36 | void circle( double radius); 37 | 38 | int main( void ) { 39 | circle( -1.0 ); 40 | circle( 2.5 ); 41 | } 42 | 43 | void circle( double radius ) { 44 | double r = 0.0; 45 | double d = 0.0; 46 | 47 | if( radius <= 0.0 ) r = unit_circle_radius; 48 | else r = radius; 49 | d = 2 * r; 50 | 51 | printf( " pi (as literal) = 3.14159265358979323846L\n" ); // 20 decimals 52 | printf( " pi (as float) = %9.7f\n" , (float)global_Pi ); // accurate to 7 decimals 53 | printf( " pi (as double) = %18.16F\n" , (double)global_Pi ); // accurate to 16 decimals 54 | printf( " pi (as long double) = %22.20LF\n\n" , global_Pi ); // accurate to 19 decimals 55 | 56 | if( radius <= 0.0 ) printf( "Unit circle:\n" ); 57 | else printf( "Circle\n"); 58 | 59 | printf( " radius = %10.4f inches\n" , r ); 60 | printf( " circumference = %10.4f inches\n" , circle_circumference( d ) ); 61 | printf( " area = %10.4f square inches\n" , circle_area( r ) ); 62 | printf( " volume = %10.4f cubic inches\n\n" , circle_volume( r ) ); 63 | } 64 | 65 | // eof 66 | 67 | -------------------------------------------------------------------------------- /Chapter25/trig.c: -------------------------------------------------------------------------------- 1 | // trig.c 2 | // Chapter 25 3 | // Learn C Programming 4 | // 5 | // Demonstrate various types of scope: 6 | // 1. local scope 7 | // 2. static scope 8 | // 3. function prototype scope 9 | // 4. external / file scope 10 | // 5. global / multi-file scope 11 | // 12 | // NOTE: no header file is employed to show what the source file 13 | // looks like after preprocessing. 14 | // 15 | // Dependencies: 16 | // 17 | // circle.c 18 | // 19 | // Compile with: 20 | // 21 | // cc circle.c trig.c -o cirle -Wall -Werror -std=c18 22 | // 23 | 24 | // === trig.h 25 | double circle_circumference( double diameter ); 26 | double circle_area( double radius ); 27 | double circle_volume( double radius ); 28 | 29 | extern const long double global_Pi; 30 | // === 31 | 32 | 33 | static double square( double d ); 34 | static double cube( double d ); 35 | 36 | const long double global_Pi = 3.14159265358979323846L; 37 | 38 | 39 | double circle_circumference( double diameter ) { 40 | double result = diameter * global_Pi; 41 | return result ; 42 | } 43 | 44 | double circle_area( double radius ) { 45 | double result = global_Pi * square( radius ); 46 | return result; 47 | } 48 | 49 | double circle_volume( double radius ) { 50 | double result = 4.0/3.0*global_Pi*cube( radius ); 51 | return result; 52 | } 53 | 54 | 55 | static double square( double d ) { 56 | double result = d * d; 57 | return result; 58 | } 59 | 60 | static double cube( double d ) { 61 | double result = d * d * d; 62 | return result; 63 | } 64 | 65 | // eof 66 | 67 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------