Mandalika's scratchpad [ Work blog @Oracle | Stock Market Notes | My Music Compositions ]

Old Posts: 09.04  10.04  11.04  12.04  01.05  02.05  03.05  04.05  05.05  06.05  07.05  08.05  09.05  10.05  11.05  12.05  01.06  02.06  03.06  04.06  05.06  06.06  07.06  08.06  09.06  10.06  11.06  12.06  01.07  02.07  03.07  04.07  05.07  06.07  08.07  09.07  10.07  11.07  12.07  01.08  02.08  03.08  04.08  05.08  06.08  07.08  08.08  09.08  10.08  11.08  12.08  01.09  02.09  03.09  04.09  05.09  06.09  07.09  08.09  09.09  10.09  11.09  12.09  01.10  02.10  03.10  04.10  05.10  06.10  07.10  08.10  09.10  10.10  11.10  12.10  01.11  02.11  03.11  04.11  05.11  07.11  08.11  09.11  10.11  11.11  12.11  01.12  02.12  03.12  04.12  05.12  06.12  07.12  08.12  09.12  10.12  11.12  12.12  01.13  02.13  03.13  04.13  05.13  06.13  07.13  08.13  09.13  10.13  11.13  12.13  01.14  02.14  03.14  04.14  05.14  06.14  07.14  09.14  10.14  11.14  12.14  01.15  02.15  03.15  04.15  06.15  09.15  12.15  01.16  03.16  04.16  05.16  06.16  07.16  08.16  09.16  12.16  01.17  02.17  03.17  04.17  06.17  07.17  08.17  09.17  10.17 


Saturday, March 26, 2016
 
Programming in C: Few Tidbits #6

[1] Case-insensitive String Comparison

strcasecmp() is the case-insensitive version of strcmp(). When building, make sure to include strings.h (note the plural form).

strncasecmp() is the counterpart to strncmp().

eg.,
..
#include <string.h>
void main(int argc, char** argv)
 ..
        printf("\n\"%s\" and \"%s\" are ", argv[1], argv[2]);
        strcasecmp(argv[1], argv[2]) ? printf(" .. not identical") : printf(" .. identical");
        ..

% ./strcompare next NeXT
"next" and "NeXT" are  .. identical

[2] Initializing a Variable Length Array

As of the length of the variable length array is not known to the compiler at compile time, initializing a variable length automatic array with some default value usually results in a compilation error.

eg.,
% cat -n varlen.c
     1  #include <stdlib.h>
     2
     3  void main(int argc, char** argv) {
     4          int size=atoi(argv[1]);
     5          int array[size] = { 0 };
     6  }
/home/gmandali/C % cc -o varlen varlen.c
"varlen.c", line 5: variable length array can not be initialized: array
cc: acomp failed for varlen.c

One option is to explicitly initialize each element in the array to the desired default value.

eg.,
% cat -n varlen.c
     1  #include <stdlib.h>
     2
     3  void main(int argc, char** argv) {
     4          int size=atoi(argv[1]);
     5          int array[size];
     6          for (int i = 0; i < size; ++i)
     7                  array[i] = 0;
     8  }

% cc -o varlen varlen.c
%

Another option is to rely on memset().

eg.,
% cat -n varlen.c
     1  #include <stdlib.h>
     2  #include <string.h>
     3
     4  void main(int argc, char** argv) {
     5          int size=atoi(argv[1]);
     6          int array[size];
     7          memset(array, 0, sizeof(array));
     8  }

% cc -o varlen varlen.c
%

In this case, sizeof operator evaluates the operand (variable length array).


[3] Check if a Process is Alive

kill() function can be used to send a null signal (signal 0) to check the validity of a process.

eg.,
% cat -n chkproc.c
     1  #include <sys/types.h>
     2  #include <signal.h>
     3  #include <stdlib.h>
     4  #include <stdio.h>
     5
     6  void main(int argc, char **argv) {
     7          pid_t pid = atoi( argv[1] );
     8          int rc = kill( pid, 0 );
     9          if ( !rc ) {
    10                  printf("process with pid ( %d ) is alive", pid);
    11          } else {
    12                  printf("process with pid ( %d ) is not found", pid);
    13          }
    14  }

% cc -o chkproc chkproc.c

% ps
  PID TTY         TIME CMD
19846 pts/25      0:00 ps
28978 pts/25      0:00 bash

% ./chkproc 28978
process with pid ( 28978 ) is alive

% ./chkproc 28979
process with pid ( 28979 ) is not found

pid_t is actually int data type.


[4] Evaluating "( integer )" Expression

This is a simple one but probably an important one to remember. When dealing with an expression that yields an integer or when testing an integer, only a value of zero evaluates to false. Everything else including negative numbers, floating point numbers, characters, strings, .. are evaluated to true. In other words, anything non-zero is true.

eg.,
% cat -n ifexpr.c
     1  #include <stdio.h>
     2  #include <stdlib.h>
     3  #include <ctype.h>
     4
     5  void main(int argc, char **argv) {
     6          printf("\n[ %10d ] : %s",  0, (0) ? "true" : "false" );
     7          printf("\n[ %10d ] : %s",  1, (1) ? "true" : "false" );
     8          printf("\n[ %10d ] : %s",  -2, (-2) ? "true" : "false" );
     9          printf("\n[ %10s ] : %s",  "dummy", ("dummy") ? "true" : "false" );
    10          printf("\n[ %10c ] : %s",  'C', ('C') ? "true" : "false" );
    11          printf("\n[ %10f ] : %s",  2.34, (2.34) ? "true" : "false" );
    12          printf("\n[ %10f ] : %s\n",  0.0000, (0.0000) ? "true" : "false" );
    13  }

% cc -o ifexpr ifexpr.c
% ./ifexpr

[          0 ] : false
[          1 ] : true
[         -2 ] : true
[      dummy ] : true
[          C ] : true
[   2.340000 ] : true
[   0.000000 ] : false

[5] Variable Declaration in a switch { case: } Statement

Let's start with an example that shows compilation failure.

% cat -n varincase.c
     1  #include 
     2
     3  void main() {
     4          switch ( 1 ) {
     5                  case 2:
     6                          int i = 15;
     7                          break;
     8                  default:
     9                          printf("default\n");
    10          }
    11  }

% cc -o varincase varincase.c
"varincase.c", line 6: syntax error before or at: int
"varincase.c", line 7: undefined symbol: i
cc: acomp failed for varincase.c

In this example, identifier i is being declared and initialized in the case label of switch statement. Since no linkage or no static scope was specified, identifier i will have automatic storage duration that is local to the block containing the invocation (switch() { .. }, that is).

However the problem with this code is that case <expression> and default are labels and the controlling expression in switch statement causes the control to jump to appropriate label. In the example, when the control is transferred to default label, it enters the scope of identifier i without initializing it [as it bypasses the case where the identifier is being declared and initialized], which is not permitted. Therefore the fix is to declare the identifier (if at all needed) in its own compound statement so the scope is limited to that compound statement. (A compond statement is a block of code.)

Adding curly braces around case 2: statements will make the code compile and run as shown below.

% cat -n varincase.c
     1  #include <stdio.h>
     2
     3  void main() {
     4          switch ( 1 ) {
     5                  case 2:
     6                  {
     7                          int i = 15;
     8                          break;
     9                  }
    10                  default:
    11                          printf("default\n");
    12          }
    13  }

% cc -o varincase varincase.c

% ./varincase
default


(Stacked Paper CSS Theme Credit: Chris McLeod)

Labels:





2004-2017 

This page is powered by Blogger. Isn't yours?