MacLochlainns Weblog

Michael McLaughlin's Technical Blog

Site Admin

Archive for the ‘C/C++ Programming’ Category

Quick C How-to add .h

without comments

Somebody wanted a quick example of using a user-defined header file for a constant value. While I think there a lot of examples on the Internet already, here’s quick example.

You can define a header (or global.h) file in the local directory with the value of pi, like this:

1
2
// A global header file for constants.
double pi = 3.1415926535;

Then, you can write a little circle.c program like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include "global.h"
 
int main() {
  int r;
  double area;
 
  // Get the radius.
  printf("Enter a radius in inches: ");
  scanf("%i",&r);
 
  // Calculate the area of a circle.
  area = pi * (r * r);
 
  // Print the radius and circle area.
  printf("Area of a %d inch circle is %lf square inches!\n",r,area);
  return(0); }

The local global.h file is enclosed in double quotes rather than less than and great than symbols. You can compile circle.c like this on Linux, provided both files are in the same directory:

gcc -o circle circle.c

According to the gcc-documentation, the priority for include <> is, on a “standard Unix system”, as follows:

/usr/local/include
libdir/gcc/target/version/include
/usr/target/include
/usr/include

You should chmod the circle file as executable and then you can run it like so:

./circle

You’ll see more or less the following:

Enter a radius in inches: 3
Area of a 3 inch circle is 28.274334 square inches!

As always, I hope the example helps those looking for a starting point.

Written by maclochlainn

January 26th, 2020 at 12:49 am

Posted in C,C/C++ Programming,Linux,Unix

Tagged with

IT Salary Thought

with 2 comments

During the holidays, I check salaries for my students and the IT industry overall. I’m never surprised by the reality, after all salaries pay for return on skills and effort. Here’s my annual look, which some may find unkind but reality is seldom kind.

Before looking at IT salaries, it seems like a good opportunity to first look at the overall job market for Millennials in the United States. AOL provides a great graphic of the median income for Millennials (those born between 1981 and 1997), which is $18,000 to $43,000 a year:

millennial-median-income-state-map

That’s a stark contrast to Forbes’ statistics on the top college baccalaureate degrees. In fact, the top five with the highest salary are between $58 to $67 thousand a year. They are:

  1. Computer Science ………… $66,800
  2. Engineering ………………… $65,000
  3. Mathematics & Statistics … $60,300
  4. Economics ………………….. $58,600
  5. Finance ……………………… $58,000

Computer science, applied computer science, and information technology are probably lumped into the first category. Information systems, exposure without real skills, is a management degree and probably opens positions equivalent to the business degree at $50 thousand a year. More or less, that’s a nine thousand dollar difference between having real skills and being able to talk the game and supervise technical resources. (The 10 hottest IT skills for 2015 are listed in Computerworld.)

There’s no surprise that Ruby, Objective C (iPhone, iPad, Mac OS X), Python, Java, C++ are at the top of the pyramid. Starting salaries in the Salt Lake area are higher for programmers college than they are for other computer science skill sets. In fact, my informal contacts peg them as starting at $70+ thousand. That’s higher than Forbes average for computer science. Here’s a visual on experienced programmers by language:

2015LanguageSalaries

It seems fair to say that a computer science, applied computer science, and information technology degree with an emphasis in real programming skills is the best bet to pay off student loans. However, some will wait for politicians to do that for them, but really that’s quite unlikely, isn’t it?

Reality is always blunt. Reality also seems to frequently differs from what politicians say. After all, politicians pander to audiences, which generally means they say a great deal of nonsense. Nonsense like economics doesn’t matter, everyone should earn the same regardless of their education, skills, or work ethic. Aldous Huxley said it more elegantly when he said, “That all men are equal is a proposition to which, at ordinary times, no sane human being has ever given his assent.”

Written by maclochlainn

December 21st, 2015 at 6:24 pm

C Shared Libraries

without comments

