overview edit doc new doc remove

Jan 26, 2018

updated at: Sep 17, 2018

C

C is programming language developed by Dennis Ritchie. The C language is a general-purpose high-level language originally designed for Unix systems.

The compiler

C is written in .c files and needs to be compiled and linked.

C is what is called a compiled language. This means that once you write your C program, you must run it through a C compiler to turn your program into an executable that the computer can run (execute). The C program is the human-readable form, while the executable that comes out of the compiler is the machine-readable and executable form.

Gcc

gcc class.c -o program
./program

Basics

Syntax

Comments

/* multiple line
comment*/

// one line comment

Quotes

Double quotes creates a string litteral and single quotes identify a single character.

Datatypes

int var = 100;
char firstLetter = 'D';
char *name = "Sebastiaan";
long int bigNummer = 546564564;
float pi = 3.1415;
double Bigpi = 3.14159564654654564655;

NOTE: C doesn't have any built-in boolean type but you can use a library for boolean and then you can use:

_Bool isANumber;

if else

if (num1 > num2) {  

  printf("");  

} else if (...) { 

  ...

}

Loops

While
while () { 

  ...

}

do { 

  ...

} while();
For
for (int counter = 0; counter <= 20; counter++) {

}
Continue
if ((counter % 2) == 0) continue;
Switch
switch () {

  case "A" : printf(""); break;

  * : printf(""); break;

}

Libraries (headers)

The C language uses libraries as its primary method of extension. A library is a set of functions, you can use a library by declaring its header file. headers are written at the top of the class. You can also make your own .h file which is a header file that contains C function declarations and macro definitions to be shared between several source files.

Here are some libraries for basic uses:

#include <stdio.h> // library for printing, printf for example

#include <string.h> // library for string

#include <stdlib.h> // when you want to use exit()

#include <strings> // strings

#include <stdbool.h> // needed if you want to use bool

Main

C needs a main class to run.

int main() {

  ....

  return 0;

}

Constants

You can define constansts with define.

#define MYNAME "Sebastiaan"

Printing and scanning

Printing

Printing is done by using the printf function.

printf ("\n");
printf ("\" \' \/ ");
printf ("this is my first C line");
printf ("I am %d years old\n\n"), age;

Scanning

There are different ways to scan/read from input. One way is to use scanf which is not smart and is bloated, a better way is to use fgets. fgets needs a specified size limit to make it work. Another way is to use getchar, it will wait until the enter button is pressed and push everything to the screen. The data is stored in a buffer as it is entered. In essence a buffer is just a pointer without specified size. getchar is an example of line buffering because the buffer ends when a newline is entered.

# scanf
scanf ("%c", &yourAge);
printf ("Your age is %c", yourAge);
scanf ("%s %s", firstName, lastName);
printf ("Your Name is %s %s\n\n", firstName, lastName);

# fgets
fgets (name, 30, stdin);
fputs ("hi", stdout);

# getchar
getchar();

Passing arguments

int main (int argc, char *argv []) {

  if (argc < 2) {

    printf ("%s\n", "Pass your name as an argument");

    return 0;

  } else {

    printf ("Hello %s\n", argv[1]);

    return 0;

  }

}

Sizeof

The unary operator sizeof generates the size of a variable or datatype in bytes.

printf ("a char takes up %d bytes \n\n", sizeof(char));

to get the size of an array:

char * students[] = {"Sally", "Mark","Robert","Molie","Bert"};
printf ("print size : %d",sizeof(students)/ sizeof(* students));

Casting

int num1 = 10, num2 = 15, numAnswer;
printf ("num2 / num1 : %f\n\n", (float) num2 / num1);

Random numbers

srand ((unsigned) time(NULL));
int r = rand() % 50;
printf ("%d\n", r);

Pointers

In C every variable is a memory location and every memory location has its address defined which can be accessed using an "&", which stands for an address in the memory. Through pointers a developer can directly access memory from his/her code which makes memory related operations very fast. But, as always, with great power comes great responsibility.

The reason why C has pointers is that it could have direct interactions with hardware. That's a must for any systems programming language as without pointers you are unable to write a device driver. Pointers can be used also to optimize a program to run faster or use less memory that it would otherwise. In most program languages all these memory allocations happens automatically with the Garbage Collector.

