Chapter 5: Pointers and Arrays.

Original C examples from the existing C programming archive. Source text is preserved; these historical examples have not been compiled or tested against a current toolchain.

undcl.c

This declaration exercise constructs C declaration text from a simplified token sequence. It combines names, pointer markers, parentheses and array suffixes, showing how declarator precedence changes the resulting expression. It supports only a small grammar and uses fixed buffers, so malformed or long input is not safely handled as a general parser.

#include<stdio.h>
#include<string.h>
#include<ctype.h>

#define	MAXTOKEN  100
#define BUFSIZE 100

char buf[BUFSIZE];
int bufp=0;

int getint(int *);
int getch(void);
void ungetch(int);

enum { NAME, PARENS, BRACKETS };

void dcl(void);
void dirdcl(void);

int gettoken(void);
int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char out[1000];


int main()
{
  int type;
  char temp[MAXTOKEN];

  while (gettoken() != EOF)
   {
     strcpy(out, token);
     while ((type=gettoken()) != '\n')
       if (type == PARENS || type == BRACKETS)
           strcat(out, token);
       else if (type == '*')
        {
          sprintf(temp, "(*%s)", out);
          strcpy(out, temp);
        }
       else if (type == NAME)
        {
          sprintf(temp, "%s %s", token, out);
          strcpy(out, temp);
        }
       else
         printf("invalid input at %s\n", token);
   }

 return 0;
}


int gettoken(void)
 {
   int c, getch(void);
   void ungetch(int);
   char *p = token;

   while ((c=getch()) == ' ' || c =='\t');
   if (c=='(')
     {
        if ((c=getch()) == ')')
         {
           strcpy(token, "()");
           return tokentype = PARENS;
         }
        else
         {
           ungetch(c);
           return tokentype = '(';
         }
     }
    else if ( c == '[')
     {
       for (*p++ = c; (*p++ = getch()) != ']'; );
       *p='\0';
     return tokentype = BRACKETS;
     }
    else if (isalpha(c))
     {
       for (*p++ = c; isalnum(c=getch()); ) *p++ = c;
       *p='\0';
       ungetch(c);
       return tokentype = NAME;
     }
    else
       return tokentype = c;
 }
  
void dcl(void)
 {
   int ns;

   for(ns = 0; gettoken() == '*'; ) ns++;
   dirdcl();
   while (ns-- > 0) strcat(out, " pointer to");
 }

void dirdcl(void)
 {
   int type;
   
   if (tokentype == '(')
    {
      dcl();
      if (tokentype != ')')
        printf("error: missing )\n");
    }
   else if (tokentype == NAME) 
        strcpy(name, token);
   else
       printf("error: expected name or (dcl)\n");
   
   while ((type=gettoken()) == PARENS || type == BRACKETS)
    if (type == PARENS)
       strcat(out, " function returning");
    else
      {
        strcat(out, " array");
        strcat(out, token);
        strcat(out, " of");
      }
}

int getch(void)
 {
    return (bufp > 0) ? buf[--bufp] : getchar();
 }

void ungetch(int c)
 {
   if (bufp >= BUFSIZE) printf("ungetch: too many characters\n");
   else
     buf[bufp++]=c;
}

array.c

This example initializes an integer array and prints the same elements through array indexing, pointer arithmetic and a moving pointer. The equivalent expressions show how array access relates to dereferencing an offset address. Pointer movement must remain inside the array or at its permitted one-past endpoint.

#include<stdio.h>

int main()

{
  int i,array[10];
  int *pa;

  for(i=0; i < 10; i++)
   array[i]=2*i;

  pa=array;

  for(i=0; i < 10; i++)
   printf(" %d  %d  %d  \n",pa[i],*(array+i),*(pa+i));
  
  pa=array;
  for(i=0; i < 10; i++)
   printf(" %d ",*pa++);
  printf("\n");

return 0;
}

  
 

cmlarg1.c

This echo-style program visits command-line arguments by index, skipping argv[0], and prints spaces between them. The conditional separator avoids an extra trailing space. It demonstrates argc and argv as a count and an array of strings rather than shell parsing or option interpretation.

#include<stdio.h>

int main(int argc, char *argv[])
{
  int i;
  
  for(i=1; i < argc; i++)
   printf("%s%s", argv[i], (i < argc-1) ? " ": "");
   
  printf("\n");
  return 0;
} 

