0

The C ~ Operator

The ~ operator is an unary operator, means that it only works with one number. I don’t know what is the ~ called. It’s kinda like – (negative) operator.

It’s used to reverse each bit in the bit pattern of the number. This means that it turns 0 to 1 and vise versa.

The following example uses 8-bit numbers:

~211 = 44
211 (11010011)
 44 (00101100)

The sum of the numbers in the above example is the largest 8-bit number (255).

211 + 44 = 255

Here is the example code for the ~ operator:

/*
 *
 * complement.c
 *
 * Program to demonstrate the ones complement (~) operator
 *
 * by Mark Virtue, 2001.
 *
 */

#include <stdio.h>
#include <stdlib.h>

static void goodbye() {
	while (getchar() != 'n') {}
	printf("nPress ENTER to exit: ");
	fflush(stdin);
	getchar();
}

main() {
	unsigned int number;
	unsigned char result;	// We shall use 8-bit demonstrations

	atexit(goodbye);

	printf("Please enter a number: ");
	scanf("%d", &number);

	result = ~number;

	printf("The ones complement of %u (hex %X) is %u (hex %X)n", number, number, result, result);

	return 0;
}

If you have any issue compiling the above code or question about this post, leave a comment below and I will be happy to help you.

0

The C Shift-left and Shift-right Bitwise Operators

This is the continuation of the C programming tutorial series from the last post which I wrote Dec 7 of last year.

The shift-left operator (<<, or double left) is used to shift the bit pattern of a number by a certain number of bits to the left.

The shift-right operator (>>, or double right) is used to shift this bit pattern to the opposite direction (right).

For example, the bit pattern of five (5) is 101. The result bit pattern of shifting it 4 bits to the left is 1010000.

If shifting left are too far such as 50, it will produce undefined results, while right shifting too far will simply be truncated.

Here is an example of shift-left operator:

13<<3=104
 13 (00001101)
104 (01101000)

The bit pattern between 13 and 104 is exactly shifted left 3 places.

Notice the division of 104 and 13 is exactly 8, which is 2 to the power of 3, which means

13*2^3=104

which is almost the same as the above statement with shift-left operator.

Here is another example for the shift-right operator:

52>>4=3
52 (00110100)
 3 (00000011)

The bit pattern between 52 and 3 is shifted right 4 spaces, which removed the last 4 digit (0100) which is the reminder of 3.

This is exactly the same as the last example except this one is divide by 2 to the power of 4:

52 / 2^4 = 3

Note that this is integer division, therefore there is no remainder or decimal.

Based on the above examples, you can see that shifting left is multiply by 2 and sifting right is divide by 2.

Below is the example code for the shift operators:

/*
 * shift.c
 *
 * Program to demonstrate the shift left and right operators
 *
 * by Mark Virtue, 2001.
 *
 */

 #include <stdio.h>
 #include <stdlib.h>

 static void goodbye() {
 	while (getchar() != 'n') {};
 	printf("nPress ENTER to exit: ");
 	fflush(stdin);
 	getchar();
 }

 main() {
 	unsigned int number;
 	int shift;
 	unsigned int result;

 	atexit(goodbye);

 	printf("Please enter a number: ");
 	scanf("%d", &number);
 	printf("How many bits would you like to shift (negative to shift right)? ");
 	scanf("%d", &shift);

 	if (shift >= 0) {
 		result = number << shift;
 	}
 	else {
 		result = number >> -shift;
 	}

 	printf("%u (hex %X) shifted %s %d is %u (hex %X)n",
 		number, number,
 		shift >= 0 ? "left" : "right",
 		shift >= 0 ? shift : -shift,
 		result, result);

 	return 0;
 }

If you have any issue compiling the above code or any question regarding this post, leave a comment below and I will help you ASAP.

2

C Bitwise Operators

Introduction

The bitwise operators are used to manipulate the individual bits.

About Bits

Any type of integer number (int, long, short) is a series of bits. For example, long has an array of 32 bits.

These bits represent the number in binary arithmetic or base-2, which I think it’s the machine code representation which are translated to 0 and 1. For example, the decimal number 87 can be represented in base-2 as 1010111.

Note that since the base-2 numbers only have 0 and 1 and these two numbers also represent boolean values, the bits can be represented as individual boolean values. And they are the purpose of bitwise operators – to access the boolean values from the integers.

Video

Here is the video which this post is based on:

Sorry about the quality of the video. I suppose it’s because it’s in .mov format, but I’m glade that it successfully converted to Flash video. It doesn’t play properly in all the players I’ve tried other than Totem Movie Player. It can’t even convert properly using FFmpeg.

1

C Language Reference Resources

C Plus Plus Minus Minus

C Plus Plus Minus MinusThis is just a small post to list some of the references for C standard library functions:

Do you have any other resources for the C language? Please share them in the comment below.

1

Generating Random Numbers with C

C Plus Plus Minus Minus

