CHAPTER 2: PROGRAMMING TOPICS
2.1 Compiling in Microsoft Visual C++ 1.5 in Windows
2.2 Necessary Topics in C++
2.3 Class, Function and Objects in C++ (CLASS.CPP)
2.4 Routine to Perform Complex Arithmetic

2.5 Utility Program Lister (LISTER.C)

Only topics that are a little bit hard to understand are included here. They are presented with code snippets, in compact form. The reader will have to read between the lines.

 

2.1 Compiling in Microsoft Visual C++ 1.5 in Windows 3.1

We can use even old C programs in this new environment. We utilize Windows Programming only for large software implementation . The procedure for compiling will be,
1. Open the MSVC by clicking its icon.
2. Using file open click the filename.c.
3. In projects click compile or build.
4. If the compilation and linking is successful, you can now click the execute.

2.2 Necessary Topics in C/C++

2.2.0 Pointer
int p integer
int *p pointer to integer
int *p[3] array of 3 pointers to integer
int (*p)[3] pointer to an array of 3 integers (?)
int *p() function returning a pointer to an integer
int (*p)() pointer to function returning an integer

2.2.1 String Manipulation

char s[255];
int i;
for (i=0;s[i]!='\0';i++); \0=null character=ASCII 0
\\...after the loop, i=length of string
Although C appends '\0' automatically, it is the responsibility of the programmer.
 
char alphabet[27],letter;
int index;
for (index=0,letter='A';letter<='Z';index++,letter++)
   alphabet[index]=letter;
alphabet[index]='\0';
printf("%s\n",alphabet);  automatic ends to '\0'

2.2.2 Strings as Parameters
 
char strvar[20];
count=string_length(strvar);
\\...
void string_length(char str[])  ---str[] has no array bound
{
\\...
}
or you may use
void string_length(char* str)


2.2.3 Minimizing Source Code
for (i=0;s1[i]!='\0';i++)
s2[i]=s1[i];
s2[i]='\0'; <---affix null
This can be shortened to
for (i=0;(s2[i]=s1[i])!='\0';++i); <--semi-colon required
When s2[i]='\0' the loop terminates and null has been assigned to s2[]
already. In C, the boolean FALSE=0. The code can be shortened further to
for (i=0; (s2[i]=s1[i]); ++i);
The loop terminates if the statement (s2[i]=s1[i])=0
Notes:
1. Is speed more important than reliability?
2. Is the code as simple as possible?
3. Does the code maintain readability?
2.2.4 Case Manipulation
 
  "a"  ASCII code 97 =  0  1  1  0  0  0  0  1
  "A"  ASCII code 65 =  0  1  0  0  0  0  0  1
                      128 64 32 16  8  4  2  1
To Lower Case
   "A"|32="a"                  |-bitwise or      The 3 bit operators
   0100 0001 "A"               &-bitwise and
or 0010 0000  32               ~-compliment
   ------------
   0110 0001  "a"

To Upper Case              32=  0010 0000     The value 32
"a"&~32="A"               ~32=  1101 1111     after the compliment
   a= 0110 0001
 ~32= 1101 1111   &
   ---------------
   A= 0100 0001  The result after performing &(~32) on "a".
                 Compliment of 32 is performed first, then bitwise AND.
void str_to_uppercase(char s[])
{int i;
 for (i=0;s[i];i++)   --loop terminates when s[i]='\0'
 if (s[i]>='a'&&s[i]<= 'z') s[i]=s[i]&~32;
}                           s[i]&=~32   <--compact

void str_to_lowercase (char s[])
{int i;
 for (i=0;s[i];i++)
  if (s[i]>='A'&&s[i]<='Z') s[i]=s[i]|32;
}                           s[i]|=32;  <--compact

2.2.5 White Space
blank ASCII 32 'b'
tab ASCII 9 '\t'

2.2.6 String Comparison
 
for (i=0;s1[i]==s2[i];++i)
  if(s1[i])=='\0')
{printf("Equal strings\n");
 ...}
exits the loop when 1. s1[i]!=s2[i]
                    2. s1[i]='\0'

With Ignore Case, AAA=aaa