cmlarg2.c

This echo variation decrements the argument count and increments the argv pointer before printing each string. It produces the same kind of joined argument output as the indexed version while illustrating pointer-to-pointer traversal. The original argv position is consumed as the loop progresses.

#include<stdio.h>

int main(int argc, char *argv[])
{
  while ( --argc > 0)
   printf("%s%s", *++argv, (argc > 1) ? " " : "");  
 
  printf("\n");
  return 0;
} 

cmlarg3.c

This third echo variation uses a post-decrement count test and a conditional printf format to select whether a separating space is needed. It illustrates how evaluation order in the loop affects the remaining-argument count. The formats are fixed literals, so argument text is printed through a string placeholder.

#include<stdio.h>

int main(int argc, char *argv[])
{

  while(argc--  > 1)
  printf((argc > 1) ? "%s " : "%s", *++argv); 
  
  printf("\n");
  return 0;
} 

daymonth.c

This calendar example uses separate month-length tables for leap and ordinary years. One function sums preceding months to obtain a day of year; another subtracts month lengths and writes month/day results through pointers. The routines assume valid input ranges and do not validate every date or day-of-year value.

#include<stdio.h>

static char daytab[2][13] =
  {
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 29, 31, 30 ,31, 31, 31, 31, 30, 31, 30, 31},
  };

int day_of_year(int year, int month, int day);
void month_day(int year, int yearday, int *pmonth, int *pday);
char *month_name(int n);

int main()

{
int month=0, day=0;
month_day(2007, 100, &month, &day);
printf("Number of days from Jan 1-2007 to Nov 11 -2007 is : %d\n",day_of_year(2007,11,11));
printf("The month and day of 100 days from Jan 1-2007 is: %s  %d 2007 \n",month_name(month),day);

return 0;
}

int day_of_year(int year, int month, int day)
 {
   int i, leap;

   leap = (year%4==0 && year%100 != 0 || year%400 == 0);

   for(i=1; i < month; i++)
    day += daytab[leap][i];
  
   return day;
}

void month_day(int year, int yearday, int *pmonth, int *pday)
 {
   int i, leap;

   leap = ( year%4==0 && year%100 != 0 || year %400 ==0);
   for(i = 1; yearday > daytab[leap][i]; i++)
     yearday -= daytab[leap][i];
   *pmonth = i;
   *pday = yearday;
 }

char *month_name(int n)
 {
   static char *name[] = 
     {
        "Illegal month", "January", "February", "March", "April", "May", "June", "July",
        "August", "September", "October", "November", "December"
     };

   return (n<1 || n>12) ? name[0] : name[n];
 }

dcl.c

This recursive declaration reader translates a restricted C declarator into a descriptive phrase such as pointer to or function returning. Tokenization distinguishes names, array brackets and parentheses; recursive calls follow nested declarators. It is an educational grammar subset, with fixed buffers and incomplete error recovery rather than a compiler-quality parser.

#include<stdio.h>
#include<string.h>
#include<ctype.h>

#define	MAXTOKEN  100
#define BUFSIZE 100

char buf[BUFSIZE];
int bufp=0;

int getint(int *);
int getch(void);
void ungetch(int);

enum { NAME, PARENS, BRACKETS };

void dcl(void);
void dirdcl(void);

int gettoken(void);
int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char out[1000];


int main()
{
  while (gettoken() != EOF)
   {
     strcpy(datatype, token);
     out[0] = '\0';
     dcl();
     if ( tokentype != '\n') printf("syntax error\n");
     printf("%s: %s %s\n", name, out, datatype);
   }
 return 0;
}


int gettoken(void)
 {
   int c, getch(void);
   void ungetch(int);
   char *p = token;

   while ((c=getch()) == ' ' || c =='\t');
   if (c=='(')
     {
        if ((c=getch()) == ')')
         {
           strcpy(token, "()");
           return tokentype = PARENS;
         }
        else
         {
           ungetch(c);
           return tokentype = '(';
         }
     }
    else if ( c == '[')
     {
       for (*p++ = c; (*p++ = getch()) != ']'; );
       *p='\0';
     return tokentype = BRACKETS;
     }
    else if (isalpha(c))
     {
       for (*p++ = c; isalnum(c=getch()); ) *p++ = c;
       *p='\0';
       ungetch(c);
       return tokentype = NAME;
     }
    else
       return tokentype = c;
 }
  