So a pointer is a variable whose value is the address of another variable. Ps. Locations in the memory change every time you run.

To get the address of the variable use " & " .To access the data that is in the address use " * ".

int var1 = 11; 

// store the address of var1 into the pointer variable
int *pointerToVar1 = &var1; 

// the value of var1 in hex : 0xb
printf ("value of var1 as hex :  %p\n", var1); 
// the value of var1 in dec : 11
printf ("value of var1 as dec:  %d\n\n", var1); 
// location in the memory in hex : 0x7fff418594ac
printf ("Location in the memory of var1 as hex :  %p\n", &var1); 
// location in the memory in dec : 1099273388 !!same!!
printf ("Location in the memory of var1 as dec :  %d\n\n", &var1); 

// the value of the pointer : 1099273388 !!same!!
printf ("value of pointerToVar1 as dec:  %d\n\n", * pointerToVar1); 

// location in the memory in hex : 0x7fff418594a0
printf ("Location in the memory of var1 as hex :  %p\n", &pointerToVar1); 
// location in the memory in dec : 1099273376
printf ("Location in the memory of var1 as dec :  %d\n\n", &pointerToVar1); 

// so to get the address of the variable use &
// to access the data that is in the address use *

Dereference pointers

int a = 10;
int* ptr = &a;

printf ("%d",* ptr); // with *ptr I'm dereferencing the pointer.
                    // which means, I am asking the value pointed at by the pointer.
                    // ptr is pointing to the location in memory of the variable a.
                    // in a's location, we have 10. So, dereferencing gives this value.

// since we have indirect control over a's location, we can modify its content using the pointer.
// this is an indirect way to access a.

*ptr = 20; // now a's content is no longer 10, and has been modified to 20.

Pointer arithmetic

Once you understand pointers, pointer arithmetic is easy. The only difference between it and regular arithmetic is that the number you are adding to the pointer will be multiplied by the size of the type that the pointer is pointing to. For example, if you have a pointer to an int and an int's size is 4 bytes, (pointer_to_int + 4) will evaluate to a memory address 16 bytes (4 ints) ahead.

Example of pointer arithmetic:

#include<stdio.h>
#include<conio.h>

int main () {

  int int_var = 10, * int_ptr;
  char char_var = 'A', * char_ptr;
  float float_val = 4.65, * float_ptr;

  // initialize pointers
  int_ptr = &int_var;
  char_ptr = &char_var;
  float_ptr = &float_val;

  printf ("Address of int_var = %u\n", int_ptr);
  printf ("Address of char_var = %u\n", char_ptr);
  printf ("Address of float_var = %u\n\n", float_ptr);

  // incrementing pointers
  int_ptr++;
  char_ptr++;
  float_ptr++;

  printf ("After increment address in int_ptr = %u\n", int_ptr);
  printf ("After increment address in char_ptr = %u\n", char_ptr);
  printf ("After increment address in float_ptr = %u\n\n", float_ptr);

  // adding 2 to pointers
  int_ptr = int_ptr + 2;
  char_ptr = char_ptr + 2;
  float_ptr = float_ptr + 2;

  printf ("After addition address in int_ptr = %u\n", int_ptr);
  printf ("After addition address in char_ptr = %u\n", char_ptr);
  printf ("After addition address in float_ptr = %u\n\n", float_ptr);

  getch();

  return 0;
}

Strings

Strings in C are represented as arrays of characters. The default size of a string in C is 8.

char * p = "String"; 
char p2[] = "String"; // will take size of the string
char p3[7] = "String"; // size is 7

printf ("%s\n",p2);

To concat strings:

strcat(stringA,stringB);

To get the length of a string:

strlen(stringA);

To compare strings:

strcmp(stringA,stringB);

To Convert strings to uppercase or lowercase use:

tolower (string);
toupper (string);

To cycle trough characters to give information about them run:

void getCharInfo () {
  char theChar;

  while ((theChar = getchar()) != '\n\') {

    printf ("Letters or Numbers %d\n",isalnum(theChar));
    printf ("Alphabetic or Numbers %d\n",isalpha(theChar));
    printf ("Standard blank %d\n",isblank(theChar));
    printf ("Number char %d\n",isdidgit(theChar));
    printf ("Anything but space %d\n",isgraph(theChar));
    printf ("Any space %d\n",isspace(theChar));

  }

}