I wrote a shared C library example to demonstrate external procedures in the Oracle Database 11g PL/SQL Programming book. I also reused the same example to demonstrate Oracle’s external procedures in the Oracle Database 12c PL/SQL Advanced Programming Techniques book last year. The example uses a C Shared Library but a PL/SQL wrapper and PL/SQL test case.

One of my students asked me to simplify the unit test case example by writing the complete unit test in the C Progamming Language. The student request seemed like a good idea, and while poking around on the web it appears there’s a strong case for a set of simple shared C library examples. This blog post isn’t meant to replace the C Programming web site and C Programming Tutorial web site, which I recommend as a great reference point.

Like most things, the best place to start is with basics of C programming because some readers may be very new to C programming. I’ll start with basic standalone programs and how to use the gcc compiler before showing you how to use shared C libraries.

The most basic program is a hello.c program that serves as a “Hello World!” program:

1
2
3
4
5
#include <stdio.h>
 
int main() {
  printf("Hello World!\n");
  return(0); }

Assuming you put the C source files in a src subdirectory and the executable files in a bin subdirectory. You compile the program with the gcc program from the parent directory of the src and bin subdirectories, as follows:

gcc -o bin/hello src/hello.c

Then, you execute the hello executable program from the parent directory as follows:

bin/hello

It prints:

Hello World!

You can modify the basic Hello World! program to accept a single input word, like this hello_whom.c program:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
/* The executable main method. */
int main() {
  // Declare a character array to hold an input value.
  char whom[30];
 
  /* Print a question and read a string input. */
  printf("Who are you? ");
  scanf("%s", whom);
  printf("Hello %s!\n", whom);
  return(0); }

You can compile the hello_whom.c program as follows:

gcc -o bin/hello_whom src/hello_whom.c

Then, you execute the hello_whom executable program from the parent directory as follows:

bin/hello_whom
Who are you? Stuart

It prints:

Hello Stuart!

Alternatively, you can modify the hello_whom.c program to accept a stream of text, like the following hello_string.c program:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
/* The executable main method. */
int main() {
  // Declare a character array to hold an input name.
  char phrase[4000];
 
  /* Print a question and read a string input. */
  printf("Hello? ");
  scanf("%[^\n]%*c", phrase);
  printf("Hello %s!\n", phrase);
  return(0); }

The [] is the scan set character. The [^\n] on line 10 defines the input as not a newline with a white space, and the %*c reads the newline character from the input buffer. After you compile the program you can call it like this:

bin/hello_string
Hello? there, it reads like a C++ stream

It would print:

Hello there, it reads like a C++ stream!

These example, like the previous examples, assume the source files are in a src subdirectory and the executable files are in the bin subdirectory. All compilation commands are run from the parent directory of the src and bin subdirectories.

The first example puts everything into a single writingstr.c file. It defines a writestr() function prototype before the main() function and the writestr() function after the main() function.

The code follows below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
 
/* Declare two integer variables. */
char path[255], message[4000];
 
/* Define a prototype for the writestr() function. */
void writestr(char *path, char *message);
 
/* The executable main method. */
int main() {
  printf("Enter file name and message: ");
  scanf("%s %[^\n]%*c", &path, &message);
  printf("File name:    %s\n", path);
  printf("File content: %s\n", message);
  writestr(path, message);
  return(0); }
 
void writestr(char *path, char *message) {
  FILE *file_name;
  file_name = fopen(path,"w");
  fprintf(file_name,"%s\n",message);
  fclose(file_name); }

You can compile the writingstr.c function with the following syntax:

gcc -o bin/writingstr src/writingstr.c

You can run the writingstr executable file with the following syntax:

bin/writingstr
Enter file name and message: /home/student/Code/c/test.txt A string for a file.
File name:    /home/student/Code/c/test.txt
File content: A string for a file.

You’ll find a test.txt file written to the /home/student/Code/C directory. The file contains only the single sentence fragment entered above.

