The ternary operator in C

The conditional operator can be used to test data. Since there are three operands involved, the conditional operator is also referred to as the ternary operator. In fact, the conditional operator is the the C language’s only ternary operator. It enables us to express conditional tests economically.

 

#include <stdio.h>
#include <string.h>

int main(void){
 
  int a, b;
 
  char string[50];
  a = 7;
  b = 2;
 
  (a > b) ? (strcpy(string, "var a is greater")) :
         (strcpy(string, "var b is greater"));
 
  printf("\n%s\n", string);
 

  printf("\nvar %c is greater\n",
     (a > b) ? 'a' : 'b');
 
  return 0;
 
}

Although parentheses are not required around the condition tested at the start of the ternary expression, they do help to improve readability.

It is possible to nest ternary operators one within another.

#include <stdio.h>

int main(void){
 
  const double price=4.99;
  const double discountA=.05;
  const double discountB=.10;
  const double discountC=.15;
 
  int quantity;
  int total = 0;
  double discount = 0.0;
 
  while(1){
    printf("Please enter the number of items that you will buy:\n");
    printf("Or enter a negative number to finish shopping.\n");
    scanf(" %d", &quantity);
    if(quantity>0){
      total+=quantity;
      printf("Total = %d units.\n", total);
    } else {
     break;
    }
  }
 
   printf("You have ordered a total of %d units.\n", total);
    discount = (total>30 ? discountC : (
        (total>20 ? discountB : (
          (total>10 ? discountA : 0.0)))));
    
    /*
     * escape percent sign with two percent signs in a row
     */
    printf("You qualify for a %d%% discount\n",
       (int)discount*10);
    
    printf("Your total comes to %.2f\n", total*price*(1.00-discount));
 
  return 0;
 
}

The for loop

The for loop consists of three elements, the initialization, the condition, and the increment. The initialization is an assignment statement that is used to set the loop control variable. The condition is a relational expression that determines when the loop stops. The increment defines how the loop control variable changes each time the loop is repeated.

#include <stdio.h>
#include <math.h>

int main(void){
 
  int x;
 
  for(x=0; x <= 20; x++){
      printf("2^%d = %.0f\n", x, pow(2, x));
  }
 
  return 0;
 
}

The loop iteration can be a decrement as well as an increment.

#include <stdio.h>

int main(void){
 
  int i;
 
  for(i=21; i>0; i--){
     printf("%d \t %d^2 = %d \t %d^3=%d\n",
        i, i, i*i, i, i*i*i);
  }
 
  return 0;
 
}

The loop can increment or decrement by values other than one.

#include <stdio.h>

int main(void){
 
 
  int i;
 
  for(i=5;i<=200;i+=5){
   printf("%-3d\t", i);
   if(i%20==0){
    putchar('\n');
   }
  }
 
  return 0;
 
}

It is possible to have two or more variables control the loop.

We can initialize multiple variables within the for statement; we use commas to separate the multiple initialization statements.

#include <stdio.h>

int main(void){
 
  int x, y;
 
  for(x=1, y=99; x<=y; x++, y--){
    printf("%2d + %2d = %d\n", x, y, x+y);
  }
 
  return 0;
 
}

Here is a quick program to copy a string that uses two loop control variables.

#include <stdio.h>
#include <string.h>

void stringCopy(char *targetString, char *sourceString);

int main(void){
 
  char string[150];
 
  stringCopy(string,
         "If mice could swim, they would float with the tide and play with the fish down by the seaside. The cats on the shore would quickly agree.");
 
  printf("string is now: %s\n", string);
 
  return 0;
 
}


void stringCopy(char *targetString, char *sourceString){
 
  int i, j;
 
  int stringLength = strlen(sourceString);
  printf("Length of the string is %d\n", stringLength);
 
  for(i=0, j=stringLength; i<=j; i++, j--){
      targetString[i] = sourceString[i];
      targetString[j] = sourceString[j];
  }
 
  targetString[stringLength+1]='';
 
}

 

 

 

Logical Operators in C

Typically, C programmers use the int data type to represent logical data. If the data is zero, it is considered false. If it is nonzero, it is considered true.