int main () {

  getCharInfo();

  return 0;

}

Arrays

char firstName[30], lastName[30];
int primeNumbers[3] = {2,3,5};
printf ("the first primenumber: %d\n", primeNumbers[0]);

Play with pointers:

int array[] = {1,5,7};
printf ("Printing the second variable using pointers : %d", * (array+1));

To get the size of an array:

char * students[] = {"Sally", "Mark","Robert","Molie","Bert"};
printf ("print size : %d",sizeof(students)/ sizeof(* students));

To create a string array use:

char * randomString = "Just some random stuff";

// while continues until it reaches a null character, which with *randomString is equal to 0
while (*randomString) {

// prints a character in the array and then increments to the next

  putchar (* randomString++);

}

Functions

Declare functions before main.

int numberSum (int nr1 , int nr2) {

  return nr1+nr2;

}

int main () {

  numberSum (5,8);

}

Function change values (pointers)

#include <stdio.h>

void change (int * a, int * b) {

  printf ("this is the pointer from a %d\n", * a); // 20

  int temp = * a;
  * a = * b;
  * b = temp;

  printf ("this is the pointer from a %d\n", * a); // 100

}

int main (void) {

  int a = 20;
  int b = 100;

  printf ("a is now %d and b is now %d\n", a, b); // a is 20 b is 100
  printf ("address from int a : %d\n", &a); // -1342155204

  change (&a,&b);
  printf ("a is now %d and b is now %d\n", a, b); // a is 100 b is 20
  printf ("address from int a : %d\n", &a); // -1342155204

  return 0;

}

Recursion (pointers)

#include <stdio.h>

void countdown (int * a, int * b) {

  printf ("Value of a : %d Value of b : %d\n", * a,* b);

  if (* a > * b) {

    * a = * (a)-1;
    countdown(a,b);

  } else {

    return;

  }

}

int main (void) {

  int a = 20;
  int b = 10;

  countdown (&a,&b);

  return 0;

}

Structs

Structs are used when you need more then one piece of data to describe one thing. A struct is a complex data type declaration, it can be considered a class with different data types in it but without methods.

Example:

struct Dog {

  const char * name;
  const char * breed;
  int height;

};

Use typedef so you can call Cat without saying "struct Cat" but instead "Cat":

typedef struct Cat {

  const char * name;
  const char * breed;
  int height;

} cat;

Structs in structs

Example of a struct in another struct:

typedef struct Toy {

  const char * name;

} Toy;

typedef struct Cat {

  const char * name;
  const char * breed;
  int height;
  Toy toy;

} cat;

void getcatinfo (Cat cat) {

  printf ("name: %s\n", cat.name);
  printf ("breed : %s\n", cat.breed);
  printf ("height : %d\n", cat.height);
  printf ("toy : %s\n", cat.toy.name);

}

int main () {

  cat els = {"Els","Brits",35,{"bal"}};
  getcatinfo (els);

  return 0;

}

Structs linked lists

Can be as long as your memory allows you. This construction is also known as a recursive struct.

typedef struct product {

  const char * name;
  float price;

  struct product * next; // the recursive struct makes a linked list

} product;

void printLinkedList(product * pProduct) {

  while (pProduct != NULL) {

    printf ("%s%.2f", (* pProduct).name, pProduct->price); // 2 methods to get the data with dot and arrow
    pProduct = pProduct->next;

  }

}

int main () {

  product tomato = {"Tomato", 0.51, NULL};
  product apple = {"Apple", 1.51, NULL};

  tomato.next = &apple; // points to the next item

  printLinkedList(&tomato); // tomato is first item

  return 0;

}

Union

A union is a special data type available in C that allows to store different data types in the same memory location. But only one member can contain a value at a any given time. So a union provides a way to use the same memory location for multiple-purpose. You cannot store more than one value in a union variable.

int main () {

  typedef union {

    short individual; // guessing that the value will be a short
    float pound; // guessing for a float and so on
    float ounces;

  } amount;

  amount orangeAmnt = {.ounce = 16}; // this is the designated initializer
  amount orangeAmnt.ounce = 16; // this is an other way of setting the value of amount
  orangeAmnt.pound = 1.5;
  return 0;
}