C Plus Plus Minus Minus

Introduction

There are some standard library functions for generating random numbers in C:

  • The function rand is used for generating a pseudo-random number between 0 and RAND_MAX where RAND_MAX is defined using #define. Here is an example:
    x = rand();
  • Note that pseudo-random number means that sometimes the function will generate the same number each time the function is executed.
  • The function srand can be used to fix this issue so that it generates different random number all the time. It’s used to seed (which I think it’s the helper function) the rand function, Below is an example:
    srand(12345);

Example Code

/*

 *      random.c

 *

 *      Program to demonstrate the use of rand() and srand()

 *

 *      by Mark Virtue, 2001.

 */

#include <stdio.h>

#include <stdlib.h>

main()

{

    int     i;

    srand(time(NULL));	// Use the current system time as the seed so that it can generate different set of numbers each time the program is executed

    for (i = 0; i < 10; i++)

        printf("Random number #%2d is : %6dn", i+1, rand());	// Generating 10 random numbers. However, sometimes it will generate the same set of numbers each time the program is executed.

    fflush(stdin);

    getchar();

    return 0;

}

Questions or problems?

If you have any issue compiling and running the above code, fell free to discuss them in the comment below.

0

Using Standard I/O Functions

Introduction

Continue from the last post, this time I’m going to talk about the usage of standard I/O functions.

Example Code

The following code is copied from the original tutorial. It’s well documented by me. I also added and modified some places of the source code wherever GCC is mentioned in the comments.

/*

 *      average.c

 *

 *      Program to demonstrate I/O to text files

 *

 *      by Mark Virtue, 2001.

 */

#include <stdio.h>

#include <stdlib.h>
#include <errno.h>		// for printing out error message as required by GCC
#include <string.h>		// for strerror() to work correctly, required by GCC

#include <time.h>       // for time() and ctime()

#define FNAME   "./test123"		// Create the file in the program's folder'

/*

 *  pause()

 *

 *  Ask the user to press ENTER

 *  This function is used in conjunction with atexit()

 */

void pause()

{
	while (getchar() != 'n') {}	// Use the while loop to clear the input variable cache for GCC

    printf("nProgram ended, Press ENTER: ");

    fflush(stdin);

    getchar();

}

main()

{

    FILE    *fptr;

    int     count;

    int     number;

    int     total = 0;

    time_t  the_time;

    int     i;

    atexit(pause);

    /*

     *  First, open the text file for writing

     *  and write out the header info to it

     */

    fptr = fopen(FNAME, "w");	// w means that opening the file for writing

    if (fptr == NULL)	// In case if fopen fails to open the file

    {

        fprintf(stderr, "Could not open %s - %sn", FNAME, strerror(errno));	// errno contains the error number that is generated during the failure. It explans why the fopen failed. sys_errlist converts errno to the readable error message. Both sys_errlise and errno are the global variables.
        /*
         * Note that the the original variable sys_errlist is deprecated in GCC.
         * I used strerror() above as recommended by the warning message of GCC
         */

        exit(1);	// Exit the program since the file failed to open and nothing to execute without opening the file

    }

    /*

     *  Test to see if we can write to the file

     */

    if (fprintf(fptr, "This is the output file for the File I/O programnn") < 0)	// Try to print one line of text into the file to test its writability after the file is opened successfully

    {

        perror("Could not write to the file");	// It's the same as the above error statement. perror() writes to the stderror and output the message along with sys_errlist[errno] error message

        fclose(fptr);	// Close the file since it's unable to write to the file. It's a good practice to manually close the file once the program finishes operation with the file.

        exit(1);	// Exit the program once the file is closed

    }

    /*

     *  Write the rest of the header info, including the current time

     */

    the_time = time(NULL);	// time(NULL) is used for getting the system time

    fprintf(fptr, "ttCreated on %snn", ctime(&the_time));	// ctime() is used to print out the current time

    fputs("The numbers are:nn", fptr);

    /*

     *  Determine how many integers are to be averaged

     */

    printf("How many numbers do you want to average: ");

    scanf("%d", &count);

    /*

     *  We don't want to divide by zero if count == 0, so...

     */

    if (count == 0)

    {

        fputs("No numbers to averagen", fptr);	// Print the message to the file instead of on the screen

        fclose(fptr);	// Close the file since it doesn't have anything to average

        exit(0);	// Close the program

    }

    /*

     *  Otherwise, read all the numbers and accumulate them

     */

    for (i = 0; i < count; i++)	// Use for loop to enter all the required numbers

    {

        printf("Please enter number #%d: ", i+1);

        scanf("%d", &number);

        /*

         *  Add this integer to our total

         */

        total += number;

        /*

         *  Write the number out to the file

         */

        fprintf(fptr, "%3d: %4dn", i+1, number);

    }

    /*

     *  A final message, then close the file

     */

    fprintf(fptr, "nThe average is %fn", (float)total / count);

    fclose(fptr);

    return 0;

}

