- Notifications
You must be signed in to change notification settings - Fork1
intro to C language and if you think C is dead, you are really wrong! so check this out,
License
MIT, MIT licenses found
Licenses found
jdevfullstack-tutorials/learn-C
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
updated 21 April 2022
TOC
- Intro
- Intro To C
- Data Types
- Flow Control
- Loops
- Pointers
- Functions
- Structures
- Command Line Arguments
- Dynamically Allocated Arrays
- File Input Output
After this, you can study a good examplehow these things are being appliedin software development:
https://github.com/xkcph2017x/CalC
Thanks for visiting!
We prepared a detaileddocumentation for you. You don't even need tocompile the source codes because there are screenshotsof the results!
Much more, we are willing to collaborate and communicate!This is all about learning C, so we might not beable to put every information, but we are willingto answer your queries.
The source codes that were mentionedin this tutorial can be downloaded fromthis repository:
https://github.com/jdevstatic/C-Language-Tutorial
or by clicking theView on GitHub
button.
Also, in order for you to truly collaborate,you need a GitHub account and you needto be at GitHub too.There, you canfork this repository, make some changesthen create a pull requestand many more features.It's quite strange at first but this is the best way todevelop a software as one team. Furthermore, GitHub canbe used for blogging and can be a collaborative tool fornon-code projects!Also, this can be your portfolio as software developer,so why not start exploring now. It's worth it. This is the link:
Although not all the topics here were covered,but you can easilygrasp the idea because of this tutorial.Enjoy life full of coding projects!
It's very important to understand why C languageis there and why it is not obsolete, as othersbelieve.
C was created on the premise that itwould be the tool to make utilities of theexisting Unix. And later, Unix wasrewritten using C.But before C, there were problems that could not beaddressed by existing languages back then, such as:
simplifying the existingassembly languages to write programs but should bealmost of the same speed as them
each assembler basically responds to a particularmachine architecture
existing languages such as COBOL, FORTRANand BASIC were not meant to be for structuredprogramming
When C was introduced, it was the programming languagethat answered these problems.And then, there came a time, programs were complexenough thatstructured programming would not suffice.So,object-oriented programming (OOP) came into existence throughseveral programming languages like C++ and Java.But remember, C is still the one for systemprogramming, say, creatinga programming language, an operating system,and the like.
And since C language upgraded the world ofcomputer programming, its influence can be feltin almost all programming languages after C.Hence, itwill greatly help those who are still learningcomputer programming in general, aslearning C will provide a solid backgroundbecause most of the programming languagesadopted concepts from it.
When using MinGW in Windows OS,in the Command Prompt,change the directory to where you putyour source codes, say, on the Desktop.
And usinghello_world.c
as an example, type:
gcc hello_world.c
hitEnter
, then type:
a.exe
You will see the output in your console.
When you want a unique name for your executable,type:
gcc -o hello_world.exe hello_world.c
hitEnter
, then type:
hello_world.exe
Make sure that GNU Make is installed in your computer.Windows OS does not have this tool by default. So,visit this site for more information, including howto install it in Windows OS:
http://gnuwin32.sourceforge.net/packages/make.htm
GNU Make is a build tool that can runcommands automatically. It is used in largeprojects, so programmers would not end up manually updatingevery file that catches a lot of errors.
Here, we want to use Make as part of the demonstration,to prepare you using this build tool.
First, you open the Command Prompt.Change the directory to where you put your codes.Then,
to build all executables, type:
make
to build a specific executable, type:
make name_of_c_program
to delete all executables, type:
make clean
When you tell the Command Prompt to executethe commandmake
, it actually executes thecontents of theMakefile
. So, the computer andthis tool will automate things for you, particularly,in large projects to avoid errors and buildthe software with ease.
In Windows OS, it is best to use MinGW C compiler.Please refer tohttp://www.mingw.org/ forfull documentation.
Compiler is a software that takes the jobof translating source codes into machine language,one way or the other.
An assembly language, even though low-level,will still be needing an assembler to translateeverything into an instruction the machine can understand.So, every source code will alwaysbe translated to machine language. But, it is notup to us, humans, to do the translation manually.That is the reason why writing compilers takes a lotof skills and intellect.
Technology companies usually offer their own compilers.They created themaccording to their own designs,to satisfy their needs or maybe to topple every business competitor.
ACCRE licensed this repo under MIT.
xdvrx1 included that license andthe changes he made were also licensed under MIT.
#include <stdio.h> int main(){printf("Hello World!\n");return 0;}
Hello World!
In C, including files are common, just likein our example:
#include <stdio.h>
It is just like copying the content of another source fileand pasting it to the other one. Why not just copy and pastemanually? We usually don't dothat, it can cause errors. Hence, the need forthis command.
Separating one big source code into small ones is a good practicein software development. Specific parts can be located easily.The logic among them can be inferred without much hassle.
This defines a function calledmain
:
int main(){printf("Hello World!\n");return 0;}
The return type is anint
(integer)and it takes no arguments.The main function is required for allC programs. It's where execution of thecode begins.I tend to use spaces to make blocksof code more readable, you can alsouse tabs.
This line calls a function calledprintf
:
printf("Hello World!\n");
and passes a "Hello World!" string, alongwith a special end of line character\n
.A semi-colon;
is required at the end ofeach line. Take note, free-form languages just like Cdoes not terminate a command by simply pressingenter
orreturn
to create a newline, it willstill look for the semicolon as the indicator thata command is ended.
printf
is actually printing output tostdout
.This topic is quite complex for this introduction,but in basic terms,printf
is one way to outputsomething. Much of thehidden process is happening in the processor.
Again, the return type for the mainfunction is an integer.
return 0;
Here, we return theinteger zero, which is the conventionfor signifying that the program exitednormally. You actually don't need toinclude this line at all. You might geta warning from the compiler but the programwill compile and run normally.
#include <stdio.h> int i; int j = 12; const int k = 345; unsigned int l = 6789; char myletter[] = "myletter"; float x = 1.23; double y = 45.6789; int myarray[5] = { 2, 4, 6, 8, 10 }; float farray[100];int main(){ i = 1; printf("int i: %d\n", i); printf("int j: %d\n", j); printf("const int k: %d\n", k); printf("unsigned int l: %d\n", l); printf("char myletter[]: %s\n", myletter); printf("float x: %f\n", x); printf("double y: %f\n", y); printf("(@index 0) int myarray[0] : %d\n", myarray[0]); printf("(@index 0) float farray[0] : %1.2f\n", farray[0]); return 0;}
int i: 1int j: 12const int k: 345unsigned int l: 6789char myletter[]: myletterfloat x: 1.230000double y: 45.678900(@index 0) int myarray[0] : 2(@index 0) float farray[0] : 0.00
Data types are very important in a programming language.In basic terms, they tell how datashould be treated by the compiler.Other programming languages are just loosely type, but still,they have data types.
Declare an integer:
int i;
Declare and initialize an integer:
int j = 12;
Declare and initialize a constant integer:
const int k = 345;
Declare and initialize an unsigned integer:
unsigned int l = 6789;
Declare and initialize a string called "myletter":
char myletter[] = "myletter";
Take note: In C, strings are just one-dimensionalarray of characters.
Declare and initialize a single-precision floating point number:
float x = 1.23;
Declare and initialize a double-precision floating point number:
double y = 45.6789;
Arrays are contiguous in memory and can beaccessed like so:
myarray[0], myarray[1], ...
Note that the first index is always 0 in C!
Declare and initialize a 5-element integer array:
int myarray[5] = { 2, 4, 6, 8, 10 };
Declare a 100-element array of single-precision floating point numbers:
float farray[100];
#include <stdio.h>int main(){ int i = 1; if ( i ) printf("i is true with a value of: %d\n", i); i = 123; if ( i ) printf("i is true with a value of: %d\n", i); i = -321; if ( i ) printf("i is true with a value of: %d\n", i); i = 0; if ( i ) { printf("i is true with a value of: %d\n", i); } else { printf("i is false with a value of: %d\n", i); } int y = 26; if ( i > 0 && y == 26 ) { printf("Condition 1 met!\n"); } else if ( i > 0 || y == 25 ) { printf("Condition 2 met!\n"); } else if ( i != 0 ) { printf("Condition 3 met!\n"); } else if ( !i && y >= 20 ) { printf("Condition 4 met!\n"); } else if ( i == 0 ) { printf("Condition 5 met!\n"); } else { printf("no condition met!\n"); } if ( y == 26 ) { if ( i != 0 ) { printf("i is not 0!\n"); } else { printf("i is 0\n"); } } return 0;}
i is true with a value of: 1i is true with a value of: 123i is true with a value of: -321i is false with a value of: 0Condition 4 met!i is 0
We stick first to conditional statements,because this can alter the executionof the program by making decisionsand skipping some parts of the code.
NativeBoolean
data type does not exist in C.Integer is used instead, with avalue of zero evaluated asFALSE
and a non-zerovalue evaluated asTRUE
.
This will resut toTRUE
becausei
isTRUE
with a value of 1:
int i = 1; if ( i ) printf("i is true with a value of: %d\n", i);
This will result toTRUE
becausei
isTRUE
:it is not zero, it is 123.
i = 123; if ( i ) printf("i is true with a value of: %d\n", i);
This will still result toTRUE
becausei
isstillTRUE
: it is not zero, it is -321.
i = -321; if ( i ) printf("i is true with a value of: %d\n", i);
This will result toFALSE
becausei
is now zero.
i = 0; if ( i ) { printf("i is true with a value of: %d\n", i); } else { printf("i is false with a value of: %d\n", i); }
Note that in a largeif-else
block like the onebelow, program flow jumps out of the block afterthe first match is found. Its contents areexecuted, then thisif-else
block is done.
int y = 26; if ( i > 0 && y == 26 ) { printf("Condition 1 met!\n"); } else if ( i > 0 || y == 25 ) { printf("Condition 2 met!\n"); } else if ( i != 0 ) { printf("Condition 3 met!\n"); } else if ( !i && y >= 20 ) { printf("Condition 4 met!\n"); } else if ( i == 0 ) { printf("Condition 5 met!\n"); } else { printf("no condition met!\n"); }
In our case here,Condition 4
is the firstmatch, even ifCondition 5
is also true,it will not continueseeking for the other matches.This is whyCondition 5 is met!
is notprinted.
Nestedif
andif-else
blocks are also allowed:
if ( y == 26 ) { if ( i != 0 ) { printf("i is not 0!\n"); } else { printf("i is 0\n"); } }
As we see here, there are twoif
conditions,so the program flow will be like:
Is it really true thaty
is equal to 26?If yes, proceed to the secondif
.If not, thisif
block is done, canceleverything inside this block, includingtheif-else
.
In our case here,y
is really equal to 26,so it goes down to the secondif
that tests whetheri
is not equal to zero,but according to the last value ofi
,it is zero, so it will executetheelse
block, so it printsi is 0
.
After this, you can now easily grasp the ideaof loops, where it automates things for you.
#include <stdio.h>int main(){ int n = 10; int i; int x[n]; for ( i=0; i<n; i++ ) { x[i] = i * 10; printf("i: %d x[i]: %d\n", i, x[i]); } int y = 0; while ( y < 100 ) { y += 12; printf("y: %d\n", y); } y = 0; do { y += 12; printf("y: %d\n", y); } while ( y < 100 ); return 0;}
i: 0 x[i]: 0i: 1 x[i]: 10i: 2 x[i]: 20i: 3 x[i]: 30i: 4 x[i]: 40i: 5 x[i]: 50i: 6 x[i]: 60i: 7 x[i]: 70i: 8 x[i]: 80i: 9 x[i]: 90y: 12y: 24y: 36y: 48y: 60y: 72y: 84y: 96y: 108y: 12y: 24y: 36y: 48y: 60y: 72y: 84y: 96y: 108
We will usei
as an index withinfor
loop:
int i; int x[n]; for ( i=0; i<n; i++ ) { x[i] = i * 10; printf("i: %d x[i]: %d\n", i, x[i]); }
Here,i
will start at 0. Then, it will test whetheri
is less thann
which is 10. If this test evaluates to true,it will execute the commands. That range will be from 0 to 9.Then, when the value ofi
is 10,it stops looping becausei < n
evaluates to false. Then, thisfor
loop is done.
while
loop is useful in certain situations as well:
int y = 0; while ( y < 100 ) { y += 12; printf("y: %d\n", y); }
Inwhile
loop, it will first test the condition.If the condition evaluates to false, it will be skipped,so,while
loopmay not execute the commands at all.
But in the example here,while
loop succeeded.
do-while
loop is used instead ofwhile
loopif you want the code block executed before evaluationof a condition,at least once.
y = 0; do { y += 12; printf("y: %d\n", y); } while ( y < 100 );
Now, here is the tricky part: in our example,you will notice that bothdo-while
andwhile
loops ended atthe value of 108, but the problemis that, in the given condition,y
should beless than 100 to continue loopingor else it should stop looping. Then why these loops ended at 108?
#include <stdio.h>int main(){ int i = 1; int *iPtr; iPtr = &i; printf("Memory address of i: %p\n", &i); printf("iPtr: %p\n", iPtr); printf("But, iPtr has its own address: %p\n", &iPtr); printf("Getting the value the pointer points to using * :\n"); printf("i = %d, *iPtr = %d\n", i, *iPtr); printf("Changing the value directly using a pointer:\n"); *iPtr = 2; printf("After using \"*iPtr = 2;\", i is now %d\n", i); return 0;}
Memory address of i: 0x7ffce7495e0ciPtr: 0x7ffce7495e0cBut, iPtr has its own address: 0x7ffce7495e10Getting the value the pointer points to using * :i = 1, *iPtr = 1Changing the value directly using a pointer:After using "*iPtr = 2;", i is now 2
A normal integer is declared like the one below.This assigns a piece of memory fori
,and stores the value 1 in this memory.
int i = 1;
On the other hand, pointers were introduced as a way toaccess a memory location directly andthe value stored there.
Declare a pointer with the*
character:
int *iPtr;
A pointer is a variable that contains memory address. But thatpointer has its own memory address too.
printf("Memory address of i: %p\n", &i); printf("iPtr: %p\n", iPtr); printf("But, iPtr has its own address: %p\n", &iPtr);
You canreference a variable's memory using the&
symbol.Then, after getting that memory address, you can store it ina pointer variable, in our case here, it isiPtr
.
iPtr = &i;
You can also access the value in memory that apointer is pointing to using the*
symbol,in our case here,*iPtr
. Thisis calleddereferencing.
printf("i: %d, *iPtr: %d\n", i, *iPtr);
There are several benefits of using pointers, oneis passing function arguments by reference, whichis illustrated in thefunctions.c
example.
With pointers, you have the ability to alter directly the valuestored in a memory location:
*iPtr = 2; printf("After using \"*iPtr = 2;\", i is now %d\n", i);
#include <stdio.h>void printFunctionTest(){ printf("This function 'printFunctionTest()' only prints, nothing else.\n");}float mySimpleFuncByValue(int iloc, float xloc){ iloc += 101; xloc *= 14.6; float yloc = (float)iloc * xloc; return yloc; }float mySimpleFuncByReference(int *iPtr, float *xPtr){ *iPtr += 101; *xPtr *= 14.6; int iloc = *iPtr; float xloc = *xPtr; float yloc = (float)iloc * xloc; return yloc; }void modifyArray( int *array ){ array[0] = 5; array[1] = 12;}int main(){ printFunctionTest(); int i = 22; float x = 234.23; float y = mySimpleFuncByValue(i, x); printf("i: %d x: %10.5f y: %10.5f\n", i, x, y); y = mySimpleFuncByReference(&i, &x); printf("i: %d x: %10.5f y: %10.5f\n", i, x, y); int myArray[2] = { 0, 0 }; printf("Before function call, myArray[0]: %d myArray[1]: %d\n", myArray[0], myArray[1]); printf("array mem address: %d\n", myArray); modifyArray(myArray); printf("After function call, myArray[0]: %d myArray[1]: %d\n", myArray[0], myArray[1]); return 0;}
This function 'printFunctionTest()' only prints, nothing else.i: 22 x: 234.23000 y: 420630.25000i: 123 x: 3419.75806 y: 420630.25000Before function call, myArray[0]: 0 myArray[1]: 0array mem address: -214060608After function call, myArray[0]: 5 myArray[1]: 12
A declaration of a void function:
void printFunctionTest(){ printf("This function 'printFunctionTest()' only prints, nothing else.\n");}
A void function does not return any value.A void function will just do the commands inside this block.
When a function is invoked, you think of thecomputer finding the declaration of that function,then, when found, will execute everything insidethat function.
In our case here, whenprintFunctionTest()
function is calledin main function, the computer is tasked to lookfor the declaration of this function. It was declared then defined,so when the computer finds it, will execute everything inthat function.
There are instances that the computer is instructed to look outsidea source code, maybe in another external librarywith theinclude
command. As was mentioned,this is a good practice in software development.
Parameters will enable you to pass variablesof the same type or even pointers, to be processed inside thatfunction. Why not just directly do that inside afunction? One main reason is reusability. Othervariables of the same type can be passed tothese functions instantly when needed.
First of all, we need to distinguish the two for you not tobe confused.
When declaring a function,the term isparameter.
When passing variables or pointersto a parameter, the term isargument.
So, you say: "I want to declare a function with twoparameters of integer type, then in main function,I will insertx
andy
variables as arguments."
Suppose you need tocalculate the distance travelled from the inputof the distance sensor and you want to get that distance value,a void function cannot do that. You need to declare a functionwith a data type and a return value.
The keyword isreturn
. This command tells the compilerto terminate the current function with or withouta return value, or pause as thiscurrent function will call another function.return
can be usedin void functions also when needed.
A declaration of a functionwith parametersint iloc
,float xloc
and a return value namedyloc
.
float mySimpleFuncByValue(int iloc, float xloc){ iloc += 101; xloc *= 14.6; float yloc = (float)iloc * xloc; return yloc; }
Take note, inside this function,int iloc
andfloat xloc
are local variables,so, these variables cannot becalled outside this function. Also, do not beconfused of the*
iniloc * xloc
:it's a multiplication operator in this context.
float yloc = (float)iloc * xloc
At this line, sinceiloc
is an integerandyloc
is a float, we need tocastiloc
so the compiler will not return an error.(float)iloc
command will castiloc
integer type to float.
Now, in main function,i
andx
are both passed by value,meaning a copy of each of these variablesis passed tomySimpleFuncByValue(int iloc, float xloc)
.So, any changes made inthis function will not reflectoutside this function.
int i = 22; float x = 234.23; float y = mySimpleFuncByValue(i, x); printf("i: %d x: %10.5f y: %10.5f\n", i, x, y);
Another declaration of a functionwith pointers as the parameters:int *iPtr
,float *xPtr
.
float mySimpleFuncByReference(int *iPtr, float *xPtr){ *iPtr += 101; *xPtr *= 14.6; int iloc = *iPtr; float xloc = *xPtr; float yloc = (float)iloc * xloc; return yloc; }
Here, we want to dereferencethe pointer and modify the value it points to:*iPtr += 101
,*xPtr *= 14.6
.
Changes made insidethis function will now affecti
andx
afterthis function terminates. That's the reason why,when you call the secondprint
command,
printf("i: %d x: %10.5f y: %10.5f\n", i, x, y);
i
now contains the value of 123 andx
contains3419.75806.
Now, in main function,memory addresses can be inserted as an argumentfor this function, like this:
mySimpleFuncByReference(&i, &x)
That is the essence ofparameter/s of pointer type. You can easily managevariables and their contents.
Another instance of passing pointers to function isas follows:
void modifyArray( int *array ){ array[0] = 5; array[1] = 12;}
This function can modify an array whenever this is called,int *array
is the parameter. Take note, the parameteris of pointer type again.Now, in main function,we just declaremyArray[2]
. This will be modifiedby this function.
When you just call an array without a specificindex, the compiler will return thememory address of this array. By declaringa pointer as a parameter in this function, we caninsert a memory address as an argument.You can even access and manipulate every elementusing only the memory address of an array.
int myArray[2] = { 0, 0 }; printf("Before function call, myArray[0]: %d myArray[1]: %d\n", myArray[0], myArray[1]); modifyArray(myArray); printf("After function call, myArray[0]: %d myArray[1]: %d\n", myArray[0], myArray[1]);
So, pointers are truly essential to be an excellent C programmer.
#include <stdio.h>typedef struct{ char *name; int age; float height; float grades[10];} student;void printStruct( student oneStudent ){ int i; printf("=====================\n"); printf("Student name: %s\n", oneStudent.name); printf(" age: %d\n", oneStudent.age); printf(" height: %6.3f\n", oneStudent.height); printf(" grades: "); for (i=0; i<10; i++) printf("%4.1f ", oneStudent.grades[i]); printf("\n"); printf("=====================\n");}void modifyStruct( student *oneStudent ){ oneStudent->grades[0] = 72.0; oneStudent->grades[4] = 81.0; oneStudent->grades[6] = 85.0;}int main(){ student Nikki; Nikki.name = "Nikki"; Nikki.age = 19; Nikki.height = 64.75; int i; for (i=0; i<10; i++) { Nikki.grades[i] = 98.0; } printStruct(Nikki); modifyStruct(&Nikki); printStruct(Nikki); return 0;}
=====================Student name: Nikki age: 19 height: 64.750 grades: 98.0 98.0 98.0 98.0 98.0 98.0 98.0 98.0 98.0 98.0 ==========================================Student name: Nikki age: 19height: 64.750 grades: 72.0 98.0 98.0 98.0 81.0 98.0 85.0 98.0 98.0 98.0 =====================
This is an example ofa structure in C:
typedef struct{ char *name; int age; float height; float grades[10];} student;
whereint age
is in years,float height
in inchesandfloat grades[10]
are the gradesfor the 10 assignments.
Structure is a user-defineddata type in C. It is really needed tomix different data types in one declaration.
typedef
is a keyword which will enableyou to give an existing type a new name.In our case here, it is just like saying:"Let us define this structure bycallingstudent
."
student
is a structurevariable that can access the members ofthis structure.
In order to access a member of anstructure we use.
symbol, just likeoneStudent.name
.
A function to print the details:
void printStruct( student oneStudent ){ int i; printf("=====================\n"); printf("Student name: %s\n", oneStudent.name); printf(" age: %d\n", oneStudent.age); printf(" height: %6.3f\n", oneStudent.height); printf(" grades: "); for (i=0; i<10; i++) printf("%4.1f ", oneStudent.grades[i]); printf("\n"); printf("=====================\n");}
Take note of this parameter:student oneStudent
.oneStudent
is a variable of typestudent
.That is the type we defined in the structure.
Again, you might be overwhelmed by theprintf
function thatcontains strange things like this:%6.3f
.Don't worry, they are just formatting commands likewhether how many decimal places should be there, oryou want to pad those numbers with zero.
In the case of%6.3f
, it means, format the floatingtype number 6 digit wide, 3 decimal places.
A function to modify the structure:
void modifyStruct( student *oneStudent ){ oneStudent->grades[0] = 72.0; oneStudent->grades[4] = 81.0; oneStudent->grades[6] = 85.0;}
In order to modify the declared structure,we still use pointer as parameterto accept a memory location as argument:that is, to easily locate it andmodify everything using the index of eachdata member.
Pointers to structs have special->
symbolfor dereferencing the pointer and accessing adata member.
And what does it do?oneStudent->grades[0] = 72.0
is equivalent to(*oneStudent).grades[0] = 72.0
.
In main function,student
data type is used:student Nikki
is just like any other variabledeclaration, likeint myInteger
.Coming from the structure we defined,we can put data instudent Nikki
.
student Nikki; Nikki.name = "Nikki"; Nikki.age = 19; Nikki.height = 64.75; int i; for (i=0; i<10 ; i++) { Nikki.grades[i] = 98.0; }
The functions we created, we call them in main functionto act upon the structure:
printStruct(Nikki); modifyStruct(&Nikki); printStruct(Nikki);
We first check whetherNikki
was successfully created bycalling the commandprintStruct(Nikki)
.Then, we modify the initial contents of this structureby calling the commandmodifyStruct(&Nikki)
. Remember that placing&
before a variable will return the address of that variable.And finally, we check again whether the changes weresaved by calling the commandprintStruct(Nikki)
.
There are confusing terms that you might be thinking:data type, database and data structure.
As was demonstrated, a structure in C is thereto mix different data types in one declaration. Every membercan be accessed easily. In general,data structure is data thatcan be accessed piece by piece. For example, an XML file isconsidered semi-structured, for elements can be parsed but fromtop to bottom while a database file is a structured data,for pieces of information can be accessed randomly without parsingthe entire database.
Data type is declared to easily tell the compilerhow a particular data should be treated.
Database is an organizedcollection of data usually expressed as tables.It is commonly built upon a filesystem.Data will persist after the computer is turned off because dataresides on persistent storage.
#include <stdio.h>#include <stdlib.h>int main(int argc, char **argv){ printf("argc: %d\n", argc); if ( argc != 3 ) { printf("Usage: ./pass_command_line_options arg1 arg2\n"); printf("where arg1 is an integer and arg2 is a floating point number\n"); exit(0); } int i; for (i=0; i<argc; i++) { printf("i: %d argv[i]: %s\n", i, argv[i]); } i = 1; int myarg_int = 0; float myarg_float = 0.0; if ( argc > 1 ) myarg_int = atoi(argv[i]); ++i; if ( argc > 2 ) myarg_float = atof(argv[i]); printf("myarg_int: %d myarg_float: %10.5f\n", myarg_int, myarg_float); return 0;}
#include <stdio.h>
, as we all know, is forprintf
.#include <stdlib.h>
is foratoi
andatof
.
atoi()
function converts string intoan integer and returns that integer.
atof()
converts string into a double,then returns that value.
argc
captures the number of command line arguments.
printf("argc: %d\n",argc); if ( argc != 3 ) { printf("Usage: ./pass_command_line_options arg1 arg2\n"); printf("where arg1 is an integer and arg2 is a floating point number\n"); exit(0); }
Take note: the executable isalways the first argument and the remaining argumentsare separated by spaces.Since we want to require a user to supply two arguments,there will be a total of three arguments including the requiredexecutable file. This is inside theif
block so as to makesure there will be three arguments inserted or elsethe user will be instructed to supply three arguments.
argv
captures each argument in an array of characters.Here, we loop over all arguments and print the value:
int i; for (i=0; i<argc; i++) { printf("i: %d argv[i]: %s\n", i, argv[i]); }
Since command line arguments are read in as anarray of characters, they must be convertedto the appropriate type (e.g. int, float),for further processing:
i = 1; int myarg_int = 0; float myarg_float = 0.0; if ( argc > 1 ) myarg_int = atoi(argv[i]); ++i; if ( argc > 2 ) myarg_float = atof(argv[i]);
We makei
with a value of 1. This will be laterused for the increment. Then,myarg_int
andmyarg_float
were declared with an initialvalue of 0.
Then, there are twoif
blocks. We did not usethe conventional { } since we only haveone command in eachif
block.The first test says ifargc
is greater than 1, which means the user enteredtwo or more arguments,myarg_int
will getthe value from the second argument.That is, at index 1 and is an integer type,so, conversion will be done throughatoi
.
Then,i
will be incremented but using++i
. There are several discussions out there for thisincrement first then assign or assign first then increment.But, it depends on the situation yet in this examplewhere it was used just an index,it is almost neglible.
Before the secondif
is tested,i
now has a value of 2.If ever the user entered the third argument,if ( argc > 2 )
will result to true andmyarg_float
will get the valuefrom the third argument, that is at index 2, which is a float.Conversion will be done throughatof
.
#include <stdio.h> // printf()#include <stdlib.h> // exit(), atoi(), atof()int main(int argc, char **argv){ if ( argc != 2 ) { printf("Usage: dynamically_allocated_arrays arraySize\n"); exit(0); } int n = atoi(argv[1]); int *myDynamicArray = malloc( n * sizeof(int) ); if ( myDynamicArray == NULL ) { printf("Allocation failed, exiting!\n"); exit(0); } int i; for ( i=0; i<n ; i++ ) { myDynamicArray[i] = i * 9; printf("i: %d, myDynamicArray[i]: %d\n", i, myDynamicArray[i]); } free(myDynamicArray); return 0;}
Sometimes you can't predict the sizeof an array at compile time, or you needto grow or shrink the size of an array.Dynamically-allocated arrays are greatfor each of these purposes.
Here, we first test whether a user enteredexactly two arguments, the first argumentbeing the executable file and the secondargument, the size of an array:
if ( argc != 2 ) { printf("Usage: dynamically_allocated_arrays arraySize\n"); exit(0); }
Then,initialize an allocatable array of sizen
.
By standard definition,malloc()
returns a pointer to a chunkof memory of sizesize, or NULL if there is an error.The memory pointed to will be on the heap, not on the stack,so make sure to free it when you are done with it.
In our case here,malloc
reserves a block of memory for the array.malloc
needs to know the number of bytes you'dlike to reserve, which you can get by multiplyingthe desired size of the array timessizeof(type)
.
int n = atoi(argv[1]); int *myDynamicArray = malloc( n * sizeof(int) );
Also, it's good practice to check that the array wasallocated correctly. You do this by checking fora NULL pointer.
if ( myDynamicArray == NULL ) { printf("Allocation failed, exiting!\n"); exit(0); }
Then,fill and access your dynamic array like anyother "normal" array:
int i; for ( i=0; i<n ; i++ ) { myDynamicArray[i] = i * 9; printf("i: %d, myDynamicArray[i]: %d\n", i, myDynamicArray[i]); }
As was mentioned, the memory for dynamically allocated arrays mustbe manually released before a program terminates.Failure to do so can lead to memory leaks.
free(myDynamicArray);
#include <stdio.h>#include <stdlib.h>int main(){ FILE *fp_in; fp_in = fopen("input_file.txt", "r"); if ( fp_in == NULL ) { printf("input_file.txt not opened, exiting...\n"); exit(0); } int x, y, z; int i; for (i=0; i<3; i++) { fscanf(fp_in, "%d %d %d", &x, &y, &z); printf("x: %d y: %d z: %d\n", x, y, z); } fclose(fp_in); FILE *fp_out; fp_out = fopen("output_file.txt", "w"); if ( fp_out == NULL ) { printf("output_file.txt not opened, exiting...\n"); exit(0); } for ( i=0 ; i < 50 ; i++ ) { fprintf(fp_out, "%d %d\n", i, i*10); } fclose(fp_out); printf("`output_file.txt` created successfully.\n"); return 0;}
An example of reading from a file:
FILE *fp_in; fp_in = fopen("input_file.txt","r");
It is good practice to check whether the filewas opened successfully.fopen()
willfail if the file does not exist:
if ( fp_in == NULL ) { printf("input_file.txt not opened, exiting...\n"); exit(0); }
And finally, getting the contents of that file throughfscanf
and closing it right after reading.
int x, y, z; int i; for (i=0; i<3; i++) { fscanf(fp_in,"%d %d %d", &x, &y, &z); printf("x: %d y: %d z: %d\n", x, y, z); } fclose(fp_in);
Now, an example of writing to a file:
FILE *fp_out; fp_out = fopen("output_file.txt", "w");
Then, checking whether it was successfully created:
if ( fp_out == NULL ) { printf("output_file.txt not opened, exiting...\n"); exit(0); }
Then, writing data to this file and closing it after:
for ( i=0 ; i < 50 ; i++ ) { fprintf(fp_out,"%d %d\n", i, i*10); } fclose(fp_out);
You have reached the end of this tutorial,and we are glad you did. Not all thetopics were covered here but the importantthing is you get the idea what C is all about.
To demonstrate how C is used in writingcomputer programs, please visit thisrepository:
https://github.com/jdevstatic/CalC
Thanks a lot!
About
intro to C language and if you think C is dead, you are really wrong! so check this out,
Topics
Resources
License
MIT, MIT licenses found
Licenses found
Uh oh!
There was an error while loading.Please reload this page.