Now, let’s create a writestr.h header file, a writestr.c shared object file, and a main.c testing file. You should note a pattern between the self-contained code and the approach for using shared libraries. The prototype of the writestr() function becomes the definition of the writestr.h file, and the implementation of the writestr() function becomes the writestr.so shared library.

The main.c file contains the only the main() function from the writingstr.c file. The main() function uses the standard scanf() function to read a fully qualified file name (also known as a path) as a string and then a text stream for the content of the file.

You define the writestr.h header file as:

1
2
3
4
5
6
#ifndef writestr_h__
#define writestr_h__
 
extern void writestr(char *path, char *message);
 
#endif

You define the writestr.c shared library, which differs from the example in the book. The difference is the #include statement of the writestr.h header file. The source code follows:

1
2
3
4
5
6
7
8
#include <stdio.h>
#include "writestr.h"
 
void writestr(char *path, char *message) {
  FILE *file_name;
  file_name = fopen(path,"w");
  fprintf(file_name,"%s\n",message);
  fclose(file_name); }

You define the main.c testing program as:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include "writestr.h"
 
/* Declare two integer variables. */
char path[255], message[4000];
 
/* The executable main method. */
int main() {
  printf("Enter file name and message: ");
  scanf("%s %[^\n]%*c", &path, &message);
  writestr(path, message);
  return(0); }

Before you begin the process to compile these, you should create an environment file that sets the $LD_LIBRARY_PATH environment variable or add it to your .bashrc file. You should point the $LD_LIBRARY_PATH variable to the directory where you’ve put your shared libraries.

# Set the LD_LIBRARY_PATH environment variable.
export LD_LIBRARY_PATH=/home/student/Code/c/trylib/libfile

With programs defined, you need to first compile the writestr.c shared library first. You use the following syntax from the parent directory of the src and bin subdirectories.

gcc -shared -fPIC -o bin/writestr.so src/writestr.c

If you haven’t set the $LD_LIBRARY_PATH, you may raise an exception. There’s also an alternative to setting the $LD_LIBRARY_PATH before you call the gcc executable. You can use the -L option set the $LD_LIBRARY_PATH for a given all to the gcc executable, like:

gcc -L /home/student/Code/c/trylib/libfile -shared -fPIC -o bin/writestr.so src/writestr.c

Then, you compile the main.c program. You must put the writestr.so shared library before you designate the main target object and main.c source files, like this:

gcc bin/writestr.so -o bin/main src/main.c

Now, you can perform a C-only unit test case by calling the main executable. However, you must have set the $LD_LIBRARY_PATH environment variable at runtime too. You see the following reply to the “Enter file name and message” question when you run the main program unit:

bin/main
Enter file name and message: /home/student/Code/c/trylib/libfile/test.txt A long native string is the second input to this C program.

You can now see that the a new test.txt file has been written to the target directory, and that it contains the following string:

A long native string is the second input to this C program.

As always, I hope this helps those you want to write shared libraries in the C programming language.

Written by maclochlainn

May 7th, 2015 at 1:46 am

Ruby Thin Web Server

without comments

Somebody suggested that I try out thin, “A fast and very simple Ruby web server.” So, I thought it might be interesting to test, and a simplification over Rails to demonstrate an small Ruby MVC pattern.

Installing thin seemed straight forward as a gem installation, like

gem install thin

The initial install didn’t work out of the box because I’d neglected to install the gcc-c++ library. It raised the following errors:

Fetching: eventmachine-1.0.7.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing thin:
	ERROR: Failed to build gem native extension.
 
    /usr/bin/ruby extconf.rb
checking for main() in -lssl... no
checking for rb_trap_immediate in ruby.h,rubysig.h... no
checking for rb_thread_blocking_region()... yes
checking for ruby/thread.h... yes
checking for rb_thread_call_without_gvl() in ruby/thread.h... yes
checking for inotify_init() in sys/inotify.h... yes
checking for writev() in sys/uio.h... yes
checking for rb_thread_fd_select()... yes
checking for rb_fdset_t in ruby/intern.h... yes
checking for rb_wait_for_single_fd()... yes
checking for rb_enable_interrupt()... no
checking for rb_time_new()... yes
checking for sys/event.h... no
checking for epoll_create() in sys/epoll.h... yes
checking for clock_gettime()... yes
checking for CLOCK_MONOTONIC_RAW in time.h... yes
checking for CLOCK_MONOTONIC in time.h... yes
creating Makefile
 