Questions or Problems?

If you have any problem compile and running above source code, please leave a comment below.

0

Explanation and Usage of each File Function in C

fopen

fopen is used to open files for reading, writing, and/or appending. It is the most important function for C for file operations. Below is the format of the function:

FILE *fopen(char *name, char *mode);

The name variable represents file name which will be opened. The possible modes for the variable mode in the function are:

  • “r” – read
  • “w” – write
  • “a” – append
  • “rb” – read binary
  • “wb” – write binary
  • “ab” – append binary

Here are some good practices for using fopen:

  • All opened file should be closed using fclose.
  • Any contents of files are lost if opened using write mode (“w”), use append mode (“a”) instead.
  • Files don’t need to exist for append mode.
  • stdin, stdout, and stderr are opened at the start of the program and do not need to be closed manually.

fclose

fclose is used to close the files that have been opened using fopen. Blow is the format:

void fclose (FILE *fp);

The fp is the variable name for the file pointer.

All opened files using fopen will be closed by the OS at the end of the program. However, the opened files will remain in the memory until they are closed manually using fclose or when the program terminated.

fprintf and fscanf

fprintf and fscanf are the same as printf and scanf, except that it needs to specify a file handle. Here are the formats of these two functions:

int fprintf(FILE *fp, char *string, ...);
int fscanf(FILE *fp, char *string, ...);

For example,

printf("The answer is %d", x);

is the same as

fprintf(stdout, "The answer is %d", x);

Note that stdout can be replaced by a file handle.

fread and fwrite

fread and fwrite are mostly used to read and write the data to and from the binary files:

int fwrite (void *data, int size, int count, FILE *fp);
int fread (void *data, int size, int count, FILE *fp);

The variable data is a collection of memory, items, or data. Both functions will return variable count if successful. Otherwise, they will return -1. fread will return a smaller number or zero (0) if the function is finished reading the file.

0

More About File Functions in stdio.h

All file-based functions in stdio.h use a file handle object to operate files in a C program. The file handle is a pointer to a structure type called FILE. Below is the format of the FILE declaration:
FILE *handle;
handle = fopen ("x.txt", "r");

Note that the constants stdin, stdout, an stderr are already declared as file handles. These are special variables that do not represent true files. They are automatically opened when the program starts.

1

Introduction to C File-based Input and Output

The functions which are used for read and write data to a file are specified in stdio.h. When performing file operations, the three special files are used (stdin, stdout, and stderr):

  • stdin is the standard input file. It’s used for reading inputted data from keyboard.
  • stdout is the standard output file. It’s used for writing data onto the screen.
  • stderr is the standard error file. It’s used for writing output errors onto the screen.

The basic steps for reading/writing the data from/to a file are follows:

  1. Open the file
  2. Read/write data from/to the file
  3. Close the file

Two types of files can be opened in C – text files and binary files:

  • Text files only could contain printable characters and can be read and written on a line-by-line bases
  • Binary files could contain any data and can be read and written in fixed blocks of data

During the opening process of the file, one of these two file types needs to be specified in order to open the file.

These are the common functions used to do the file operations:

  • fopen and fclose
  • fprintf and fscanf (for text files)
  • fputs and fgets (also for text files)
  • fputc and fgetc (also for text files)
  • fread and fwrite (for binary files)
  • fseek (also for binary files)

Note that some of the above functions are different from the following corresponding functions:

  • open and close
  • read and write
  • seek
0

Exit a C Program

There are two functions in the Standard C Libraries that are used for exiting the program.

The function exit() is used to exit the program from any point in the code. It needs to have an integer as the only parameter. The integer represents the exit status. Here is the prototype for the exit function:

void exit(int status);

Another function, atexit(), also takes only one parameter. However, it needs to be a function name instead of an integer. This function is used to execute the specified function during the termination of the program (executed from the exit() function or at the end of the main() function). Below is an example:

atexit(log_off_database);

Here is the sample code for atexit() function:

/*
 * atexit.c
 *
 * Program to demonstrate the use of atexit
 *
 * by Mark Virtue, 2001.
 */

#include <stdio.h>
#include <stdlib.h>

void say_goodbye() {
 printf("Goodbye for now (press ENTER): ");
 fflush(stdin);
 getchar();
}

static void log_off_database() {
 printf("We are now logged off the databasen");
}

static void log_onto_database() {
 printf("We are now logged onto the databasen");
 atexit(log_off_database);
}

static void process_things() {
 int x;

 printf("Please enter a number: ");
 scanf("%d", &x);

 if (x > 10) {
 printf("That number is too big - exiting...n");
 exit(1);
 }

 printf("No problem - continuing normally..n");
}

main() {
 atexit(say_goodbye);

 log_onto_database();
 process_things();

 return 0;
}
Pages ... 1 2 3 4 5 6 7 8