void dcl(void)
 {
   int ns;

   for(ns = 0; gettoken() == '*'; ) ns++;
   dirdcl();
   while (ns-- > 0) strcat(out, " pointer to");
 }

void dirdcl(void)
 {
   int type;
   
   if (tokentype == '(')
    {
      dcl();
      if (tokentype != ')')
        printf("error: missing )\n");
    }
   else if (tokentype == NAME) 
        strcpy(name, token);
   else
       printf("error: expected name or (dcl)\n");
   
   while ((type=gettoken()) == PARENS || type == BRACKETS)
    if (type == PARENS)
       strcat(out, " function returning");
    else
      {
        strcat(out, " array");
        strcat(out, token);
        strcat(out, " of");
      }
}

int getch(void)
 {
    return (bufp > 0) ? buf[--bufp] : getchar();
 }

void ungetch(int c)
 {
   if (bufp >= BUFSIZE) printf("ungetch: too many characters\n");
   else
     buf[bufp++]=c;
}

find.c

This line filter reads standard input and uses strstr to print lines containing the pattern supplied as its argument. A counter records matches and is returned as the process status, which differs from conventional grep status semantics. The fixed line buffer and historical getline name limit direct portability.

#include<stdio.h>
#include<string.h>

#define  MAXLINE  1000

int getline(char line[], int lim);

int main(int argc, char *argv[])
{
  char line[MAXLINE];
  int found =0;
 
  if (argc != 2)
    printf("Usage: $.\\find pattern\n");
  else
    while (getline(line, MAXLINE) > 0)
     if (strstr(line, argv[1]) != NULL)
      {
        printf("%s", line);
        found++;
      }
  
 return found;
} 

int getline(char s[], int lim)
{
  int c, i;
  i=0;
  while(--lim > 0 && (c=getchar()) != EOF && c!='\n')
    s[i++]=c;
  if(c=='\n')
   s[i++]=c;
  s[i]='\0';
 return i;
}


find2.c

This filter adds -n line numbering and -x inverted selection to the preceding substring search. It scans option characters, tracks the input line number and compares match presence with the inversion flag. These flags belong to this program: its -x does not mean the same thing as GNU grep -x.

/* find -nx pattern */
#include<stdio.h>
#include<string.h>

#define  MAXLINE  1000

int getline(char *line, int max);

int main(int argc, char *argv[])
{
  char line[MAXLINE];
  long lineno = 0;
  int c, except=0, number=0, found=0; 

  while (--argc > 0 && (*++argv)[0]=='-')
   
      while ( c = *++argv[0])
        
           switch(c)
             {
                case 'x':  except=1; break;
                case 'n':  number=1; break;
                default: printf("find: illegal option%c\n",c); argc=0;
                         found=-1; break;
             }

           if (argc != 1) printf("Usage: find -x -n pattern\n");
           else
             while(getline(line, MAXLINE) > 0)
               {
                 lineno++;
                 if ((strstr(line, *argv) != NULL) != except)
                   {
                      if (number)
                        printf("%ld:", lineno);
                      printf("%s", line);
                      found++;
                   }
               }
          
  

    
 return found;

} 

/*int getline(char *line, int max)
{
  int c, i=0;
  
  while(--max > 0 && (c=getchar()) != EOF && c!='\n')
    { *line++=c; i++; }
  if(c=='\n')
   { *line++=c; i++; }
  *line='\0';
 return i;
}

*/

int getline(char s[], int lim)
{
  int c, i;
  i=0;
  while(--lim > 0 && (c=getchar()) != EOF && c!='\n')
    s[i++]=c;
  if(c=='\n')
   s[i++]=c;
  s[i]='\0';
 return i;
}

getint.c

The getint helper skips whitespace, collects signed digits and stores a result through an int pointer, using a pushback buffer for the next token. The preserved main can read beyond the array at termination and prints a value with putchar rather than formatted integer output. Invalid input can also prevent useful progress, so treat this as an annotated exercise.

#include<stdio.h>
#include<ctype.h>

#define SIZE 10
#define BUFSIZE 100

char buf[BUFSIZE];
int bufp=0;

int getint(int *);
int getch(void);
void ungetch(int);