C has three logical operators for combining logical values and creating new logical values. These three operators are the not operator, !, the and operator, &&, and the inclusive or operator, ||. The not operator, !, is a unary operator that changes a true value to a false value.

#include <stdio.h>

int main(void){
 
  int a = 7;
  int b = 0;
 
  printf("a = %d\n", a);
  printf("!a = %d\n", !a);
  printf("b = %d\n", b);
  printf("!b = %d\n", !b);
 
  return 0;
 
}

The and operator, &&, is a binary operator. Four distinct combinations of its operands are possible, and in only one case is the result true.

#include <stdio.h>

int main(void){
 
  int false = 0;
  int true = 1;
  int other = 2;
 
 
  printf("false && true = %d\n", false && true);
  printf("true && other = %d\n", true && other);
  printf("false && 0 = %d\n", false && 0);
  printf("!false && true = %d\n", !false && true);
 
  return 0;
 
}

The or operator is also a binary operator. Since it is a binary operator, four distinct combinations of values in its operands are possible. The result is false only if both operands are false; in all other cases it is true.

#include <stdio.h>

int main(void){
 
  int true = 1;
  int false = 0;
 
 
  printf("true || false = %d\n", true || false);
  printf("0 || 1 = %d\n", 0 || 1);
  printf("12 || true = %d\n", 12 || true);
  printf("!true || false = %d\n", !true || false);
  printf("false || 0 = %d\n", false || 0);
 
 
  return 0;
 
}

There are six relational operators that support logical relationships. They are all, of course, binary operators. Each of the six operators is a complement of another operator. The complement of the == operator is the != operator; the complement of the < operator is the >= operator; and, the complement of the > operator is the <= operator.

#include <stdio.h>

int main(void){
 
  int x = 7;
  int y = -3;
 
  printf("%d < %d is %d\n", x, y, x < y);
  printf("%d == %d is %d\n", x, y, x == y);
  printf("%d != %d is %d\n", x, y, x != y);
  printf("%d > %d is %d\n", x, y, x > y);
  printf("%d <= %d is %d\n", x, y, x <= y);
 
 
  return 0;
 
}

 

 

Conditional Expressions and Input in C

We can extend the if statement with the if-else statement, giving us an either-or situation.

In the following program, we will prompt the user for input. If the user enters a value larger than 10, we will apply a discount to the price calculation. Otherwise, no discount will be provided.

#include <stdio.h>


int main(void){
 
  const double itemPrice = 4.99;
 
  int quantity = 0;
 
 
  printf("Please enter the number of items you'd like to purchase:\n");
 
  //read input
  scanf(" %d", &quantity);
 
  if(quantity > 10){
    printf("The original price is %.2f\n", itemPrice*quantity);
    printf("With a 5\% discount that is: %.2f\n",
       itemPrice*quantity-(itemPrice*quantity*.05));
  } else {
    //no discount
    printf("The price for %d is %.2f\n", quantity, itemPrice*quantity);
  }
 
  return 0;
 
}

As we have seen earlier, blocks of statements are enclosed between curly braces, meaning we can provide a multitude of instructions to the computer after resolving the value of a conditional expression simply by enclosing them in curly braces after the if statement. Likewise, we can nest if statements within the conditionally executed blocks of code associated with another if statement.

The following program makes use of the INT_MAX definition from the <limits.h> header file that specifies the maximum value of an int data type.

#include <stdio.h>
#include <limits.h>
#include <math.h>

int main(void){
 
  int num;    
  printf("Please enter a number less than %d\n", INT_MAX);
 
  scanf(" %d", &num);
 
  printf("You entered %d\n", num);
 
  if(num%2==0){
   printf("That number is even.\n");
   if(sqrt(num)*sqrt(num)==num){
    printf("It is also a perfect square.\n");
   }
  } else {
   printf("That number is odd.\n");
  }
 
  return 0;
 
}

Three additional relational operators worth looking at are greater than or equal to, >=; less than or equal to, <=; and not equal to, !=.

Remember, a char value can be expressed either as an integer or as a single keyboard character. This means that we can use comparison operators on char values the same as we would with int values.

#include <stdio.h>


