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;
 
}
Advertisements

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.