Enumerated type

Enums are used when you only need the values that are stored inside an enum.

int main () {

  typedef enum { INDIV, OUNCE, POUND } quantity; 

  quantity quantityType = INDIV;
  orangeAmt.individual = 4;

  if (quantityType == INDIV) {

    printf ("something");

  }
}

  return 0;

}

Buffer

A buffer is a temporary storage area, all standard input output devices are containing input output buffers. In implementation when we are passing more than required number of values as a input then rest of all values will automatically holds in standard input buffer, this buffer data will automatically pass to next input functionality if it is exist.

#include<stdio.h>
#include<conio.h>

void main () {

  int v1,v2;
  clrscr ();

  printf ("\n Enter v1 value: ");
  scanf ("%d",&v1);
  printf ("\n Enter v2 value: ");
  scanf ("%d",&v2);
  printf ("\n v1+v2=%d ",v1+v2);
  getch ();

}

Malloc

Basically what malloc does is allocating memory at runtime. When malloc() is called you pass it the amount of memory required and it returns the address to that memory that you can refer to using a pointer. If the space couldn't be found null is returned.

int main () {

  int amtOfNumbersToStore;
  printf ("How many numbers do you want to store: ");
  scanf ("%d", &amtOfNumbersToStore);

  int * pRandomNumbers;
  pRandomNumbers = (int * ) malloc(amtOfNumbersToStore * sizeof(int));

  // check if memory was located by malloc
  if (pRandomNumbers != NULL) {

    int i = 0;

    printf ("Enter a Number or Quit: ");

    while (i < amtOfNumbersToStore && scanf("%d", &pRandomNumbers[i]) == 1) {

      printf ("Enter a Number or Quit: ");
      i++;

    }

    printf ("\nYou entered the following numbers\n");

    for (int j = 0; j < i; j++) {

      printf ("%d\n", pRandomNumbers[j]);

    }

  }

Free

Make sure you give back the memory allocated by malloc when you are finished with it.

  free(pRandomNumbers);

  return 0;

}

NOTE: In this program free() isn't actually required because all allocated memory is returned to the system when the program terminates. free() would be required though if you were allocating large blocks of memory over and over without returning it. Let's say you store 10k of data using malloc, use it and have no further use for it but don't use free. Then you grab another 10k over and over. Eventually you'll run out of memory and get a memory leak.

Text file I/O

C provides numerous methods for working with files, a file is just a block of memory with a name , the file can be stored across many blocks in memory, but the C compiler acts as if it is in sequence.

Writing file

int main () {

  int randomNumber;

  // will store the pointer to the file

  FILE * pFile;

  // opens a text file so we can write data to it.
  // it returns a pointer to the file

  // options:
  // w - If a file doesn't exist create it. If it does overwrite it
  // a - Open or create text file and append to original content
  // r - Open a file to read from it
  // r+ - Open for reading and writing
  // w+ - Open or create, delete original and read and write
  // a+ - Open or create, append for writing and reading

  pFile = fopen ("randomnumbers.txt", "w");

  // if the file wasn't opened a 1 is returned from fopen()

  if (!pFile) {

    printf ("Error : Couldn't Write to File\n");

    return 1;

  }

}

Printing random numbers to the file:

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

    randomNumber = rand() % 100;

    fprintf (pFile, "%d\n", randomNumber);

  }

  printf ("Success Writing to File\n");

if (fclose(pFile) != 0)
  printf ("Error : File Not Closed\n");

  return 0;

}

Reading file

int main () {

  // defining that we only expect there to be a maximum of 1,000
  // characters per lines read.
  char buffer[1000];

  FILE * pFile;

  // opens the file for reading
  pFile = fopen ("randomnumbers.txt", "r");

  if (!pFile) {

    printf ("Error : Couldn't Read the File\n");

    return 1;

  }

  while (fscanf (pFile, "%s", buffer) == 1) {

    puts (buffer);

  }

  printf ("Success Reading from File\n");

  if (fclose(pFile) != 0)
    printf ("Error : File Not Closed\n");

  return 0;

}
1