int main(void){
 
    char a = 'z';
    char b = 'Z';
    
    if(a != b){
      printf("%c [%d] does not equal %c [%d]\n\n",
         a, a, b, b);
    }
    
    if(a>b){
     printf("%c is greater than %c", a, b);
    } else {
     printf("%c is greater than %c", b, a);
    }
    
    printf("\nThe difference between %c and %c is %d\n",
       a, b, a-b);
 
    return 0;
}

Note that in ASCII code lowercase letters are greater than their uppercase equivalents by the constant value of 32.

 

Buy my book on Standard C, it contains 100% unique tutorial programs not available on this blog: http://www.amazon.com/Big-Als-C-Standard-ebook/dp/B00A4JGE0M

 

 

 

 

 

 

Yet Another Introduction to C Pointers

Pointers are memory locations that store other memory locations. Pointers are not a data type in the same sense that char, int, and double are data types. Pointers provide access to another data type, rather than being a data type in and of themselves.

#include <stdio.h>

int main(void){
 
  //declare some basic data types
 
  char charExmp;
  int intExmp;
 
  /*
   * declare a pointer
   *specify the data type that
   *will be pointer to
   *and put an asterisk in front of the
   *variable's identifier
  */
  char *charPtr;
  int *intPtr;
  void *voidPtr;
 
  return 0;
 
}

When we assign a value to a pointer, we must only assign an address. To assign an address we use the address of operator, the ampersand symbol to access the memory address of the variable. The compiler sets aside the amount of memory for a variable when it is declared, so we can be sure that declared variables have addresses.

#include <stdio.h>


int main(void){
 
  char charVal;
  double doubleVal;
 
  char *charPtr;
  double *doublePtr;
  void *voidPtr;
 
  //use the assignment operator
  //followed by the address of operator
  charVal='h';
  charPtr = &charVal;
 
  printf("charVal is %c.\n", charVal);
  printf("the address of charVal is %p\n", &charVal);
  printf("the value stored in charPtr is %p\n", charPtr);
 
  doubleVal = 918.664;
  doublePtr = &doubleVal;
 
  printf("doubleVal is %f.\n", doubleVal);
  printf("the value pointed to by doublePtr is %f\n", *doublePtr);
 
 
  return 0;
 
}

The dereference operator is the same as the asterisk used to declare a pointer. When used outside of a declaration, the asterisk is a dereference operator that tells the compiler to access the value stored where the pointer is pointing to.

#include <stdio.h>

int main(void){
 
 
  int intSrc, intDest;
 
  int *intPtr;
 
  intSrc = 2600;
 
  intPtr = &intSrc;
 
  intDest = *intPtr;
 
  printf("intDest has the value %d\n", intDest);
 
   return 0;
 
}

Introduction to Pointers

A pointer is a variable that holds a memory address that is the location of another variable in memory.

The variable that holds the memory address is said to point to the variable stored at that address.

Pointers are one of the most powerful, and also the trickiest, features of the C programming language. They are especially important in passing arguments to functions by reference, as well as constructing dynamic data structures.

Pointers depend on two operators, the & operator and the * operator. The & operator is a unary operator that returns the memory address of the object to the right of it. To print the memory address returned to us from the & operator we use the %p conversion character.

#include <stdio.h>

int main(void){
 
  int x = 0;
  double y = 8086.1976;
 
  printf("int x has the value %d and is stored at %p\n", x, &x);
  printf("double y has the value %f and is stored at %p\n", y, &y);
 
  return 0;
 
}

The second pointer operator is *, which is a unary operator that returns the value of the variable located at the address that follows it. Perversely, this same symbol must also be placed in front of the variable name with declaring a pointer variable.

#include <stdio.h>


int main(void){
 
  int a;
  int *b;
 
  a = 1138;
 
  b = &a;
 
  printf("a = %d\n", a);
  printf("b = %p\n", b);
  printf("&a = %p\n", &a);
  printf("*b = %d\n", *b);
 
  return 0;
 
}

The type of data that a pointer points to is called the base type of the pointer. It is the base type that determines what sort of variable the pointer can point to.

#include <stdio.h>

