Create your repository: https://classroom.github.com/a/0JA3zMle
Then edit the README.md file in the GitHub web editor.

Due: Tuesday 9/4 at 11:59PM, see submission instructions.

Updates:
  • 8/30/18: Added submissions instructions. Clarified Exercise 0.22

Objectives

The goal of this module is:

  • To introduce the syntax of basic C: variables, assignment, operators, and control flow.


History

A brief history of C:

  • Developed in 1972 at AT&T Bell Labs by Dennis Ritchie and Brian Kernighan.

  • Primary purpose: provide a higher-level programming language than assembly in which to write Unix.

  • Why the name C?
    • C was preceded by B, a language designed by Ken Thompson (another Unix designer).
    • B was based on BCPL, another high-level language.

  • Classic book: "The C Programming Language" by Kernighan and Ritchie.

  • Since then:
    • C has gone through many changes.
    • Original C is called "K&R C".
    • ANSI defined a standard in 1989, now called ANSI C89.
    • Most common: update in 1999 called ANSI C99.
    • Current: 2011, called ANSI C11.

  • See The Development of the C Language, a history of C written by Dennis Ritchie.


Why learn C?

Highlights of C:

  • C has many high-level programming features, but also let's you work at the lowest level (manipulating bits).

  • C is amenable to compiler optimization: compiled C code is generally very efficient.

  • C gives the programmer a lot of freedom in accessing memory and hardware.

  • Most operating systems, embedded systems are written in C.

  • A lot of open-source projects are written in C.

The world of C:

  • Software development in C usually involves using additional C-related tools.

  • Tools for programming:
    • Development environments, e.g., Eclipse, Emacs
    • Debuggers, e.g. gdb
    • Useful tools/libraries, e.g., lex and yacc.

  • Tools for managing projects, e.g., make, ant.

  • Tools for configuring software, e.g., autoconf.

  • Tools for GUI development: tk/tcl, QT, GTK.

  • Scripting languages: perl, awk.

Open-source software:

  • GNU-Linux is written in C, as are most tools from GNU.

  • Most open-source projects today are written in C - see www.sourceforge.net

  • Open-source projects tend to use the gcc compiler (itself an open-source project) and related tools.


Going from Java to C