int equal_strings(char s1[], char s2[])
{int i;
 char a,b;
 for (i=0; s1[i]&&s2[i];i++) <-operator AND,loop stops if 
   if (s1[i]!=s2[i])           s1[i]='\0' and/or s2[i]='\0'
     {a=(s1[i]>='a'&&s1[i]<= 'z')? s1[i] &= ~32: s1[i];
         TRUE if lowercase         to_upper_case
      b=(s2[i]>='a'&&s2[i]<='z')? s2[i] &= ~32: s2[i];
      if (a!=b) return 0;  <--unequal string
     }
After the for-loop  s1[i]='\0' and/or s2[i]='\0'   

if(s1[i]||s2[i]) return 0;  <--unequal string
       else return 1;     <--equal string 

|| - must be operator XOR
Must be equal in string length

2.2.7 Pointer Manipulation
int a=5; &a = address of a
pointer - is a variable that contains memory address
int *int_pointer,b
int_pointer=&b
b=*int_pointer use (*) to get the value
---------------------------
int i,*iptr;
iptr=&i
*iptr=5; <-- results to i=5
2.2.8 Call by Value
main ()
{ int a=5, b=10;
some_function(a,b);
printf("main a=%d b=%d\n",a,b);
}
some_function(int a,int b)
{printf("somef a=%d b=%d\n",a,b);
a=9;b=11;
printf("somef a=%d b=%d\n",a,b);
}
result: somef a=5 b=10
somef a=9 b=11
main a=5 b=10 <--unchanged

2.2.9 Call by Address
main ()
{int a,b;
initialize(&a,&b)
}
initialize(int *a, int *b)
{*a=1;
*b=2;
}

Passing an array address, Reading input file
The line data can be;
0 1 0.01 0.01
2 3 0.084 0.037
99 0 0 0
where it is called free-format. Separation between data is a comma
or several white spaces. The code looks like;
 
#include 
int kp[10],kq[10]  etc  nl=0;
float x1[10],x0[10];
void main (void)
{file=fopen("filename.ext", "r");
 while (1)     <--infinite loop
   {nl++;
    fscanf(file,"%d %d %f %f",&kp[nl],&kq[nl],&x1[nl],&x0[nl]);
    if (kp[nl]==99) break; <--exit the while block
    etc...
   }    <--while block
}
kp <--means address of kp[0]
Since array and pointers are synonymous
kp+nl, kq+nl,x1+nl,x0+nl is equivalent to --> &kp[nl] etc..


The compiler takes care that nl*2 bytes for integers and nl*4
for float in kp+nl, x1+nl (which address to use).
&(kp+nl) = is error in C because kp is already an address.

2.2.10 Pointer Schemes
(*a)++ =post-increment its value
while (*a++) =the value is used in the while loop,
then increment the address.
++(*a) or ++*a =get the value then increment that value
*++a =increment address, then get its value

2.2.11 Pointers and Strings
char s[20];
show_string(s); <--passes &s[0]
\\...
void show_string(char *r)
{while (*r) printf("%c",*r++)
-------
void string_length(char *s)
{int len=0;
while (*s++) len++; for (len=0;*s;len++,s++);
return (len);
}
2.2.12 Ascii To int
"value" is the integer result from the string str. At line_4, the char pointer str moves to a non-blank character. That first character can be a + or - sign. Line_6 moves the pointer after that +/- and sign gets -1 or +1. Line_7 loops until the terminating value=0 is reached and checks if that character is ascii 0 to 9. If it is a different character, returns (-1), otherwise, the value is moved to "tens" position and adds the integer equivalent by subtracting the ascii position of zero=48. At line_11, its value is multiplied by the sign and normally returns (0). So the returned value of (-1) means an error code.
 
1.  void ascii_to_int(char *str,int *value)
2.   {int sign=1;  //-1 if negative
3.    *value=0;
4.    while(*str==32) str++;          //blank=32, skip leading blanks
5.    if (*str=='-' || *str=='+')
6.        sign=(*str++=='-')? -1: 1;
7.    while (*str)       <-end of string is *str='\0'
8.       if ( (*str>='0')&& (*str<='9'))
9.         *value=(*value*10) + (*str++ - 48);  //'0'= ASCII 48
10.       else return (-1);              //invalid character
11.   *value *=sign;
12.   return (0);
13.  }

2.2.13 Passing Address and Reference to Function Calls
Passing by reference is neater because your code seems ordinary. Both situation gets the passed variables modified upon return. Without this "*" in line_1 and "&" in line_9 the said function is passed by "value". Passed by "value" will not alter the variables upon return.
 
Passing by Address
1.  void swap(int *a, int *b)
2.  {int temp;
3.    temp=*a; *a=*b; *b=temp;
4.  }
5.  void main()
6.  {int x=2,y=3;
7.   swap(&x,&y);   //<--passing address
8.  }

Passing by Reference
9.  void swap(int &a,int &b)  //<--passing an alias
10.  {int temp;
11.    temp=a; a=b; b=temp;    //no need for pointer *
12.  }
13.  void main()
14.  {int x=2,y=3;
15.   swap(a,b);
16.  }

2.2.14 Array of Pointers
<<2.3.0 Declaring Structure in C
A C++ class declaration is an outgrowth of the C structure declaration. In C:
struct Point <--Point is a structure.
{int x,y;}
...

struct Point ul,ur; <--declaring a data type. ul,ur are instance of Point.
ul.x +=ur.x; <--accessing the member of the structure
--------
typedef struct
{int x,y;} Point;
...
Point ul,ur={0,0}; <--no need for structto declare a data type. ul,ur correspond to C++ objects
Point *m;
ul.x+=m->x; <-- accessing a member of a pointer;

2.3.1 Declaring a Class
Files must have an extension name "cpp". A file with *.c that contains classes will not compile.
Class visibility uses private, public, protected keywords to variables sometimes called "members" and functions sometimes called "methods".

2.3.2 Scope Resolution Operator ::
The scope resolution operator has the highest precedence.
 
int N,count=0;
void main(void)
{
//
}

void how_many(float w[], float x, int& count)
{for (int i=0; i< N; i++)
   count+=(w[i]==x);
 ++::count;         //keeps track of calls
}

2.3.3 static Member
Data members can be declared with storage class modifier static. The variable declared static is stored uniquely in one place and is shared by all objects declared to that class. Methods can be declared with static modifier also.

2.3.4 A Friend Function
The keyword friend is a function specifier. It gives a non member function access to the private members of a class. One reason for using friend functions is that some functions need access to more than one class. If all member functions of one class are friend functions of a second class, this can be specified by writing friend class classname.
 
class one
{friend void function1();   //friend function
 int function2();           //member function
 int function3();
 float function4(); 
 . . .
};

class two
{. . .
 friend int one::function2();  //function of class one with
 . . .                         //access to variables of class two
}

class three
{. . .
 friend class one;       //all member functions of class one
 . . .                   //have access
}

void function1()        //has access to variables of class one
{
. . .
}

2.3.4 A Friend of 2 Classes
Consider multiplying a matrix by a vector. A matrix is a class and a vector is another class. The resulting product is a vector returned by the friend function.
 
class matrix;  //forward reference

class vector
{private:
 float p[10];
 int size;
 friend vector multiply(const vector& v, const matrix& m);
 public:
  . . .
};

class matrix
{float b[10][10];
 int row, column;
 friend vector multiply(const vector& v, const matrix& m);
 public:
 . . .
}

vector multiply(const vector& v, const matrix& m)
{int i,j;
 vector answer;
 if (v.size != m.column) exit(1);  //not compatible for multiplication
 for (i=0; i< m.row; i++)
   {answer.p[i]=0.0;      //initialize the totalizer
    for (j=0; j< m.column; j++)
       answer.p[i]+=m.b[i][j]*v.p[j];
   }
 return (answer);
}   

2.4 Complex Arithmetic in C++ using Friend Functions

Output of the program shown below.


Some Code Explanation
Although there is no word "private", variables real and imag are private. Lines _6 and _7 are two constructors. The first one refers to when you declare like "complex z;" without an initialization. The second constructor has an initialization like "complex a(2.5,3.0);" In line_12 and _13 use or no use of "const" and "&" does not make any difference. "const" is just a safeguard that the variable will not get altered inside the function. The "&" simply means that you are passing a reference. Any modification of the variable will be reflected back. It is a neat way compared to passing a pointer. "friend" is an access modifier to functions that are not members of the class. So the functions add() and myprint() are not members of class complex. They can access a.real because they are permitted with the "friend" prefix. In the main program, you may include "float x;" then later "x=a.real;". This will cause an error because a.real is a private data. It can be permitted if you defined real to be "public". To access "private" variables, you need the member getReal(), as "x=a.getReal();".

Without the use of overloaded operator in line_13, you may add complex numbers using a call like in line_56 "d=add(a,b);" instead of a neater call like "d=a+b;". You are allowed a call in line_63 "d=operator+(a,b);" The overloaded operator is a "friend" and not a member function because the said function does not operate on the (*this) object. This particular friend function "friend complex operator +(.." can be made a member function but the concept is trickier. The declaration as a member inside the class is:
1. complex operator +(const complex& b);
The definition will be;
2. complex complex::operator +(const complex& b)
3. {
4. real+=b.real;
5. imag+=b.imag;
6. return *this;
7.}
and you may use "d=a+b;" or
8. d=a.operator+(b);
This is trickier because the variable a is not included in line_1. Never specify the first argument when writing overloaded operator member functions because the first argument of all member functions is the *this pointer. The *this pointer is always passed to member functions no matter what else you pass to the member functions.

Friend functions are given access to the private variables using the dot operator. It can not access without the use of the dot operator. It can not access the (*this) too. Can the member function "complex operator +=(complex& c);" be made a friend function? The answer is no, because this function access the left side of "d+=a;", the "d" as the "this". A friend function can not access the "this". You may however use friend complex operator +=(complex a, complex b) and return another complex, but who will receive the returned value? In "d+=a;", the "d" becomes the first argument and "a" becomes the second. No one will received the returned argument.

Can we make the friend function "friend complex add(complex a, complex b);" as a member instead? Yes, but the code will be different.
 
complex complex::add(complex a, complex b)
{//complex c;
 real=a.real + b.real;
 imag=a.imag + b.imag;
 return *this;       <--use of this will modify d.real ,d.imag in the  
}                        d.add(a,b)  call

and the call will be

d.add(a,b);  instead of
d=add(a,b);

2.5 Using Overloaded Operators, completing the Class Complex

Output of the program shown below.


As before, the default constructor has a declaration as "Complex z;" and line_15 sets its variables to zero. Lines_19 to _22 are methods or member functions. Why not friend functions? All of these operates on the self reference objects defined by the lvalue as the first parameter and returns (*this) which is equated back to the lvalue. Lines_25 to _30 are friend functions where 2 parameters are passed. These functions do not use the (*this) member variable.
Note the meaning of unary operator in location_101, -a; where we could not do this in other programming languages. So in the statement d=-a; will cause a problem if you do not intend to negate a within a itself. The proper way to do this is d=a; -d; And a is unchanged.

2.6 Utility Program Lister.c

This is a small program used to append line numbers on the beginning of the source code. Although this is not part of algorithms development, it will aid in explaining the source code. Shown below is the code with numbering on the left side. This is the result of executing the file itself.

Some Code Explanation:
1. We do not have an error checking in Line_25.
2. In Line_27 our destination output is a fixed filename: "output.txt"
3. The main program will loop on Line_28. Inside the parenthesis is declared a BOOLEAN function. It will return only TRUE=1 or FALSE=0. Loop will stop only when the function returns FALSE.
4. Line_38 and Line_39 are the output of the program. One on the CRT and another on a file to be used later on a word processor.



HOME
CHAPTER ONE: INTRODUCTION
CHAPTER TWO: PROGRAMMING TOPICS
CHAPTER THREE: MATRIX INVERSION ROUTINE
CHAPTER FOUR: STEP-BY-STEP ALGORITHMS
CHAPTER FIVE: DIRECT METHODS IN Ybus FORMATION
CHAPTER SIX: SPARSITY
CHAPTER SEVEN: MATRIX FACTORIZATION AND OPTIMAL ORDERING
CHAPTER EIGHT: SPARSE Zbus FROM FACTORED SPARSE Ybus
CHAPTER NINE: FAULT CALCULATIONS
REFERENCES
i n n o v a t e   o r   s t a g n a t e  
Free Web Hosting