C tutorial [Chapter 1]

[Introduction]
The purpose of this tutorial is to learn how to use C with some of its best features like pointers, process and thread creation, semaphores and signal handling. Of course to learn how to do all this we need to start from the beginning.
This is not a basic programming tutorial. If you don't know how the art of programming works this is not a tutorial for you. C is a very complex language if you are a beginner. Try Python or even Java if you want to start with something easy then you will be prepared to learn this awesome language.
I love Linux. Linux loves C. I don't know if any of the techniques exposed here work in a Windows machine... I really don't care if they work... Linux is a very efficient OS. I won't explain why, but in the references below, you will find the book that explains why any Unix based system is better than any flavor of Windows.

[In the beginning there was darkness]
Lets learn some syntax first:

Variable types


int: Integer
char: Character
float: Float
char* or char[]: Strings



Among others...

Assignment


int intName = 10;
char charName = 48; // "0"
char* str1Name = "Hello World";



IF-ELSE IF-ELSE statements


if(condition1){
Instructions
}else if(condition2){
Instructions
...
}else if(conditionN){
Instructions
}else{
Instructions
}


Switch statements
Faster than If statements


switch(condition){
case 1:
Instructions
break;
...
case N:
Instructions
break;
default:
Instructions
}



Loops
While loop


while(condition){
Instructions
}


For Loop


int i;
for(i=0; condition; i++){
Instructions
}


Do-While Loop


do{
Instructions
}while(condition);


Useful functions
Search in the man pages of your Linux distribution how to use them. In Debian you have to install them from the repositories.

apt-get install manpages-dev


The functions you should man for now are:
printf
scanf
strlen
strcpy
strcat
malloc
free

Pointer
The beautiful pointers... Thanks to them we have Orient Object Programming.
Let's say this is our memory (All numbers in Hex with a Little-Endian 32 bits hardware):

Endianness -> http://en.wikipedia.org/wiki/Endianness



-----------------------------
Address | Memory |
-----------------------------
0x00 | 00 | 00 | 00 | 0A |
-----------------------------
0x04 | 00 | 00 | 00 | 00 |
-----------------------------
0x08 | 4C | 4C | 45 | 48 |
-----------------------------
0x0C | 00 | 00 | 00 | 4F |
-----------------------------

Also lets say our program is:

int a = 10; //Address 0x00
int* b = &a; //Address 0x04
char* c = "HELLO"; //Address 0x08

b is a pointer. If I print b I will get 0x00000000
which is the address of a. If I print *b I will print
the value of the thing b is pointing, in this case a.
So printing *b will result in 0x0000000A or 10
If I print &a I will get the address of a which is 0x00000000

Now if I print c[2] I will get 4C which is L in the ascii table.
If I print all the string, it will print till it gets to the null byte
In this case the null byte is in the sixth byte of the string.




Now you know how to get the information of a pointer :)
To reserve memory use the function malloc like this:


char* str;
int* i;
/*
* To reserve 10 bytes for str. The (char *)
* is for the program to know what kind of
* pointer will be.
*/
str = (char *)malloc(10);
/*
* To reserve enough space for a int I use the
* sizeof function.
*/
i = (int *)malloc(sizeof(int));


Precompiler Instructions
This are special instructions. All the calculations are made by the compiler, but make us the life easier.
Include precompiler instruction
It's to import the libraries you want to use in your program.
For system libraries:


#include //This will include the stdio.h file
.


For user defined libraries:


#include "list.h"//This will include the lis.h file.


efine precompiler instruction
To define a constant:


#define TRUE 1//This will define the word TRUE as 1


The .h files are the headers files. There you'll have the firm of every function in the .c with the same name.

sum.h

#include

void printSum(int, int);


sum.c


#include "sum.h"

int sum( int a, int b ){
return ( a + b );
}

void printSum(int a, int b ){
printf("The result is %d", sum( a , b ));//Prints result on screen
}


As you can see, the the sum.h only have the printSum function. This is because printSum is a public function while sum is just a private function. If someone use this useless library will not be able to use sum, but will be able to use printSum. So to define a class you should to use a header file. But how do you define a new data type? With Structures :)

Structures
Let's say we want to define the data type Person (Name, Age, Gender)

person.h


#include
#include
#include

struct PERSON{
char* pName;
int pAge;
int pGender;//0 for man, 1 for woman
}

typedef struct PERSON Person;

Person* newPerson(char*, int, int);

person.c



#include "person.h"

//Constructor of Person. Returns NULL on error
Person* newPerson(char* name, int age, int gender){
/*
* To reserve some memory use malloc with the size you need
* In this case I need the space enough to hold a Person type
* so I use sizeof(Person);
*/
Person* nPerson = (Person *) malloc(sizeof(Person));
//To access the members of this class we should use the "->" operator.
if(gender != 0 && gender != 1){
free(nPerson);//To free the space used by nPerson
return NULL;
}
//To access the pGender, member of Person
nPerson->pGender = gender;
if(age<0){
free(nPerson);//To free the space used by nPerson
return NULL;
}
//To access the pAge, member of Person
nPerson->pAge = age;
/*
* With the function malloc I reserve as many bytes the char* name has and then
* and I assign the new address to the pName, member of Person. If the malloc
* return NULL the system call to ask some more memory failed, and the creation
* of the new type also should failed. It's efficient to free the space used for
* any reference data type if it won't be used anymore. That's why I use free(void*)
* everytime a inconsistent data or a failed system call appears.
*/
if((nPerson->pName = (char *) malloc(strlen(name)))==NULL){
free(nPerson);//To free the space used by nPerson
return NULL;
}
/*
* This function copies name to pName
* This nPerson->pName = name would only copie the
* address of name to nPerson->pName
*/
strcpy(nPerson->pName,name);
return nPerson;
}




You can also use "." intead of "->", but you need to change some things... I think is easier to work this way...

Explanation of the code:
Here I declare the members of the "class". In this case you have pName, pAge, pGender.


struct PERSON{
char* pName;
int pAge;
int pGender;
}



Here I rename the "class" from "struct PERSON" to "Person". It's just to write less code :)


typedef struct PERSON Person;


Then I declare the "constructor" of the "class"


Person* newPerson(char*, int, int);



reference:zeroidentity

0 komentar:

Posting Komentar