make "DESTDIR="
g++ -I. -I/usr/include -I/usr/include/ruby/backward -I/usr/include -I. -DWITHOUT_SSL -DBUILD_FOR_RUBY -DHAVE_RB_THREAD_BLOCKING_REGION -DHAVE_TBR -DHAVE_RUBY_THREAD_H -DHAVE_RB_THREAD_CALL_WITHOUT_GVL -DHAVE_RB_THREAD_CALL_WITHOUT_GVL -DHAVE_INOTIFY_INIT -DHAVE_INOTIFY -DHAVE_WRITEV -DHAVE_WRITEV -DHAVE_RB_THREAD_FD_SELECT -DHAVE_RB_THREAD_FD_SELECT -DHAVE_TYPE_RB_FDSET_T -DHAVE_RB_FDSET_T -DHAVE_RB_WAIT_FOR_SINGLE_FD -DHAVE_RB_TIME_NEW -DOS_UNIX -DHAVE_EPOLL_CREATE -DHAVE_EPOLL -DHAVE_CLOCK_GETTIME -DHAVE_CONST_CLOCK_MONOTONIC_RAW -DHAVE_CONST_CLOCK_MONOTONIC    -fPIC -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -mtune=generic -m64 -o ed.o -c ed.cpp
make: g++: Command not found
make: *** [ed.o] Error 127
 
 
Gem files will remain installed in /usr/local/share/gems/gems/eventmachine-1.0.7 for inspection.
Results logged to /usr/local/share/gems/gems/eventmachine-1.0.7/ext/gem_make.out

Naturally, I installed the gcc-c++ library with the yum utility, like this:

yum list gcc-c++

It displayed the following log output:

Loaded plugins: langpacks, refresh-packagekit
mysql-connectors-community                                  | 2.5 kB  00:00     
mysql-tools-community                                       | 2.5 kB  00:00     
mysql56-community                                           | 2.5 kB  00:00     
pgdg93                                                      | 3.6 kB  00:00     
updates/20/x86_64/metalink                                  |  14 kB  00:00     
updates                                                     | 4.9 kB  00:00     
updates/20/x86_64/primary_db                                |  13 MB  00:04     
(1/2): updates/20/x86_64/updateinfo                         | 1.9 MB  00:02     
(2/2): updates/20/x86_64/pkgtags                            | 1.4 MB  00:00     
Resolving Dependencies
--> Running transaction check
---> Package gcc-c++.x86_64 0:4.8.3-7.fc20 will be installed
--> Processing Dependency: libstdc++-devel = 4.8.3-7.fc20 for package: gcc-c++-4.8.3-7.fc20.x86_64
--> Running transaction check
---> Package libstdc++-devel.x86_64 0:4.8.3-7.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package                Arch          Version              Repository      Size
================================================================================
Installing:
 gcc-c++                x86_64        4.8.3-7.fc20         updates        7.2 M
Installing for dependencies:
 libstdc++-devel        x86_64        4.8.3-7.fc20         updates        1.5 M
 
Transaction Summary
================================================================================
Install  1 Package (+1 Dependent package)
 
Total download size: 8.7 M
Installed size: 25 M
Downloading packages:
(1/2): gcc-c++-4.8.3-7.fc20.x86_64.rpm                      | 7.2 MB  00:05     
(2/2): libstdc++-devel-4.8.3-7.fc20.x86_64.rpm              | 1.5 MB  00:01     
--------------------------------------------------------------------------------
Total                                              1.3 MB/s | 8.7 MB  00:06     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : libstdc++-devel-4.8.3-7.fc20.x86_64                          1/2 
  Installing : gcc-c++-4.8.3-7.fc20.x86_64                                  2/2 
  Verifying  : gcc-c++-4.8.3-7.fc20.x86_64                                  1/2 
  Verifying  : libstdc++-devel-4.8.3-7.fc20.x86_64                          2/2 
 