int main()
{
int i,n, array[SIZE];

for(n=0; n < SIZE && getint(&array[n]) != EOF; n++);
putchar(array[n]);
return 0;
}

int getint(int *pn)
{
 int c, sign;
  
 while(isspace(c=getch()));

 if(!isdigit(c) && c!=EOF && c!= '+' && c!='-')
  {
     ungetch(c); 
     return 0;
  }

 sign = (c=='-') ? -1 : 1;
 if(c == '+' || c == '-')  c=getch();

  for(*pn=0; isdigit(c); c=getch())
   *pn = 10 * *pn + (c - '0');
 *pn *= sign;
 if ( c != EOF) ungetch(c);
 return c;
}


int getch(void)
 {
    return (bufp > 0) ? buf[--bufp] : getchar();
 }

void ungetch(int c)
 {
   if (bufp >= BUFSIZE) printf("ungetch: too many characters\n");
   else
     buf[bufp++]=c;
}

pointer.c

This pointer practice takes addresses of scalar, array and character objects and reads their values through dereferencing. It then traverses a zero-terminated name with both an incrementing pointer and array offsets. The key distinction is between a pointer address, the object it points to and the value stored in that object.

#include<stdio.h>

int main()

{
  int x=1, y=2, z[10]={5};
  char name[]={'d','a','n','i','e','l','\0'};
  int *ip;
  char *cp;
  
  ip=&x;
  cp=&name[0];

  printf("\t-----Pointers Practice---------\n");
   printf("x=%d  or x=%d \n",x,*ip);
   printf("char=%c or char=%c \n",name[0], *cp);  
   printf("y before = %d    ",y);
   y=*ip;
   printf("  y after = %d   \n",y);
   ip=&z[0];
   printf("ip = %d\n", *ip);

   printf("Get My Name ...");
  
   while(*cp) putchar(*cp++); 
   printf("\n");
   int counter=0;
   printf("Let us use arrays....");
   while(counter<6) { putchar(*(name+counter)); counter++; }
   printf("\n");
    
return 0;
}

sort.c

This text sorter stores pointers to input lines in a fixed arena, partitions the pointer array with quicksort and prints the reordered strings. Moving pointers avoids copying full strings during each swap. Its line reader, storage limits and handling of a final line without a newline need review before real use.

#include<stdio.h>
#include<string.h>

#define	MAXLINES   5000
#define MAXLEN     1000
#define   ALLOCSIZE  10000

char *lineptr[MAXLINES];
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf;

int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
int getline(char *, int);
char *alloc(int);
void qsort(char *lineptr[], int left, int right);
void swap(char *v[], int i, int j);



int main()
{
  int nlines;

 if(( nlines = readlines(lineptr, MAXLINES)) >= 0)
   {
     qsort(lineptr, 0, nlines-1);
     writelines(lineptr, nlines);
     return 0;
   }
 else
  {
    printf("Erro: input too big to sort\n");
    return 1;
  }
}


int readlines(char *lineptr[], int maxlines)
 {
   int len, nlines;
   char *p, line[MAXLEN];

   nlines = 0;
   
   while (( len = getline(line, MAXLEN)) > 0)
    if((nlines >= maxlines) || (p = alloc(len)) == NULL)
       return -1;
    else
      {
         line[len-1] = '\0';
         strcpy(p, line);
         lineptr[nlines++] = p;
      }
     return nlines;
}

void writelines(char *lineptr[], int nlines)
 {
   int i;
   
   for(i=0; i < nlines; i++)
    printf("%s\n", lineptr[i]);
 }

void qsort(char *v[], int left, int right)
 {
   int i, last;
   
   if(left >= right) return;
   swap(v, left, (left + right)/2);
   last = left;
   for(i = left+1; i <= right; i++)
     if (strcmp(v[i], v[left]) < 0)
       swap(v, ++last, i);
   swap(v, left, last);
   qsort(v, left, last-1);
   qsort(v, last+1, right);
 }

void swap(char *v[], int i, int j)
 {
   char *temp;
   temp = v[i];
   v[i] = v[j];
   v[j] = temp;
 }

char *alloc(int n)
{
  if(allocbuf + ALLOCSIZE - allocp >= n)
   {
      allocp += n;
      return allocp -n;
   }
  else
   return 0;
}

