Statements are the executable parts of a C function. All statements end with a semicolon. If you know the name of the statement for which you need help, you can go to this section:
goto label; goto *expression; continue; break; return [expression];
i = 0;
while (i < 100)
{
if (++i % 5)
continue; /* unconditional jump to top of while loop */
printf ("%2d ", i);
}
printf ("\n");
i = 0;
L: while (i < 100)
{
if (++i % 5)
goto L: /* unconditional jump to top of while loop */
printf ("%2d ",i);
}
printf ("\n");
i = 0;
while (1)
{
if ((++i % 5) == 0)
printf ("%2d ", i);
if (i > 100)
break; /* unconditional jump past the while loop */
}
printf ("\n");
i = 0;
while (1)
{
if ((++i % 5) == 0)
printf ("%2d ", i);
if (i > 100) {
printf ("\n");
return; /* unconditional jump to calling function */
}
}
compound-statement ::=
{[declaration-list][statement-list]}
declaration-list ::=
declaration
declaration-list
declaration
statement-list ::=
statement
statement-list statement
Variables and constants declared in the block are local to the block and to any inner blocks unless declared extern. If the objects are initialized, the initialization is performed each time the compound statement is entered from the top through the left brace ({) character. If the statement is entered via a goto statement or in a switch statement, the initialization is not performed.
Any object declared with static storage duration is created and initialized
when the program is loaded for execution. This is true even if the object
is declared in an inner block.
if (x > y)
{
int temp;
temp = x;
x = y;
y = temp;
}
In this example, variable temp is local to the compound statement.
It can only be accessed within the compound statement.
expression-statement ::= [expression];
You can use any valid expression as an expression statement by terminating it with a semicolon. Expression statements are evaluated for their side effects such as assignment or function calls. If the expression is not specified, but the semicolon is still provided, the statement is treated as a null statement.
Null statements are useful for specifying no-operation statements. No-operation
statements are often used in looping constructs where all of the work of
the statement is done without an additional statement.
for(i=0,s=0; i<10; s+=x[i++]);The syntax of the for statement requires a statement following the closing ) of the for. A null statement (;) satisfies this syntax requirement.
labeled-statement ::= identifier : statement case constant-expression : statement default: statement
The case and default labels can only be used inside
a switch statement.
if (fatal_error) goto get_out; . . . get_out: return(FATAL_CONDITION);The return statement is labeled get_out.
while (expression) statement do statement while (expression); for ([expression1] ; [expression2]; [expression3]) statement
C has several looping statements: while ,
do...while
,
and for
. The main difference between these
statements is the point at which each loop tests for the exit condition.
Refer to the goto
,
continue
,
and break
statements for ways to exit a
loop without reaching its end or meeting loop exit tests.
i = 0;
while (i < 5)
{
a[i] = i;
i++;
}
i = 0;
do
{
a[i] = i;
i++;
} while (i < 5);
for (i = 0; i < 5; i++)
{
a[i] = i;
}
if (expression) statement [else statement] switch (expression) statement
if (expression) statement:
if (x<y) x=y;
if (expression) statement else statement:
if (x<y) x=y; else y=x;
switch (expression) statement:
switch (x)
{ case 1: x=y;
break;
default: y=x;
break;
}
Control passes to the statement following the switch or iteration statement. You cannot use a break statement unless it is enclosed in a switch or loop statement. Further, a break only exits out of one level of switch or loop statement. To exit from more than one level, you must use a goto statement.
When used in the switch statement, break normally
terminates each case statement. If you use no break (or
other unconditional transfer of control), each statement labeled with case
flows into the next. Although not required, a break is usually
placed at the end of the last case statement. This reduces the
possibility of errors when inserting additional cases at a later time.
for (i=0; i<=6; i++)
if(i==3) break;
else printf ("%d\n",i);
This example prints:
0 1 2
/* Program name is "continue_example". This program
* reads a file of student names and test scores. It
* averages each student"s grade. The for loop uses
* a continue statement so that the third test score
* is not included.
*/
#include <stdio.h>
int main(void)
{
int test_score, tot_score, i;
float average;
FILE *fp;
char fname[10], lname[15];
fp = fopen("grades_data", "r");
while (!feof(fp)) /* while not end of file */
{
tot_score = 0;
fscanf(fp, "%s %s", fname, lname);
printf("\nStudent"s name: %s %s\nGrades: ", fname, lname);
for (i = 0; i < 5; i++)
{
fscanf(fp, "%d", &test_score);
printf("%d ", test_score);
if (i == 2) /* leave out this test score */
continue;
tot_score += test_score;
} /* end for i */
fscanf(fp, "\n"); /* read end-of-line at end of */
/* each student"s data */
average = tot_score/4.0;
printf("\nAverage test score: %4.1f\n", average);
} /* end while */
fclose(fp);
}
If you execute this program, you get the following output:
Student"s name: Barry Quigley Grades: 85 91 88 100 75 Average test score: 87.8 Student"s name: Pepper Rosenberg Grades: 91 76 88 92 88 Average test score: 86.8 Student"s name: Sue Connell Grades: 95 93 91 92 89 Average test score: 92.2
do statement; while (expression);
Two ways to jump out of a dowhile loop prematurely (that is, before expression becomes false) are the following:
/* Program name is "do.while_example". This program finds the
* summation (that is, n*(n+1)/2) of an integer that a user
* supplies and the summation of the squares of that integer.
* The use of the do/while means that the code inside the loop
* is always executed at least once.
*/
#include <stdio.h>
int main(void)
{
int num, sum, square_sum;
char answer;
printf("\n");
do
{
printf("Enter an integer: ");
scanf("%d", &num);
sum = (num*(num+1))/2;
square_sum = (num*(num+1)*(2*num+1))/6;
printf("The summation of %d is: %d\n", num, sum);
printf("The summation of its squares is: %d\n",
square_sum);
printf("\nAgain? ");
fflush(stdin);
scanf("%c", &answer);
} while ((answer != "n") && (answer != "N"));
}
If you execute this program, you get the following output:
Enter an integer: 10 The summation of 10 is: 55 The summation of its squares is: 385 Again? y Enter an integer: 25 The summation of 25 is: 325 The summation of its squares is: 5525 Again? n
for ([expression1]; [expression2]; [expression3]) statement;
If the loop body executes a continue statement, control passes to expression3. Except for the special processing of the continue statement, the for statement is equivalent to the following:
expression1;
while (expression2) {
statement
expression3;
}
You may omit any of the three expressions. If expression2 (the controlling
expression) is omitted, it is taken to be a nonzero constant.
for (j = 0; j < 10; j++)
{
do_something();
}
is the same as the following while loop:
j = 0;
while (j<10)
{
do_something();
j++;
}
/* Program name is "for_example". The following computes a
* permutation that is, P(n,m) = n!/(n-m)! using for
* loops to compute n! and (n-m)!
*/
#include <stdio.h>
#define SIZE 10
int main(void)
{
int n, m, n_total, m_total, perm, i, j, mid, count;
printf("Enter the numbers for the permutation (n things ");
printf("taken m at a time)\nseparated by a space: ");
scanf("%d %d", &n, &m);
n_total = m_total = 1;
for (i = n; i > 0; i--) /* compute n! */
n_total *= i;
for (i = n - m; i > 0; i--) /* compute (n-m)! */
m_total *= i;
perm = n_total/m_total;
printf("P(%d,%d) = %d\n\n", n, m, perm);
/* This series of for loops prints a pattern of "Z"s" and shows
* how loops can be nested and how you can either increment or
* decrement your loop variable. The loops also show the proper
* placement of curly braces to indicate that the outer loops
* have multiple statements.
*/
printf("Now, print the pattern three times:\n\n");
mid = SIZE/2;
/* controls how many times pattern is printed */
for (count = 0; count < 3; count++)
{
for (j = 0; j < mid; j++)
{
/* loop for printing an individual line */
for (i = 0; i < SIZE; i++)
if (i < mid - j || i > mid + j)
printf(" ");
else
printf("Z");
printf("\n");
}
for (j = mid; j >= 0; j--)
{
for (i = 0; i <= SIZE; i++)
if (i < mid - j || i > mid + j)
printf(" ");
else
printf("Z");
printf("\n");
}
}
}
If you execute this program, you get the following output:
Enter the numbers for the permutation (n things taken m at a time) separated by a space: 4 3 P(4,3) = 24 Now, print the pattern three times: Z ZZZ ZZZZZ ZZZZZZZ ZZZZZZZZZ ZZZZZZZZZZZ ZZZZZZZZZ ZZZZZZZ ZZZZZ ZZZ Z Z ZZZ ZZZZZ ZZZZZZZ ZZZZZZZZZ ZZZZZZZZZZZ ZZZZZZZZZ ZZZZZZZ ZZZZZ ZZZ Z Z ZZZ ZZZZZ ZZZZZZZ ZZZZZZZZZ ZZZZZZZZZZZ ZZZZZZZZZ ZZZZZZZ ZZZZZ ZZZ Z
Few programming statements have produced as much debate as the goto statement. The goto statement is necessary in more rudimentary programming languages, but its use in high-level languages is generally frowned upon. Nevertheless, most high-level languages, including C, contain a goto statement for those rare situations where it can"t be avoided.
With deeply nested logic there are times when it is cleaner and simpler
to bail out with one goto rather than backing out of the nested
statements. The most common and accepted use for a goto is to
handle an extraordinary error condition.
/* Program name is "goto_example". This program finds the
* circumference and area of a circle when the user gives
* the circle"s radius.
*/
#include <stdio.h>
#define PI 3.14159
int main(void)
{
float cir, radius, area;
char answer;
extern void something_different(void);
circles:
printf("Enter the circle"s radius: ");
scanf("%f", &radius);
cir = 2 * PI * radius;
area = PI * (radius * radius);
printf("The circle"s circumference is: %6.3f\n", cir);
printf("Its area is: %6.3f\n", area);
printf("\nAgain? y or n: ");
fflush(stdin);
scanf("%c", &answer);
if (answer == "y" || answer == "Y")
goto circles;
else {
printf("Do you want to try something different? ");
fflush(stdin);
scanf("%c", &answer);
if (answer == "y" || answer == "Y")
/* goto different; WRONG! This label is in */
/* another block. */
something_different();
} /* end else */
}
void something_different(void)
{
different:
printf("Hello. This is something different.\n");
}
If you execute this program, you get the following output:
Enter the circle"s radius: 3.5 The circle"s circumference is: 21.991 Its area is: 38.484 Again? y or n: y Enter the circle"s radius: 6.1 The circle"s circumference is: 38.327 Its area is: 116.899 Again? y or n: n Do you want to try something different? y Hello. This is something different.
if (exp) /* format 1 */ statement if (exp) /* format 2 */ statement1 else statement2
In the first form, if exp evaluates to true (any nonzero value), C executes statement. If exp is false (evaluates to 0), C falls through to the next line in the program.
In the second form, if exp evaluates to true, C executes statement1, but if exp is false, statement2 is performed.
A statement can be an if or ifelse statement.
if (exp1) /* multiple conditions */ statement1 else if (exp2) statement2 else if (exp3) statement3 .. . else statementNThe important thing to remember is that C executes at most only one statement in the ifelse and ifelse/ifelse constructions. Several expressions may indeed be true, but only the statement associated with the first true expression is executed.
/* determine reason the South lost the American Civil War */
if (less_money)
printf("It had less money than the North.\n");
else if (fewer_supplies)
printf("It had fewer supplies than the North.\n");
else if (fewer_soldiers)
printf("It had fewer soldiers.\n");
else
{
printf("Its agrarian society couldn"t compete with the ");
printf("North"s industrial one.\n");
}
All the expressions in the above code fragment could be evaluated to true,
but the run-time system would only get as far as the first line and never
even test the remaining expressions.
if (x > y) {
temp = x;
x = y;
y = temp;
}
else
/* make next comparison */
Braces also are important when you nest if statements. Since the
else
portion of the statement is optional, you may not have one for an inner
if. However, C associates an else with the closest previous
if
statement unless you use braces to show that isn"t what you want. For example:
if (month == 12) { /* month = December */
if (day == 25)
printf("Today is Christmas.\n");
}
else
printf("It"s not even December.\n");
Without the braces, the else would be associated with the inner
if
statement, and so the no-December message would be printed for any day
in December except December 24. Nothing would be printed if
month
did not equal 12.
/* Program name is "if.else_example". */
#include <stdio.h>
int main(void)
{
int age, of_age;
char answer;
/* This if statement is an example of the second form (see
* "Description" section). */
printf("\nEnter an age: ");
scanf("%d", &age);
if (age > 17)
printf("You"re an adult.\n");
else {
of_age = 18 - age;
printf("You have %d years before you"re an adult.\n",
of_age);
} /* end else */
printf("\n");
printf("This part will help you decide whether to jog \
today.\n");
printf("What is the weather like?\n");
printf(" raining = r\n");
printf(" cold = c\n");
printf(" muggy = m\n");
printf(" hot = h\n");
printf(" nice = n\n");
printf("Enter one of the choices: ");
fflush(stdin);
scanf("\n%c", &answer);
/* This if statement is an example of the third form (see
* "Description" section. */
if (answer == "r")
printf("It"s too wet to jog today. Don"t bother.\n");
else if (answer == "c")
printf("You"ll freeze if you jog today. Stay indoors.\n");
else if (answer == "m")
printf("It"s no fun to run in high humidity. Skip it.\n");
else if (answer == "h")
printf("You"ll die of the heat if you try to jog today. \
So don"t.\n");
else if (answer == "n")
printf("You don"t have any excuses. You"d better go \
run.\n");
else
printf("You didn"t give a valid answer.\n");
}
If you execute this program, you get the following output:
Enter an age: 15 You have 3 years before you"re an adult. This part will help you decide whether to jog today. What is the weather like? raining = r cold = c muggy = m hot = h nice = n Enter one of the choices: r It"s too wet to jog today. Don"t bother.
return; /* first form */ return exp; /* second form */
A function may contain any number of return statements. The first one
encountered in the normal flow of control is executed, and causes program
control to be returned to the calling routine. If there is no return
statement, program control returns to the calling routine when the right
brace of the function is reached. In this case, the value returned is undefined.
The following example shows a function that returns a float, and some legal return values.
float f(void)
{
float f2;
int a;
char c;
f2 = a; /* OK, quietly converts a to float */
return a; /* OK, quietly converts a to float */
f2 = c; /* OK, quietly converts c to float */
return c; /* OK, quietly converts c to float */
}
char *f(void)
{
char **cpp, *cp1, *cp2, ca[10];
int *ip1, *ip2;
cp1 = cp2; /* OK, types match */
return cp2; /* OK, types match */
cp1 = *cpp; /* OK, types match */
return *cpp; /* OK, types match */
/* An array name without a subscript is converted
* to a pointer to the first element.
*/
cp1 = ca; /* OK, types match */
return ca; /* OK, types match */
cp1 = *cp2; /* Error, mismatched types */
/* (pointer to char vs. char) */
return *cp2; /* Error, mismatched types */
/* (pointer to char vs. char) */
cp1 = ip1; /* Error, mismatched pointer types */
return ip1; /* Error, mismatched pointer types */
return; /* Produces undefined behavior */
/* should return (char *) */
}
Note in the last statement that the behavior is undefined if you return
nothing. The only time you can safely use return without an expression
is when the function type is void. Conversely, if you return an
expression for a function that is declared as returning void,
you will receive a compile-time error.
Functions can return only a single value directly via the
return
statement. The return value can be any type except an array or
function. This means that it is possible to return more than a single value
indirectly by passing a pointer to an aggregate type. It is also possible
to return a structure or union directly. HP C implements this by passing
the structure or union by reference if the structure or union is greater
than eight bytes.
/* Program name is "return_example".
* This program finds the length of a word that is entered.
*/
#include <stdio.h>
int find_length( char *string )
{
int i;
for (i =0; string[i] != '\0'; i++);
return i;
}
int main( void )
{
char string[132];
int result;
int again = 1;
char answer;
printf( "This program finds the length of any word you ");
printf( "enter.\n" );
do
{
printf( "Enter the word: ");
fflush(stdin);
gets( string );
result = find_length( string );
printf( "This word contains %d characters. \n", result);
printf("Again? ");
scanf("%c", &answer);
} while (answer == 'Y' || answer == 'y');
}
If you execute this program, you get the following output:
This program finds the length of any string you enter. Enter the string: Copenhagen The string is 10 characters. Again? y Enter the string: galaxy The string is 6 characters. Again? n
switch ( exp )
{
case const_exp : [statement]...
[case const_exp : [statement]...]
[default : [statement]...]
}
The expression immediately after the switch keyword must be enclosed in parentheses and must be an integral expression.
The expressions following the case keywords must be integral constant expressions; that is, they may not contain variables.
An important feature of the switch statement is that program flow continues from the selected case label until another control-flow statement is encountered or the end of the switch statement is reached. That is, the compiler executes any statements following the selected case label until a break, goto, or return statement appears. The break statement explicitly exits the switch construct, passing control to the statement following the switch statement. Since this is usually what you want, you should almost always include a break statement at the end of the statement list following each case label.
The following print_error() function, for example, prints an error message based on an error code passed to it.
/* Prints error message based on error_code.
* Function is declared with void because it doesn"t
* return anything.
*/
#include <stdio.h>
#define ERR_INPUT_VAL 1
#define ERR_OPERAND 2
#define ERR_OPERATOR 3
#define ERR_TYPE 4
void print_error(int error_code)
{
switch (error_code) {
case ERR_INPUT_VAL:
printf("Error: Illegal input value.\n");
break;
case ERR_OPERAND:
printf("Error: Illegal operand.\n");
break;
case ERR_OPERATOR:
printf("Error: Unknown operator.\n");
break;
case ERR_TYPE:
printf("Error: Incompatible data.\n");
break;
default: printf("Error: Unknown error code %d\n",
error_code);
break;
}
}
The break statements are necessary to prevent the function from
printing more than one error message. The last break after the
default case is not really necessary, but it is a good idea to
include it anyway for the sake of consistency.
/* This function returns 1 if the argument is a
* punctuation character. Otherwise, it returns 0.
*/
is_punc(char arg)
{
switch (arg) {
case ".":
case ",":
case ":":
case ";":
case "?":
case "-":
case "(":
case ")":
case "!": return 1;
default : return 0;
}
}
/* Use the switch statement to decide which comment should be printed */
#include <stdio.h>
int main(void)
{
char answer, grade;
answer = "y";
printf("\n\n");
while (answer == "y" || answer == "Y") {
printf("Enter student"s grade: ");
fflush(stdin);
scanf("%c", &grade);
printf("\nComments: ");
switch (grade) {
case "A":
case "a":
printf("Excellent\n");
break;
case "B":
case "b":
printf("Good\n");
break;
case "C":
case "c":
printf("Average\n");
break;
case "D":
case "d":
printf("Poor\n");
break;
case "E":
case "e":
case "F":
case "f":
printf("Failure\n");
break;
default:
printf("Invalid grade\n");
break;
} /* end switch */
printf("\nAgain? ");
fflush(stdin);
scanf("%s", &answer);
}
}
If you execute this program, you get the following output:
Enter student"s grade: B Comments: Good Again? y Enter student"s grade: C Comments: Average Again? n
while ( exp ) statement
The following describes two ways to jump out of a while loop prematurely (that is, before exp becomes false):
/* Program name is "while_example" */
#include <stdio.h>
int main(void)
{
int count = 0, count2 = 0;
char a_string[80], *ptr_to_a_string = a_string;
printf("Enter a string -- ");
gets(a_string);
while (*ptr_to_a_string++)
count++; /* A simple statement loop */
printf("The string contains %d characters.\n", count);
printf("The first word of the string is ");
while (a_string[count2] != " " && a_string[count2] != "\0")
{
/* A compound statement loop */
printf ("%c", a_string[count2]);
count2++;
}
printf("\n");
}
If you execute this program, you get the following output:
Enter a string Four score and seven years ago The string contains 30 characters. The first word of the string is Four