<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>unixworks</title><generator>teletype.in</generator><description><![CDATA[Thoughts on unix-like working environments (BSD). Helpful guides. 

Do you want to support it?
https://buymeacoffee.com/n0madcoder]]></description><image><url>https://teletype.in/files/39/c4/39c41221-3416-48cf-8bd4-de4f18e6eeb8.jpeg</url><title>unixworks</title><link>https://teletype.in/@unixworks</link></image><link>https://teletype.in/@unixworks?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/unixworks?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/unixworks?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Sat, 04 Apr 2026 00:01:01 GMT</pubDate><lastBuildDate>Sat, 04 Apr 2026 00:01:01 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@unixworks/c-programming-working-with-threads</guid><link>https://teletype.in/@unixworks/c-programming-working-with-threads?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/c-programming-working-with-threads?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>C programming | Working with threads</title><pubDate>Mon, 11 Jan 2021 21:39:49 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/97/ed/97ed2fd3-f086-4f00-938a-becb8e385b4d.png"></media:content><category>C programming</category><description><![CDATA[<img src="https://teletype.in/files/7f/86/7f865c30-4426-4d15-ad01-29ccf88a8f29.png"></img>When we run a program inside the OS, a process is asked to handle the task. If our code isn't designed in a concurrent way, then the process uses only one thread to run the main function. This makes the program to perform its actions sequentially, but we can take advantage of threads to perform more than one thing at a time if needed.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/7f/86/7f865c30-4426-4d15-ad01-29ccf88a8f29.png" width="720" />
  </figure>
  <p>When we run a program inside the OS, a process is asked to handle the task. If our code isn&#x27;t designed in a concurrent way, then the process uses only one thread to run the main function. This makes the program to perform its actions sequentially, but we can take advantage of threads to perform more than one thing at a time if needed.</p>
  <p></p>
  <p>Modern microprocessors are built with multiple processors (cores). To achieve programming concurrency we can face two scenarios:</p>
  <ul>
    <li>Multiple threads running inside one process.</li>
    <li>Multiple processes running at the same time.</li>
  </ul>
  <p>Concurrent programming defines an environment where created tasks <em>can be</em> <em>performed</em> at the same time, but it doesn&#x27;t mean that all tasks are going to be executed in parallel. </p>
  <p>A process consists in a running program plus the resources that allow the program&#x27;s execution. Processes can have multiple threads running inside them.</p>
  <blockquote>We can check running processes inside *nix using commands like <code>ps</code>, <code>pstree</code> or <code>top</code>.</blockquote>
  <p>In this article, we are going to focus in the first case scenario: multiple threads running inside one process.</p>
  <p></p>
  <p></p>
  <h2>What is a thread?</h2>
  <p>A thread is a separate dynamic set of code executions or instructions that run alongside the main process in a program, and it can be scheduled. </p>
  <p></p>
  <p>Threads give us concurrency without isolation, working in the same process and sharing memory space, which makes the ability for threads to intercommunicate. </p>
  <blockquote>Creating a thread is cheaper than creating a process, and ending a thread is faster than ending a process.</blockquote>
  <p>Until now, all the examples shown in previous articles have been made using serial or sequential computation. That&#x27;s not wrong, but we were using only one thread in one process to achieve our functionality.</p>
  <p></p>
  <p>Sequential commands run like this:</p>
  <pre>start -&gt; job_a -&gt; job_b -&gt; job_c -&gt; ... -&gt; end</pre>
  <p>which in code is as we usually call functions in main:</p>
  <pre>int main() {
    job_a();
    job_b();
    job_c();
    ...
    
    return 0;
}</pre>
  <p></p>
  <p>A thread set is executed like this:</p>
  <pre>       -&gt; job_a -&gt;
      /           \
start -&gt;  job_b   -&gt; end
      \           /
       -&gt; job_c -&gt;</pre>
  <p>which in pseudo code would look like this:</p>
  <pre>int main() {
    createThread(job_a());
    createThread(job_b());
    createThread(job_c());
    
    ...
    
    join_thread(job_a());
    join_thread(job_b());
    join_thread(job_c());
    
    return 0;
}</pre>
  <p></p>
  <p>In order for a program to take advantage of threads, it needs to be able to be organized into discrete, independent tasks which can execute concurrently.</p>
  <pre>|-- job_a --| |-- job_b --| ... |-- job_n --|</pre>
  <p>Considering our sequential code from above, we can check three situations to check if threading is possible in our program:</p>
  <ul>
    <li>Jobs or routines can be interchanged and result is not modified.</li>
  </ul>
  <pre>|-- job_b --| |-- job_a --| ... |-- job_n --|</pre>
  <ul>
    <li>Jobs or routines can be interleaved and result is not modified.</li>
  </ul>
  <pre>|- rA -| |- rB -| |- rA -| |- rB -| |- rA -| |- rN -|</pre>
  <ul>
    <li>Jobs or routines can be overlapped and result is not modified.</li>
  </ul>
  <pre>|-- job_a --|        |-- job_n --|
        |-- job_b --|</pre>
  <p></p>
  <p>We can take a look at the internal workflow inside an IDE (Integrated Development Environment). An IDE usually contains various spaces inside a workspace.</p>
  <p>When we launch the program, a process is created by the operating system. That process contains the required threads for the IDE to run the multiple operations it needs, like the integrated terminal emulator, the file explorer, the text editor, or the syntax checker.</p>
  <p></p>
  <p>We can implement threading in our program as a matter of trial and error, or to specific task only at the beginning, incrementing the number of tasks and threads as the program evolve and grow up the thread model. If we want to start from a proven ground, the POSIX threads standard offers some existing models for threaded programs, which are not designed for any specific application kind, but are worth knowing, like:</p>
  <p></p>
  <p><strong>— Pipeline model</strong></p>
  <p>The pipeline model takes a long input stream and process each of the inputs through a series of stages or sub-operations. Each stage can handle a different unit of input at a time.</p>
  <pre>input -&gt; thread_a -&gt; thread_b -&gt; thread_n -&gt; output</pre>
  <p>The overall throughput of a pipeline is limited by the thread that processes its slowest stage, meaning threads that follow it in the pipeline are stopped until it has finished. In this type of threading model is good to design the program in a way where all stages take about the same amount of time to finish.</p>
  <p>The standard Graphics Pipeline uses this threading model.</p>
  <p></p>
  <p><strong>— Thread pool</strong></p>
  <p>In this model, one thread is in charge of work assignments for the other threads. The thread in charge deals with requests and communications that arrive in an asynchronous way, while the other threads perform how to handle the requests and process the data. </p>
  <p>This model is also known as the <em>manager-worker</em> model.</p>
  <pre>input_a -&gt;              -&gt; worker_a
          \            /
input_b    -&gt; manager  -&gt;  worker_b
          /            \
input_c -&gt;              -&gt; worker_c</pre>
  <p>This model fits well in database servers, or desktop related tasks like window managing.</p>
  <p></p>
  <p><strong>— Peer model</strong></p>
  <p>In this model, a thread must create all the other peer threads when the program starts but after that, all threads work concurrently on their tasks without a specific leader. This makes each thread responsible for its own input.</p>
  <pre>       -&gt; thread_a -&gt;
      /              \
input -&gt;  thread_b   -&gt; output
      \              /
       -&gt; thread_c -&gt;</pre>
  <p>Given the lack of a manager thread, peers need to synchronize their access to common input sources.</p>
  <p></p>
  <p></p>
  <h2>Implement threading in C</h2>
  <p>We can work with threads in C, however there isn&#x27;t any built-in solution for this. Inside unix-like machines we have a set of POSIX types and calls wrapped in a header named <code>pthread.h</code> that let us access threading functions in C. So before we even start, we need to add the header to our code.</p>
  <pre>#include &lt;pthread.h&gt;</pre>
  <p></p>
  <p>Let&#x27;s create a first threads&#x27; boilerplate. It&#x27;s easier than you may expect. </p>
  <p>In short, we need a function we want to execute in parallel to our <code>main()</code> one, then we need to create a thread, assign the desired function to it, ensure that we are executing it, and terminate the thread once we&#x27;re done.</p>
  <h3>Create a function to execute an entry point</h3>
  <p>The standard prototype for a function that is going to be passed to a thread follows the scheme <code>void *function_name(void *arg)</code></p>
  <pre>void *thread_job() { 
    printf(&quot;We are in a new thread\n&quot;); 
    return NULL;
}</pre>
  <p></p>
  <h3>Create a thread</h3>
  <pre>pthread_t thread;
pthread_create(&amp;thread, NULL, function_to_execute, &amp;value_to_pass);</pre>
  <p>We need to pass the following parameters to the thread creation:</p>
  <ul>
    <li>The ID from the created thread.</li>
    <li>The attributes we want to use to create the thread. Pass <code>NULL</code> if you don&#x27;t need any special ones, so defaults are applied.</li>
    <li>A pointer to the function to execute by the thread.</li>
    <li>A pointer to the thread argument.</li>
  </ul>
  <p>This returns <code>0</code> if thread creation is successful and nonzero if not.</p>
  <p>It&#x27;s a good practice to avoid code errors checking the returning value of the thread creation function. </p>
  <pre>pthread_create(&amp;thread, NULL, function_to_execute, &amp;value_to_pass) != 0 ? printf(&quot;Failed to create Thread\n&quot;) : printf(&quot;Thread created!\n&quot;);</pre>
  <p></p>
  <p>— Note that we are creating threads from the <code>main()</code> function of the program, but we can create them from inside actual threads too.</p>
  <pre>            -&gt; thread_c -&gt;
           /              \
thread_a -&gt;    thread_b    -&gt; thread_d ...</pre>
  <p></p>
  <p>Once a thread is created, it has a life cycle that consists in four states:</p>
  <ul>
    <li><strong>Ready</strong> state, meaning the thread is waiting for a processor, and able to run.</li>
    <li><strong>Running</strong> state, when the thread is currently executing.</li>
    <li><strong>Blocked</strong> state, meaning the thread is waiting for a synchronization mechanism or an I/O operation to complete.</li>
    <li><strong>Terminated</strong> state, once the thread is done or cancelled.</li>
  </ul>
  <pre>blocked --&gt; ready &lt;---&gt; running --&gt; terminated
   |                       |
   └----------&lt;------------┘</pre>
  <p></p>
  <h3>Ensure thread execution</h3>
  <p>We can use <code>pthread_join()</code> as a thread synchronization call to ensure that our main thread waits until the second thread finishes:</p>
  <pre>pthread_join(thread, NULL);</pre>
  <blockquote>Note we are passing <code>NULL</code> as the second argument. We&#x27;ll use this second argument in a few lines below to return data from our thread.</blockquote>
  <p></p>
  <h3>Terminate a thread</h3>
  <p>Threads normally terminate once they done their inside work correctly. However there are more options to terminate a thread.</p>
  <ul>
    <li>We can explicitly tell a thread to terminate using <code>pthread_exit()</code>:</li>
  </ul>
  <pre>pthread_exit(NULL);</pre>
  <ul>
    <li>We can specify which thread to terminate using <code>pthread_cancel()</code>:</li>
  </ul>
  <pre>pthread_cancel(thread);</pre>
  <p></p>
  <p>— After following the steps, our code should look like this:</p>
  <pre>#include &lt;stdio.h&gt;
#include &lt;pthread.h&gt;

int error_close() {
    printf(&quot;Failed to create Thread\n&quot;);
    return 1;
}

void *thread_job() { 
    printf(&quot;We are in a new thread\n&quot;); 

    pthread_exit(NULL); /* optional, but recommended */
    return NULL;        /* optional, but recommended */
}

int main() {
    pthread_t thread;
    pthread_create(&amp;thread, NULL, function_to_execute, &amp;value_to_pass) != 0 ? error_close : printf(&quot;Thread created!\n&quot;);
    
    printf(&quot;We are inside Main()\n&quot;);
    
    pthread_join(thread, NULL);
    
    pthread_exit(NULL);  /* optional, but recommended */
    
    return 0;
}</pre>
  <p></p>
  <h3>Tell the compiler to use pthread lib</h3>
  <p>To compile our program using threads we need to link it along with the POSIX thread library. Adding the <code>-pthread</code> flag to the compiler should work.</p>
  <pre>$ gcc -pthread -o test_threads main.c
$ ./test_threads</pre>
  <p></p>
  <p></p>
  <h2>Sharing data between threads</h2>
  <p>Threads can communicate each other, but they need fast communication methods. Most thread communication involves using memory, since all threads created by the program live in the same process and share the same memory space.</p>
  <p></p>
  <p>We have three types of memory to work with (Refer <a href="https://telegra.ph/C-programming--Working-with-memory-04-25" target="_blank">here</a> to read about managing memory in C) and to place data to be shared between threads.</p>
  <p>— <strong>Global memory</strong></p>
  <p>If we know that we are only going to have an instance of an object inside our multi threaded program like a mutex, which we don&#x27;t want to be inside individual threads.</p>
  <p>— <strong>Stack memory</strong></p>
  <p>Storing data in this memory location is recommended for thread routines since its lifetime is the same of the routine execution.</p>
  <p>— <strong>Dynamic memory</strong></p>
  <p>Storing data dynamically requires some memory management routine like <code>malloc()</code>. Data stored in this type of memory has a lifetime scoped between memory allocation and memory deallocation.</p>
  <p>This is usually recommended to manage persistent context, since it&#x27;s independent from all program&#x27;s threads.</p>
  <p>We can find the following shared data between threads in a process:</p>
  <ul>
    <li>Memory space.</li>
    <li>Global variables.</li>
    <li>Opened files.</li>
    <li>Children processes.</li>
    <li>Timers.</li>
    <li>Semaphores and signals.</li>
  </ul>
  <p>Threads also have private data. Variables declared within the thread function are local to the thread.</p>
  <p>Other private data from a thread is:</p>
  <ul>
    <li>Thread ID.</li>
    <li>Registers.</li>
    <li>Thread status.</li>
    <li>Thread context when it&#x27;s not executing.</li>
  </ul>
  <p>— A thread doesn&#x27;t keep track of the other created threads, nor does it know the thread that created it. As part of the POSIX thread header functions, we can take advantage of <code>pthread_self()</code> to get the running thread&#x27;s id.</p>
  <p>Inside the <code>thread_job()</code> function we can add the following lines:</p>
  <pre>void *thread_job() { 
    printf(&quot;We are in a new thread with ID: %ld\n&quot;, pthread_self()); 
    pthread_exit();
}</pre>
  <p>Since <code>pthread_self()</code> returns the thread handle of the calling thread, we can use it in combination to <code>pthread_equal()</code> to identify a thread when entering a routine.</p>
  <p></p>
  <p></p>
  <h2>Passing arguments to threads</h2>
  <p>Thread functions take a void pointer as an argument, and return a void pointer as result. Since this is generic data, it leaves us almost total freedom to operate with our data.</p>
  <p></p>
  <p>Let&#x27;s modify our actual code. We are going to define a thread count number, and we are going to create as much threads as the defined value has.</p>
  <p>We are going to print which thread are we in when running the <code>thread_job()</code> function. To know which one is the working one, we are passing the thread counter as the argument value.</p>
  <pre>#include &lt;stdio.h&gt;
#include &lt;pthread.h&gt;

#define THREAD_COUNT 10

void *thread_job(void *value) { 
    long t_num;
    t_num = (long)value;    
    
    printf(&quot;Thread %ld with ID %ld is working...\n&quot;, t_num, pthread_self());
    
    /* sleep acts as a dummy, simulating some work being made */
    sleep(2);

    printf(&quot;Thread %ld with ID %ld is done!\n&quot;, t_num, pthread_self());
    
    pthread_exit(NULL);
    return NULL;
}

int main() {
    pthread_t *threads = (pthread_t*)malloc(sizeof(pthread_t));
    long i;
    
    for(i = 0; i &lt; THREAD_COUNT; i++){
        printf(&quot;We are inside Main()\n&quot;);
        
        if(pthread_create(&amp;threads[i], NULL, thread_job, (void *)i) != 0){
            printf(&quot;error creating thread[%ld]&quot;, i);
            return 1;
        }
    }

    for(i = 0; i &lt; THREAD_COUNT; i++) {
        pthread_join(thread[i], NULL);
    }
    
    return 0;
}</pre>
  <p></p>
  <p>This is nice but in real life we&#x27;ll probably need to pass more than one argument to our thread on creation. We can collect all the data we need to pass to a thread inside a struct type.</p>
  <pre>typedef struct tdata {
    int      amount;
    char     *account_name;
    e_action action;
}tdata_t;</pre>
  <p>When we pass a struct into the thread job function, we can access its data by simply casting the type of the struct:</p>
  <pre>void *thread_job(void *data) { 
    tdata_t received_data;
    
    received_data.amount = ((tdata_t*)data)-&gt;amount;
    received_data.account_name = ((tdata_t*)data)-&gt;account_name;
    received_data.action = ((tdata_t*)data)-&gt;action;

    
    printf(&quot;Thread job. Account name is: %s\n&quot;, received_data.account_name);

    /* free data struct before leaving if not needed anymore */
    free(data);
    return NULL;
}</pre>
  <p></p>
  <p></p>
  <h2>Returning values from threads</h2>
  <p>Sometimes we may need our thread to make some operations and return something from it. </p>
  <p></p>
  <p>We can return almost anything since thread functions are type of void pointer. The important point here is to allocate memory to the local value we want to return. Otherwise it will cause a segmentation fault since it&#x27;s going to be on the stack memory of the function.</p>
  <p>Allocate some memory in the thread function.</p>
  <pre>void *thread_job(void *value) { 

    /* allocate some memory for our desired return value */ 
    int *t_int = (int *)malloc(sizeof(int));
    
    for(int i = 0; i &lt; (int)value; i++)
        (*t_int)++;

    /* return the value */
    return t_int;
}</pre>
  <p>Inside our external function that controls the thread creation and execution, we can create a variable to hold what is returned from the thread job.</p>
  <pre>int *ext_result;</pre>
  <p>Using <code>pthread_join()</code> we can get the return value from the function using the second argument of the function:</p>
  <pre>pthread_join(entry_point, (void*)&amp;ext_result);</pre>
  <p>Now we can use the returned value in the rest of our program.</p>
  <p>Following the good practice of freeing memory up when we are done using it. Inside the external function we have to free <code>*ext_result</code> after using it (since we cannot do it inside the thread job function, and both variables point at the same memory address).</p>
  <pre>free(ext_result);</pre>
  <p></p>
  <p></p>
  <h2>Explicit synchronization</h2>
  <p>In concurrent programs is not possible to determine what is going to happen when we execute it just by looking at it. Threads run concurrently and the execution order depends on the scheduler, but we can manage to intentionally make a thread wait for another one to finish.</p>
  <p></p>
  <p>If more than one thread is asked to access or write a memory location we can run into a situation known as <em>race condition</em>. </p>
  <pre> race condition between two threads accessing and writing the same memory
   
   thread_a      memory      thread_b           threads&#x27; steps
     
              |00|0A|0B|0C|
             /             \
|00|0A|0B|0C|               |00|0A|0B|0C|    1. read the value
     |                           |
   |08|                        |0E|          2. modify the value
     |                           |
|00|08|0B|0C|               |00|0E|0B|0C|    3. write the value
             \             /
              |00|0E|0B|0C|
              
          this time thread_b wins</pre>
  <p>Avoiding these situations can be achieved via mechanisms that manage read/write locks and barriers such as mutexes or semaphores.</p>
  <p>— If we use threads to run completely independent functions that have no correlation from each other, synchronization isn&#x27;t a problem, and we would choose to skip this process. </p>
  <p></p>
  <h3>MUTEX</h3>
  <p>A mutex is the basic pthread synchronization mechanism. Its name stands for mutual exclusion lock. It&#x27;s useful to solve unpredictable race conditions by serializing the execution of threads.</p>
  <p></p>
  <p>If a thread succeeds calling a mutex lock, it will block the other threads to execute the code below until the owner thread unlocks the mutex.</p>
  <blockquote>The pthreads API provides mutex functions and operations to work with.</blockquote>
  <p></p>
  <p>In order to create a mutex we need to declare a <code>pthread_mutex_t</code>. We can do it in an static or a dynamic way:</p>
  <ul>
    <li>Static, declaring it outside any function:</li>
  </ul>
  <pre>/* just the mutex */
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


/* A mutex inside a struct, holding protected data */
typedef struct m_data {
    pthread_mutex_t mutex;
    int             value;
} m_data_t;

m_data_t data = {PTHREAD_MUTEX_INITIALIZER, 0};</pre>
  <ul>
    <li>Dynamic, declaring it when we allocate memory to it:</li>
  </ul>
  <pre>/* A mutex inside a struct, holding protected data */
typedef struct m_data {
    pthread_mutex_t mutex;
    int             value;
} m_data_t;

...

foo(){
    m_data_t *data;
    data = (m_data_t*)malloc(sizeof(data_t));
    pthread_mutex_init(&amp;data-&gt;mutex, NULL);
    ...
}</pre>
  <p></p>
  <blockquote>Remember to initialize the mutex before creating any threads.</blockquote>
  <p></p>
  <p>Once its initialized, we can lock it and unlock it using the following functions:</p>
  <pre>pthread_mutex_lock(&amp;mutex); 

/* code to execute in between */

pthread_mutex_unlock(&amp;mutex);</pre>
  <p>If a thread calls the mutex lock, the code between the lock function call and the unlock function call can only be accessed by a single thread until the mutex is unlocked.</p>
  <p>This kills parallelism, but allow to make responsiveness in places like user interfaces. We can have a thread doing the I/O and the rest calculating whatever needed in the back.</p>
  <p>The example below calculates the first 21 <a href="https://en.wikipedia.org/wiki/Fibonacci_number" target="_blank">Fibonacci</a> numbers using a separate thread for each one. Try commenting out the mutex lock and run several times the program. Different results in the numbering order may occur. </p>
  <pre>#include &lt;stdio.h&gt;
#include &lt;pthread.h&gt;

#define THREAD_COUNT 21

int result;
pthread_mutex_t result_mutex = PTHREAD_MUTEX_INITIALIZER;

int calc_fibonacci (long num) {
    if (num &lt;= 1) {
        return 1;
    }
    return calc_fibonacci(num -1) + calc_fibonacci(num -2);
}

void *thread_job(void *value) { 
    pthread_mutex_lock(&amp;result_mutex); 
    
    result = calc_fibonacci((long)value);
    
    pthread_mutex_unlock(&amp;result_mutex);
    
    printf(&quot;We are in thread num %ld, and result is %d\n&quot;, (long)value, result);
    
    sleep(1);
    return NULL;
}


int main() {
    pthread_t thread;
    long i;
    
    for(i = 0; i &lt; THREAD_COUNT; i++){
        
        if(pthread_create(&amp;threads[i], NULL, thread_job, (void *)i) != 0){
            printf(&quot;error creating thread[%ld]&quot;, i);
            return 1;
        }
    }

    for(i = 0; i &lt; THREAD_COUNT; i++){
    
        pthread_join(thread[i], NULL);
    
        pthread_exit(NULL);
    }
    
    return 0;
}</pre>
  <p> </p>
  <p>When implementing mutexes, we need to take care of a few factors:</p>
  <ul>
    <li>Waiting threads are not good for performance. It&#x27;s a good practice to apply several small mutexes to unrelated code executions rather than using a single mutex that locks them all at once.</li>
  </ul>
  <blockquote>If the data to lock is independent, is a good idea to use separate mutexes. Complications face up when data isn&#x27;t independent at all.</blockquote>
  <ul>
    <li>It takes time to lock and unlock mutexes. This means performance issues, so the first factor should be guided by the common sense of mutexing only critical parts.</li>
  </ul>
  <p></p>
  <h3>CONDITION VARIABLES</h3>
  <p>Condition variables are a signal mechanism associated with mutexes and their protected shared data. They control threads&#x27; access to data, and let threads synchronize between them based on the value of the data.</p>
  <blockquote>We can think about condition variables as a notification system among threads.</blockquote>
  <p></p>
  <p>To create a condition variable, the process is fairly familiar:</p>
  <pre>pthread_cond_t;

/* using an initializer macro */
condition_var = PTHREAD_COND_INITIALIZER;

/* or using the function call */
int pthread_cond_init(&amp;condition_var, NULL);</pre>
  <p>Once a condition variable has been initialized, we can use it with a thread in the following two ways:</p>
  <ul>
    <li>Make the thread wait on the condition variable.</li>
  </ul>
  <pre>pthread_cond_wait(&amp;condition_var, &amp;mutex);

/* or specifying a timeout with */

pthread_cond_timedwait();</pre>
  <p>Calling any of the waiting functions require to pass a locked mutex next to the condition variable.</p>
  <p></p>
  <ul>
    <li>Make the thread signal other threads waiting on the condition variable.</li>
  </ul>
  <pre>/* signal only one of the waiting threads */
pthread_cond_signal(&amp;condition_var); 

/* singal all the waiting threads */
pthread_cond_broadcast(&amp;condition_var);</pre>
  <p>Both functions make the thread calling them to hold the mutex. The mutex must be unlocked after the call.</p>
  <p></p>
  <h3>SEMAPHORE</h3>
  <p>A semaphore is a synchronization mechanism made from an unsigned int whose changes can&#x27;t be interrupted. It&#x27;s stored in a memory location accessible by all the processes that need to synchronize their operations.</p>
  <blockquote>Semaphores&#x27; header is separated from pthreads. In order to implement semaphores in our project, the header <code>semaphore.h</code> is required.</blockquote>
  <p></p>
  <p>The main difference with a mutex, is that semaphores don&#x27;t have a concept of ownership. While we cannot use a thread to lock a mutex and another one to unlock it, since the mutex expect the same thread to unlock it, it&#x27;s possible to do the same using semaphores.</p>
  <p>In most case scenarios, using mutexes  and condition variables is more than enough to solve synchronization problems.</p>
  <p>— In order to have a semaphore inside our code we need to declare it and start it:</p>
  <pre>sem_t *semaphore;

sem_init(&amp;semaphore, 0, N);</pre>
  <p></p>
  <p>We can work with semaphores using two operations:</p>
  <ul>
    <li><code>WAIT</code> operation which will try to decrease the semaphore value if its value is greater than zero. If not, it&#x27;ll wait.</li>
  </ul>
  <pre>sem_wait();</pre>
  <ul>
    <li><code>SIGNAL</code> operation which will increment the value of the semaphore, and return.</li>
  </ul>
  <pre>sem_post();</pre>
  <p></p>
  <p>As most of the data structures in C, we need to create it before using it, and destroy it after using it so we avoid garbage.</p>
  <p>A complete overview on how to implement a semaphore could look like this:</p>
  <pre>#include &lt;semaphore.h&gt;

#define N 6 /* can be any positive value */

/* create a semaphore */
sem_t semaphore;

/* initialize semaphore */
sem_init(&amp;semaphore, 0, N); 

/* allocate a resource */
sem_wait(&amp;semaphore);

...

/* return semaphore to pool */
sem_post(&amp;semaphore);

...

sem_destroy(&amp;semaphore);

return 0;</pre>
  <p></p>
  <p>— We can use a semaphore in a similar way to a mutex by using a binary semaphore (define <code>N</code> as <code>1</code>), to protect critical parts of the code from race conditions.</p>
  <pre>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;pthread.h&gt;
#include &lt;semaphore.h&gt;

#define THREADS 4
sem_t semaphore;
int counter = 0;

void* thread_job(void* args) {
    printf(&quot;Hi from thread %d\n&quot;, *(int*)args);
    
	sem_wait(&amp;semaphore);
	counter++;
    printf(&quot;Counter value is: %d\n&quot;,counter);
	sem_post(&amp;semaphore);
	
	free(args);
}

int main(void) {
	
	pthread_t *threads = malloc(sizeof(pthread_t) * THREADS);
	
	sem_init(&amp;semaphore, 0, 1); //we can change 1 to other value and have more threads running at a time
	int i;
	
	for(i = 0; i &lt; THREADS; i++) {
		int *a = malloc(sizeof(int));
		*a = i;
		if(pthread_create(&amp;thread[i], NULL, &amp;thread_job, a) !=0){
			printf(&quot;cannot create thread.\n&quot;);
		}
	}
	
	for(i = 0; i &lt; THREADS; i++) {
		if(pthread_join(thread[i], NULL) !=0){
			printf(&quot;cannot join thread.\n&quot;);
		}
	}
	
	sem_destroy(&amp;semaphore);
	return 0;
}</pre>
  <p></p>
  <p></p>
  <h2>A working example</h2>
  <p>In the previous article we worked on a fictitious weather forecast program to explain how to save files. Let&#x27;s grow our program a bit.</p>
  <p></p>
  <p><strong>The single thread program</strong></p>
  <p>In a serialized way, if we&#x27;d want the user to make interaction with the program, we can think of three main functions to implement:</p>
  <ul>
    <li>Add data to the program.</li>
    <li>Return data from the program.</li>
    <li>Generate new data from existing data.</li>
    <li>Exit the program when done, or requested.</li>
  </ul>
  <p>This can be translated into code this way:</p>
  <pre>typedef enum {
    EXIT = 0,
    WRITE,
    READ,
    OPERATE,
} e_action;</pre>
  <p>And so, our main function can deal with the type of action, one at a time:</p>
  <pre>/* simple error message handling */
int handle_error(char* msg) {
    printf(&quot;%s\n&quot;, msg);
    return 1;
}

int main(int argc, char *argv[]) {
    
    /* Get the desired action (this time from argv[1]) */
    int action;
    if(argc &gt; 1)
        action = atoi(argv[1]);
    else
        action = -1;

    
    switch(action) {
        case WRITE:
            func_write();
            break;
        
        case READ:
            func_read();
            break;
        
        case OPERATE:
            func_operate();
            break;
        
        case EXIT:
            func_end_program();
            break;
            
        default:
            handle_error(&quot;No action passed to argv[1]&quot;);
            break;
    }

    return 0;
}</pre>
  <p>If the program is going to be used from a single terminal by a single user, there is no much complication, but let&#x27;s scale our fictitious program a bit. </p>
  <p>Let&#x27;s take in consideration that weather&#x27;s forecast data is coming from several automatic stations around a country&#x27;s region. That data is sent to a server along with the action to perform and once done, the server responses back.</p>
  <p>If we maintain a serial version of the program, the moment many automatic weather forecast stations send actions, the performance of the server is going to degrade quickly.</p>
  <p></p>
  <p><strong>The multi-threaded program</strong></p>
  <p>If we want to keep server performance in a good state, one solution is to add threads to our program, so looking at the general tasks we can make threads that operate independent from each other. </p>
  <p>Since we need to pass more than one argument to the threads we create, we can use a struct to do so:</p>
  <pre>typedef struct tdata {
    int              action;    /* the action to perform */
    e_operation      operation; /* the operation to perform, if any */
    daily_forecast_t day;       /* the data to work with */
} tdata_t;


int main(int argc, char *argv[]) {
    tdata_t   *thread_data;
    pthread_t *thread;
    
    int action;
    if(argc &gt; 1)
        action = atoi(argv[1]);
    else
        action = -1;
    
    thread_data = (tdata_t*)malloc(sizeof(tdata_t));
    
    thread = (pthread_t*)malloc(sizeof(pthread_t));
    
    ...</pre>
  <p>This way the data handling falls into the thread&#x27;s function:</p>
  <pre>void *thread_job(void *data) { 
   
    tdata_t received_data;
    received_data.action = ((tdata_t*)data)-&gt;action;
    received_data.operation = ((tdata_t*)data)-&gt;operation;
    received_data.day = ((tdata_t*)data)-&gt;day;

 
    switch(received_data) {
        case WRITE:
            func_write();
            break;
        
        case READ:
            func_read();
            break;
        
        case OPERATE:
            func_operate();
            break;
            
        default:
            handle_error(&quot;No valid action passed to argv[1]&quot;);
            break;
    }
 
    free(data);
    return NULL;
}</pre>
  <p></p>
  <p>— Now instead of creating a new thread each time a station needs to perform an action, we can define a maximum number of threads, initialize them at the beginning of the program, and reuse them in a thread pool.</p>
  <p>A thread pool needs to take care of the following things:</p>
  <ul>
    <li>The total number of available threads, so we can limit the number of data requests at the same time.</li>
  </ul>
  <pre>#define NUM_THREADS 10</pre>
  <ul>
    <li>The max size for the data queue, so we can limit the number of requests waiting for service.</li>
  </ul>
  <pre>#define QUEUE_SIZE 10</pre>
  <p>Since the queue is a critical part, we need some sort of control over it. We can have a counter to keep track of it, and a mutex to avoid other threads to run over the same queue at the same time.</p>
  <pre>int queue_count = 0;
pthread_mutex_t data_mutex;</pre>
  <ul>
    <li>A way to behave when all threads are working and the data queue is full, so we don&#x27;t loose data.</li>
    <li>A way to behave if the data queue is empty so we don&#x27;t overheat the processor.</li>
  </ul>
  <pre>pthread_cond_t data_cond;</pre>
  <p></p>
  <p>— In terms of design, we could figure out the main behavior of the program in the following steps:</p>
  <ol>
    <li>The thread pool is waiting until a job is created.</li>
    <li>The main thread creates a job and signals the thread pool.</li>
    <li>The thread pool gets the task and executes it.</li>
    <li>If required, a result is sent back to the main thread.</li>
  </ol>
  <p></p>
  <p>First of all, we need to define what our threads are going to do when created.</p>
  <pre>void* start_thread() {

    /* create a struct var to hold data */
    tdata_t data;
        
    /* lock critical part with mutex */
    pthread_mutex_lock(&amp;data_mutex); 
    
    /* if we don&#x27;t have any data in the queue, we tell the threads to wait */    
    while (data_count == 0) {
        pthread_cond_wait(&amp;data_cond, &amp;data_mutex);
    }
    
    /* if we receive data, then we assign the first element of the queue 
     * to our data holder, and shift the data queue */    
    data = data_queue[0];
    for(int i = 0; i &lt; data_count -1; i++) {
        data_queue[i] = data_queue[i +1];
    }
    
    /* keep track of the data slots */
    data_count--;
    
    /* unlock mutex when done */    
    pthread_mutex_unlock(&amp;data_mutex); 
    
    /* execute the thread job */
    thread_job(&amp;data);
}</pre>
  <p>Our function <code>thread_job()</code> does not require anymore to be a <code>void*</code> so we can leave it just as a <code>void</code> function.</p>
  <pre>void thread_job(void *data) { 
   
    tdata_t received_data;
    received_data.action = ((tdata_t*)data)-&gt;action;
    received_data.operation = ((tdata_t*)data)-&gt;operation;
    received_data.day = ((tdata_t*)data)-&gt;day;

 
    switch(received_data) {
        case WRITE:
            func_write();
            break;
        
        case READ:
            func_read();
            break;
        
        case OPERATE:
            func_operate();
            break;
            
        default:
            handle_error(&quot;No valid action passed to argv[1]&quot;);
            break;
    }
}</pre>
  <p>Then we need a function to submit jobs with data to the waiting threads:</p>
  <pre>void submit_job(tdata_t data) {
    
    /* managing the data queue is a critical part so let&#x27;s lock it
     * before doing anything */
    pthread_mutex_lock(&amp;data_mutex); 
    
    /* assign the data to our data queue and
     * keep track of the data slots */
    data_queue[data_count] = data;
    data_count++;
    
    /* unlock the mutex when done */
    pthread_mutex_unlock(&amp;data_mutex);
 
    /* Wake up one thread */
    pthread_cond_signal(&amp;data_cond);
}</pre>
  <p></p>
  <p>Inside the main function, we can create an infinite loop that listens to user input after we create the thread pool:</p>
  <blockquote>The expression <code>for ( ;; )</code> is the same as <code>while(1)</code></blockquote>
  <pre>for ( ;; ) {
    
    printf(&quot;\nAutomatic weather forecast station\nWrite action to take: &quot;);
    scanf(&quot;%s&quot;, buffer);
    action = atoi(buffer);
    
    if(action == EXIT) {
        printf(&quot;\nExiting...\n&quot;);
        
        free(buffer);
        free(thread_data);
        free(thread);
        
        break;
    }
    
    thread_data-&gt;action = action;
    
    submit_data(*thread_data);
}</pre>
  <p>If we run the code right now, text in the terminal emulator is going to overlap. We need to signal the menu when we are done executing a thread job so the text appears in order.</p>
  <p>There are many ways to handle this. Since in this article we talked about semaphores, let&#x27;s create a binary semaphore that signals when our thread job is done.</p>
  <blockquote>Using a simple integer that changes from <code>0</code> to <code>1</code> can do the trick too. </blockquote>
  <pre>/* create the semaphore */
sem_t ready_sem;

/* initialize it in the main function, before using it 
 * note that the value is 1, so we can print the menu for the first time */
int main(int argc, char *argv[]) {
    sem_init(&amp;ready_sem, 0, 1);
    ...
}</pre>
  <p>We need the semaphore to wait before printing the menu:</p>
  <pre>for ( ;; ){
    sem_wait(&amp;ready_sem);
    ...</pre>
  <p>And we need to signal once our thread job has finished:</p>
  <pre>void thread_job(void *data) {
    
    ...
    sem_post(&amp;ready_sem);
}</pre>
  <p>Now we can operate from the command line without overlapping text messages. </p>
  <p>Another option could be not printing any confirmation message from the thread_jobs, leading only errors to prone in the terminal emulator, and that way we can experiment with multiple tasks at a time from a single machine.</p>
  <p></p>
  <blockquote>Working examples along with compiling instructions are going to be uploaded at <a href="https://codeberg.org/unixworks/workshop" target="_blank">unixworks&#x27; repo</a>.</blockquote>
  <p></p>
  <p></p>
  <h2>Summing up</h2>
  <p>Threading in computer programs is an extensive field. Covering in depth threads would require more than an article to do it right however, after diving a bit through threading, applied to POSIX and C in this article, we can see that most of it is a game on locking and releasing, waiting and signaling. </p>
  <p></p>
  <p>Although using threads is not always the best idea to make a program faster, knowing how to implement them can help in our programming design workflows.</p>
  <p>There is a newer header for threads, designed for C11 named <code>threads.h</code> which maybe substitutes <code>pthread.h</code> in a future. Right now using it reduces portability and is only available in major C compilers.</p>
  <p>Also <a href="https://www.openmp.org/" target="_blank">OpenMP</a> is a multi threading implementation worth mentioning for larger projects. It is an industry standard and is portable and multi-platform.</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@unixworks/c-programming-working-with-files-ii</guid><link>https://teletype.in/@unixworks/c-programming-working-with-files-ii?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/c-programming-working-with-files-ii?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>C programming | Working with files II</title><pubDate>Mon, 21 Dec 2020 19:28:13 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/99/e0/99e03b82-d829-490e-82ff-b41b3ec6501e.png"></media:content><category>C programming</category><description><![CDATA[<img src="https://teletype.in/files/c4/5a/c45a8993-e52b-4d49-9ed1-02602720586c.png"></img>There are two main types of data we can store in a file: ASCII or text data, and binary data. Binary serialization involves taking some arbitrary set of structured data and transform that data into a consistent stream of bytes.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/c4/5a/c45a8993-e52b-4d49-9ed1-02602720586c.png" width="721" />
  </figure>
  <p>There are two main types of data we can store in a file: ASCII or text data, and binary data. Binary serialization involves taking some arbitrary set of structured data and transform that data into a consistent stream of bytes.</p>
  <blockquote>Many high-level programming languages have custom solutions to achieve binary serialization, while in C there&#x27;s not a standard solution at all.</blockquote>
  <p></p>
  <p>Binary data encoding and decoding can be useful in two main fields: </p>
  <ul>
    <li>Networking.</li>
    <li>File saving. </li>
  </ul>
  <p>We saw in the <a href="https://teletype.in/@unixworks/c-programming-working-with-files" target="_blank">previous article</a> how to encode and decode text data, using <code>JSON</code> as our main data structure type.</p>
  <p>Text data files are portable and can be moved between computers with ease but, when we ask our computer to work with a text file, it needs to convert it to binary data somehow, which can be rather slow depending the situation.</p>
  <p>In the other hand, working with binary data files needs no conversion at all, and usually these kind of files are smaller than text-based ones. We break down complex structures apart and write their individual properties into the buffer. Once it&#x27;s done, when requested we can read the same data to reconstruct the complex structure.</p>
  <p>The main downside is that we cannot print directly their content to our console.</p>
  <blockquote>Note that we are using specific byte sizes when defining data. This is important since when we design or use an actually binary file format, its contents are (or should be) ordered in structs specifying which data is inside. The way to know each part of the file is by interpreting those structs which contain the data values. </blockquote>
  <p></p>
  <p></p>
  <p></p>
  <h2>A practical example with data</h2>
  <p>Let&#x27;s suppose we have to create a structured data format for a program that takes daily weather forecast data from the user. </p>
  <p>We need at least some constant variables to be filled, such as sunlight hours, cloud formation&#x27;s type, precipitation&#x27;s type, rate and amount (if any), minimum and maximum humidity, minimum and maximum temperature, etc. Data the program can later use to make weather predictions and estimations, monthly statistics, etc.</p>
  <p>— We can think of our structure as:</p>
  <pre>typedef enum {
    CLEAR = 0,
    CIRRUS,
    CUMULUS,
    STRATUS,
    NIMBUS
} e_cloud;

typedef enum {
    NONE = 0,
    RAIN,
    DRIZZLE,
    SNOW,
    SLEET,
    HAIL
} e_precipitation;

typedef struct daily_forecast_t {
    float           sunlight_hours;
    e_cloud         cloud_type;
    e_precipitation prec_type;
    float           prec_rate;
    float           prec_hours;
    float           prec_amount;
    float           min_temp;
    float           max_temp;
    float           average_temp;
    float           min_humidity;
    float           max_humidity;
    float           average_humidity;
} daily_forecast_t;</pre>
  <p></p>
  <p>— Now that we have our data structures defined we can create some data to work with. In a real program this data would come from the terminal emulator <em>args</em> or inputs, or from the input fields of a window made for the purpose. </p>
  <pre>daily_forecast_t day = {
        .sunlight_hours = 14.2,
        .cloud_type = 2,
        .prec_type = 0,
        .prec_rate = 0.0,
        .prec_hours = 0.0,
        .prec_amount = 0.0,
        .min_temp = 7.0,
        .max_temp = 21.2,
        .average_temp = 0.0,
        .min_humidity = 18.3,
        .max_humidity = 25.6,
        .average_humidity = 0.0
    };

day.average_temp = (day.min_temp + day.max_temp) / 2;
day.average_humidity = (day.min_humidity + day.max_humidity) / 2;</pre>
  <p></p>
  <p>— The next step is to store this data so we don&#x27;t loose any. In a binary format, using <code>fwrite()</code> should be enough. From the previous article, we know we need a <code>FILE</code> handler in write mode where to save our binary data.</p>
  <pre>FILE *out = fopen(&quot;day1.bin&quot;, &quot;w&quot;);
if(out != NULL) {
    fwrite(&amp;day, sizeof(daily_forecast_t), 1, out);
    fclose(out);
} else {
    printf(&quot;%s\n&quot;, &quot;there&#x27;s been an error with the file.&quot;);
}</pre>
  <p></p>
  <p>— If we compile and execute our program, we should have a new file named <code>day1.bin</code> in the program&#x27;s directory.</p>
  <p>Trying to read it as plain text is going to print some weird stuff to the console:</p>
  <pre>$ less day1.bin
33cA^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@&lt;E0&gt;@&lt;9A&gt;&lt;99&gt;&lt;A9&gt;A&lt;9A&gt;&lt;99&gt;aAff&lt;92&gt;A&lt;CD&gt;&lt;CC&gt;&lt;CC&gt;A&lt;9A&gt;&lt;99&gt;&lt;AF&gt;A
day1.bin (END)</pre>
  <p>not so useful for the human eye. </p>
  <p>Since we are inside a *nix machine, let&#x27;s use <code>hd</code> to properly inspect the file.</p>
  <pre>$ hd day1.bin
00000000  33 33 63 41 02 00 00 00  00 00 00 00 00 00 00 00  |33cA............|
00000010  00 00 00 00 00 00 00 00  00 00 e0 40 9a 99 a9 41  |...........@...A|
00000020  9a 99 61 41 66 66 ca 41  66 66 12 42 99 99 f7 41  |..aAff.Aff.B...A|
00000030</pre>
  <p>This still isn&#x27;t much useful for us as console readers, but the program can interpret the information contained in it much faster as if it were plain text.</p>
  <p></p>
  <p>— We suppose the file&#x27;s content is fine, but we need a way to check it, and to read that data in a workable way. Let&#x27;s create a read function to do so.</p>
  <ul>
    <li>Since we know how data is structured and it needs to be deconstructed in that specific way, first create a <code>daily_forecast_t</code> variable where to hold the read data.</li>
  </ul>
  <pre>daily_forecast_t day_data;</pre>
  <ul>
    <li>Then create a <code>FILE</code> handler in read mode that reads the file we just saved. To prove it&#x27;s working let&#x27;s print the average data values we calculated.</li>
  </ul>
  <blockquote>Note that once we&#x27;ve read the file, we have the data stored in memory so it&#x27;s a good practice to close the file before doing anything else.</blockquote>
  <pre>FILE *in = fopen(&quot;day1.bin&quot;, &quot;r&quot;);
        if(in != NULL) {
                fread(&amp;day_data, sizeof(daily_forecast_t), 1, in);
                fclose(in);
                printf(&quot;Average temp from day has been: %.2f\nAverage humidity from day has been: %.2f\n&quot;, day_data.average_temp, day_data.average_humidity);
        } else {        
                printf(&quot;%s\n&quot;, &quot;there&#x27;s been an error reading the file.&quot;);
        }</pre>
  <ul>
    <li>After compiling and running it we should have something like this in the command line:</li>
  </ul>
  <pre>$ ./weather
Average temp from day has been: 14.10
Average humidity from day has been: 30.95</pre>
  <p></p>
  <p>— Right now, that data structure is filled daily and we have the ability to write a file per day. It&#x27;d be great if it could to be stored in a way we can manage days in months, and months in years.</p>
  <p>So a month data structure could be:</p>
  <pre>typedef struct month_forecast_t {
    int days;        /* total days in month */
    void *days_data; /* an array containing all days&#x27; data */
} month_forecast_t;</pre>
  <p>and a year data structure could be:</p>
  <pre>typedef struct year_forecast_t {
    int months;        /* total months in a year */
    void *months_data; /* an array containing all months&#x27; data */
} year_forecast_t;</pre>
  <p>— If we want to pass our created day&#x27;s data into a <code>month_forecast_t</code> first we need to allocate some memory for the month&#x27;s data:</p>
  <pre>month_forecast_t january;
january.days = 31;
january.days_data = malloc(january.days * sizeof(daily_forecast_t));</pre>
  <p>and then we can pass the data to our desired day:</p>
  <pre>january.days_data[0] = day1;</pre>
  <blockquote>Always remember to free() allocated memory once it&#x27;s no longer needed.</blockquote>
  <p></p>
  <p></p>
  <h2>Creating file formats</h2>
  <p>At this point, we have our structured data stored in a file, yet we have no way to determine which file is the correct one for our weather forecast program to load and read (except for the file extension if we decide a unique one, but that alone isn&#x27;t so reliable as an identifier).</p>
  <p></p>
  <p>Getting it a bit worse, when we apply serialization we need to take care of the compiler&#x27;s padding system and the way the computer and the OS represent data in binary form. That is Big Endian or Little Endian representation.</p>
  <p>— From a technical view, Big Endian store the most significant byte at lower addresses while Little Endian does it the opposite way, storing the most significant byte at higher addresses.</p>
  <pre>  Little Endian     |       Big Endian
32bit int  memory   |   memory    32bit int
0A0B0C0D   | .. |   |   | .. |    0A0B0C0D
| | | |___ | 0D |   |   | 0A | ___| | | |
| | |_____ | 0C |   |   | 0B | _____| | |
| |_______ | 0B |   |   | 0C | _______| |
|_________ | 0A |   |   | 0D | _________|
           | .. |   |   | .. |</pre>
  <p>In plain text we can say that Big Endian just represents the data the way we read it, and Little Endian represents the data flipped.</p>
  <p></p>
  <p>— File formats can help us defining and maintaining how our data should be interpreted, no matter which machine or OS the program is running in.</p>
  <p>When creating file formats it&#x27;s important to take care of the following aspects:</p>
  <ul>
    <li><u>Unique file identification</u></li>
  </ul>
  <p>It&#x27;s common between binary file formats to use the first bytes of the file to include a unique number that identifies the format. That is, the magic number or signature of the file.</p>
  <ul>
    <li><u>Versioning</u></li>
  </ul>
  <p>Our program can grow in the future, and maybe it can handle new data, or maybe some parts are refactored and so the file format. In order to avoid wrong data parsing when this events happen, it&#x27;s important to keep track of the file format&#x27;s version. </p>
  <p>There&#x27;s no need to go crazy with conventions. One or two digits should be enough. A more professional approach can be starting at version <code>1.0.0</code> use the last digit for patch releases, the middle digit for minor releases and the left one for major releases.</p>
  <ul>
    <li><u>Header checksum</u></li>
  </ul>
  <p>This is optional (depending on who you ask to) to add into a file format. It mainly let us know that the file isn&#x27;t damaged.</p>
  <ul>
    <li><u>Offset to data</u></li>
  </ul>
  <p>This provides a hint on where to start reading the data contained in the file.</p>
  <p></p>
  <p>Making a simple try for a file format is less scary than you may think. To make things easier from this point, let&#x27;s use the extension <code>.fct</code> for our forecast program files. </p>
  <p></p>
  <p><strong>— ADDING A FILE FORMAT HEADER</strong></p>
  <p>Diving into it, we have to create a <code>HEADER</code> struct that has to be read before our actual file&#x27;s data.</p>
  <pre>typedef struct fct_header_t {
    char     identifier[12];
    char     version;
    char     data_offset;
} fct_header_t;</pre>
  <p>We can also define a <code>file_id</code> in a way that can be almost unique:</p>
  <pre>const unsigned char fct_id[12] = {
    //&#x27;«&#x27;, &#x27;F&#x27;, &#x27;C&#x27;, &#x27;T&#x27;, &#x27; &#x27;, &#x27;1&#x27;, &#x27;0&#x27;, &#x27;»&#x27;, &#x27;\r&#x27;, &#x27;\n&#x27;, &#x27;\x1A&#x27;, &#x27;\n&#x27; 
    0xAB, 0x46, 0x43, 0x54, 0x20, 0x31, 0x30, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
};</pre>
  <p></p>
  <p><strong>— DEFINING A FILE STRUCTURE</strong></p>
  <p>Right now we have evolved our program, and just writing out the forecast structure for a day is no longer useful. We have to give our file a structure where we can handle both the header and the data.</p>
  <pre>typedef struct fct_file_t {
    fct_header_t     header;
    daily_forecast_t data;
} fct_file_t;</pre>
  <p>Then we can implement our write and read functions separately to make things tidier.</p>
  <p></p>
  <p><strong>— MAKING A WRITE FUNCTION</strong></p>
  <p>Moving the write components out of the <code>main()</code> function allows us to call the function where needed, when needed in a cleaner way.</p>
  <p>We can pass to it a <code>fct_file_t</code> parameter as well as a filename parameter (in the form of a <code>char*</code>).</p>
  <p>One cool addition is to implement an auto extension for the file name. This is almost useless in terms of functionality, but gives the user the ability to fast check the file in a file explorer visually.</p>
  <pre>int write_to_file(fct_file_t fct, char *filename) {
    
    /* auto append file extension */
    char *ext = &quot;.fct&quot;;
    strcat(filename, ext);
    
    /* open in write mode*/
    FILE *out = fopen(filename, &quot;w&quot;);
    
    /* check if there&#x27;s a problem with the file before doing anything*/
    if(out != NULL) {
        fwrite(&amp;fct, sizeof(fct_file_t), 1, out);
        fclose(out);
        printf(&quot;%s written!\n&quot;, filename);
        return 0;
    } else {
        printf(&quot;there&#x27;s been an error with the file %s&quot;, filename);
        return 1;
    }
}</pre>
  <p></p>
  <p>We can handle specific chunks of data by creating buffers and passing the info through functions like <code>memcpy()</code> . </p>
  <p>Let&#x27;s say we have the following header:</p>
  <pre>fct_file_t file1 = {
        .file_header = header,
        .data = day1
};</pre>
  <p>and we want to copy just the header to a buffer:</p>
  <pre>unsigned char *header_buffer = (unsigned char*)malloc(sizeof(fct_header_t));</pre>
  <p>The code would perform something like this:</p>
  <pre>identifier (12) -&gt; ab 46 43 54 20 31 30 bb 0d 0a 1a 0a -&gt; header_buffer
version (1) -&gt; 01 -&gt; header_buffer
data_offset (1) -&gt; 0e -&gt; header_buffer</pre>
  <p>which we can confirm by printing out the value of the <code>header_buffer</code>:</p>
  <pre>printf(&quot;header_buffer content:\n&quot;);
    for(int i = 0; i &lt; sizeof(fct_header_t); i++)
        printf(&quot;%02x &quot;,header_buffer[i]);

printf(&quot;\n&quot;);</pre>
  <p>Now we can use our buffer for many things, since it&#x27;s structured and we can handle the information.</p>
  <p></p>
  <p><strong>— MAKING A READ FUNCTION</strong></p>
  <p>Same as the write function, moving the read file instructions away from the <code>main()</code> function gives us more freedom later when scaling the program.</p>
  <p>One key part in the reading function are to check if the data is valid for our program. We can achieve it by comparing the file header id against our known <code>fct_id</code> we created earlier using <code>memcmp()</code>.</p>
  <pre>int read_from_file(char *filename){
    
    /* generate a temporal fct_file type to store read data */
    fct_file_t tmp_fct;
    
    /* open in read mode */
    FILE *in = fopen(filename, &quot;r&quot;);
    
    /* check if there&#x27;s a problem with the file before doing anything*/
    if(in != NULL) {
        fread(&amp;tmp_fct, sizeof(fct_file_t), 1, in);
        fclose(in);
        
        /* verify it&#x27;s a valid fct file comparing the header id */
        if (memcmp(&amp;tmp_fct.file_header.id, fct_id, 12) != 0) {
            printf(&quot;%s\n&quot;, &quot;Not a FCT V1 file or corrupted file. Identifier isn&#x27;t valid&quot;);
            return 1;
        }
        
        /* print some file header info */
        printf(&quot;fct file version is %d\n&quot;, tmp_fct.file_header.version);
        printf(&quot;we can skip %d bytes to reach our data\n\n&quot;, tmp_fct.file_header.data_offset);

        /* test print some file data */
        printf(&quot;Average temp from day has been: %.2f\nAverage humidity from day has been: %.2f\n&quot;, tmp_fct.data.average_temp, tmp_fct.data.average_humidity);
        printf(&quot;Cloud type from day has been: %d\nPrecipitation type from day has been: %d\n&quot;, tmp_fct.data.cloud_type, tmp_fct.data.prec_type);
        
        return 0;
    } else {    
        printf(&quot;there&#x27;s been an error with the file %s&quot;, filename);
        return 1;
    }
}</pre>
  <p></p>
  <p><strong>— MAKING A FLEXIBLE FILE FORMAT</strong></p>
  <p>At this point we can save forecast data for a day and read it back. Scaling the project, we could make our program ask the user to create a forecast session, initializing a data structure inside the program that can be stored in a file that understand days inside months, and months inside years (using the structs we proposed earlier in the article).</p>
  <p>That way we would be able to give flexibility to the users, allowing them to work with data for an entire year, appending and/or modifying values over one file across time.</p>
  <p></p>
  <p></p>
  <h2>A practical example with existing file formats</h2>
  <p>Having to deal with existing file formats is another reality worth looking at. Usually when designing a program to interact with other programs&#x27; data, it&#x27;s common to use file formats that actually exist.</p>
  <p></p>
  <p>Tasks like saving or reading pixel data for images and video, loading or writing samples data for audio have already a huge amount of available file formats to work with.</p>
  <p>Unless we need a custom tailored data format to our software (because of encryption or efficiency), using existing file formats can give us some benefits like:</p>
  <ul>
    <li>Avoid to reinvent the wheel.</li>
    <li>Portability.</li>
  </ul>
  <p></p>
  <p>— We are going to check the TGA image file format for the example, so we need to find the file specification to know where to start.</p>
  <p>TGA files store red, green and blue channels with 8 bit precision each. This leaves us with 24 bits per pixel. </p>
  <p>TGA files also offer an additional 8 bit alpha channel that can be really useful. Assuming we are working with RGBA it should be 32 bit per pixel.</p>
  <p></p>
  <p>According to the format specification we have a header which contains the following data:</p>
  <ul>
    <li><u>Image ID length (1 byte)</u> usually contains the date and time the file was created.</li>
    <li><u>Color map type (1 byte)</u> handles whether a color map is included. Can be <code>0</code> or <code>1</code>.</li>
    <li><u>Image type (1 byte)</u> contains compression and color type information.</li>
    <li><u>Color map specification (5 bytes)</u> describes the color map.</li>
    <li><u>Image specification (10 bytes)</u> has Image dimensions and format.</li>
  </ul>
  <p>—This gives us an 18 byte header where we know which data goes to each part. We can translate that info into a struct like this:</p>
  <pre>typedef struct tga_header_t {
    char id_size;
    
    char color_map_type;
    
    char image_data_type;
    
    short int color_map_origin;
    short int color_map_length;
    char  color_map_depth;
    
    short int x_origin;
    short int y_origin;
    short image_width;
    short image_height;
    char  bits_per_pixel; 
    char  image_descriptor;
} tga_header_t;  </pre>
  <p></p>
  <p>Next we have to define how our pixels are constructed:</p>
  <pre>typedef struct pixel_t {
    unsigned char r;
    unsigned char g;
    unsigned char b;
    unsigned char a;
} pixel_t;</pre>
  <p></p>
  <p>So a TGA file can be described as such struct:</p>
  <pre>typedef struct tga_file_t {
     tga_header_t header; /* a header struct defining the type of TGA */
     pixel_t *pixels;     /* the pixels forming the image */
} tga_file_t;</pre>
  <p></p>
  <p>Now if we want to open a TGA file and check what info does it have inside the header we can create a read function like this:</p>
  <pre>int read_tga_file(char *filename) {
    FILE *fptr;
    fptr = fopen(filename, &quot;r&quot;);
    tga_header_t tmp_header;
    pixel_t *pixels;
    
    tga_file_t tmp_file;
    
    if(fptr != NULL) {
        /* in order to get the image width and height we have to 
           jump into the desired position of the file.
           Since we know that they are 12bytes from the origin, we can use
           fseek() */
        fseek(fptr, 12, SEEK_CUR);
        
        fread(&amp;tmp_file.header.image_width, 2, 1, fptr);
        fread(&amp;tmp_file.header.image_height, 2, 1, fptr);
        printf(&quot;image %s has width: %d and height %d\n&quot;, filename, tmp_file.header.image_width, tmp_file.header.image_height);        
    } else {
        printf(&quot;there&#x27;s been an error with the file %s\n&quot;, filename);
        return 1;
    }    
}</pre>
  <p>If we want to work with the pixel data, we need to create some space to handle their information.</p>
  <p>We know that an image is constructed in two dimensions (x and y) given a size for each dimension (width and height). At each point of that 2D grid there&#x27;s a pixel, which we assume contains four values as color information (RGBA).</p>
  <pre>tmp_file.pixels = malloc(tmp_file.header.image_width * tmp_file.header.image_height * sizeof(pixel_t));</pre>
  <p>To avoid having garbage data we can initialize each value to zeros:</p>
  <pre>for(int i=0; i&lt;tmp_file.header.image_width * tmp_file.header.image_height; i++) {
     tmp_file.pixels[i].r = 0;
     tmp_file.pixels[i].g = 0;
     tmp_file.pixels[i].b = 0;
     tmp_file.pixels[i].a = 0;
}</pre>
  <p>Now we can read the image. Let&#x27;s change some color values as a quick test. Here we have a function that stores the referenced value from an actual image pixel into our own pixel data, only leaving the green channel to its absolute value.</p>
  <pre>/* TGA is Little Endian encoded, so values in pixel are bgra instead of rgba. */
void change_pixel_color(pixel_t *pixel, unsigned char *p_value) {
      pixel-&gt;a = p_value[3];
      pixel-&gt;r = p_value[2];
      pixel-&gt;g = 255;        /* p_value[1]; */
      pixel-&gt;b = p_value[0];
}</pre>
  <p>So after allocating our pixel data from the file pointer we can run that function until we reach the last pixel in the image like this:</p>
  <pre>int n = 0;
char p_value[4];

while(n &lt; (tmp_file.header.width * tmp_file.header.height) ) {
    fread(p, 1, 4, fptr);
    change_pixel_color(&amp;(tmp_file.pixels[n]), p_value);
    n++;
}
fclose(fptr);</pre>
  <p>To write the data out into a file we can whether reopen our file in write mode and overwrite data there, or open a new file in write mode, and then store the new pixel data along with a TGA header.</p>
  <p>Here&#x27;s a result of a four pixel TGA Image passed through the previous <code>change_pixel_color()</code> function:<br /></p>
  <figure class="m_original">
    <img src="https://teletype.in/files/ab/6a/ab6a182b-9354-449d-a759-508903587506.png" width="480" />
  </figure>
  <p></p>
  <p></p>
  <h2>Summing up</h2>
  <p>Now that we&#x27;ve covered both ways of storing data from a program inside the computer, it&#x27;s time for your creativity to flow in your next project. </p>
  <p>Some data types and projects require more tailored byte buffers than just a bulk read and a bulk write of bytes. That topic will be covered in other series of articles.</p>
  <p>Full working examples of the code shown above are coming to the <a href="https://codeberg.org/unixworks" target="_blank">unixworks repository</a>. Stay tuned, and I&#x27;ll see you in the next article (:</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@unixworks/c-programming-working-with-files</guid><link>https://teletype.in/@unixworks/c-programming-working-with-files?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/c-programming-working-with-files?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>C programming | Working with files</title><pubDate>Sun, 15 Nov 2020 20:16:34 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/9c/c0/9cc046c4-dda5-4470-9b65-5430ca2b832f.png"></media:content><category>C programming</category><description><![CDATA[<img src="https://teletype.in/files/75/c7/75c7b081-5147-40b6-82c1-31a4f680d083.png"></img>At some point when developing software no matter how big o small the program is going to be, we need to store some data in the computer, and read from other sources too. Let's take a look at how to work with external files in C.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/75/c7/75c7b081-5147-40b6-82c1-31a4f680d083.png" width="720" />
  </figure>
  <p>At some point when developing software no matter how big o small the program is going to be, we need to store some data in the computer, and read from other sources too. Let&#x27;s take a look at how to work with external files in C.</p>
  <p></p>
  <blockquote>Files in C programming don&#x27;t have a predefined structure. They are meant to be a container for some sequence of bytes. That way the internal structure of a file is something that the program itself has to deal with.</blockquote>
  <p>As long as we know how a file structure is made, we can open, work and write with any file.</p>
  <p></p>
  <p></p>
  <h2>Opening files</h2>
  <p>Opening files in C can be achieved in two ways; using the <code>stdio</code> function <code>fopen()</code> or using the lower level one <code>open()</code>.</p>
  <p>The main difference between them is that <code>open()</code> is a system call while <code>fopen()</code> is a library call.</p>
  <p><code>fopen()</code> calls <code>open()</code> under the hood and uses buffering to improve execution timing. When timing is critical(eg. embedded systems), is better to use <code>open()</code> and take full control on when we want the data to be processed.</p>
  <p></p>
  <h3>— The fopen() way</h3>
  <p>The <code>fopen()</code> function associates a file with a stream and initializes an object of the type <code>FILE</code>, which contains a structure with information to control the stream.</p>
  <p>We can specify how we want to operate with the data by passing different modes into the <code>mode</code> parameter.</p>
  <p>Possible modes are:</p>
  <ul>
    <li><code>r</code> opens a file for reading</li>
    <li><code>w</code> creates a file for writing. If it&#x27;s not empty, it discards the previous content.</li>
    <li><code>a</code> opens or creates a file (in case it doesn&#x27;t exist) and writes at the end of it.</li>
  </ul>
  <p>Adding a <code>+</code> sign after any of the letters make the file to work in update mode. That is, the mode allows both reading and writing.</p>
  <pre>FILE *file = fopen(&quot;path/to/file.type&quot;, &quot;mode&quot;);</pre>
  <p></p>
  <h3>— The open() way</h3>
  <p>The <code>open()</code> function returns an <code>int</code> object called file descriptor. Every open file has a file descriptor number, which is used by the operating system to keep track of them.</p>
  <p>Similar to fopen(), we can specify how we want to work with the opened file passing specific flags into the <code>flags</code> parameter.</p>
  <p>Valid mandatory flags are:</p>
  <ul>
    <li><code>O_RDONLY</code> which opens a file in read-only mode.</li>
    <li><code>O_WRONLY</code> which opens a file in write-only mode.</li>
    <li><code>O_RDWR</code> which opens a file in read/write mode.</li>
  </ul>
  <p>Additional flags can be added in order to perform other operations such as <code>O_APPEND</code> to open a file in append mode, or <code>O_ASYNC</code> to use a pipe of a FIFO.</p>
  <p>We can add a third optional parameter to specify permissions of the file, like:</p>
  <ul>
    <li><code>S_IRUSR</code> user has read permissions.</li>
    <li><code>S_IWUSR</code> user has write permissions.</li>
  </ul>
  <pre>int fileData = open(&quot;path/to/file.type&quot;, flags, mode);</pre>
  <p></p>
  <p></p>
  <h2>Writing files</h2>
  <p>We can run a program that takes arguments from the user via the terminal emulator, and perform operations based on those arguments, print them back to the terminal, and ask for more operations if needed, but each time we close the program, that data is gone. </p>
  <blockquote>We can write data in binary files and in text files.</blockquote>
  <p>The standard library has two useful functions to help us in the task of saving that data we ask for and process during the program execution, into a file. These functions are <code>fwrite()</code> and <code>fprintf()</code>.</p>
  <p></p>
  <h3>— Using fwrite() </h3>
  <p>The function <code>fwrite()</code> writes a number of objects of a given size to a file. Is often used to write binary data.</p>
  <p>The information we need to pass to <code>fwrite()</code> is the following:</p>
  <ul>
    <li>A memory buffer, or the address of the data to store.</li>
    <li>The size in bytes of each element of the data to store.</li>
    <li>The amount of elements to write.</li>
    <li>A pointer to a FILE object.</li>
  </ul>
  <pre>fwrite(&amp;data, sizeof(data_type), strlen(data), file);</pre>
  <p>This is going to return us a binary file. We can check its content using a tool like <code>hexdump(1)</code>.</p>
  <pre>typedef struct Car {
    int power;     //kW
    int torque;    //NM
    int wheels;    //[4, 5]
    int seats;     //up to 7
    int doors;     //[3, 5]
}

Car rallyCar {
    .power = 235,
    .torque = 384,
    .wheels = 5,
    .seats = 2,
    .doors = 3
};

FILE *file = fopen(&quot;cars.bin&quot;, &quot;w&quot;);

fwrite(&amp;rallyCar, sizeof(Car), 1, file);

fclose(file);</pre>
  <p>— We can however, write text files using <code>fwrite()</code> by making use of the function <code>sprintf()</code>, which writes its output as a string in the buffer referenced.</p>
  <pre>char buffer[40];

sprintf(buffer, &quot;The actual engine torque is %f.\n&quot;, engine.torque);
fwrite(buffer, sizeof(char), strlen(buffer), file);

fclose(file);</pre>
  <p></p>
  <h3>— Using fprintf()</h3>
  <p>Similar to the <code>printf()</code> function, we have <code>fprintf()</code> in the standard library, with which we can write formatted outputs into a file, passing a character constant as a format parameter. </p>
  <p>The information we need to pass to fprintf() is the following:</p>
  <ul>
    <li>A file pointer of type FILE.</li>
    <li>The desired output format, which is a <code>const *char</code>.</li>
    <li>The desired content to format.</li>
  </ul>
  <pre>fprintf(file_pointer, format, content);</pre>
  <p>This way we store text data by default in a file.</p>
  <pre>FILE *file = fopen(&quot;temp.log&quot;, &quot;a&quot;);

if (file != null)
   fprintf(file, &quot;%s\n&quot;, &quot;Appending data to temp file.&quot;);

fclose(file);</pre>
  <p>At the end of the article we&#x27;ll use this function to <em>serialize</em> some JSON data.</p>
  <p></p>
  <p></p>
  <h2>Other operations with files</h2>
  <p>Apart from opening and writing files the header file <code>stdio.h</code> has more functions required to work with I/O which we can use to rename, remove, and close files among other operations.</p>
  <p></p>
  <h3>— Close a file</h3>
  <p>Once we are done working with a file, we can close the stream and free up the memory using the function <code>fclose()</code>. The function deletes any unwritten data for the stream and discards any unread buffered input, so be sure to write changes before.</p>
  <pre>fclose(file);</pre>
  <p></p>
  <h3>— Rename a file</h3>
  <p>We can rename a file using the function <code>rename()</code> by passing the name of the old file and a string (<code>const *char</code>) to use as the new one.</p>
  <pre>rename(&quot;old_file_name&quot;, &quot;new_file_name&quot;);</pre>
  <p></p>
  <h3>— Remove a file</h3>
  <p>We can make a file unavailable using the <code>remove()</code> function, passing the file&#x27;s filename. If the file has no other names linked, then the file is deleted. Depending on the mode used by the file, the function may or may not be able to perform the deletion.</p>
  <pre>remove(&quot;file_name&quot;);</pre>
  <p></p>
  <h3>— Create a temporary file</h3>
  <p>Using <code>tmpfile()</code> we can create a temporary file with a unique name in <code>wb+</code> mode which is automatically removed once we close it or the program terminates.</p>
  <p>If the function is unable to open a temporary file, it returns a <code>NULL</code> pointer, otherwise it returns a pointer to the temp file.</p>
  <pre>FILE *file = tmpfile(); //file is pointing to a tempfile.</pre>
  <p></p>
  <p></p>
  <h2>How to map files in memory</h2>
  <p>There is a way to work more efficiently with files, that is allocating them in virtual memory with <code>mmap</code>.</p>
  <p>Virtual memory helps when the processes ask for more memory than the system has. At that point the operating system&#x27;s memory management takes memory from the RAM and places it into the swap, bringing it back to the RAM when requested. Is basically moving data from the RAM to the hard drive back and forward.</p>
  <p>We can use that way of work to read and write files too.</p>
  <p>Let&#x27;s use <code>mmap</code> to request blocks of memory from a text file (it can be any other file too):</p>
  <h3>— Open a file</h3>
  <pre>int fileData = open(&quot;text_file.txt&quot;, O_RDONLY, S_IRUSR | S_IWUSR);</pre>
  <p>If we want to also write content into the file we have to open it in a read-write mode using different flags in the <code>open()</code> function:</p>
  <pre>int fileData = open(&quot;text_file.txt&quot;, O_RDWR, S_IRUSR | S_IWUSR);</pre>
  <p></p>
  <p>We can do the same using <code>fopen()</code>, but is a good thing not to mix high level I/O with low level operations. We would killing the performance.</p>
  <blockquote>If we use <code>fopen()</code> then we need to use the function <code>fileno()</code> to get the file descriptor from our opened file.</blockquote>
  <pre>FILE *fileData = fopen(&quot;text_file.txt&quot;, &quot;r&quot;);
int fileDescriptor = fileno(fileData);</pre>
  <p></p>
  <h3>— Get the size of the file</h3>
  <p>We need to include <code>&lt;sys/stat.h&gt;</code> and <code>&lt;unistd.h&gt;</code> to help:</p>
  <pre>#include &lt;sys/stat.h&gt;
#include &lt;unistd.h&gt;
...
struct stat sb;
if(fstat(file, &amp;sb) == -1)
    printf(&quot;couldn&#x27;t get file size\n&quot;);</pre>
  <h3>— Allocate in memory using mmap()</h3>
  <p>We need to pass the following parameters to the function:</p>
  <ul>
    <li>The desired starting address, <code>NULL</code> in this case, letting the system to choose the address.</li>
    <li>The length of the file to map. We are using file status to get the total size in bytes with <code>sb.st_size</code>.</li>
    <li>The flag or flags representing how we want to operate with the memory page. </li>
  </ul>
  <blockquote>If we just want to read the file it&#x27;s <code>PROT_READ</code>. If we want to read and write the file it needs to be <code>PROT_READ | PROT_WRITE</code>.</blockquote>
  <p></p>
  <ul>
    <li>The flag or flags representing if the mapping is going to be shared with other processes or not. In this case <code>MAP_PRIVATE</code>.</li>
  </ul>
  <blockquote>If we want to write the file we need to change <code>MAP_PRIVATE</code> to <code>MAP_SHARED</code> otherwise the program is not going to share the memory with the rest of the system, and it&#x27;s not going to be able to write back to the file.</blockquote>
  <p></p>
  <ul>
    <li>The file descriptor from our opened file, <code>fileData</code>.</li>
    <li>The offset where to start mapping the file, in this case <code>0</code>, which is the beginning.</li>
  </ul>
  <pre>char *fileInRAM = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fileData, 0);</pre>
  <h3>— Operate with the data</h3>
  <p>Now that we have mapped our file we can start working freely with it.</p>
  <pre>for (int i = 0, i &lt; sb.st_size; i++)
    printf(&quot;%c&quot;, fileInRAM[i];
printf(&quot;\n&quot;);</pre>
  <h3>— Unmap memory and close the file</h3>
  <p>Once we&#x27;re done working with the file, just by closing the file descriptor we don&#x27;t unmap the data. The function <code>munmap()</code> takes mapped file and deletes its mappings in the specified address range.</p>
  <p>After that we can close the file descriptor to finish.</p>
  <pre>munmap(fileInRAM, sb.st_size);
close(fileData);</pre>
  <p></p>
  <blockquote>A complete view of the code should look like this:</blockquote>
  <pre>int main()
{
  int fileData = open(&quot;plain_text_file.txt&quot;);
  
  struct stat sb;
  
  char *fileInRAM = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fileData, 0);

  for (int i = 0, i &lt; filesize; i++)
    printf(&quot;%c&quot;, fileInRAM[i];

  munmap(fileInRAM, filesize);
  close(fileData);
}</pre>
  <p></p>
  <p></p>
  <h2>Structuring data</h2>
  <p>We know that the C programming language doesn&#x27;t care about the type of file we use. Some applications may be fulfilled by storing data in plain text files, but even by being text files, they may need to follow a structure so we can interoperate later with the data inside them.</p>
  <p>To achieve this we need to convert the abstract in-memory data into a series of bytes that record the data structure into a recoverable format. This is called serialization.</p>
  <p>Our data structure can be a simple list or array, a complex group of nested arrays and structs, or whatever required.</p>
  <p></p>
  <h3>Writing structured data to a file</h3>
  <p>— As an example, let&#x27;s take a look at a program where the user can store information about a vehicle&#x27;s engine.</p>
  <ul>
    <li>We should have a struct type that handles how an engine is defined.</li>
  </ul>
  <pre>/*simplified engine structure*/
typedef struct Engine {
    char model[10];                  //engine model
    char manufacturer[10];           //engine manufacturer
    int power;                       //kW
    int torque;                      //NM
    int cylinders;                   //total cylinders in engine
    int structure;                   //block structure [1, 2, 3] rows
    char fuelType[10];               //fuel type [gasoline, diesel]
} Engine;</pre>
  <p></p>
  <ul>
    <li>Once we are working in the program we can create an engine and assign values to it.</li>
  </ul>
  <pre>Engine engine {
    .model = &quot;RB26DETT&quot;,
    .manufacturer = &quot;nismo&quot;,        
    .power = 235,                  
    .torque = 384,                  
    .cylinders = 6,            
    .structure = 1,
    .fuelType = &quot;gasoline&quot;     
};</pre>
  <p></p>
  <ul>
    <li>Now it&#x27;s time to define a constant to serialize the data into a file. Instead of reinventing the wheel, let&#x27;s use an existing data-interchange format such as <a href="http://json.org" target="_blank">JSON</a> (XML applies here too).</li>
  </ul>
  <pre>const char *ENGINE_EXPORT_FMT =
&quot;{\n\t\&quot;model\&quot;: \&quot;%s\&quot;,\n\t\&quot;manufacturer\&quot;: \&quot;%s\&quot;,\n\t\&quot;power\&quot;: %d,\n\t\&quot;torque\&quot;: %d,\n\t\&quot;cylinders\&quot;: %d,\n\t\&quot;structure\&quot;: %d,\n\t\&quot;fuel\&quot;: \&quot;%s\&quot;\n}\n&quot;;</pre>
  <p>Most of the &quot;complexity&quot; here is to correctly describe our object. As for this simple example, we can just go with this constant. For serious projects we would need to improve this in a header file and probably make some functions that warp the process.</p>
  <p></p>
  <ul>
    <li>Moving on, we have to open a file to write the data to, or create a new one.</li>
  </ul>
  <pre>FILE *file = fopen(&quot;engine_data.json&quot;, &quot;w+&quot;);</pre>
  <p></p>
  <ul>
    <li>Once we have our file opened, we need to print the content of our engine struct into it, using the function <code>fprintf()</code>.</li>
  </ul>
  <pre>fprintf(file, ENGINE_EXPORT_FMT, engine.model, engine.manufacturer, engine.power, engine.torque, engine.cylinders, engine.structure, engine.fuelType);</pre>
  <blockquote>Note that we have named our example file as <code>.json</code> but we could actually add the name and extension we&#x27;d want, and the result would be the same.</blockquote>
  <p></p>
  <p>A complete view of the code should look like this:</p>
  <pre>#include&lt;stdio.h&gt;
#include&lt;stdlib.h&gt;

/*engine struct format data*/
const char *ENGINE_EXPORT_FMT = &quot;{\n\t\&quot;model\&quot;: \&quot;%s\&quot;,\n\t\&quot;manufacturer\&quot;: \&quot;%s\&quot;,\n\t\&quot;power\&quot;: %d,\n\t\&quot;torque\&quot;: %d,\n\t\&quot;cylinders\&quot;: %d,\n\t\&quot;structure\&quot;: %d,\n\t\&quot;fuel\&quot;: \&quot;%s\&quot;\n}\n&quot;;

/*simplified engine structure*/
typedef struct Engine {
    char model[10];                  //engine model
    char manufacturer[10];           //engine manufacturer
    int power;                       //kW
    int torque;                      //NM
    int cylinders;                   //total cylinders in engine
    int structure;                   //block structure [1, 2, 3] rows
    char fuelType[10];               //fuel type [gasoline, diesel]
} Engine;


int main()
{
    Engine engine {
        .model = &quot;RB26DETT&quot;,
        .manufacturer = &quot;nismo&quot;,        
        .power = 235,                  
        .torque = 384,                  
        .cylinders = 6,            
        .structure = 1,
        .fuelType = &quot;gasoline&quot;     
    };
    
    FILE *file = fopen(&quot;engine_data.json&quot;, &quot;w+&quot;);
    
    fprintf(file, ENGINE_EXPORT_FMT, engine.model, engine.manufacturer, engine.power, engine.torque, engine.cylinders, engine.structure, engine.fuelType);
    
    fclose(file);
    
    return 0;
}</pre>
  <p>We should have a new file named <code>engine_data.json</code> in our directory with the engine struct parsed into it.</p>
  <p></p>
  <h3>Parsing structured data from a file</h3>
  <p>If we want the saved data to be used back in the program, we have to kinda reverse engineering our constant to parse our object.</p>
  <ul>
    <li>Create a new constant char.</li>
  </ul>
  <pre>const char *ENGINE_IMPORT_FMT =
&quot;{\n\t\&quot;model\&quot;: \&quot;%[^\&quot;]\&quot;,\n\t\&quot;manufacturer\&quot;: \&quot;%[^\&quot;]\&quot;,\n\t\&quot;power\&quot;: %d,\n\t\&quot;torque\&quot;: %d,\n\t\&quot;cylinders\&quot;: %d,\n\t\&quot;structure\&quot;: %d,\n\t\&quot;fuel\&quot;: \&quot;%[^\&quot;]\&quot;\n}&quot;;</pre>
  <p></p>
  <ul>
    <li>We need to specify where we want to start reading the data from the file. </li>
  </ul>
  <pre>fseek(file, 0, SEEK_SET);</pre>
  <p></p>
  <ul>
    <li>Finally we can assign the read data to a new variable using <code>fscanf()</code>.</li>
  </ul>
  <pre>Engine iEngine;
fscanf(file, ENGINE_IMPORT_FMT, iEngine.model, iEngine.manufacturer, &amp;iEngine.power, &amp;iEngine.torque, &amp;iEngine.cylinders, &amp;iEngine.structure, iEngine.fuelType);</pre>
  <p></p>
  <p>A complete view of the code should look like this:</p>
  <pre>#include&lt;stdio.h&gt;
#include&lt;stdlib.h&gt;

/*engine struct format data*/
const char *ENGINE_IMPORT_FMT = &quot;{\n\t\&quot;model\&quot;: \&quot;%[^\&quot;]\&quot;,\n\t\&quot;manufacturer\&quot;: \&quot;%[^\&quot;]\&quot;,\n\t\&quot;power\&quot;: %d,\n\t\&quot;torque\&quot;: %d,\n\t\&quot;cylinders\&quot;: %d,\n\t\&quot;structure\&quot;: %d,\n\t\&quot;fuel\&quot;: \&quot;%[^\&quot;]\&quot;\n}&quot;;

/*simplified engine structure*/
typedef struct Engine {
    char model[10];                  //engine model
    char manufacturer[10];           //engine manufacturer
    int power;                       //kW
    int torque;                      //NM
    int cylinders;                   //total cylinders in engine
    int structure;                   //block structure [1, 2, 3] rows
    char fuelType[10];               //fuel type [gasoline, diesel]
} Engine;


int main()
{
    Engine engine;
    
    FILE *file = fopen(&quot;engine_data.json&quot;, &quot;r&quot;);
    
    fseek(file, 0, SEEK_SET);
    
    fscanf(file, ENGINE_EXPORT_FMT, engine.model, engine.manufacturer, &amp;engine.power, &amp;engine.torque, &amp;engine.cylinders, &amp;engine.structure, engine.fuelType);
    
    fclose(file);
    
    return 0;
}</pre>
  <p></p>
  <p></p>
  <h2>Summing up</h2>
  <p>Files play a really important role in software programs. We&#x27;ve seen how to work with operations that read, write and format text both from and into files, but the same can be achieved for binary files such as images or audio.</p>
  <p>In addition to that, we can also implement ways to obfuscate how our program writes the data so not everyone can open our format back. This is kind of an unfriendly way to do the things, but corporate often makes this so the competition cannot just sneak into a company&#x27;s new software and steal how they engineer things. But hey, we have reverse engineers to do so (:</p>
  <p>A further discussion in this field will be present in a future article. </p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@unixworks/c-programming-working-with-pointers</guid><link>https://teletype.in/@unixworks/c-programming-working-with-pointers?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/c-programming-working-with-pointers?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>C programming | Working with pointers</title><pubDate>Sun, 08 Nov 2020 11:37:21 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/7f/4f/7f4fc048-6304-45fe-b12c-d07c7f8d2b64.png"></media:content><category>C programming</category><description><![CDATA[<img src="https://teletype.in/files/07/0f/070f6eed-13ba-4b08-a92b-ff7870eb11bf.png"></img>Accessing memory locations is one of the greatest features of the C programming language, although it requires some responsibility. The word pointer often scares programmers away, but it shouldn't.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/07/0f/070f6eed-13ba-4b08-a92b-ff7870eb11bf.png" width="720" />
  </figure>
  <p>Accessing memory locations is one of the greatest features of the C programming language, although it requires some responsibility. The word <em>pointer</em> often scares programmers away, but it shouldn&#x27;t.</p>
  <blockquote>Pointers give support for dynamic memory allocation, level-up flow control in a program and are closer to hardware which makes code more efficient.</blockquote>
  <h4>  </h4>
  <h2>What are pointers?</h2>
  <p>In C programming, variables hold values at a specific memory address. Pointers are variables that hold memory addresses and types of other variables and functions, giving direct access to physical memory locations anywhere inside the computer.</p>
  <blockquote>Given the variable <code>var</code>, <code>&amp;var</code> is a pointer to <code>var</code>.</blockquote>
  <p>You can think about pointers and variables like license-plates and vehicles. While vehicles can seize too many types and forms, license-plates usually come in an unified form.</p>
  <p>  </p>
  <p>  </p>
  <h2>How pointers work</h2>
  <p>With pointers it&#x27;s possible to access any memory location and change the data contained at that location.</p>
  <p>A pointer is declared by adding an asterisk (<code>*</code>) in front of the variable name in the declaration statement.</p>
  <blockquote>It&#x27;s heavily recommended to initialize pointers as <code>NULL</code> since when we create a pointer it isn&#x27;t initialized and holds random data that can point to anywhere in the computer memory.</blockquote>
  <pre>int variable_name = 8;         //define a variable
int *variable_pointer = NULL;  //define a pointer to a variable</pre>
  <p>  </p>
  <p><code>NULL</code> is a macro to address <code>0</code>. In programming terms <code>0</code> is an invalid address. It can be defined like this:</p>
  <pre>#define NULL ((void*)0)</pre>
  <p>  </p>
  <p>— In order to work with declared pointers, we have two basic pointer operators:</p>
  <ul>
    <li><code>&amp;</code> Address constant of an object in memory. Given a variable, point to it. </li>
  </ul>
  <pre>/* we pass a variable asking for its memory address */
printf(&quot;%d\n&quot;, &amp;variable_name);

/* the program should return a memory address */
&quot;0xfbee324b&quot;</pre>
  <p>  </p>
  <ul>
    <li><code>*</code> Content of a memory address. Given a pointer, get the value stored in it. This is usually called pointer dereferencing.</li>
  </ul>
  <pre>/* make our pointer point to the address of the given variable */
variable_pointer = &amp;variable_name;

/* we pass a variable asking for its value */
printf(&quot;%d\n&quot;, *variable_pointer);

/* the program should return the content of the memory address */
&quot;8&quot;</pre>
  <p>  </p>
  <p>Let&#x27;s make a quick reminder of how to work with simple pointers:</p>
  <pre>int main() {
/* define a variable for a number */
  int num;
  
/* define a pointer to num */
  int *int_ptr = NULL;

/* add a value to num */
  num = 14;

/* now make the pointer point to num. This assigns num address to int_ptr */
  int_ptr = &amp;num;

/* let&#x27;s check what values contain each variable */
  printf(&quot;num = %d\n&quot;, num);
  printf(&quot;&amp;num = %p\n&quot;, &amp;num);
  printf(&quot;int_ptr = %p\n&quot;, int_ptr);
  printf(&quot;*int_ptr = %p\n&quot;, *int_ptr);
  printf(&quot;&amp;int_ptr = %p\n&quot;, &amp;int_ptr);

/* int_ptr points to num, changing int_ptr value modifies num too */
  *int_ptr = 8;
  printf(&quot;modified *int_ptr = %p modified num to num = %d\n&quot;, *int_ptr, num);

  return 0;
}</pre>
  <p>  </p>
  <p>The result of that program should be similar to this:</p>
  <pre>num = 14
&amp;num = 0x6fff86d087a5
int_ptr = 0x6fff86d087a5
*int_ptr = 14
&amp;int_ptr = 0x6fff86d087a5
modified *int_ptr = 8 modified num to num = 8</pre>
  <p>  </p>
  <p>  </p>
  <h2>Pointer utilities</h2>
  <p>We&#x27;ve seen a quick refresh of how pointers work. Now let&#x27;s take a look at some options pointers give to us.</p>
  <p>  </p>
  <p><strong>— We can have multiple pointers pointing to the same variable.</strong></p>
  <pre>int main() {
  int num;
  int *first_ptr;
  int *second_ptr;
  
  num = 14;
  
  first_ptr = &amp;num;
  second_ptr = first_ptr;

  return 0;
}</pre>
  <p>since <code>first_ptr</code> and <code>second_ptr</code> are both pointers we can reference them.</p>
  <p>  </p>
  <p><strong>— We can pass pointers as function arguments.</strong></p>
  <p>Passing data using a pointer allows the function to modify the external data. </p>
  <p>If we try to do the same with data passed as values instead of pointers then we only modify the function parameter, and not the original value since the addresses of the parameter and the variable in main are not the same.</p>
  <pre>void ModifyData(int *data);

int main() {
    
    int externalData = 10; 
    
    printf(&quot;\nExternal data value before modify is %d&quot;, externalData);
    
    ModifyData(&amp;externalData);
    
    printf(&quot;\nExternal data value after been modified is %d&quot;, externalData);
} 

void ModifyData(int *data) {
    
    *data = 0;
}</pre>
  <p>The result should be:</p>
  <pre>External data value before modify is 10 
External data value after been modified is 0</pre>
  <p>However, we can&#x27;t change the actual pointer to the data since passed a copy of the pointer. </p>
  <p>A common practical example using pointers as function parameters is a swap function.</p>
  <pre>void SwapFloat( float *a, float *b) { 
    float tmp = *a; 
    *a = *b; 
    *b = tmp; 
}</pre>
  <p></p>
  <p><strong>— We can pass pointer to a pointer as a function argument.</strong></p>
  <p>This way we can modify the original pointer and not its copy. Similar to passing a variable in the previous example.</p>
  <p></p>
  <p><strong>— We can return pointers.</strong></p>
  <p>This is pretty much straight forward. We have to declare the return type to be a pointer to the appropriate data type. </p>
  <pre>int *RoundFloat(float num);</pre>
  <p>An example implementing the function:</p>
  <pre>int *RoundFloat(float *num);

int main()
{
    float fnum = 5.23;
    int *frounded;
    
    frounded = RoundFloat(&amp;fnum);
    
    printf(&quot;rounded value from %f is %d.&quot;, fnum, *frounded);
    return 0;
}

int *RoundFloat(float *num) {
    int *tmp;
    *tmp = ((*num + 0.5f) *1) /1;
    
    return tmp;
}</pre>
  <p></p>
  <p><strong>— We can create function pointers.</strong></p>
  <p>A function pointer is a variable that stores the address of a function to be used later on the program.</p>
  <pre>typedef float (*OperationsTable)(float, float);</pre>
  <p>When we call a function, we might need to pass the data for it to process along pointers to subroutines that determine how it processes the data.</p>
  <pre>typedef float (*OperationsTable)(float, float);

float Add( float x, float y) { 
    return x+y;
}
float Sub( float x, float y) { 
    return x-y;
}

float Operate(OperationsTable opTable, float x, float y) { 
    return opTable(x,y);
};

int main() {
    int a, b;
    int a = 5;
    int b = 10;

    Operate(Add, a, b);
}</pre>
  <p>Another option is to store function pointers in arrays and later call the functions using the array index notation.</p>
  <pre>float Add( float x, float y) { 
    return x+y;
}
float Sub( float x, float y) { 
    return x-y;
}

float (*OperationsTable[2])(float, float) = { Add, Sub};

int main() {
    int a, b;
    int a = 5;
    int b = 10;

    OperationsTable[0](a, b);
}</pre>
  <p> </p>
  <p><strong>— We can use pointers with structs.</strong></p>
  <p>Normally we access struct components with a dot <code>.</code> but when a struct is marked as pointer, we access their values using the <em>point-to</em> operator <code>-&gt;</code>.</p>
  <blockquote>Note that is possible to still use a dot <code>.</code> , but then the call to the component is as follows: <code>(*foo).variable</code>.</blockquote>
  <pre>typedef struct Vector3 {
    int x;
    int y;
    int z;
} Vector3;

int main() {
    Vector3 origin = {3, 5, 10};
    
    Vector3 *point;
    
    point-&gt;x = origin.x;
    point-&gt;y = 0;
    point-&gt;z = origin.z;
    
    printf(&quot;\npoint values are x = %d | y = %d | z = %d&quot;, (*origin).x, (*origin).y, (*origin).z);
} </pre>
  <p>  </p>
  <p><strong>— We can define strings.</strong></p>
  <p>There&#x27;s no such thing recognized as a &quot;string&quot; in C. Strings in C are arrays of characters terminated with a NUL (represented as <code>\0</code>). </p>
  <pre>char *title = &quot;unixworks&quot;;</pre>
  <p>The array way of creating a string literal would be:</p>
  <pre>char title[] = &quot;unixworks&quot;;</pre>
  <p>Which is the equivalent to:</p>
  <pre>char title[] = {&#x27;u&#x27;, &#x27;n&#x27;, &#x27;i&#x27;, &#x27;x&#x27;, &#x27;w&#x27;, &#x27;o&#x27;, &#x27;r&#x27;, &#x27;k&#x27;, &#x27;s&#x27;, &#x27;\0&#x27;};</pre>
  <p>Note that using the pointer approach to create strings doesn&#x27;t allow to modify the string later as it&#x27;s supposed to be treated as a <code>const</code>.</p>
  <p>However, we can work with the string pointer as an array. It will return the value of the first character, since the variable actually points exactly to the beginning of the string.</p>
  <p>  </p>
  <p>  </p>
  <h2>Pointers and arrays</h2>
  <p>Although pointers and arrays aren&#x27;t the same thing, they can work hand to hand in C. In most of the cases, the name of the array is converted to a pointer to the first element.</p>
  <p></p>
  <ul>
    <li>An array notation like <code>array[index]</code> can be achieved using pointers with <code>*(array + index)</code>.</li>
    <li>The same way the array notation <code>&amp;array[index]</code> can be achieved using pointer notation <code>array + index</code>.</li>
  </ul>
  <p>  </p>
  <p>  Arrays in C programming need to have its size declared when we create them, or at least we are told to do so when learning. Other programming languages can perform dynamic arrays without declaring its size when created.</p>
  <p>—The fact is that we can create dynamic arrays in C combining pointers and arrays. <a href="https://teletype.in/@unixworks/c-programming-working-with-memory" target="_blank">Managing memory</a> in real-time is extremely useful to arrays that are generated at run-time.</p>
  <p>The only prerequisite to create a dynamic array using pointers is to reserve memory for it. That is achieved calling <code>malloc()</code>.</p>
  <pre>int *num_ptr;
num_ptr = malloc(MAX_NUMBERS * sizeof(int));</pre>
  <p>where:</p>
  <ul>
    <li><code>(int *)</code> casts the data type.</li>
    <li><code>MAX_NUMBERS</code> can be whatever value that determines the max elements in the array.</li>
    <li><code>sizeof(int)</code> is the amount of bytes that each element in the array holds.</li>
  </ul>
  <p>  </p>
  <p>    </p>
  <h2>Dynamic array of void pointers</h2>
  <p>A useful utility mixing pointers and arrays we can create is a dynamic array of void pointers.</p>
  <p>We start defining a struct as follows:</p>
  <pre>typedef struct Set {
    void **data;
    int capacity;
    int count;
} * Set_t;</pre>
  <p>Where we have:</p>
  <ul>
    <li><code>void **data</code> that are void pointers stored as a dynamic arrays. When used in a pointer, <code>void</code> defines a generic pointer (pointer of any type).</li>
    <li><code>capacity</code> which is the total allowed items.</li>
    <li><code>count</code> which is the current amount of items. It acts as an index for the stored data.</li>
  </ul>
  <p>We can initialize our List structure with the same criteria for dynamic arrays, using <code>malloc()</code>:</p>
  <pre>Set_t set = malloc(sizeof(struct List)); 

*set = (struct Set_t) { 
    .count = 0, 
    .capacity = 1, 
    .data = malloc(sizeof(void *))
};</pre>
  <p>If we want to add data to our list, we can increase the count value of our struct:</p>
  <pre>set-&gt;count += 1;</pre>
  <p>and compare it against the capacity value. </p>
  <pre>if(set-&gt;count == set-&gt;capacity) {
    set-&gt;capacity *=2; 

    set-&gt;data = realloc(list-&gt;data, list-&gt;capacity * sizeof(void *));
}</pre>
  <p>As most of the data structures, this dynamic array of pointers becomes useful when we create some functions to work with it.</p>
  <p>As an example we can make a function to get a value from an index of the set, and another one to check if a value is contained in an index of the set.</p>
  <pre>void *IndexValue(Set_t set, int index) { 
    if (index &gt; set-&gt;count) {
        printf(&quot;Index is out of bounds.\n&quot;);
        exit(1);
    }
    return set-&gt;data[index];
}

void SetContains(Set_t set, void * value) {
    for (int i = 0; i &lt; set-&gt;count; i++) { 
        if (Index(set, i) == value) 
            printf(&quot;Value is in the set.\n&quot;); 
    }
    printf(&quot;Value is not in the set.\n&quot;);
}</pre>
  <p>  </p>
  <p></p>
  <h2>Linked lists</h2>
  <p>Arrays are fine, but they can be inefficient depending the program to create and the target device architecture. </p>
  <p>Linked lists are a data structure. Instead of asking a large contiguous block of memory in a request to store an array, ask for one data unit at a time, for one element at a time in a separate request.</p>
  <p></p>
  <p>Let&#x27;s say we have some data we want to store as a list.</p>
  <pre>int x, y, z, w;</pre>
  <p>This makes the memory to allocate the data in non contiguous memory blocks. But we need to link the memory blocks in some way.</p>
  <pre>+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|  x  |     |     |  y  |     |  z  |     |     |     |  w  |     |     |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+</pre>
  <p></p>
  <p>One common solution is to store next to each data value, the memory address of the next data block.</p>
  <p>—This can be represented in C creating a struct, which we can name <code>Node</code>, where we store the data value, and the next node address (a pointer):</p>
  <pre>typedef struct Node {
  int data;
  node* next;
} Node_t;</pre>
  <p>This way we&#x27;ll have something like this:</p>
  <pre>+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|  x  |y_mem|     |  y  |z_mem|  z  |w_mem|     |  w  |  0  |     |     |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+</pre>
  <p>instead of</p>
  <pre>arr[3] = {x, y, z, w};

+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|     | a[0]| a[1]| a[2]| a[3]|     |     |     |     |     |     |     |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+</pre>
  <p>We are using some extra memory in the list compared with the array method, but that gives us the ability to create and free nodes dynamically where we need, and when we need.</p>
  <p>—Worth mention here is the last node of the list points to <code>NULL</code> or <code>0</code> as the next node address, indicating there&#x27;s no more data in the list.</p>
  <p>In the other hand, the address of the first node of the list gives us access to the complete linked list. Usually this first node is called <code>head</code>.</p>
  <pre>Node_t *head = NULL;</pre>
  <p>If we&#x27;d need to create another data link to our list, we first need to create a separate node, and then link the last node address to the newly created node instead of <code>NULL</code>.</p>
  <pre>Node_t *nodeA; 

nodeA = malloc(sizeof(node_t));
nodeA-&gt;data = 10;

head = nodeA;</pre>
  <p>We can also insert nodes anywhere in the list. The only thing to take care is to relocate the address values of each node.</p>
  <pre>Node_t *head = NULL;
Node_t *nodeA, *nodeB; 

nodeA = malloc(sizeof(node_t));
nodeB = malloc(sizeof(node_t));

nodeA-&gt;data = 10;
nodeB-&gt;data = 43;

head = nodeB;

nodeB-&gt;next = nodeA;
nodeA-&gt;next = NULL;</pre>
  <p>At this point the process starts to repeat itself a lot, and programming is intended to automate tasks. We can organize this a bit, creating a function that creates nodes for us.</p>
  <pre>Node_t *CreateNode(int data) { 
    Node_t *result = malloc(sizeof(node_t));
    result-&gt;data = data;
    result-&gt;next = NULL;
    return result;
}</pre>
  <p>This way we can start working dynamically and add nodes each time we need them.</p>
  <pre>Node_t *head = NULL;
Node_t *dummy; 

dummy = CreateNode(10);
head = dummy;

dummy = CreateNode(43);
dummy-&gt;next = head;
head = dummy;</pre>
  <p>This data structures are more useful if we implement functions to work with them. As an example, we can make a function to locate a node inside the list.</p>
  <pre>Node_t *LocateNode(Node_t *head, int data) {
    Node_t *tmp = head;
    while(tmp != NULL) {
        if (tmp-&gt;data == data)
            return tmp;
        tmp = tmp-&gt;next;
    }
    return NULL;
}</pre>
  <p>Another great feature in linked lists is the possibility to insert nodes at a certain point of the list. We can make a function for it too:</p>
  <pre>void InsertNodeAt(Node_t *insertPoint, Node_t *newNode) {
    newNode-&gt;next = insertPoint-&gt;next;
    insertPoint-&gt;next = newNode;
}</pre>
  <p></p>
  <p></p>
  <p></p>
  <h2>Summing up</h2>
  <p>Pointers open a huge field of possibilities in C but remember, with great power comes great responsibility. </p>
  <p>We have to take care of the heap use in some way. Using pointers introduce us the power to dynamically allocate elements in memory and this can cause to out of memory errors.</p>
  <p>When using <code>malloc()</code> to allocate memory, we know that it will return <code>NULL</code> if it runs out of memory, so a good practice is to check if we really got the memory needed when allocating.</p>
  <pre>pointerVar = malloc(sizeof(type_t)); 

if (pointerVar == NULL) {
    printf(&quot;\nOut of memory&quot;);
    exit(1);
}</pre>
  <p>Another good practice is to free up memory once we are done using it. A reminder on working with memory can be found <a href="https://teletype.in/@unixworks/c-programming-working-with-memory" target="_blank">here</a>.</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@unixworks/c-programming-working-with-memory</guid><link>https://teletype.in/@unixworks/c-programming-working-with-memory?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/c-programming-working-with-memory?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>C programming | Working with memory</title><pubDate>Sat, 25 Apr 2020 08:05:50 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/68/75/68752540-b8e3-4b46-a2cd-87679ece8ce2.png"></media:content><category>C programming</category><description><![CDATA[<img src="https://teletype.in/files/32/be/32be0135-bf92-4940-a012-1642aec183d3.png"></img>We need memory to perform processes and store values. C programs usually get their memory by calling the function malloc() and release that used memory calling the function free() when they're done.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/32/be/32be0135-bf92-4940-a012-1642aec183d3.png" width="720" />
  </figure>
  <p>We need memory to perform processes and store values. C programs usually get their memory by calling the function <code>malloc()</code> and release that used memory calling the function <code>free()</code> when they&#x27;re done.</p>
  <p></p>
  <blockquote>Some programming languages have garbage collectors to take care of memory. C doesn&#x27;t. It may be seen as a negative aspect, but it&#x27;s in fact a really good one since we as programmers can have more specific control on how memory is managed.</blockquote>
  <p></p>
  <p>— There are three basic ways to store memory. If we know the memory needed, it can be stored as static or as automatic, and if we don&#x27;t know how much memory we are going to need, then it can be stored as dynamic.</p>
  <ul>
    <li><em>static memory allocation</em> applies to global variables and variables marked with static. It is handled when the program starts and has a fixed size when the program is created.</li>
  </ul>
  <pre>int horsePower = 120;
static float pressure = 34.0f;</pre>
  <ul>
    <li><em>Automatic memory allocation</em> applies to variables defined inside functions that aren&#x27;t marked as <code>static</code>.</li>
  </ul>
  <pre>function GetTorque(EngineType engine)
{
  float defaultTorque = 2.4f;
  ...
}</pre>
  <ul>
    <li><em>dynamic memory allocation</em> is performed at run-time to allocate an arbitrary amount of memory at an arbitrary point in the program. This operation is handled by the operating system the program is running on, and the memory itself it&#x27;s allocated on the heap.</li>
  </ul>
  <pre>int *speed = malloc(sizeof(int);</pre>
  <p></p>
  <p>— The memory assigned to a program in a common architecture can be divided in <strong>four blocks</strong>:</p>
  <pre>+-------------+-------------+-----------+---------------------------+
|    Code     |  Static     |   Stack   |           Heap            |
+-------------+-------------+-----------+---------------------------+</pre>
  <ul>
    <li><strong>Code</strong> stores the instructions to execute, the program code.</li>
    <li><strong>Static/Global</strong> stores the variables declared outside functions (and the ones marked as static) that consequently are accessible anywhere while the program is running. This block is available until the program closes.</li>
    <li><strong>Stack</strong> stores the information from function calls and local variables. If we exceed the amount reserved for this block, the program will crash. The point about the information inside the stack block is that once a process ends, it&#x27;s automatically removed from the memory block (until it&#x27;s needed again).</li>
    <li><strong>Heap/Global</strong> stores large amounts of memory and maintains the variables in memory. Unlike the other blocks, the size of the Heap block is not fixed and we can control how much memory we want to use, and for how long we want to maintain data in the memory.</li>
  </ul>
  <blockquote>The way a heap block is implemented can vary between operating systems or compilers. When we work with dynamic memory allocation, we&#x27;re always working with the heap memory block.</blockquote>
  <p>The only limit for the heap block is the available amount of memory that the system running the program has.</p>
  <h4></h4>
  <p></p>
  <h2>malloc, calloc, realloc &amp; free</h2>
  <p>These are the four functions that generally deal with dynamic memory allocation in C. They are included in <code>stdlib.h</code></p>
  <p><strong>— malloc</strong></p>
  <pre>void* malloc(size_t size)</pre>
  <p>When we call <code>malloc()</code>, we are asking for a block of memory of a certain size in the heap memory block. <code>malloc()</code> returns a pointer to a block.</p>
  <ul>
    <li>If there&#x27;s not more memory available, <code>malloc()</code> returns NULL.</li>
    <li><code>malloc()</code> doesn&#x27;t initialize the allocated memory.</li>
  </ul>
  <pre>int *speed = malloc(sizeof(int);

speed = 180;</pre>
  <p><strong>— calloc</strong></p>
  <pre>void* calloc( size_t num, size_t size)</pre>
  <p>If we know the number of elements that we want to store and the size of each element, we can use <code>calloc()</code>.</p>
  <ul>
    <li><code>calloc()</code> also initializes the bytes in the block to zeroes, which avoids random garbage. This is useful when debugging.</li>
  </ul>
  <pre>int *checkpoints;
checkpoints = calloc(sizeof(int), 2);

checkpoints[0] = 1;
checkpoints[1] = 2;</pre>
  <p><strong>— realloc</strong></p>
  <pre>void* realloc(void* pointer, size_t size)</pre>
  <p>If we allocated a block of memory but at a certain point of our program we need to change its size, we can call <code>realloc()</code>.</p>
  <p>We need to pass the memory block we want to change, and the new size (that can be bigger or smaller).</p>
  <ul>
    <li>The address that <code>realloc()</code> returns can be different from the one of the original memory block. Once we reallocate a block we need to point to the new address, otherwise the program would crash.</li>
  </ul>
  <pre>checkpoints = realloc(checkpoints, sizeof(int)*200);</pre>
  <p><strong>— free</strong></p>
  <pre>void free(void* memory)</pre>
  <p>When we are done using the memory, we can call <code>free()</code> to tell the program&#x27;s memory that the specified block can be back to the operating system.</p>
  <pre>free(speed);
free(checkpoints);</pre>
  <p>If we don&#x27;t call <code>free()</code> after using a particular memory block we will be making an unnecessary memory usage.</p>
  <p></p>
  <p></p>
  <h2>Getting the memory</h2>
  <p>We know that calling <code>malloc()</code> gets us memory to store dynamic values in the heap block, but what happens there is like a black box. Where does the memory come from?</p>
  <p><code>malloc()</code> calls a function named <code>mmap()</code> where the magic happens. <code>mmap()</code> requests memory from the kernel.</p>
  <pre>void mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);</pre>
  <ul>
    <li><code>*addr</code> indicates where we want to allocate the memory. It can be <code>NULL</code> if we don&#x27;t care where to store the values, otherwise we can specify a memory address <code>(void*)0xFEEDB0000</code> and the system will try to satisfy the allocation.</li>
    <li><code>length</code> determines the size of the memory block that we want to map. We can request sizes that aren&#x27;t multiples of <code>4k</code>, but the system is going to return <code>4k</code> multiples either way, so we can set it to <code>4096</code> as a base and we are good to go. If we want to allocate more blocks we can multiply the initial value.</li>
  </ul>
  <pre>PAGESIZE 4096</pre>
  <ul>
    <li><code>prot</code> stands for protection and indicates which use do we want with the mapped memory. Common uses are <code>PROT_READ</code> and <code>PROT_WRITE</code>.</li>
    <li><code>flags</code> tell the kernel how we want the memory to be managed. We can make memory available only for the ongoing process with <code>MAP_PRIVATE</code>, we can share the memory with external processes with <code>MAP_SHARED</code>, or use <code>MAP_ANONYMOUS</code> as common cases.</li>
    <li><code>fd</code> stands for file descriptor and is used to access <code>i/o</code> resources. File descriptors are non-negative integers. If we don&#x27;t want to store any file, we can pass a negative value -1.</li>
    <li><code>offset</code> indicates where we want to start allocating memory so we can map only the parts we want.</li>
  </ul>
  <p>We can un-map memory calling <code>munmap()</code>:</p>
  <pre>int munmap(void *addr, size_t length);</pre>
  <p>— <code>mmap()</code> is useful when working with files since it allows us to handle them as memory buffers. A dedicated article on files will cover it.</p>
  <p></p>
  <h2>Shared memory</h2>
  <p>Since <code>mmap()</code> allows having memory buffers, we can use them as shared memory in scenarios where we don&#x27;t want to use pipes or signals and we want different processes to communicate each other.</p>
  <p>When a program starts running, it becomes a process. A program may have multiple processes. We can identify each process by the id the system creates to differentiate them using the function <code>getpid()</code>.</p>
  <blockquote>If we use the command-line with a tool like <code>top</code>, we can see all running processes and each one&#x27;s ID.</blockquote>
  <p>*nix systems create processes using <code>fork()</code>, which clones a process creating a parent process and a child process.</p>
  <pre>int main()
{
  printf(&quot;A single process. ID: %d\n&quot;, getpid());
}</pre>
  <p>The example above will print the statement once.</p>
  <pre>int main()
{
  fork();
  printf(&quot;A single process. ID: %d\n&quot;, getpid());
}</pre>
  <p>If we call <code>fork()</code> in the main function we are cloning the process and we&#x27;ll print twice the <code>printf()</code> call. We should see different values for each process ID.</p>
  <p>— Usually we want to make multiple processes so we can have each one doing different things. Right now we have two processes but apart from the ID, it&#x27;s not clear which one is the parent and which one is the child.</p>
  <p>Luckily we know the returning values of each one:</p>
  <ul>
    <li>The parent returns the ID of the child.</li>
    <li>The child returns <code>0</code>;</li>
    <li>On error, the parent returns <code>-1</code> and no child process is created.</li>
  </ul>
  <p>— At this point, changes made in either the parent or the child process are made locally so they can&#x27;t see each other changes.</p>
  <pre>int nonShared = 4;
int main()
{
  //check if the process is the child
  if (fork() == 0)
    nonShared = 0;
  else
    //parent waits for child to complete before the next instruction
    wait(NULL); 

  printf(&quot;Parent not shared value: %d\n&quot;, nonShared);
  return 0;
}</pre>
  <p>If we want the parent and child processes to be able to communicate with each other, we can make use of <code>mmap()</code> to create a memory buffer that shares the information.</p>
  <pre>int nonShared = 4;
int main()
{
  uint8_t *sharedMem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
  
  int pid = fork();

  //check if the process is the child
  if (pid == 0)
    *sharedMem = 1;
    nonShared = 0;
  else
    //parent waits for child to complete before the next instruction
    wait(NULL); 

  printf(&quot;not shared value: %d\n&quot;, nonShared);
  printf(&quot;shared value: %d\n&quot;, *sharedMem);
  return 0;
}</pre>
  <p>Now we can take some advantage on this and perform different operations for each process with shared values.</p>
  <pre>#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;   //fork()
#include &lt;sys/mman.h&gt; //mmap() 

int nonShared = 4;
int main()
{
  int *sharedMem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);

  int pid = fork();

  //check if the process is the child
  if (pid == 0)
    *sharedMem = nonShared + 2;
  else
    //parent waits for child to complete before the next instruction
    wait(NULL); 

  int result = *sharedMem / 2;
  if(pid != 0)
    printf(&quot;\nOperation result is: %d&quot;, result);
  return 0;
}</pre>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@unixworks/c-programming-working-with-headers</guid><link>https://teletype.in/@unixworks/c-programming-working-with-headers?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/c-programming-working-with-headers?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>C programming | Working with headers</title><pubDate>Thu, 23 Apr 2020 17:48:18 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/23/45/234546b3-b8cc-4285-bd5c-e6b058404b97.png"></media:content><category>C programming</category><description><![CDATA[<img src="https://teletype.in/files/ed/bb/edbb9df2-4908-49f1-8850-c9cb95d6dcfc.png"></img>Eventually at a certain point in our development, we'll have a big single source file or we'll need to reuse code from a source file in another source. Header files are just source C files with a .h extension that have C code inside. They are designed to store function declarations and macros.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/ed/bb/edbb9df2-4908-49f1-8850-c9cb95d6dcfc.png" width="720" />
  </figure>
  <p>Eventually at a certain point in our development, we&#x27;ll have a big single source file or we&#x27;ll need to reuse code from a source file in another source. Header files are just source C files with a .h extension that have C code inside. They are designed to store function declarations and macros.</p>
  <p></p>
  <blockquote>Header files are not mandatory but play a big game when sharing code between source files. They also help creating documentation and make code cleaner and more tidy.</blockquote>
  <p></p>
  <p></p>
  <h2>Why we need header files</h2>
  <p>The way C is designed, requires the programmer to declare what functions he&#x27;s going to use before defining them. This means that the compiler needs to know that there is some function <code>Foo</code> that takes parameters <code>x</code> and <code>y</code> before taking care of what <code>Foo</code> does inside.</p>
  <p>There are two types of C header files:</p>
  <ul>
    <li>Built-in header files.</li>
    <li>Programmer-defined header files.</li>
  </ul>
  <p>The first ones are provided by the C standard library, the GNU C library and similar.</p>
  <p>The user-defined header files are the ones that we need to create manually and fill with our content.</p>
  <p></p>
  <p>— If we create a function <code>CalcRadius</code> that takes one <code>float</code> value for a circle&#x27;s circumference and return the result, we have to declare it first:</p>
  <pre>//function declaration
float CalcRadius (float circumference);

//function definition
float CalcRadius (float circumference);
{
  float result;
  result = circumference / 2 * 3.14f;
  return result;
}</pre>
  <p>The function at the beginning is a declaration. It exists somewhere in the program but there&#x27;s no memory allocated to it.</p>
  <p>The detailed function below is the function definition.</p>
  <p>— Header files describe what you can use from the outside module while the function definitions are stored in a source file with a <code>.c</code> extension.</p>
  <p>When the compiler runs, it copies and pastes each header file included in a source file at the beginning of the code.</p>
  <p>To implement a header in our calculation program we need to create two files:</p>
  <ul>
    <li><code>math.h</code></li>
    <li><code>math.c</code></li>
  </ul>
  <p>Now we can cut and paste our function declaration inside <code>math.h</code>:</p>
  <p><strong>math.h</strong></p>
  <pre>//function declaration
float CalcRadius (float circumference);
</pre>
  <p>In order to link them together, inside the <code>math.c</code> file we need to add the <code>math.h</code> file at the beginning of the program, using the <code>#include</code> directive:</p>
  <p><strong>math.c</strong></p>
  <pre>#include &quot;math.h&quot;

//function definition
float CalcRadius (float circumference)
{
  float result;
  result = circumference / 2 * 3.14f;
  return result;
}
</pre>
  <p>This should be enough for the <code>.c</code> source file however, inside our <code>.h</code> file we have to perform some extra work in order to prevent some future errors that can happen when our program grows.</p>
  <p></p>
  <p></p>
  <h2>Header guards</h2>
  <p>We know when the compiler runs, it&#x27;s going to copy-paste our header file in each <code>#include</code> directive. Since we can include the same header file in multiple <code>.c</code> source files we need a way to not copy-paste the same header multiple times.</p>
  <p></p>
  <p>— <code>#ifdef</code>&#x27;s are pre-processor directives that are here needed to ensure the header file is only included once. Otherwise we would face an error similar to this when we run the compiler:</p>
  <pre>./math.h:4:7 error redefinition of CalcRadius function
./math.h:4:7 note previous definition is here
</pre>
  <p>They work similar to <code>if</code> statements. The best way to protect our header for duplication is to name it with a unique identifier (usually its file name) and check if it&#x27;s already defined or not. If not, then it&#x27;s copied until the end of the condition.</p>
  <p>Let&#x27;s guard our header file:</p>
  <p><strong>math.h</strong></p>
  <pre>#ifndef MATH_H /* This is our identifier */
#define MATH_H 

//function declaration
float CalcRadius (float circumference);

#endif /* MATH_H */</pre>
  <p>This way we can ensure that no matter how many times we need to include <code>math.h</code> in our program sources.</p>
  <p></p>
  <p></p>
  <h2>Compiler guards</h2>
  <p>Sometimes the C source code is compiled with a C++ compiler. This can be because of part of the program has been written in C++, or we have to use some modules that are created in C++. It also can be the case where we are including some C modules inside a C++ project.</p>
  <p>— While C don&#x27;t, C++ does name mangling due to function overloading. In C++ we can have two functions that have the same name with different arguments or return values, and the program can run without problems.</p>
  <p><code>extern &quot;C&quot; {}</code> ensures the compiler to treat the code inside the <code>extern</code> as C code.</p>
  <p><strong>math.h</strong></p>
  <pre>#ifndef MATH_H 
#define MATH_H 

#ifdef __cplusplus
extern &quot;C&quot; {
#endif

//function declaration
float CalcRadius (float circumference);

#ifdef __cplusplus
}
#endif

#endif /* MATH_H */</pre>
  <p>Now we can work with the function <code>CalcRadius</code> in any other <code>.c</code> source file without worrying when our program grows.</p>
  <p></p>
  <p></p>
  <h2>Other types to include</h2>
  <p>We&#x27;ve seen how to declare functions in header files and define them later in source files. In header files we can also include structs and variables without giving them any values. In the <code>.c</code> source file we can access those variables and initialize them.</p>
  <p></p>
  <p>If we initialize variables with values in header files, the compiler is going to prompt an error when it runs.</p>
  <p><strong>math.h</strong></p>
  <pre>...
float givenCircumference;
...</pre>
  <p>— There&#x27;s an exception with declaring values in header files, which are constants. We know (in the example above) that <code>3.14~</code> is the PI value and that value never changes, it&#x27;s a constant.</p>
  <p>Let&#x27;s add it into our header by defining the value:</p>
  <p><strong>math.h</strong></p>
  <pre>#define PI 3.14159f
...
float givenCircumference;
...</pre>
  <p><strong>math.c</strong></p>
  <pre>...
result = circumference / 2 * PI;
...</pre>
  <p>Our final files should look like this:</p>
  <p><strong>math.h</strong></p>
  <pre>#ifndef MATH_H /* This is our identifier */
#define MATH_H 

#define PI 3.14159f
float radius;
float circumference;


#ifdef __cplusplus
extern &quot;C&quot; {
#endif

//function declaration
float CalcRadius (float circumference);

#ifdef __cplusplus
}
#endif

#endif /* MATH_H */
</pre>
  <p><strong>math.c</strong></p>
  <pre>#include &quot;math.h&quot;

//function definition
float CalcRadius (float circumference);
{
  float result;
  result = circumference / 2 * PI;
  return result;
}</pre>
  <h4></h4>
  <p></p>
  <h2>Summing up</h2>
  <p>We can create a <code>main.c</code> file to perform the needed operations, and by including the <code>math.h</code> header, we should be able to access any function or value stored inside it, since the compiler is going to know where to find those values and functions when it runs.</p>
  <p><strong>main.c</strong></p>
  <pre>#include &lt;stdio.h&gt;
#include &quot;math.h&quot;

int main()
{
  /* assign a value for our declared float */
  givenCircumference = 4.8f;

  /* execute our function */
  printf(&quot;Radius from circle is: %f \n&quot;, CalcRadius(givenCircumference);

  return 0;
}</pre>
  <p>Now you can start growing up your own math library and use it in every project that needs one (:</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@unixworks/c-programming-beyond-basis</guid><link>https://teletype.in/@unixworks/c-programming-beyond-basis?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/c-programming-beyond-basis?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>C programming | Beyond basis</title><pubDate>Thu, 23 Apr 2020 09:31:38 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/27/49/2749348a-86e7-4d0d-80d7-8a7c26da9647.png"></media:content><category>C programming</category><description><![CDATA[<img src="https://teletype.in/files/f4/4d/f44da9bf-368b-4898-a77d-4188d22f3054.png"></img>Programming in C is something that is often considered old-fashioned or complicated. The C programming language was created to be used in Unix systems as a high-level language. It's been almost fifty years since the creation of the Unix operating system, and the C programming language still plays a rock-solid role nowadays.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/f4/4d/f44da9bf-368b-4898-a77d-4188d22f3054.png" width="720" />
  </figure>
  <p>Programming in C is something that is often considered old-fashioned or complicated<em>. </em>The C programming language was created to be used in Unix systems as a high-level language. It&#x27;s been almost fifty years since the creation of the Unix operating system, and the C programming language still plays a rock-solid role nowadays.</p>
  <p></p>
  <blockquote>Programming software is not far away from programming operating systems and embedded devices. Not all software has to be <em>mobile-first</em> or web-ready.</blockquote>
  <h4></h4>
  <p></p>
  <h2>Why C?</h2>
  <p>Apart from operating system kernels, code written in C can be found in database servers, embedded systems, cars, computational engines and real-time systems.</p>
  <p>— C is an easy to learn programming language. Compared to other programming languages, it expects the programmer to take care of details like variable types or memory allocation but it&#x27;s not that hard. We&#x27;re working inside a machine that understands data that flows between memory directions, yet we&#x27;re not asked to program in hex or binary code.</p>
  <p>It&#x27;s true that it takes longer than other high-level languages to get a finished program. But by programming in C you are going to learn a lot about how software communicates with the machine to achieve results.</p>
  <p></p>
  <p></p>
  <h2>What C offers</h2>
  <p>This are some <em>-huge-</em> advantages of developing software with C:</p>
  <ul>
    <li>C is simple (compared to C++, Java) yet powerful.</li>
    <li>No need to install any interpreter, virtual machine or library to start working with it.</li>
    <li>No need to install any specific IDE, a text editor is enough.</li>
    <li>Compilers are really easy to use and there is at least one C compiler for almost every existent architecture.</li>
    <li>You can bind scripting languages such as Lua or Python to your program.</li>
    <li>Direct access to memory. If done correctly, programs can be really memory efficient.</li>
    <li>Cross-platform is mostly ensured (depends if the software project in the making uses specific libraries like a GUI and which one we use in that case).</li>
  </ul>
  <h4></h4>
  <p></p>
  <h2>Wait, there is C++</h2>
  <p>C++ it&#x27;s trendy, considered the go-to language to do heavy object oriented programming software projects.</p>
  <p>— C++ is a superset of C, most of the people that program in C++ are using C programming features 99% of the time, and 1% using C++ features. Most software projects don&#x27;t need object oriented programming.</p>
  <p>— C is completely capable of making a good heavy-duty software, without over complicating methods. Take the <a href="https://www.blender.org/" target="_blank">Blender</a> 3D authoring tool as an example.</p>
  <p></p>
  <p></p>
  <h2>What to expect</h2>
  <blockquote>If you&#x27;re new to programming in C, the basis can be learnt with the <a href="https://en.wikipedia.org/wiki/The_C_Programming_Language" target="_blank">K&amp;R C Programming language book</a> which was written by the language creators.</blockquote>
  <p></p>
  <p>Through these articles we&#x27;re going to explore specific functionality and workflows in C that comes to a programmer&#x27;s mind once the basis have been acquired. I&#x27;m not a PhD. nor a recognized teacher of any famous university, but I hope you can find the content useful and interesting (:</p>
  <p>Here&#x27;s an index for the content of the articles:</p>
  <ol>
    <li><a href="/C-programming--Working-with-headers-04-23">Working with headers</a></li>
    <li><a href="/C-programming--Working-with-memory-04-25">Working with memory</a></li>
    <li><a href="https://teletype.in/@unixworks/c-programming-working-with-pointers" target="_blank">Working with pointers and arrays</a></li>
    <li><a href="https://teletype.in/@unixworks/c-programming-working-with-files" target="_blank">Working with files</a></li>
    <li><a href="https://teletype.in/@unixworks/c-programming-working-with-files-ii" target="_blank">Working with files II</a></li>
    <li>Threading basis</li>
    <li>Minimal GUI applications</li>
  </ol>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@unixworks/makefiles-the-power-to-build</guid><link>https://teletype.in/@unixworks/makefiles-the-power-to-build?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/makefiles-the-power-to-build?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>Makefiles | The power to build</title><pubDate>Fri, 17 Apr 2020 17:17:05 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/11/2a/112a7ec4-9c60-45dd-a31d-3b4a603d9323.png"></media:content><category>C programming</category><description><![CDATA[<img src="https://teletype.in/files/fd/48/fd484040-5c1f-4b90-b552-e065d73ce90f.png"></img>Working with languages like C/C++ requires running a process to compile our project. That process can look like a black box where magic happens, but it's not that complicated. Let's see how Makefiles work and how to write practical ones for your everyday hacks and projects.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/fd/48/fd484040-5c1f-4b90-b552-e065d73ce90f.png" width="720" />
  </figure>
  <p>Working with languages like C/C++ requires running a process to compile our project. That process can look like a black box where magic happens, but it&#x27;s not that complicated. Let&#x27;s see how Makefiles work and how to write practical ones for your everyday hacks and projects.</p>
  <p></p>
  <blockquote>You&#x27;ve maybe heard of Makefile generators like cmake. We&#x27;re not using them here, neither a heavy IDE. The article is explained using a plain text editor and the command-line.</blockquote>
  <p></p>
  <p><code>make</code> is a tool used mostly to compile and build C/C++ source code. Makefiles just tell <code>make</code> how to compile and build a program. They consist in a series of instructions that perform automatically rather than having to manually type them in the command-line.</p>
  <p>— Before we go further with make let&#x27;s check what happens when we call the compiler so we know how to structure steps inside the Makefile later.</p>
  <p>A simple compiling process takes four steps:</p>
  <ul>
    <li>The first step a compiler does is take our <code>.c</code> files and call the <em>preprocessor</em>, which handle the directives that start with a <code>#</code> like <code>#include</code> and <code>#define</code> and gets rid of the comments that may be present in our code.</li>
  </ul>
  <p>At this point, all the code inside the header files that we have included using the directive <code>#include &quot;header.h&quot;</code> is copied and pasted in the program.</p>
  <ul>
    <li>The second step takes the source file and calls the compiler to translate C code into Assembly code, ending up with a file that has a <code>.s</code> extension.</li>
    <li>Once the compiler is done, it needs to translate the Assembly code into machine code, creating an object file, which is done via the assembler. The result file <code>.o</code> isn&#x27;t an executable yet.</li>
    <li>The last step is bringing together all the object files to produce an executable. This part is done with the linker.</li>
  </ul>
  <p></p>
  <p></p>
  <h2>Flags</h2>
  <p>Each one of the steps needed to build a program can be invoked with a specific option to the compiler.</p>
  <p>Flags give us the ability to enable or disable functionality for our building processes.</p>
  <ul>
    <li><code>-E</code> calls the <em>preprocessor</em> only.</li>
    <li><code>-S</code> runs the compiler and stops at the assembly file.</li>
    <li><code>-c</code> is used to run the compiler up to the creation of an object file.</li>
    <li><code>-o</code> generates the executable program from the object files.</li>
    <li><code>-g</code> allows using <code>gdb</code> debugging.</li>
    <li><code>-Wall</code> enables the compiler to print all warnings encountered while building the program.</li>
    <li><code>-I</code> specifies a directory that contains prerequisites.</li>
  </ul>
  <p>All the previous flags can be manually typed in a command-line environment:</p>
  <pre>$ cc -o demo_program main.c</pre>
  <p>but the idea here is to store those commands in a Makefile to automatically perform the build.</p>
  <p></p>
  <p></p>
  <h2>Basic structure</h2>
  <p>A Makefile (case sensitivity named) is a plain text file that can contain the following sections:</p>
  <ul>
    <li>Rules (that can be explicit or implicit)</li>
    <li>Macros (variable definitions)</li>
    <li>Comments</li>
  </ul>
  <p><strong>— Rules</strong></p>
  <p>A Makefile rule needs three basic items:</p>
  <ul>
    <li>A <u>target</u>, which is the name of the generated file.</li>
    <li>The <u>dependencies</u> needed to build the target.</li>
    <li>An <u>action</u> to realize in order to get the target.</li>
  </ul>
  <p>Actions need to be indented by a tab character (not spaces) in order to work.</p>
  <blockquote>Note that we can have more than one action per target, and each one needs to be in a new line.</blockquote>
  <pre>target: dependencies
    action</pre>
  <p>Let&#x27;s pretend that we have a set of source files that we can compile into a program named <em>calculator </em>which depends on five independent source files.</p>
  <pre>calculator : main.c sum.h sub.h mult.h div.h
      cc -o calculator main.c</pre>
  <ul>
    <li>Our target can be named as the program we want to create, so in this case is <code>calculator</code>.</li>
    <li>Our dependencies are five object files. Each of those files comes from it&#x27;s own source.</li>
    <li>Our action is to execute the desired compiler, in this case <code>cc</code> to generate an output executable with the name <code>calculator</code> .</li>
  </ul>
  <p>Compiled programming languages like C require us to recompile the program each time we change the source code. While the program keeps being simple there&#x27;s no problem in rebuilding the whole program even if we only changed one file. But when we start to have a more complex program, compilation times increase, and recompiling everything just to update few changes is not effective.</p>
  <p>The same way we create the target calculator we can make a target for each of the files that build it.</p>
  <pre>calculator: main.o sum.o sub.o mult.o div.o
      cc -o calculator main.o sum.o sub.o mult.o div.o

main.o: main.c main.h
      cc -c main.c
sum.o: sum.c sum.h
      cc -c sum.c
sub.o: sub.c sub.h
      cc -c sub.c
mult.o: mult.c mult.h
      cc -c main.c
div.o: div.c div.h
      cc -c div.c</pre>
  <p>This method forces us to write function declarations in separated <code>.h</code> header files and definitions in <code>.c</code> files to avoid multiple definitions. But we take the advantage of building only the objects that have modified dependencies.</p>
  <p><code>make</code> checks the timestamp of the files to keep track of modifications. If an object dependency gets a timestamp that is newer than the object&#x27;s timestamp, it&#x27;ll recompile that object when executed.</p>
  <p>We can also create rules for steps that don&#x27;t involve compiling or building the program, such as placing the built program in the correct directory, removing it (the same as uninstalling) or cleaning the compiled objects.</p>
  <pre>clean: 
      rm -f *.o calculator</pre>
  <p>Now instead of manually removing those files when we need a clean build, we can call <code>make clean</code> and the rule will perform the action.</p>
  <p>To make an install rule we can follow the same procedure, just adding the binary as a dependency to the rule:</p>
  <pre>install: calculator
      mkdir  -p /opt/calc
      cp $&lt; /opt/calc/calculator</pre>
  <p>and the uninstall rule is a simple recipe that removes the copied file:</p>
  <pre>uninstall:
      rm -f /opt/calc/calculator</pre>
  <p>The rules that don&#x27;t involve compiling or building a program can get us in trouble if we ever meet the situation where an object is named like them (clean, install or uninstall in this case). To solve this, <code>make</code> has <code>PHONY</code> targets which are just a name for a recipe to be executed when you make an explicit request.</p>
  <pre>.PHONY: clean
clean: 
      rm -f *.o calculator</pre>
  <p>This way we avoid conflicts with other files.</p>
  <p></p>
  <p><strong>— Macros</strong></p>
  <p>When programs start increasing the number of source files and library dependencies, the amount of objects and files to track increases. Luckily for us, <code>make</code> can handle this if we use macros (variables).</p>
  <p>A macro has the following format:</p>
  <pre>name = data</pre>
  <p>where <em>name</em> is an identifier and <em>data</em> is the text that&#x27;ll be substituted each time <code>make</code> sees <code>${name}</code>.</p>
  <p>Some predefined macros are:</p>
  <ul>
    <li><code>CC</code> is used to store the name of the compiler which we want to use (cc, gcc, clang, etc).</li>
  </ul>
  <pre>CC = cc</pre>
  <ul>
    <li><code>CFLAGS</code> is used to list the flags we want the compiler to use.</li>
  </ul>
  <pre>CFLAGS = -c -g -Wall</pre>
  <ul>
    <li><code>LDFLAGS</code> is used to link libraries. Some header files like <code>&lt;math.h&gt;</code> are part of the system and aren&#x27;t locally present in our code, but as any other header file, they contain just declarations and the compiler needs to check for the actual definitions somewhere.</li>
  </ul>
  <pre>LDFLAGS = -lm</pre>
  <p>Similarly we can make a macro for all our source files, dependencies and objects.</p>
  <pre>SRC = main.c sum.c sub.c mult.c div.c
OBJ = $(SRC:.c=.o)</pre>
  <p>We are storing all our source files in the <code>SRC</code> macro, and since the object files share names with the source files, we are transforming the content inside <code>SRC</code> by changing the <code>.c</code> suffix with <code>.o</code> and storing it in the OBJ macro.</p>
  <p>Source files can be huge in number, and manually typing each source file name can end up being tedious and make the line hard to work with. We can take the advantage of wildcards:</p>
  <pre>SRC = $(wildcard *.c)</pre>
  <p>which will take every <code>.c</code> file inside the current directory.</p>
  <p>Note that the value for <code>SRC</code> is encapsulated between brackets and includes the explicit <code>wilcard</code> word. If we just associate <code>src</code> to <code>*.c</code> it will store the literal set of characters and won&#x27;t behave as expected.</p>
  <p>Source files may happen to be in different directories. In that case we only need to repeat the wildcard process:</p>
  <pre>SRC = $(wildcard src/*.c) $(wildcard src/modules/*.c)</pre>
  <p>Macros don&#x27;t need to be upper case, and can be used arbitrarily to simplify name repetitions like our program&#x27;s name:</p>
  <pre>prog_name = calculator</pre>
  <p>Our Makefile can be transformed in something cleaner:</p>
  <pre>CC = cc
CFLAGS = -c -g -Wall
LDFLAGS = -lm
SRC = $(wildcard *.c)
OBJ = $(SRC:.c=.o)

prog_name = calculator

calculator: ${OBJ}
      ${CC} -o ${prog_name} ${OBJ} ${LDFLAGS}

main.o: main.c main.h
      ${CC} -c main.c
sum.o: sum.c sum.h
      ${CC} -c sum.c
sub.o: sub.c sub.h
      ${CC} -c sub.c
mult.o: mult.c mult.h
      ${CC} -c mult.c
div.o: div.c div.h
      ${CC} -c div.c

.PHONY: clean
clean: 
      rm -f *.o ${prog_name}

.PHONY: install
install: ${prog_name}
      mkdir  -p /opt/calc
      cp $&lt; /opt/calc/calculator

.PHONY: uninstall
uninstall:
      rm -f /opt/calc/calculator</pre>
  <p><code>make</code> can figure out that we want an object file from a source file as it has an implicit rule for updating an object <code>.o</code> file from a correspondingly named <code>.c</code> file using a <code>cc -c</code> command.</p>
  <pre>cc -c main.c -o main.o</pre>
  <p>The source <code>.c</code> file is automatically added to the dependencies, so we can reduce our rule:</p>
  <pre>main.o: main.c main.h
      ${CC} -c main.c</pre>
  <p>letting it appear as:</p>
  <pre>main.o: main.h </pre>
  <p>Chances are that when building a program with <code>make</code> we get an error like this:</p>
  <pre>cannot find file &quot;sum.h&quot;</pre>
  <p>telling us that some required header isn&#x27;t found. We can tell <code>make</code> where to look for prerequisites using the <code>VPATH</code> macro.</p>
  <p>The value of <code>VPATH</code> specifies a list of directories that <code>make</code> should search expecting to find prerequisite files and rule targets that are not in the current directory.</p>
  <pre>VPATH = /inc /modules/inc</pre>
  <p>Note that <code>VPATH</code> will look through the directories list in the order we write them from left to right.</p>
  <p>Another option to look for prerequisites is telling the compile where to look for them using the <code>-I</code> flag which indicates a directory where the requested code should be:</p>
  <pre>-I/src/inc</pre>
  <p>and should be included in the <code>CFLAGS</code> macro.</p>
  <p>We can take our example and clean it with the new shown resources:</p>
  <pre>CC = cc
CFLAGS = -c -g -Wall -I/src/inc
LDFLAGS = -lm
SRC = $(wildcard *.c)
OBJ = $(SRC:.c=.o)

prog_name = calculator

calculator: ${OBJ}
      ${CC} -o ${prog_name} ${OBJ} ${LDFLAGS}

main.o: main.h
sum.o: sum.h
sub.o: sub.h
mult.o: mult.h
div.o: div.h

.PHONY: clean
clean: 
      rm -f *.o ${prog_name}

.PHONY: install
install: ${prog_name}
      mkdir  -p /opt/calc
      cp $&lt; /opt/calc/calculator

.PHONY: uninstall
uninstall:
      rm -f /opt/calc/calculator</pre>
  <p>Now we only need to save the file and execute <code>make</code> calling the desired command. To build the calculator program it&#x27;d be:</p>
  <pre>$ make calculator</pre>
  <p></p>
  <p><strong>— Comments</strong></p>
  <p>Comments are pretty much self explanatory. They are lines of text that as in programming languages, do nothing but provide useful information or reminders.</p>
  <p>We can place comments around our Makefile by using the hastag <code>#</code> symbol. Anything after a <code>#</code> will be ignored.</p>
  <pre># An example comment</pre>
  <h4></h4>
  <p></p>
  <h2>Summing up</h2>
  <p>In addition to compiling and building our own C/C++ code, working inside a BSD system involves being working close with its source code, and most of the times we have to compile and build packages from ports. That process works the same way so you can now start tweaking and inspecting source Makefiles each time you need to change or install a program. It&#x27;ll grant you access to custom install instructions specific for your machine.</p>
  <p>We can do more things with <code>make</code> like building install menus, compiling libraries and including Makefiles inside other Makefiles. All those topics need a dedicated article for each of them.</p>
  <p>There&#x27;s an <a href="https://www.gnu.org/software/make/manual/make.pdf" target="_blank">official manual</a> for GNU Make that you can read for advanced knowledge in the tool.</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@unixworks/command-line-git-quick-guide</guid><link>https://teletype.in/@unixworks/command-line-git-quick-guide?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/command-line-git-quick-guide?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>Command-line Git | Quick guide</title><pubDate>Tue, 31 Mar 2020 07:14:16 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/6f/f7/6ff77d76-d74f-4a14-ab8d-2d21c2a90fdd.png"></media:content><category>Command-line</category><description><![CDATA[<img src="https://teletype.in/files/2e/ad/2ead1c74-9b6b-415f-b5dc-b5bff9267d8e.png"></img>There are a lot of graphical interfaces to interact with Git with cozy buttons and windows. There's also a fast and powerful alternative: using Git directly from the command line.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/2e/ad/2ead1c74-9b6b-415f-b5dc-b5bff9267d8e.png" width="720" />
  </figure>
  <p>There are a lot of graphical interfaces to interact with Git with cozy buttons and windows. There&#x27;s also a fast and powerful alternative: using Git directly from the command line.</p>
  <blockquote>There are different version control systems like Mercurial, Subversion or Bazaar. We are using Git in this guide.</blockquote>
  <h4></h4>
  <h3>What is Git?</h3>
  <p>Git is a powerful tool to maintain our code projects up to date and keep track of the changes we&#x27;ve made. Using it from the command-line is not that complicated as it could be seen.</p>
  <p>To verify that we have <code>git</code> installed in our system, ask for it&#x27;s version in the command line:</p>
  <pre>$ git --version</pre>
  <p>If the result is similar to <code>git version 0.00.0</code> we are good to go. If not, just grab the package into your system:</p>
  <pre>$ doas pkg install git</pre>
  <p></p>
  <p>— The first thing to perform after installing git is to set a username and an email address since git commit uses that information every single time.</p>
  <pre>$ git config --global user.name &quot;Your Name&quot;
$ git config --global user.email yourname@example.com
</pre>
  <p>The <code>--global</code> flag is useful if we don&#x27;t want to write the credentials each time we want to perform an action inside Git, since Git will always use that information for anything you do on that system.</p>
  <p>In order to override global settings a different name or email address for specific projects, we can run the command without the <code>--global</code> option when working in that project.</p>
  <p></p>
  <p>— To check our actual settings we only need to ask git for them:</p>
  <pre>$ git config --list</pre>
  <h4></h4>
  <h3>Create a repository from a local folder</h3>
  <p>If we have a recently started project that starts growing up and we decide to upload it into a git hosting service we have two options:</p>
  <p>— The first one is to create a repository in the hosting service, initialize it with a <code>README.md</code>, clone it in our local drive, and then move all our project inside the cloned repository. This is pretty much self explanatory.</p>
  <p>— The second one is to tell git to get our actual project file and upload it into an empty repository hosted in our git service.</p>
  <p></p>
  <p>The second option is pretty easy to achieve:</p>
  <ul>
    <li>We need to create an empty repository in our git hosting service (github, gitlab, codeberg...) <strong>without initializing</strong> it.</li>
  </ul>
  <p></p>
  <blockquote>Both names (the project directory name and the git repository name) have to match.</blockquote>
  <p></p>
  <ul>
    <li>In our local repository we have to initialize git.</li>
  </ul>
  <pre>$ git init</pre>
  <ul>
    <li>After initializing git we have to add the content and commit our action</li>
  </ul>
  <pre>$ git add -A
$ git commit -m &quot;commit message&quot;</pre>
  <ul>
    <li>Now we have to remotely add our git origin, which is our newly cloud created repository.</li>
  </ul>
  <pre>$ git remote add origin https://githost.com/username/repository.git</pre>
  <ul>
    <li>The final step is pushing the content to the origin master branch.</li>
  </ul>
  <pre>$ git push -u origin master</pre>
  <p>We&#x27;ll be asked for our git hosting credentials when pushing content.</p>
  <h4></h4>
  <h3>Select what to upload</h3>
  <p>Chances are that we have come files inside our local project that we don&#x27;t want to upload, like temporary files that the system creates or test builds that serve for debugging purposes.</p>
  <p></p>
  <p>— We can create a special file for git that allow us to specify which content to omit when pushing the project to the git service.</p>
  <p>This file needs to be named <code>.gitignore</code> and is a good idea to create it in the top level directory of our repository.</p>
  <p>Git uses <em>globbing patterns</em> to match against file names. We can construct our patterns using a set of symbols:</p>
  <ul>
    <li><code>**</code> A pattern with a double asterisk will match directories anywhere in the repository.</li>
  </ul>
  <pre>**/debug</pre>
  <ul>
    <li><code>*.</code> A patter with an asterisk will match zero or more characters anywhere in the repository.</li>
  </ul>
  <pre>*.o *.log</pre>
  <ul>
    <li><code>!</code> Prepending an exclamation mark to a pattern negates it. A file <em>will not</em> be ignored if it matches a pattern, but <em>also</em> matches a negating pattern defined later in the file.</li>
  </ul>
  <pre>!important.log</pre>
  <h4></h4>
  <h3>Commit and Push our content</h3>
  <p>Once we&#x27;ve made changes locally to our code or project, we need to merge them into the hosted git repository.</p>
  <p></p>
  <p>First we need to tell git to add our changes.</p>
  <pre>$ git add -A</pre>
  <p>The following step is to commit the changes, usually with a comment.</p>
  <pre>$ git commit</pre>
  <p>If we want to make a one line comment we can add the flag <code>-m</code> after commit and write inside double quotes our message:</p>
  <pre>$ git commit -m &quot;Updated foo.c -Changed boo function -Removed trash&quot;</pre>
  <p>In the short run, we are most likely going to remember what we did in that commit. A lot of commit messages are similar to &quot;update code&quot; or &quot;wrote function boo&quot;.</p>
  <p>In the long run, you&#x27;re going to love the time spent writing the commit messages with detail and common sense. Here&#x27;s a short template of how can we structure a commit message:</p>
  <pre>Summarize the change in a few but meaningful words.

Additions:
- what you added

Fixes:
- what it fixes

Changes:
- what it changes


Longer explanation if needed goes here, along with additional notes, or relevant info.
</pre>
  <p></p>
  <p>When typing <code>git commit</code> without the <code>-m</code> flag, the shell will open the default text editor and will ask us to write the commit message.</p>
  <p></p>
  <h4>Pull changes to our local folder</h4>
  <p>Every time we access the repository locally, we need to keep track of the cloud updates, so the work can flow seamlessly.</p>
  <p></p>
  <p>The first thing we have to do before start working inside the local repository, is to check for changes:</p>
  <pre>$ git status</pre>
  <p>if we have changes we can add them to our local repository via git pull:</p>
  <pre>$ git pull</pre>
  <p>Then we can start messing around.</p>
  <p></p>
  <p>— Things went nuts, the content inside the cloud repository had new changes but we were working locally without pulling them first!</p>
  <p>Don&#x27;t worry, there&#x27;s a solution for that. You can stash (hide) your changes, pull and then apply your changes again:</p>
  <pre>$ git stash -u
$ git pull
$ git stash pop </pre>
  <h4></h4>
  <h3>Copy a repository from the web</h3>
  <p>It&#x27;s probably something you already know, but just for refreshing the memory, let&#x27;s take a brief look at it.</p>
  <p>When we want to get a repository from the web, we have an option to zip the entire repository and download it with just one click in the specified icon. This requires to manually unzip it later. But we are trying to use git from the command-line, and extra steps like unzip projects aren&#x27;t part of the goal.</p>
  <p>Every code repository has an <code>https</code> direction we can use to clone using git in the command-line in a very easy and quick way:</p>
  <ul>
    <li>First we need to create (or navigate to) a directory where we would like to store the git project.</li>
    <li>The second step is to copy that url and clone it via git clone:</li>
  </ul>
  <pre>$ git clone https://hosting.site/user/repo-name.git</pre>
  <h4></h4>
  <h3>Git hosting</h3>
  <p>Project tracking in git is great, but we need to keep our repository somewhere. One of the solutions is to create our own server and make our own repository with tools like <a href="https://gogs.io/" target="_blank">Gogs</a>.</p>
  <p>— Another way is to go online and register in a git hosting service. The most popular out there is GitHub. Since Microsoft acquired it, is becoming a social hub where developers share code, follow each others, post updates and sponsor projects they like. There&#x27;s nothing wrong going GitHub. <u>Just be sure to read the terms &amp; conditions carefully</u> if you&#x27;re concern about privacy, and don&#x27;t forget to license your code.</p>
  <p>Luckily there are alternatives to GitHub. All the following services provide options to store your code freely and the ability to decide whether your code is public or private.</p>
  <ul>
    <li><a href="https://gitea.io/en-us/" target="_blank">Gitea</a> is based on Gogs. It&#x27;s offered as a self-hosted service but you can use an already free hosted service at <a href="https://gitea.com/" target="_blank">gitea.com</a></li>
    <li><a href="https://codeberg.org/" target="_blank">Codeberg</a> is great to store open source projects. It&#x27;s based on Gitea.</li>
    <li><a href="https://notabug.org/" target="_blank">NotABug</a> is based on Gogs and offers free code hosting for any project that is distributed under any free license.</li>
    <li><a href="https://about.gitlab.com/" target="_blank">Gitlab</a> is a commercial git service that offers enterprise ready tools and also a free plan where you can store your code and take advantage of a limited set of their tools.</li>
    <li><a href="https://bitbucket.org/" target="_blank">Bitbucket</a> is another commercial git service aimed for teams and big projects. If you work solo or your project is less than five persons, you can opt for a free plan.</li>
  </ul>
  <p></p>
  <h4>Summing up</h4>
  <p>Git is way more complex and powerful than just the content we read here. There&#x27;s no point in copy-pasting complex workflows and custom needs in a guide that pretends to explain core common things and be useful in a hurry .</p>
  <p>If you want to deep dive in Git, there is an official book available to <a href="https://git-scm.com/book/en/v2" target="_blank">read for free online</a> in the official Git site.</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@unixworks/shell-scripts-functionality</guid><link>https://teletype.in/@unixworks/shell-scripts-functionality?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks</link><comments>https://teletype.in/@unixworks/shell-scripts-functionality?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=unixworks#comments</comments><dc:creator>unixworks</dc:creator><title>Shell scripts | Awk &amp; Sed</title><pubDate>Mon, 23 Mar 2020 08:32:46 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/cd/7c/cd7c789f-9c28-45f8-a16c-5e6c996ace7e.png"></media:content><category>Shell Scripting</category><description><![CDATA[<img src="https://teletype.in/files/d8/72/d8722cb5-870e-4027-a05c-7d872a13dd29.png"></img>Shell scripting covers almost every essential need to create automated command-line programs. But what about going beyond the standards and extending our arsenal with some external tools? Let's dive a bit inside awk and sed.]]></description><content:encoded><![CDATA[
  <figure class="m_custom">
    <img src="https://teletype.in/files/d8/72/d8722cb5-870e-4027-a05c-7d872a13dd29.png" width="720" />
  </figure>
  <p>Shell scripting covers almost every essential need to create automated command-line programs. But what about going beyond the standards and extending our arsenal with some external tools? Let&#x27;s dive a bit inside <em>awk</em> and <em>sed</em>.</p>
  <p></p>
  <blockquote>Write programs to handle text streams, because that is a universal interface. — Ken Thompson.</blockquote>
  <p></p>
  <ul>
    <li>Awk is a programming language that let us manipulate structured data.</li>
    <li>Sed is a stream editor to manipulate, filter, and transform text.</li>
  </ul>
  <p>Both of them are stream-oriented; they read input from text files one line at a time and direct the result to the standard output, which means the input file itself is not changed if it&#x27;s not specified to do so.</p>
  <p></p>
  <p>Although their syntax may look cryptic, <em>awk</em> and <em>sed</em> can solve a lot of complex tasks in a single line of code. Combining them with the use of regular expressions we have a Swiss army knife for anyone working with text files. Since we&#x27;re working inside a *nix system this is perfect for us.</p>
  <p>One of the most useful cases with <code>awk</code> and <code>sed</code> is parsing files and generating reports. It&#x27;s a bit complicated to explain both tools without seeing them in action. To work through this post without searching too much for a file to parse, create a file named <code>pieces-list</code> and populate with some text inside:</p>
  <pre>Name= &quot;Capacitor&quot; ID= 3456 quant.= 204 Man.= &quot;Bosch&quot;
Name= &quot;Battery&quot; ID= 2760 quant.= 0 Man.= &quot;Phillips&quot;
Name= &quot;Fan-Frame&quot; ID= 7864 quant.= 131 Man.= &quot;Mitsubishi&quot;
Name= &quot;Bluetooth-Emmiter&quot; ID= 19085, quant.= 184 Man.= &quot;Intel&quot;
Name= &quot;WiFi-Card&quot;, ID= 2941, quant.= 115, Man.= &quot;Intel&quot;
Name= &quot;Fan&quot; ID= 4512 quant.= 98 Man.= &quot;OEM&quot;
</pre>
  <h4></h4>
  <h3>AWK</h3>
  <p>Awk is a full fledged programming language and a powerful file parser. It offers a more general computational model for processing a file, allowing us to replace an entire shell script with an <code>awk</code> single liner.</p>
  <p></p>
  <p>Awk programs consist of a series of rules. Rules generally consist of a pattern and a set of actions.</p>
  <p>When a file is processed, <code>awk</code> reads the file line by line, then it checks to see if the line matches one or more of the patterns in the file and executes the actions associated to the matching pattern, taking the selected line as it&#x27;s input.</p>
  <blockquote>If you&#x27;ve been reading the blog, you&#x27;ll notice that <a href="/Ricing-your-nix-desktop-epIV-01-23"><em>we&#x27;ve used awk previously</em></a> to configure our panel bar.</blockquote>
  <p>— The basic command-line syntax to invoke <code>awk</code> is:</p>
  <pre>$ awk [options] &#x27;pattern {actions}&#x27; inputFile</pre>
  <p></p>
  <p>We&#x27;ve seen how to get an output of a file before, using the <code>cat</code> command.</p>
  <pre>$ cat pieces-list</pre>
  <p>We&#x27;ve also seen how to split data to print only the parts we want using grep.</p>
  <pre>$ cat pieces-list | grep Intel</pre>
  <p></p>
  <p>To start working with <code>awk</code> let&#x27;s use it to print our <code>pieces-list</code> file:</p>
  <pre>$ awk &#x27;{ print }&#x27; pieces-list</pre>
  <p>We should have the same output result after running the program with both <code>cat</code> and the new <code>awk</code> method.</p>
  <p></p>
  <p>With <code>awk</code> we can use patterns too:</p>
  <pre>$ awk &#x27;/Intel/ { print }&#x27; pieces-list</pre>
  <p>patterns are declared between forward slashes.</p>
  <p>This is useful but we still get a complete line containing the pattern we were looking for. One powerful feature of <code>awk</code> is that we can select pieces (named fields) of the line.</p>
  <p>Named fields are represented with a dollar sign and the position number (<code>$N</code>).</p>
  <pre>$ awk &#x27;/Intel/ { print $2 }&#x27; pieces-list</pre>
  <p>Sometimes our pattern has to meet some conditions to be useful for us. We can use boolean statements to perform as patterns too:</p>
  <p>In this example, the condition is that the sixth field has to be greater than one hundred:</p>
  <pre>$ awk &#x27;$6 &gt; 1 { print $2 }&#x27; pieces-list</pre>
  <p>By default field separators are defined by spaces or tabs. If we want to use other pattern as a field separator we have to indicate so, changing the <code>F</code> variable:</p>
  <pre>-F=,</pre>
  <p></p>
  <p>Awk allows us to use some internal functions to perform several actions.</p>
  <ul>
    <li><code>length()</code> allows to get the number of characters for the specified named fields.</li>
  </ul>
  <pre>$ awk &#x27;{ print length($2) }&#x27; pieces-list</pre>
  <ul>
    <li><code>printf</code> formats the output of the specified named fields. We can align items both to the left and to the right using <code>-%</code> and <code>%</code> respectively.</li>
  </ul>
  <pre>$ awk &#x27;$6 &gt; 1 { printf &quot;%-19s&quot;, $2 }&#x27; pieces-list</pre>
  <p></p>
  <p>— We can go further with <code>awk</code> and store all our commands inside a file so it&#x27;s easier to apply the same line of commands for multiple files.</p>
  <p>Awk command files can contain two special patterns:</p>
  <ul>
    <li><code>BEGIN{}</code> is a pattern that is executed only once before running the main commands.</li>
    <li><code>END{}</code> is a pattern that performs actions after all the instructions have been executed. It&#x27;s only executed once.</li>
  </ul>
  <p>Let&#x27;s create a script to store our <code>awk</code> commands:</p>
  <pre>$ touch steps.awk</pre>
  <p>so now we can perform some <code>awk</code> examples into our <code>pieces-list</code> file.</p>
  <p></p>
  <p><strong>— Format output</strong></p>
  <p>Our example <code>pieces-list</code> text is a bit messy. Wouldn&#x27;t it be great to have each field ordered in nice columns?</p>
  <p>First we need to define which character size our columns need. This value is given by our longest value in each field.</p>
  <p>Using the builtin function <code>length($N)</code> we can get those values.</p>
  <p>Let&#x27;s define our main columns with the given values in our <code>BEGIN</code> pattern:</p>
  <pre>BEGIN{ printf &quot;\n%-15s %-22s %-5s %9s\n&quot;, &quot;MANUFACTURER &quot;, &quot;| PIECE NAME &quot;,&quot;| ID &quot;,&quot;|QUANTITY&quot;}</pre>
  <p>In the main body we need a similar line for each one of the products in the list. This time we have to change our printed format in the fields that need to output a number:</p>
  <pre>{printf &quot;%-16s %-22s %6d %9d\n&quot;, $8, $2, $4, $6}</pre>
  <p>In order to execute our stored <code>awk</code> commands, we simply need to indicate <code>awk</code> to read the file as follows:</p>
  <pre>$ awk -f steps.awk pieces-list</pre>
  <p></p>
  <p>Our result should look similar to this:</p>
  <pre>MANUFACTURER   | PIECE NAME          | ID    | QUANTITY
-------------------------------------------------------

&quot;Bosch&quot;         &quot;Capacitor&quot;            3456         204
&quot;Phillips&quot;      &quot;Battery&quot;              2760           0
&quot;Mitsubishi&quot;    &quot;Fan-Frame&quot;            7864         131
&quot;Intel&quot;         &quot;Bluetooth-Emmiter&quot;   19085         184
&quot;Intel&quot;         &quot;WiFi-Card&quot;            2941         115
&quot;OEM&quot;           &quot;Fan&quot;                  4512          98</pre>
  <p>The same we used our messy example file we can use a web server ip traffic, username and password databases... endless possibilities to format.</p>
  <p></p>
  <p><strong>— Process command-line arguments</strong></p>
  <p>We can take input from the user and pass it as a variable to perform actions with our data.</p>
  <p></p>
  <p>Let&#x27;s say we want to ask the user for the product&#x27;s ID and report them the manufacturer&#x27;s name, the product&#x27;s name and it available quantity.</p>
  <p>Create a <code>search.awk</code> script we can perform the following instructions:</p>
  <pre>BEGIN{ print &quot;Search results:\n&quot; }

{if ( id == $4 ) print &quot;Item ID &quot; $4 &quot;\n\t— Manufacturer: &quot; $8 &quot;\n\t— Piece Name: &quot; $2, &quot;\n\t—Stock Amount: &quot; $6}

END{ print &quot;\n---------------------------------\n&quot;}</pre>
  <p>In this case we have created a variable named <code>id</code> to compare against our ID field. To make it work we should run the script addressing a value for the variable:</p>
  <pre>$ awk -v id=3456 -f search.awk pieces-list

Search results:

Item ID 3456
   — Manufacturer: &quot;Bosch&quot;
   — Piece Name: &quot;Capacitor&quot; 
   — Stock Amount: 204

---------------------------------</pre>
  <p></p>
  <p><strong>— Arithmetic and string operators</strong></p>
  <p>As in almost every programming programming language we can perform arithmetic operations inside <code>awk </code>passing named fields as values to operate with:</p>
  <pre>$ awk &#x27;{result += $6} END{printf &quot;total amount of items: %d\n&quot;, result}&#x27; pieces-list 

total amount of items: 732</pre>
  <h4></h4>
  <p></p>
  <h3>SED</h3>
  <p>Sed automates actions that seem a natural extension of interactive text editing. Most of these actions like replacing text, deleting lines, inserting new text, removing words... could be done manually from a text editor.</p>
  <p></p>
  <p>Automating all editing instructions inside one place and execute them in one pass can change hours of manual working in minutes of automated computing.</p>
  <p>The command-line syntax to invoke <code>sed</code> is:</p>
  <pre>$ sed [options] instructions inputFile</pre>
  <p>If we run <code>sed</code> without any of these three parts we will have our file printed into our command line:</p>
  <pre>$ sed &#x27;&#x27; pieces-list</pre>
  <p></p>
  <p>As you can see, the structure of calling <code>sed</code> is similar to calling <code>awk.</code></p>
  <p>This are a few instructions we can combine:</p>
  <ul>
    <li><code>/</code> acts as a <em>separator</em> for numbers or patterns.</li>
  </ul>
  <pre>/patternA/patternB/</pre>
  <p></p>
  <ul>
    <li><code>s</code> <em>replace</em> all the occurrences with a pattern.</li>
  </ul>
  <pre>s/orig/new/ </pre>
  <p>We can indicate where to replace the matching pattern by adding the number of lines before the <code>s</code> character.</p>
  <pre>2s/orig/new/</pre>
  <p>This will replace <code>orig</code> with <code>new</code> in the second line of the file.</p>
  <p></p>
  <ul>
    <li><code>g</code> means <em>everywhere.</em></li>
  </ul>
  <pre>s/orig/new/g</pre>
  <p></p>
  <ul>
    <li><code>w</code> <em>writes</em> the contents of the pattern space into a file.</li>
  </ul>
  <pre>w /path/to/output_file</pre>
  <p></p>
  <ul>
    <li><code>d</code> <em>deletes</em> a specified line <code>Nd</code> where <code>N</code> is the line number. This can be act just the opposite, deleting all non matching input by adding an exclamation point <code>N!d</code>.</li>
  </ul>
  <pre>1d inputfile
1!d inputfile</pre>
  <p></p>
  <p>Running multiple commands with <code>sed</code> can be achieved by separating them inside the single quotes with semi colons <code>;</code> in the command line, or by writing all the commands into a file with the extension <code>.sed</code>.</p>
  <p>Let&#x27;s use some <code>sed</code> power to work inside our <code>pieces-list</code>.</p>
  <p></p>
  <p><strong>— Find and replace</strong></p>
  <pre>$ sed &#x27;s/quant./Quantity/&#x27; pieces-list
$ sed &#x27;s/Man./Manufacturer/&#x27; pieces-list</pre>
  <p>This method will change any <code>origPat</code> match in worklist with <code>newPat</code> that occurs the first time on a line.</p>
  <p>We can replace a pattern with an empty space too by leaving the new pattern blank:</p>
  <pre>$ sed &#x27;s/&quot;//g&#x27; pieces-list</pre>
  <p>Now let&#x27;s combine both instructions at once:</p>
  <pre>$ sed &#x27;s/quant./Quantity/&#x27;; &#x27;s/&quot;//g&#x27; pieces-list</pre>
  <p>so our pieces-list looks like this:</p>
  <pre>Name= Capacitor ID= 3456 Quantity= 204 Manufacturer= Bosch
Name= Battery ID= 2760 Quantity= 0 Manufacturer= Phillips
Name= Fan-Frame ID= 7864 Quantity= 131 Manufacturer= Mitsubishi
Name= Bluetooth-Emmiter ID= 19085, Quantity= 184 Manufacturer= Intel
Name= WiFi-Card, ID= 2941, Quantity= 115, Manufacturer= Intel
Name= Fan ID= 4512 Quantity= 98 Manufacturer= OEM</pre>
  <p></p>
  <p><strong>— Extract and edit</strong></p>
  <p>Another powerful option that we have the ability to perform within <code>sed</code> is to extract information from a file, edit that information in memory and put the new edited data inside another file, without using pipelines.</p>
  <p>Let&#x27;s use a file for storing the instructions for <code>sed</code>.</p>
  <pre>$ vim extract.sed</pre>
  <p>We want to inspect a whole file, and we&#x27;re not going to know the number of lines. We need to search from pattern one through to pattern two:</p>
  <pre>/Name=/,/Man.=/ </pre>
  <p>so we work with the text contained between the start and the end pattern.</p>
  <p>Working on that pattern space we can open a curly brackets section, just like a function so we can store the commands to execute in.</p>
  <pre>/Name=/,/Man.=/ {
s/&quot;//g
s/.*Man.=//g
w manufacturer_list
}</pre>
  <p></p>
  <p>Now we can run <code>sed</code> with this file to create our output file.</p>
  <pre>$ sed -f extract.sed pieces-list

Bosch
Phillips
Mitsubishi
Intel
Intel
OEM</pre>
  <p>Of course all of this can be scripted through pipelines but using just <code>sed</code> we&#x27;ve achieved the same in fewer lines and less time.</p>
  <p></p>
  <p></p>
  <h4>Combining Awk and Sed</h4>
  <p>We&#x27;ve seen that we can take the advantage of clean our text data with <code>sed</code>, and format it with <code>awk</code>. Let&#x27;s go a step further and combine both powers to get a better report.</p>
  <pre>$ sed &#x27;s/&quot;//g&#x27; pieces-list | awk -f steps.awk</pre>
  <p>This way we remove the double quotes from all names and get a clean result.</p>
  <p>We can sort results taking any desired field as an index base. In this case we are going to use the Manufacturer&#x27;s name to perform a sorted list at the items:</p>
  <pre>$ sed &#x27;s/&quot;//g&#x27; pieces-list | awk &#x27;{ print $8 &quot; &quot; $0 }&#x27; | sort | awk -f steps.awk</pre>
  <p>We know what the <code>sed</code> line does. Let&#x27;s analyze the <code>awk</code> one:</p>
  <ol>
    <li>After the first pipe, we call <code>awk</code> to print the eighth value of the list with <code>print $8</code>.</li>
    <li>Next, we add a blank space with <code>&quot; &quot;</code>. This acts as our separator. Since the file is using spaces, we keep the method.</li>
    <li>Lastly we print the whole corresponding line so the next program in the pipe can read the information correctly.</li>
  </ol>
  <p>Our result is going to be something weird. The formatted list maybe looks like this:</p>
  <pre>MANUFACTURER   | PIECE NAME          | ID    | QUANTITY
-------------------------------------------------------

Man.=           Name=                     0           0
Man.=           Name=                     0           0
Man.=           Name=                     0           0
Man.=           Name=                     0           0
Man.=           Name=                     0           0
Man.=           Name=                     0           0

---- End of report. Time: 06:44 | Date: 2020-04-01 ----</pre>
  <p>Since we are adding the eighth field as an index, we have increased the length of the lines and we need to increase the field to print inside our <code>steps.awk</code> file.</p>
  <p>Having to track all this steps individually and in different files is not useful at all, that&#x27;s why writing shell scripts for multiple tasks is so handy (yes, we can call <code>sed</code> and <code>awk</code> from within a shell script!).</p>
  <p></p>
  <p>— Create a script named <code>format-report.sh</code> and open it.</p>
  <ul>
    <li>Remember this is a Shell script so indicate it at the beginning of the file.</li>
  </ul>
  <pre>#!/bin/sh</pre>
  <p></p>
  <ul>
    <li>First we need to order our list based on the manufacturer&#x27;s name.</li>
  </ul>
  <pre>awk &#x27;{print $8&quot; &quot; $0 }&#x27; $* | sort | </pre>
  <p></p>
  <ul>
    <li>We have to add a header for our report using the <code>BEGIN</code> pattern from <code>awk</code>.</li>
  </ul>
  <pre>awk &#x27;BEGIN{ printf &quot;\n%-15s %-22s %-5s %9s\n&quot;, &quot;MANUFACTURER &quot;, &quot;| PIECE NAME &quot;,&quot;| ID &quot;,&quot;| QUANTITY&quot;
print &quot;-------------------------------------------------------\n&quot;}</pre>
  <p></p>
  <ul>
    <li>Next we execute the main loop of <code>awk</code> to print the formatted list.</li>
  </ul>
  <pre>{printf &quot;%-18s %-23s %6d %9d\n&quot;, $9, $3, $5, $7}
</pre>
  <p></p>
  <ul>
    <li>And we can add some condition to check if an item is out of stock.</li>
  </ul>
  <pre>{ if ($7 &lt; 1) printf &quot;\nWarning! Item %d is out of stock.(%s from %s)\n&quot;, $5, $3, $9}</pre>
  <p></p>
  <ul>
    <li>Once the main loop is done we can print a footer for our report using the <code>END</code> pattern, indicating time and date.</li>
  </ul>
  <pre>END {&quot;date +&#x27;%Y-%m-%d&#x27;&quot;|getline d; &quot;date +&#x27;%H:%M&#x27;&quot;|getline t; print &quot;\n---- End of report. Time: &quot; t &quot; | Date: &quot; d &quot; ----&quot;}&#x27; | </pre>
  <p></p>
  <ul>
    <li>Lastly we call <code>sed</code> to get rid of the double quotes that the names inside the list have.</li>
  </ul>
  <pre>sed &#x27;s/&quot;//g&#x27;</pre>
  <p></p>
  <p>In order to run the script, save it, change its permissions to make it executable, and pass the <code>pieces-list</code> as the first argument:</p>
  <pre>$ ./format-report.sh pieces-list</pre>
  <p>We should see something similar to this:</p>
  <pre>MANUFACTURER   | PIECE NAME          | ID |    QUANTITY
-------------------------------------------------------

Bosch           Capacitor              3456         204
Intel           Bluetooth-Emmiter     19085         184
Intel           WiFi-Card              2941         115
Mitsubishi      Fan-Frame              7864         131
OEM             Fan                    4512          98
Phillips        Battery                2760           0

Warning! Item 2760 is out of stock.(Battery from Phillips)

---- End of report. Time: 07:40 | Date: 2020-04-01 ----</pre>
  <h4></h4>
  <h3>Summing up</h3>
  <p>A fundamental part of the power of *nix systems are pipes and the ability to use them to combine programs as building blocks in many ways to create automated workflows.</p>
  <p>We&#x27;ve seen how to manage text data without touching a manual text editor in several ways, so now we can introduce these techniques using <code>awk</code> and <code>sed</code> to our pipe workflow with a new level of flexibility.</p>

]]></content:encoded></item></channel></rss>