int getline(char s[], int lim)
{
  int c, i;
  i=0;
  while(--lim > 0 && (c=getchar()) != EOF && c!='\n')
    s[i++]=c;
  if(c=='\n')
   s[i++]=c;
  s[i]='\0';
 return i;
}

sort2.c

This sorting variation replaces library string comparison and copying with pointer-based helpers. The overall arena-backed line sorting remains the same. In the preserved pointer-style getline, s has already advanced when an indexed write is used for termination, so the terminator can be written at the wrong location; the custom qsort name also conflicts with the standard interface.

#include<stdio.h>

#define	MAXLINES   5000
#define MAXLEN     1000
#define ALLOCSIZE  10000

char *lineptr[MAXLINES];
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf;

int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
int getline(char *, int);
char *alloc(int);
void qsort(char *lineptr[], int left, int right);
void swap(char *v[], int i, int j);
int strcmp(char *s, char *t);
void strcpyy(char *s, char *t);

int main()
{
  int nlines;

 if(( nlines = readlines(lineptr, MAXLINES)) >= 0)
   {
     qsort(lineptr, 0, nlines-1);
     writelines(lineptr, nlines);
     return 0;
   }
 else
  {
    printf("Erro: input too big to sort\n");
    return 1;
  }
}


int readlines(char *lineptr[], int maxlines)
 {
   int len, nlines;
   char *p, line[MAXLEN];

   nlines = 0;
   
   while (( len = getline(line, MAXLEN)) > 0)
    if((nlines >= maxlines) || (p = alloc(len)) == NULL)
       return -1;
    else
      {
         line[len-1] = '\0';
         strcpyy(p, line);
         lineptr[nlines++] = p;
      }
     return nlines;
}

void writelines(char *lineptr[], int nlines)
 {
   int i;
   
   for(i=0; i < nlines; i++)
    printf("%s\n", lineptr[i]);
 }

void qsort(char *v[], int left, int right)
 {
   int i, last;
   
   if(left >= right) return;
   swap(v, left, (left + right)/2);
   last = left;
   for(i = left+1; i <= right; i++)
     if (strcmp(v[i], v[left]) < 0)
       swap(v, ++last, i);
   swap(v, left, last);
   qsort(v, left, last-1);
   qsort(v, last+1, right);
 }

void swap(char *v[], int i, int j)
 {
   char *temp;
   temp = v[i];
   v[i] = v[j];
   v[j] = temp;
 }

char *alloc(int n)
{
  if(allocbuf + ALLOCSIZE - allocp >= n)
   {
      allocp += n;
      return allocp -n;
   }
  else
   return 0;
}

int getline(char *s, int lim)
{
  int c, i;
  i=0;
  while(--lim > 0 && (c=getchar()) != EOF && c!='\n')
    { *s++=c; i++; }
  if(c=='\n')
   { *s++=c; i++; }
  s[i]='\0';
 return i;
}

int strcmp(char *s, char *t)
 {
   for( ; *s == *t; s++, t++)
    if(*s == '\0') return 0;
   return *s - *t;
 }

void strcpyy(char *s, char *t)
 {
   while(*s++ = *t++);
 }

sort3.c

This sorter chooses lexical or numeric ordering through a function pointer, with -n selecting conversion to numeric values. The partition routine calls the selected comparator instead of hard-coding one ordering. Its historical casts between comparator signatures and unchecked numeric conversion are not a model for type-safe modern generic sorting.

/* find -nx pattern */
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define  MAXLINES  5000
#define  MAXLEN    1000
#define  ALLOCSIZE 10000

static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf;
char *lineptr[MAXLINES];
char *alloc(int n);
int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
void qsort1(void *lineptr[], int left, int right, int (*comp) (void *, void *));
int numcmp(char *, char *);
int getline(char *line, int max);
void swap1(void *v[], int i, int j);

int main(int argc, char *argv[])
{
 int nlines;
 int numeric = 0;

 if (argc > 1 && strcmp(argv[1], "-n") == 0) numeric=1;
 if ((nlines = readlines(lineptr, MAXLINES)) >= 0)
  {
     qsort1((void**) lineptr, 0, nlines-1, (int (*)(void*,void*))(numeric ? numcmp : strcmp));
     writelines(lineptr, nlines);
     return 0;
  }
 else
 {
   printf("Input too big to sort\n");
   return 1;
 }
} 