For a Java programmer:

  • C's syntax is similar.

  • Large parts of C will appear to be a subset of Java.

  • But ...
    • C has pointers, with a lot of freedom to manipulate them (direct memory access).
    • C has less type-checking than Java.
    • C's variable declarations can look strange.
    • C provides no support for objects.
    • C has function declarations.
    • C has a preprocessor language that's processed before compilation.

  • The programming experience in C:
    • Because of the additional freedom in the language, it's much easier to create errors.
    • There's less help from the compiler, and no help from the runtime system.
    • You need to use a debugger to track pointer errors.

  • C's freedom in programming allows one to construct some highly unreadable code. For example, here is one winning entry from the International Obfuscated C Code Contest:
    int i;main(){for(;i["] < i;++i){--i;}"];read('-'-'-',i+++"hell\
    o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
    
    (It prints "Hello world!" to the screen).


HelloWorld in C

Here is the classic HelloWorld program in C:

#include <stdio.h>

int main ()
{
  printf ("Hello World!\n");
}

Note:

  • The #include command is a preprocessor directive to load the stdio library.

  • Execution starts in a function (method) called main:
    • There are other signatures for main as we will see.
    • Although a return type is declared, nothing needs to be returned.

  • The printf method is used for screen output.

  • The "newline" character \n is explicitly required.
Exercise 0.1: Use the editor below to write your first C program mimicking the one above, but with a more creative message. Press the Play button to compile and execute the code. Paste your code into your readme in a code block.


C-related languages

Languages related to C:

  • C++
    • C++ is "mostly" a superset of C, offering support for objects.
    • gcc can compile C++ as well - this is useful for projects that combine C and C++.

  • Objective C
    • Another C enhancement to support objects.
    • Popular on Apple/MAC platforms.

  • C#
    • Microsoft's answer to Java.

  • Many other experimental variations: TinyC, Cyclone, D.


Reserved words and identifiers

C's 37 reserved words:

auto          enum          restrict          unsigned
break         extern        return            void
case          float         short             volatile
char          for           signed            while
const         goto          sizeof            _Bool
continue      if            static            _Complex
default       inline        struct            _Imaginary
do            int           switch
double        long          typedef
else          register      union
Note:
  • None of these may be used as identifiers.

  • ANSI C99 added some keywords, shown in boldface above.

  • ANSI C11 (2011) added more (for somewhat esoteric uses), which we won't describe here.

  • By category:
    • Data type keywords (11): char, double, enum, float, int, struct, union, void, _Bool, _Complex, _Imaginary
    • Data type modifiers (9): auto, const, long, register, short, signed, static, unsigned, volatile
    • Data type definition (1): typedef
    • Control-flow keywords (12): break, case, continue, default, do, else, for, goto, if, return, switch, while
    • Compiler directives (3): extern, inline, restrict
    • Memory allocation (1): sizeof

Identifiers in C:

  • For use as variable or function names.

  • Rules:
    • Any combination of letters, digits and underscore.
    • Must begin without a digit.
    • Case is significant:
            int myAge;
      
      is different from
            int MyAge;
      
    • Identifiers may be arbitrarily long, but only first 31 characters are significant. Thus, all compilers will distinguish between
            int abcdefghijklmnopqrstuvwxyz12345;
      
      and
            int abcdefghijklmnopqrstuvwxyz12346;
      
      but compilers are not guaranteed to distinguish between
            int abcdefghijklmnopqrstuvwxyz123456;
      
      and
            int abcdefghijklmnopqrstuvwxyz123457;
      

  • Note: only the first 8 characters are significant for functions in external files.

  • Convention:
    • Old C convention: use underscore's to separate out "meaning" as in:
            num_courses_taken = compute_num_courses_taken (student_ID);
      
    • The modern convention is to use Java's style:
            numCoursesTaken = computeNumCoursesTaken (studentID);
      

  • Summary of convention:
    • Start a variable or function name with a lowercase letter.
    • Use uppercase letters to mark new "meaning" within identifier.
    • Avoid using numbers if possible.
    • Use small identifiers (usually, one letter) for loop variables, temporary computations, e.g.,
            for (i=0; i < 10; i++) {
              A[i] = B[i] * C[i];
            }
      


Compilation and basic compiler errors

Open this link: https://repl.it/@twood02/EmptyC in a new tab/window for the next set of exercises.

C programs are case-sensitive. The following program will not compile:
#include <stdio.h>

Int main ()
{
}
This is because the C reserved word int is mis-spelt as Int.
Exercise 0.2 Type up and compile the above program. What is the compiler error reported?

About C compiler errors:

  • Depending on the C compiler you use, you will get more or less useful errror messages.

  • In general, the C compiler is going to be much less helpful than a Java compiler, which will make the identification of compiler errors harder.
Exercise 0.3 What is the error produced by compiling this program?
#include <stdio.h>

int Main ()
{
}
Exercise 0.4 What is the error produced by compiling this program?
#include <stdio.h>

int main ()
{
  Printf ("Hello World!\n");
}

Let's revisit helloworld and point out some syntactic features:

  • First, the program:
    #include <stdio.h>
    
    int main ()
    {
      printf ("Hello World!\n");
    }
    

  • C's only reserved word in this program: int.

  • There are two function (method) names: main, printf.

  • We see curly brackets as delimiters for the function main.

  • The semi-colon ends a statment.

  • Parentheses for are used for enclosing method parameters (arguments).

  • A string literal, Hello World! is enclosed in double-quotes.

Next, let us get accustomed to errors produced by the compiler when the syntax is incorrect.

Exercise 0.5 What errors are reported by the compiler with this program?
#include <stdio.h>

int main (  // Forgot the matching right parenthesis
{
  printf ("Hello World!\n");
}
Exercise 0.6 What errors are reported by the compiler with this program?
#include <stdio.h>

int main ()
{
  printf ("Hello World!\n);   // Forgot the matching right quote (")
}
Exercise 0.7 What errors are reported by the compiler with this program?
#include <stdio.h>

int main ()
{
  printf ("Hello World!\n")  // Forgot the semi-colon.
}
Exercise 0.8 What errors are reported by the compiler with this program?
#include <stdio.h>

int main ()
{
  printf ("Hello World!\n");
// Missing brace 
Exercise 0.9 What errors are reported by the compiler with this program?
#include <stdio.h>

main ()
{
  printf ("Hello World!\n");
}
Exercise 0.10: What kind of a compiler error do you get if you try to use a reserved word as an identifier? Use a reserved word to declare an integer identifier.


Comments

There are two types of comments in ANSI C99:

  • Inline comments, using // that comment out everything up to the end of the line.

  • Block comments, using /* and */ that comment out everything in between.
Consider this example:
#include <stdio.h>


/* This is a block comment. Everything between the begin-comment symbol
   and the end-comment symbol is ignored by the compiler. It is conventional
   to use a separate line for the end-comment symbol.
*/


// This is an in-line comment.

int main (/* A strange place for a block comment */)
{
  printf ("Hello World!\n");  // Another inline comment.
}


Include's

The first line, and perhaps the next few, typically have #include's.

  • For our helloworld.c example, we had
        #include <stdio.h>
    
  • We will later understand how to work with multiple files and libraries, but for now think of this as including some library/API functionality that we can use.

  • The typical #include's we will need are:
        #include <stdio.h>
        #include <math.h>
        #include <stdlib.h>
        #include <string.h>
    

  • Important:
    • To avoid clutter, our examples will not necessarily have these #include's.
    • When you write your code, make sure to have these "include" lines be the first lines in your program.

  • Thus, for example, we might describe our helloworld.c example as
        int main ()
        {
            printf ("Hello World!\n");
        }
    
    with the understanding that the actual file will look like
        #include <stdio.h>
        #include <math.h>
        #include <stdlib.h>
        #include <string.h>
    
        int main ()
        {
            printf ("Hello World!\n");
        }
    


Data types

About C's data types:

  • There are basic types: int, char, float, double, void.

  • There are type modifiers: const, short, long, signed, unsigned.

  • C99 has additional types: _Bool, _Complex, _Imaginary.

  • There are two complexities with regard to C's types:
    • The type rules are somewhat complicated.
    • Variable declarations can be made complicated (if desired).

  • Storage sizes are not standard: for example an int can be either:
    • 2 bytes: -32,768 to 32,767
    • 4 bytes: -2,147,483,648 to 2,147,483,647

Integer types (ANSI C99 additions shown in bold):

Type Typical
storage size
Range Print
specifier
int 2 or 4 bytes -32,768 to 32,767 (2 bytes)
-2,147,483,648 to 2,147,483,647 (4 bytes)
%d
unsigned int 2 or 4 bytes 0 to 65,535 (2 bytes)
0 to 4,294,967,295 (4 bytes)
%u
short 2 bytes -32,768 to 32,767 %d
unsigned short 2 bytes 0 to 65,535 %u
long 4 bytes -2,147,483,648 to 2,147,483,647 %ld
unsigned long 4 bytes 0 to 4,294,967,295 %lu
long long 8 bytes -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 %lld
unsigned long long 8 bytes 0 to 18,446,744,073,709,551,615 %llu

Let's look at an example:

int main ()
{
  int numDaysInYear = 365;
  long int numStarsInUniverse = 2000000000L;
  unsigned long long int largestIntegerInC = 18446744073709551615LLU;

  printf ("numDaysInYear = %d\n", numDaysInYear);
  printf ("numStarsInUniverse = %ld\n", numStarsInUniverse);
  printf ("largestIntegerInC = %llu\n", largestIntegerInC);
}
Exercise 0.11: Implement the above in your repl.it editor. What happens if you omit the "L" or "LLU" when declaring numStarsInUniverse and largestIntegerInC? What happens if you use %d for the largestIntegerInC print statement?

Note:

  • Where to declare variables:
    • Prior to C99, all variables had to be declared either at the top of a function, or globally (outside any function).
    • Since ANSI C99, variables can also be declared inside blocks, as in:
      int main ()
      {
        int numDaysInYear = 365;
        printf ("numDaysInYear = %d\n", numDaysInYear);
      
        if (numDaysInYear < 366) {
            long int numStarsInUniverse = 2000000000L;
            printf ("Thank your lucky %ld stars\n", numStarsInUniverse);
        }
        else {
            unsigned long long int numStarsInUniverse = 1844674407370955161ULL;
            printf ("Thank your lucky %llu stars\n", numStarsInUniverse);
        }
      }
      
    • Two commonly used declarations in other languages (Java, C++) were NOT permitted in older versions of C:
      1. Declaration in a for-loop:
        int main ()
        {
            int i;
        
            for (i=0; i<10; i++) {        // Allowed.
                printf ("i=%d\n", i);
            }
        
            for (int j=0; j<10; j++) {    // Not allowed in C89. j needs to be declared at the top.
                printf ("j=%d\n", j);
            }
        
        }
        
      2. Declare as needed:
        int main ()
        {
            int numDaysInYear = 365;                          // Allowed.
            printf ("numDaysInYear = %d\n", numDaysInYear);
        
            long int numStarsInUniverse = 2000000000L;        // Not allowed.
            printf ("Number of stars = %ld stars\n", numStarsInUniverse);
        }
        
    • To make matters confusing, some compilers will allow both types of declarations (for-loop, as-needed) above.
    • To be safe, you can follow ANSI C89 and always declare every needed variable at the top of the method or as a global.

  • Variables can be initialized and declared in one statement, or declared and initialized separately:
    #include <stdio.h>
    
    // Declaration and assignment.
    int numDaysInYear = 365;
    
    int main ()
    {
      // Declaration.
      long int numStarsInUniverse;
    
      printf ("numDaysInYear = %d\n", numDaysInYear);
    
      // Assignment.
      numStarsInUniverse = 2000000000L;
    
      printf ("numStarsInUniverse = %ld\n", numStarsInUniverse);
    }
    
    For variety, we have declared numDaysInYear as a global variable.

  • ANSI C99 has added the long long type, not available in C89 or earlier.

  • The int reserved word may be left out if modifiers are present:
    int main ()
    {
      int numDaysInYear = 365;
      long numStarsInUniverse = 2000000000L;
      unsigned long long largestIntegerInC = 18446744073709551615ULL;
    
      printf ("numDaysInYear = %d\n", numDaysInYear);
      printf ("numStarsInUniverse = %ld\n", numStarsInUniverse);
      printf ("largestIntegerInC = %llu\n", largestIntegerInC);
    }
    

  • The letter L is appended to the end of a long constant.

  • The letter LL is appended to the end of a long long constant.

  • The letter U is appended to the end of an unsigned constant, e.g., LLU.

Screen output: (HW)

  • The printf library function is used for output to the screen.

  • The arguments to printf are:
        printf (format-string [zero or more variables])

  • The format string needs to specify all variables that follow the format string:
    • The idea is, printf will look at additional arguments only based on what's in the format string.
    • In the first printf above, the %d symbol specifies an integer.
    • Similarly, %ld specifies a long and %llu specifies an unsigned long long int.

  • The format string can specify any number of variables, separated by arbitrary text, for example:
    int main ()
    {
      int numDaysInYear = 365;
      long int numStarsInUniverse = 2000000000L;
      unsigned long long int largestIntegerInC = 18446744073709551615ULL;
    
      printf ("numDaysInYear = %d  numStarsInUniverse = %ld  largestIntegerInC = %llu\n",
              numDaysInYear, numStarsInUniverse, largestIntegerInC);
    }
    

  • The format string can also specify the amount of space to reserve for the printed number by using %Nd, where N is a number indicating how much space to use:
    HW Exercise 0.12 Adjust the amount of space used in the printf call. What happens if x has more digits than are reserved? What happens if it has fewer digits?

Floating-point types:

Type Typical
storage size
Range Print
specifier
Approximate
precision
float 4 bytes 1.2 x 10-38 to 3.4 x 1038 %f 6 decimal places
double 8 bytes 2.3 x 10-308 to 1.7 x 10308 %lf 15 decimal places
long double 10 bytes 3.4 x 10-4932 to 1.1 x 104932 %LG 19 decimal places

Consider this example:

Exercise 0.13: What print command would you use to print PI with a reserved width of 10 characters and only one digit after the decimal place? Does the reserved width include the decimal point and "e+" notation characters?
Note:
  • The letter F is appended to the end of a "decimal" type constant:
      float PI = 3.141F;
    

  • Floating point constants can also be specified in exponent format:
      double doublePI = 314.159265E-2;
    

  • The letter L is used for a long double constant.

  • The print format string specifies both the total width of the field and the number of digits that follow the decimal point.

  • Use %e in the format string for exponent format.
HW Exercise 0.14: It's a common error to mistype the format string. What happens when you reverse the %d and %f specifiers in the program above?

Character types:

Type Typical
storage size
Range Print
specifier
char 1 byte -128 to 127 %c
unsigned char 1 byte 0 to 255 none
signed char 1 byte -128 to 127 none

Consider this example:

int main ()
{
  char letter = 'a';
  unsigned char letter2 = 'b';
  signed char letter3 = 'c';

  printf ("letter = %c\n", letter);
  printf ("letter2 = %c\n", letter2);
  printf ("letter3 = %c\n", letter3);
}
Note:
  • Generally pronounced "char" (like charred meat) or "car"
  • Characters are used to represent either letters or small numbers. The letter symbols you are used to are converted from numbers using the ASCII standard.
  • When assigning to a letter, you must use single quotes around the letter.

  • There is no special print-format specifier for signed and unsigned char.

  • char variables are also used to access memory on a byte-by-byte basis, as we will see shortly.
HW Exercise 0.15 What happens if you use double quotes when assigning a char? What happens if you put multiple letters within single quotes?
HW Exercise 0.16 Use the ASCII table above to assign c1 and c2 to numeric values that represent your initials. Then print them using both the %d and %c format specifiers.


Casting

Consider this example:

int main ()
{
  int i = 5;
  long j = 6;
  double d = 3.141;

  j = i;         // Works fine. Implicit cast from int to long.
  d = i;         // Works fine. Implicit cast from int to double

  i = j;         // May not compile.
  i = d;         // May not compile.

  d = 3.141;
  i = (int) j;   // Compiles. Explicit cast from long to int.
  i = (int) d;   // Compiles. Explicit cast from double to int.

  // Cast's can be used in any expression:
  printf ("The int part of d=%lf is %d\n", d, (int) d);
}

Note:

  • To assign a variable higher in the cast hierarchy to one lower, an explicit cast is required.

  • An explicit cast is the desired type in parentheses placed before the target of the cast:
      i = (int) d;
    

  • Many compilers don't warn you if you are "down" casting: this is a common source of error.

  • The implicit cast hierarchy is:
    shortintunsigned intlongunsigned longlong longfloatdoublelong double

  • Use an explicit cast in any assignment down the hierarchy.
Exercise 0.17: Use the editor below to find out what this program will print out.
int main ()
{
  printf ("%lf\n", ( (double) (int) 3.141 ) );
}


Operators and expressions

An example with arithmetic operators

int main ()
{
  double x = 6, y = 5;
  int i = 8, j = 5;

  // Standard: plus, minus, multiple, divide
  printf ("x+y=%lf\n", x+y);     // Prints 11.0
  printf ("x-y=%lf\n", x-y);     // Prints 1.0
  printf ("x*y=%lf\n", x*y);     // Prints 30.0
  printf ("x/y=%lf\n", x/y);     // Prints 1.2

  // Integer divide and remainder:
  printf ("i/j=%d\n", i/j);      // Prints 1
  printf ("i mod j=%d\n", i%j);  // Prints 3

  // Post and pre-increment:
  printf ("i++ = %d\n", i++);    // Prints 8
  printf ("++j = %d\n", ++j);    // Prints 6

  // Assignment shortcut example.
  i += j;
  printf ("i=%d\n", i);          // Prints 15

}

An example with bitwise operators

int main ()
{
  int a = 9;
  int b = 4;

  printf ("a&b = %d\n", a&b);          // Bitwise AND: Prints 0
  printf ("a|b = %d\n", a|b);          // Bitwise OR: Prints 13 
  printf ("a^b = %d\n", a^b);          // Bitwise EOR: Prints 13

  printf ("~a = %d\n", ~a);            // Complement: Prints -10
  printf ("b << 1 = %d\n", (b << 1));  // Left shift by 1: Prints 8
  printf ("b >> 2 = %d\n", (b >> 2));  // Right shift by 2: Prints 1
}

An example with boolean operators

int main ()
{
  double x = 5, y = 6, z = 6;
  int result;

  printf ("x < y = %d\n", (x < y));     // Prints 1 (true)
  printf ("x <= y = %d\n", (x <= y));   // Prints 1
  printf ("y > z = %d\n", (y > z));     // Prints 0 (false)
  printf ("y >= z = %d\n", (y >= z));   // Prints 1
  printf ("x == y = %d\n", (x == y));   // Prints 0
  printf ("y == z = %d\n", (y == z));   // Prints 1
  printf ("x != y = %d\n", (x != y));   // Prints 1

  result = (x < y);
  printf ("result=%d\n", result);       // Prints 1

  if (result == 1) {      // Equality comparison.
    printf ("x < y\n");
  }
  else {
    printf ("x >= y\n");
  }
  // Prints "x < y"
}

Note:

  • In C, boolean operators result in 1 (indicating "true") or 0 (indicating "false").

  • These results can be assigned to int-compatible variables.

Boolean types: (HW)

  • C originally did not provide any boolean types.

  • There are now four ways of working with boolean's:
    1. Use the original approach of 1 and 0:
      int main ()
      {
        double x = 5, y = 6;
      
        int result = (x < y);
        if (result == 1) {
          printf ("x < y\n");
        }
        else {
          printf ("x >= y\n");
        }
      }
      

    2. Define your own boolean types using the pre-processor:
      #define boolean int
      #define true 1
      #define false 0
      
      int main ()
      {
        double x = 5, y = 6;
      
        boolean result = (x < y);
      
        if (result == true) {
          printf ("x < y\n");
        }
        else {
          printf ("x >= y\n");
        }
      }
      

    3. Use a recent addition to the standard C library:
      #include <stdio.h>
      #include <stdbool.h>
      
      int main ()
      {
        double x = 5, y = 6;
      
        bool result = (x < y);
      
        if (result == true) {
          printf ("x < y\n");
        }
        else {
          printf ("x >= y\n");
        }
      }
      

    4. Use the new C99 _Bool type:
      #include <stdio.h>
      #include <stdbool.h>
      
      int main ()
      {
        double x = 5, y = 6;
      
        _Bool result = (x < y);
      
        if (result == true) {
          printf ("x < y\n");
        }
        else {
          printf ("x >= y\n");
        }
      }
      

  • We recommend using the stdbool package, as shown in (3) above.
HW Exercise 0.18 : Put the following code into the editor below. What does it print out? What is its significance?
int main ()
{
  int k = 13;
  int i;

  for (i=0; i < 8; i++) {
    printf ("%d ", (k % 2));
    k >>= 1;
  }
  printf ("%\n");
}


Constants (HW)

There are two ways of defining constants in C:

  • The simple and traditional way is to use the preprocessor:
    #define PI 3.14159
    
    int main ()
    {
      double radius = 5.0;
    
      printf ("Area of Circle with radius %lf is %lf\n", radius, PI*radius*radius);
    }
    

  • Another way is to use the const modifier that makes a variable immutable:
    const double PI = 3.14159;
    
    int main ()
    {
      double radius = 5.0;
    
      printf ("Area of Circle with radius %lf is %lf\n", radius, PI*radius*radius);
    }
    
    The latter approach is more general, and can be applied to function parameters as well:
HW Exercise 0.19 What happens when you try to modify one of the const variables? Is this a compile-time or a run-time error?


Control flow

An overview of C's control flow statements via examples:

int main ()
{
  int i = 1;

  // if-statement:
  if (i == 0) {
    printf ("i is zero\n");
  }


  // if-statement with compound expression:
  if ( (i >= -1) && (i <= 1) ) {
    printf ("-1 <= i <= 1\n");
  }


  // if-else combination
  if (i == 1) {
    printf ("one\n");
  }
  else if (i == 2) {
    printf ("two\n");
  }
  else {
    printf ("larger than two\n");
  }


  // Variation of if-else above:
  if (i == 1) {
    printf ("one\n");
  }
  else {
    if (i == 2) {
      printf ("two\n");
    }
    else {
      printf ("larger than two\n");
    }
  }


  // Equivalent switch statement:
  switch (i) {
    case 1: {
      printf ("one\n");
      break;
    }
    case 2: {
      printf ("two\n");
      break;
    }
    default: {
      printf ("larger than two\n");
    }
  }


  // for-loop example:
  printf ("Numbers 0 through 9: \n");
  for (i=0; i < 10; i++) {
    printf (" %d\n", i);
  }


  // while-loop equivalent:
  printf ("Numbers 0 through 9: \n");
  i = 0;
  while (i < 10) {
    printf (" %d\n", i);
    i++;
  }


  // do-while equivalent:
  printf ("Numbers 0 through 9: \n");
  i = 0;
  do {
    printf (" %d\n", i);
    i++;
  } while (i < 10);



  // Example of using "break"
  printf ("Numbers 0 through 9: \n");
  i = 0;
  while (1) {
    if (i == 10) {
      break;
    }
    printf (" %d\n", i);
    i++;
  }


  printf ("Odd numbers less than 10:\n");
  i = 0;
  while (1) {
    // If we've reached the limit, break out of the loop.
    if (i == 10) {
      break;
    }

    // If it's an even number, skip to next iteration of loop.
    if (i % 2 == 0) {
      i++;
      continue;
    }

    // Print odd number.
    printf (" %d\n", i);
    i++;
  }

}

Note:

  • Between a for-loop and a while-loop, use a while-loop only if the while-loop is easier to write.

  • Similarly, prefer a while-loop over an equivalent do-while.

  • ANSI C99 allows declaration of the for-loop variable in the for-loop:
        for (int i=0; i < 10; i++) {
          // ...
        }
    
    Versions prior to C99 do not. For compatibility with many textbooks, we will declare variables at the top.

Exercise 0.20 : There is a bug in this code! Why won't it print "i is not 5" like the developer expected? Is this a compile-time or run-time error?
int main(void) {
 int i = 10;
 if (i = 5)
   printf ("i is equal to 5");
 else
   printf("i is not 5");
 return 0;
}
Exercise 0.21 : Without running it, what is the error in the following code?
   int i = 10;
   while (i >= 1)
     printf ("i=%d\n", i);
     i--;

Now for some practice with control loops...

Use this code window to solve the exercises below.
HW Exercise 0.22 : Use for-loops to print "hourglasses" of different sizes. For example, here is the size=3 glass:
X------------X
  X--------X
    X----X
      XX
    X----X
  X--------X
X------------X
and here is the size=5 one:
X--------------------X
  X----------------X
    X------------X
      X--------X
        X----X
          XX
        X----X
      X--------X
    X------------X
  X----------------X
X--------------------X
Then, repeat using only while-loops. Paste your code for both versions into your README file.


Submission Instructions

Do your work in a repository created using this link.

  • Answer all of the exercise questions above in your README.md file.
  • We suggest you edit the file directly in the GitHub web editor, but alternatively you can clone the repository to your computer or CodeAnywhere.
  • Submit your assignment by committing your README.md file to your git repository (and pushing to GitHub if you are not editing through its website).
  • You should check the contents of the README.md file through the GitHub website to ensure that it has all of your correct content!
Your work will be graded out of 20 points. 1 point will be for the style/formatting of your Markdown (e.g., use appropriate markdown code blocks and headings), and the remaining 19 points will be for completing the exercises fully.


Next

© 2003, Rahul Simha (revised 2017). Further revised by Tim Wood 2018.