Installed:
  gcc-c++.x86_64 0:4.8.3-7.fc20                                                 
 
Dependency Installed:
  libstdc++-devel.x86_64 0:4.8.3-7.fc20                                         
 
Complete!

After installing the gcc-c++ libraries, I reran the gem utility to install the thin utility. It created three Ruby Gems: eventmachine-1.0.7, daemons-1.2.2.gem, and thin-1.6.3.gem, as shown:

Building native extensions.  This could take a while...
Successfully installed eventmachine-1.0.7
Fetching: daemons-1.2.2.gem (100%)
Successfully installed daemons-1.2.2
Fetching: thin-1.6.3.gem (100%)
Building native extensions.  This could take a while...
Successfully installed thin-1.6.3
Parsing documentation for daemons-1.2.2
Installing ri documentation for daemons-1.2.2
Parsing documentation for eventmachine-1.0.7
Installing ri documentation for eventmachine-1.0.7
Parsing documentation for thin-1.6.3
Installing ri documentation for thin-1.6.3
Done installing documentation for daemons, eventmachine, thin after 11 seconds
3 gems installed

Having created the Ruby Gems, I followed the thin instruction on the web site, and created the following Ruby web server:

app = proc do |env|
  [
    200,             # Status code
    {                # Response headers
      'Content-Type' => 'text/html',
      'Content-Length' => '12',
    },
    ['Hello World!'] # Response body
  ]
end
 
# You can install Rack middlewares
# to do some crazy stuff like logging,
# filtering, auth or build your own.
use Rack::CommonLogger
 
run app

Then, I tested the Ruby web server with the following command:

thin start -R thin.ru

It displayed the following test server as the result of localhost:3000 URL:

ThinRubyWebServer

As always, I hope this helps those who land on this page.

Written by maclochlainn

April 18th, 2015 at 10:00 pm

Popular Programming Languages

with 6 comments

First of all, Happy New Year!

IEEE Spectrum published a ranking of the most popular programming languages. Computational journalist Nick Diakopoulos wrote the article. While it may surprise some, I wasn’t surprised to find SQL in the top ten.