void qsort1(void *v[], int left, int right, int (*comp) (void *, void *))
 {
   int i, last;
  
  
   if (left >= right) return;
   swap1(v, left, (left+right)/2);
   last = left;
   
   for (i=left+1; i<=right; i++)
    if ((*comp)(v[i], v[left]) < 0) swap1(v, ++last, i);
   swap1(v, left, last); 
   qsort1(v, left, last-1, comp);
   qsort1(v, last+1, right, comp);
 }


int numcmp(char *s1, char *s2)
 {
   double v1, v2;
   v1 = atof(s1);
   v2 = atof(s2);
 
   if (v1 < v2) return -1;
   else if (v1 > v2) return 1;
   else
     return 0;
 }


void swap1(void *v[], int i, int j)
 {
   char *temp;
   temp = v[i];
   v[i] = v[j];
   v[j] = temp;
 }

int readlines(char *lineptr[], int maxlines)
 {
   int len, nlines;
   char *p, line[MAXLEN];

   nlines = 0;

   while (( len = getline(line, MAXLEN)) > 0)
    if((nlines >= maxlines) || (p = alloc(len)) == NULL)
       return -1;
    else
      {
         line[len-1] = '\0';
         strcpy(p, line);
         lineptr[nlines++] = p;
      }
     return nlines;
}

void writelines(char *lineptr[], int nlines)
 {
   int i;

   for(i=0; i < nlines; i++)
    printf("%s\n", lineptr[i]);
 }




int getline(char *line, int max)
{
  int c, i=0;
  
  while(--max > 0 && (c=getchar()) != EOF && c!='\n')
    { *line++=c; i++; }
  if(c=='\n')
   { *line++=c; i++; }
  *line='\0';
 return i;
}

char *alloc(int n)
{
  if(allocbuf + ALLOCSIZE - allocp >= n)
   {
      allocp += n;
      return allocp -n;
   }
  else
   return 0;
}

strlen.c

This exercise intends to count bytes until the terminating zero using an incrementing pointer. The preserved counter n is never initialized before incrementing, so the result has undefined behavior. Its custom strlen signature also differs from the standard library function; the original code is retained to make the defect visible rather than silently repaired.

#include<stdio.h>

int strlen(char *msg);

int main()

{
char msg1[] = "Hello Mr. Wrong";
char *msg2 = "How are you doing";
printf("msg1=%s  msg2=%s \n",msg1,msg2);
printf("Message length of msg1 = %d   msg2 = %d \n",strlen(msg1),strlen(msg2));
return 0;
}

  
int strlen(char *msg)
{
  int n;
   while(*msg++) n++;
   /* for(n=0; *msg!='\0'; msg++) n++; */
  return n;
} 

swap.c

This example compares swapping local integer copies with swapping caller-owned objects through pointers. The first function cannot change its caller variables, while dereferencing addresses in the second can. C passes the pointer values by value too; the useful effect is modifying the pointed-to objects, not a separate pass-by-reference calling mode.

#include<stdio.h>


void swap1(int a, int b);
void swap2(int *px, int *py);

int main()
{
int x=10, y=5, a=20, b=40;
int *px,*py;
px=&x;   py=&y;

printf("Let us Swap1 using pass by value...\n");
printf("Before a=%d   b=%d \n",a,b);
swap1(a,b);
printf("After a=%d   b=%d  \n",a,b);

printf("Let us Swap2 using pass by reference...\n");
printf("Before x=%d   y=%d \n",x,y);
swap2(&x,&y);
printf("After x=%d  y=%d \n",x,y);

return 0;
}

void swap1(int a, int b)
{
  int temp;
temp=a;
a=b;
b=temp;
}

void swap2(int *px, int *py)
{
  int temp;
temp=*px;
*px=*py;
*py=temp;
}

test.c

This small accumulator reads short lines, converts each with atof and prints the final floating-point sum. It demonstrates converting text input into a running value. The ten-byte buffer can split longer logical lines and conversion errors are not distinguished from valid zero values, so the preserved program has a narrow demonstration scope.

#include<stdio.h>
#include<stdlib.h>

#define SIZE 10
int getline(char s[], int lim);

int main()
{
  char line[SIZE];
  float sum=0.0;
  while ((getline(line,SIZE))>0)
   sum+=atof(line);
  printf("Sum = %6.3f \n",sum);
  return 0;
}