int main(void){
 
  int i = 187;
  char j = 's';
  double k = 8184.14;
 
  int *x = &i;
  char *y = &j;
  double *z = &k;
 
  printf("x = %p and *x = %d\n", x, *x);
  printf("y = %p and *y = %d\n", y, *y);
  printf("z = %p and *z = %d\n", z, *z);
 
  return 0;
 
}

We can use a pointer on the right-hand side of an assignment statement to assign its value to another pointer.

#include <stdio.h>

int main(void){
 
  int x = 404;
  int *pointer1, *pointer2;
 
  pointer1 = &x;
  pointer2 = pointer1;
 
  printf("Address stored at pointer1 = %p\n", pointer1);
  printf("Address stored at pointer2 = %p\n", pointer2);
 
  printf("Value pointed to by pointer1 = %d\n", *pointer1);
  printf("Value pointed to by pointer2 = %d\n", *pointer2);
 
  return 0;
 
}

Remember, all pointer operations are done according to the pointer’s base type. So, when we declare a pointer, we must make sure that its type is compatible with the variable to which we want to point. It is, however, possible to convert one type of pointer into another type of pointer using an explicit cast. The results, it should be noted, are often undesirable.

#include <stdio.h>

int main(void){
 
  double trouble = 909.68;
  int *pointer;
 
  pointer = (int *) &trouble;
 
  printf("The value of trouble is %f\n", trouble);
  printf("The value of *pointer is %d\n", *pointer);
 
  return 0;
 
}

 

Local Variables and Parameters

A variable is a named location in memory that is used to hold a mutable value. All variables have to be declared before they may be used. Note that in C, the name of the variable is completely independent from its type.

#include <stdio.h>


int main(void){
 
 int x, y, z;
 
 unsigned int unX, unY, shapoopie;
 
 double trouble, mint, dare;
 
 /*
  * use unsigned long
  * conversion specifier
  */
 printf("variable x is %lu bytes\n", sizeof(x));
 printf("variable dare is %lu bytes\n", sizeof(dare));
 
 return 0;
 
}

We can declare variables in two places: inside functions and outside all functions. Variables that can be declared within functions are either local variables or formal parameters. Variables declared outside of all functions are global variables.

Local variables can only be used inside the block of code in which they are declared. Local variables cease to exist after the block of code in which they are declared finishes executing. For this reason, we can have variables with the same name as long as they are contained within separate code blocks.

#include <stdio.h>

void functionExmp(void);


int main(void){
 
  printf("\n***inside main()***\n");
 
  int ace = 21;
 
  printf("value of ace=%d\n", ace);
 
  functionExmp();
 
  printf("value of ace=%d\n", ace);
 
  printf("***function main() finished***\n");
 
  return 0;
 
}

void functionExmp(void){
 
 printf("\t*inside functionExmp()*\n");
 int ace=1;

 printf("\tvalue of ace=%d\n", ace);
 
 printf("\t*functionExmp() finished*\n");
}

Note that we may declare local variables within any block of code delimited by curly braces. Declaring variables within the code of block helps modularize and compartmentalize code. Since the variable doesn’t exist anywhere else in the program outside of its own block, it cannot be altered accidentally by other code.

#include <stdio.h>


int main(void){
 
  int a=10;
 
  if(a>9){
    double dealing=19.19;
    printf("%f\t", dealing);
    dealing--;
    printf("%f\n", dealing);
    printf("%.2f\t", dealing--);
    printf("%.2f\n", --dealing);
  }
 
 
  return 0;
 
}

When we initialize a local variable to a value that value will be assigned to the variable each time the function is called.

#include <stdio.h>

int func1(void){
 
  printf("\n[entering func1()]\n");
 
  int i = 0;
 
  while(i<6){
    printf("i=%d\t", i++);
  }
 
  printf("i is now %d\n", i);
 
  printf("[exiting func1()]\n");
  return 0;
}

int main(void){
 
  int i = 1979;
 
  printf("\ni is %d\n", i);
 
 
  /*
   * call func1()
   */
  func1();
 
  printf("\ni is %d\n", i);
 
  /*
   * call func1() again
   */
  func1();
 
  printf("\ni is %d\n", i);
 
  return 0;
 
}

If a function is to receive arguments, it must declare variables that will accept the values of the arguments. The variables are called the parameters of the function. In behavior, they are the equivalent of any other local variable.