07dataflow-1403643424680Nick weighted and combined 12 metrics from 10 sources (including IEEE Xplore, Google, and GitHub) to rank the most popular programming languages.

  • Compiled programming languages (Java [#1], C [#2], C++ [#3], C# [#4], Objective-C [#16])
  • Interpreted programming languages (Python [#5], JavaScript [#6], PHP [#7], Ruby [#8], Perl [#11], HTML [#12])
  • Data languages (SQL [#9], MATLAB [#10], R [#13])

I couldn’t resist including Objective-C because it shows how the iPhone, iPad, and Mac OS impact our daily lives. At the same time, Assembly [#15] is actually more popular than Objective-C. Shell [#17] follows Objective-C. While the Visual Basic [#14] programming language still remains very popular.

There are many “why” questions raised by this list of popular programming languages. The “why” from my perspective deals with what are the market drivers for their popularity. The money drivers I see are as follows:

Business Intelligence (BI) software manages most high-level data analysis tools and they’ll continue to get better over time. However, if SQL has shown us anything over 30 years it’s that ultimately we revert to it to solve problems. The conclusion from the reality of BI probably means the programming languages that develop those tools will continue to rise and so will the underlying data languages.

It’s also interesting to note that nine out of ten of the popular programming languages work with databases, like Oracle, MySQL, PostgreSQL, or SQL Server. While JavaScript doesn’t access the database typically, it’s JSON (JavaScript Object Notation) is supported in all the databases.

Written by maclochlainn

January 1st, 2015 at 9:46 pm

Visual Studio Freedom

without comments

Some of my students want to learn to write C++ on a Windows OS. At some point, you simply surrender to the fact that many people prefer the Windows OS as a starting point. Traditionally, I’d recommend the Microsoft Visual Studio as their learning vehicle because it’s free to our students because of our relationship with Microsoft. It’s not free to graduates. When a graduate contacts me I recommend Code::Blocks. Just recently, one ask for more than a recommendation. He wanted instructions. These are the instructions.

Download and Install Code::Blocks

Here are the instructions to install and download Code::Blocks 13.12.

CodeBlocks_01

  1. You can download Download and Install Code::Blocks from the web site. Then, you can install Code::Blocks from download folder.

CodeBlocks_02

  1. You launch the codeblocks-12.12mingw-setup.exe file from the download folder.

CodeBlocks_03

  1. This is the first screen of the Code::Blocks wizard. Click the Next button to continue.

CodeBlocks_04

  1. This is the license agreement. Click the I Agree button to continue.

CodeBlocks_05

  1. This screen shows the components to install. The default has all of them checked. I recommend you keep the default. Click the Next button to continue.

CodeBlocks_06

  1. This screen lets you accept the default install location or to chose another install location. I recommend you keep the default install location. Click the Install button to continue.

CodeBlocks_07

  1. This screen shows you the extracting and deployment of files. Click the Next button to continue.

CodeBlocks_08

  1. This indicates that you’ve installed the product, and it now prompts you to run Code::Blocks programscreen shows you the extracting and deployment of files. Click the Yes button to continue.

CodeBlocks_09

  1. This indicates that the installer detects a GNU GCC Compiler. Click the OK button to continue.

CodeBlocks_10

  1. This acknowledges the completion of the installation. Click the OK button to continue.

CodeBlocks_9a

  1. This dialog tells you the installation has completed. Click the Next button to continue.

CodeBlocks_9b

  1. This dialog completes the installation. Click the Finish button to end the installation.

Configure Code::Blocks

CodeBlocks_11

  1. This is the main menu of Code::Blocks application. You need to click the Create a new project link to continue.

CodeBlocks_12

  1. You should choose a Console application for this example. Double click the Console application icon to continue.

CodeBlocks_13

  1. This dialog launches the Console page. Check the Skip this page next time and then click the Next button to continue.

CodeBlocks_14

  1. This dialog lets you choose whether you want to write a C and C++ program. Click the Next button to continue.

CodeBlocks_15

  1. This dialog lets you choose whether you want to write a C and C++ program. Click the Next button to continue.

CodeBlocks_16

  1. This dialog lets you choose the compiler, debug, and release configurations. Click the Finish button to continue.

Create and run a program in Code::Blocks

CodeBlocks_17

  1. This dialog gives you an empty project. Click the Sources item in the list of the Project tab.

CodeBlocks_18

  1. This dialog adds a main.cpp to the list of the Management console. Click the main.cpp item in the list of the Project tab.

CodeBlocks_19

  1. After clicking the main.cpp item in the Project list, the Code::Blocks IDE generates the content of the main.cpp file. Click the Green Arrow to run (compile and execute) the main.cpp file. The endl is a defined in std, and like a \n line terminator.

CodeBlocks_20

  1. A new file hasn’t been compiled (or built), which means you get the following dialog. It wants to know if you want to build the program. Click the Yes button to build the program.

CodeBlocks_21

  1. After making the file, the Build Log tells you whether the code compiles or not. Click the Run green arrow to run the program.

CodeBlocks_22

  1. After running a Console application, you’ll see the output of your program in a console window like the following. You can close it by clicking the console window’s close button.

CodeBlocks_23

  1. After executing the compiled file, the Build Log tells you whether the program compiles successfully or not.

As always, I hope this helps those who read it. Good luck learning to write C/C++ programs.

Written by maclochlainn

July 5th, 2014 at 1:48 am

Posted in C/C++ Programming

Tagged with