int getline(char s[], int lim)
{
  int c, i;
  i=0;
  while(--lim > 0 && (c=getchar()) != EOF && c!='\n')
    s[i++]=c;
  if(c=='\n')
   s[i++]=c;
  s[i]='\0';
 return i;
}

test2.c

This alternate line sorter combines custom string helpers, a fixed allocation arena and recursive quicksort. It is retained separately from sort2.c as an archive variant. Its pointer-style getline has the same misplaced terminator issue after advancing s, and it is not a validated replacement for a library sorting utility.

#include<stdio.h>
#include<stdlib.h>

#define	MAXLINES   5000
#define MAXLEN     1000
#define ALLOCSIZE  10000

char *lineptr[MAXLINES];
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf;

int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
int getline(char *, int);
char *alloc(int);
void qsort(char *lineptr[], int left, int right);
void swap(char *v[], int i, int j);
int strcmp(char *s, char *t);
void strcpyy(char *s, char *t);

int main()
{
  int nlines;

  if(( nlines = readlines(lineptr, MAXLINES)) >= 0)
   {
     qsort(lineptr, 0, nlines-1);
     writelines(lineptr, nlines);
     return 0;
   }
  else
  {
    printf("Error: input too big to sort\n");
    return 1;
  }
}


int readlines(char *lineptr[], int maxlines)
 {
   int len, nlines;
   char *p, line[MAXLEN];

   nlines = 0;
   
   while (( len = getline(line, MAXLEN)) > 0)
    if((nlines >= maxlines) || (p = alloc(len)) == NULL)
       return -1;
    else
      {
         line[len-1] = '\0';
         strcpyy(p, line);
         lineptr[nlines++] = p;
      }
     return nlines;
}

void writelines(char *lineptr[], int nlines)
 {
   int i;
   
   for(i=0; i < nlines; i++)
    printf("%s\n", lineptr[i]);
 }

void qsort(char *v[], int left, int right)
 {
   int i, last;
   
   if(left >= right) return;
   swap(v, left, (left + right)/2);
   last = left;
   for(i = left+1; i <= right; i++)
     if (strcmp(v[i], v[left]) < 0)
       swap(v, ++last, i);
   swap(v, left, last);
   qsort(v, left, last-1);
   qsort(v, last+1, right);
 }

void swap(char *v[], int i, int j)
 {
   char *temp;
   temp = v[i];
   v[i] = v[j];
   v[j] = temp;
 }

char *alloc(int n)
{
  if(allocbuf + ALLOCSIZE - allocp >= n)
   {
      allocp += n;
      return allocp -n;
   }
  else
   return 0;
}

int getline(char *s, int lim)
{
  int c, i;
  i=0;
  while(--lim > 0 && (c=getchar()) != EOF && c!='\n')
    { *s++=c; i++; }
  if(c=='\n')
   { *s++=c; i++; }
  s[i]='\0';
 return i;
}

int strcmp(char *s, char *t)
 {
   for( ; *s == *t; s++, t++)
    if(*s == '\0') return 0;
   return *s - *t;
 }

void strcpyy(char *s, char *t)
 {
   while(*s++ = *t++);
 }

alloc.c

This arena allocator advances a pointer through a fixed static byte array and returns the beginning of each reserved region; afree moves the arena pointer backward. It illustrates stack-like allocation rather than general malloc behavior. The demonstration incorrectly converts a pointer to int and subtracts that value from a pointer, so its printed allocation size is not reliable.

#include<stdio.h>

#define   ALLOCSIZE  10000

static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf;
char *alloc(int n);
void afree(char *p);

int main()
{
int nbyte;
char msg[] = "Four score and seven years ago, our forefathers ...";
printf("%s\n",msg);
nbyte = (int) alloc(sizeof(msg));
printf("original address = %p  Msg address = %p \n",allocbuf, allocp);
printf("Number of bytes allocated = %d \n",allocp-nbyte);

return 0;
}

char *alloc(int n)
{
  if(allocbuf + ALLOCSIZE - allocp >= n)
   {
      allocp += n;
      return allocp -n;
   }
  else
   return 0;
}

void afree(char *p)
{
  if (p >= allocbuf && p < allocbuf + ALLOCSIZE)
     allocp = p;
}