#include <stdio.h>

void intFunc(int param){
  printf("\n\t[inside intFunc()]\n");
  printf("\tparameter value is %d\n", param);
  printf("\t[exiting intFunc()]\n");
}

void doubleFunc(double param){
  printf("\n\t[inside doubleFunc()]\n");
  printf("\tparameter value is %f\n", param);
  printf("\t[exiting dobuleFunc()]\n");
}

int main(void){
 
  int j=-5;
  double dare=1.05;
 
  while(j++<5){
    printf("iterating while() loop");
    if(j%2==0){
     intFunc(j);
    } else {
     doubleFunc(dare++);  
    }
  }

  return 0;
 
}

Note that local variables are stored on the stack.

If Statements and an Intro to the scanf() Function

Decision making in a program revolves around choosing to execute one set of program statements rather than another. The ability to compare the values of expressions and, based on the results, chose to run on set of statements or another is one of the fundamental building blocks of programming.

 

There are four fundamental operators for making decisions: less than, <, equal to, ==, greater than, >, and not, !. Note that the equal to operator has two successive equal signs. Using these operators, we can build Boolean expressions that resolve to either a true or false value. As we have seen earlier, true in C is represented by 1, and false is represented by 0. The value of a Boolean expression can be stored in a Boolean variable.

#include <stdio.h>


int main(void){
 
  int Methuselah = 969;
  int Noah = 950;
 
 
  if(Methuselah > Noah){
   printf("Methuselah is older than Noah.\n");
  }
 
  if(Noah > Methuselah){
   printf("Noah is older than Methuselah.\n");
  }
 
  return 0;
 
}

 

If an expression evaluates to false, the associated code is not run.

The Boolean expression is contained in parentheses following the if statement. This expression is evaluated to either 0 or 1, and then the associated code is either run or not. Since a Boolean expression resolves to a single value, an if statement’s execution hinges on this value, which means that an if statement can accept a single constant value or a variable as well as a full expression. Note that in C, any nonzero integer is evaluated as being true.

#include <stdio.h>


int main(void){
 
  int a = 8088;
  int b = 8086;
 
 
  if(73){
    printf("73 is a nonzero value.\n");
  }
 
  if(a){
    printf("a is nonzero value.\n");
  }
 
  if(a > b){
   printf("a is greater than b.\n");
  }
 
  return 0;
 
}

The if statement enables us to be selective about what input we accept and what we do with that input. We can use the scanf() function as a simple mechanism for getting user input. The scanf() function uses the same conversion characters that the printf() function uses. The scanf() function reads a value from standard input, and stores in the variable specified in the function call.

 #include <stdio.h>

int main(void){
 
  int num = 0;
 
  printf("Please enter a whole number: ");
 
  //note the ampersand
  //before the variable
  scanf("%d", &num);
 
  if(num > 42){
   printf("Your number is greater than 42.\n");
  }
 
  printf("Have a nice day.\n");
 
  return 0;
 
}#include <stdio.h>

int main(void){
 
  int num = 0;
 
  printf("Please enter a whole number: ");
 
  //note the ampersand
  //before the variable
  scanf("%d", &num);
 
  if(num > 42){
   printf("Your number is greater than 42.\n");
  }
 
  printf("Have a nice day.\n");
 
  return 0;
 
}

It’s a good idea to put a leading space in the format string for the scanf() function; this leading space will tell the scanf() function to ignore any whitespace characters, including newlines.

#include <stdio.h>


int main(void){
 
  char a = 0;
  char b = 0;
 
  printf("Please enter a character: ");
 
  //use %c conversion character
  scanf(" %c", &a);
 
  printf("That character is %c; it's numeric value is %d\n", a, a);
 
  printf("Please enter another character: ");
 
  //don't forget the ampersand
  //before the variable
  scanf(" %c", &b);
 
  printf("That character is %c; it's numeric value is %d\n", b, b);
 
  if(a > b){
    printf("%c [%d] is greater than %c [%d]\n", a, a, b, b);
  }
 
  if(b > a){
    printf("%c [%d] is greater than %c [%d]\n", a, a, b, b);
  }
 
  return 0;
 
}

Note that the scanf() function, like the printf() function, is stored in the stdio.h header file.

Basic While Loops in C

The while keyword enables us to implement a loop. A loop allows repeated execution of a statement or block of statements as long as the condition remains true.

The while keyword is followed by a controlling-expression enclosed within parentheses. If the controlling expression evaluates to a nonzero value, the expression is considered to be true, and the body of the loop, consisting of one or more statements enclosed in curly braces, is executed.

#include <stdio.h>

int main(void){
 
  int x = -5;
 
  while(x++){
   printf("x = %d\n", x);
  }
 
  return 0;
 
}

Note that the curly braces are only necessary when the body consists of multiple statements. However, I feel that braces should always be used as it reduces the chance of a problem occurring if we later on decide to add a second statement to the loop.

The condition in a while loop is usually a relational expression.

#include <stdio.h>

int main(void){
 
  int x = 1;
  int y = 21;
 
  while(x!=y){
    printf("x = %d and y = %d\t", x,y);
    printf("x != y\n");
    x++;
    y--;
  }
 
  printf("\nx = %d and y = %d\t", x,y);
  printf("x == y\n");
 
  return 0;

}

When looping, we often use an increment or decrement operator to modify the variable being used in the test expression. However, we can use any sort of expression that modifies the value stored in the tested variable.

 include <stdio.h>

int main(void){
 
  int x = 30;
 
  while(x > 0){
    printf("%d > 0\n", x);
    x = x - 3;
  }
 
  return 0;
 
}

Note that each of the relational and equality operators produces a result of type int regardless of the type of its operands. The value of the result is 0 if the test is false, and 1 if the test is true.

#include <stdio.h>


int main(void){
 
  int i = 73;
  double j = 12.29;
  char k = 'c';
 
 
  printf("k > i = %d\t", k > i);
  printf("k < i = %d\n\n", k < i);
 
  printf("j == i = %d\t", j == i);
  printf("j != i = %d\n\n", j != i);
 
  i = i > k;
  printf("i == 0 = %d\n\n", i == 0);
 
  i = i == 0;
  printf("(i == 1) == (j > i) = %d", (i == 1) == (j > 1));
  return 0;
 
}

Just like if statements, while statements can be nested.

#include <stdio.h>

int main(void){
 
  int i, j;
  i = 0;

 
  while(++i<=10){
    j = 0;
    while(++j<=10){
     printf("%3d\t", i*j);
    }
    printf("\n");
  }
 
  return 0;
 
}

 

The Char Data Type and the sizeof Operator in C

We can find out how many bytes a given type occupies by using the sizeof operator. The expression sizeof(double), for instance, will result in the number of bytes takne up by a variable of type double.

#include <stdio.h>

int main(void){
 
  printf("Variables of type char are %d bytes\n", sizeof(char));
  printf("Variables of type int are %d bytes\n", sizeof(int));
  printf("Variables of type long are %d bytes\n", sizeof(long));
 
  printf("\nVariables of type float are %d bytes\n", sizeof(float));
  printf("\nVariables of type double are %d bytes\n", sizeof(double));
 
 
  return 0;
 
}

The char type is the least memory-intensive of all the data types. Typically a char requires just 1 byte. As an unsigned type, the value stored in char can be between 0 and 255; this corresponds to the binary values 00000000 and 11111111. As a signed type, char can be between -128 and 127, due to the fact that the first bit must be used to indicate the sign.

#include <stdio.h>


int main(void){
 
  char x,y;
 
  x = 254;
  y = 127;
 
  printf("x = %d\n", x);
  printf("y = %d\n\n", y);
 
  y++;
  x++;
 
  printf("y = %d\n", y);
  printf("x = %d\n", x);
 
  return 0;
 
}

A char variable can hold any single ASCII character, so we can specify the value for a char variable with a character constant. Note that a character constant is a character written between single quotes.

#include <stdio.h>


int main(void){
 
 
  char x, y;
 
  x = 'a';
  y = 'A';
 
  printf("x = %c\t and y = %c\n", x,y);
  printf("%c = %d\t and %c = %d\n", x,x,y,y);
 
  return 0;  
 
}