🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: alt.msdos.programmer
Article #1170

Re: Two C problems

#1170
From: John R Buchan
Date: Mon, 08 Jan 1996 17:16
355 lines
11469 bytes
In article <4cojnn$rgd@lugb.latrobe.edu.au>, csigjb@luxor.latrobe.edu.au 
says...
>
>I have two C problems.

The following is a reformatted (sorry, I prefer my format) version of the 
full version of the code that was originally posted (sorry about the rather 
large post folks).  I have made a few modifications (I think I remembered to
add comments by each.  Please excuse those that you have already corrected 
in your second post) and it now seems to be functional (though I can't be 
certain that it functions the way you expected).  BTW, You might want to 
consider breaking your main into smaller functions.

As a few people have probably mentioned, it is considered rather poor taste
to post non-ansi code in c.l.c and even worse to post incomplete uncompilable
code.  Always try to post a minimum compilable example (as little non-ansi 
code as possible) that illustrates your problem.  It is sometimes easier to
write a new small program for this rather than trying to edit the original
(just be sure that it probuces the same problem)  A consistant format and
well placed comments are also helpful.

#include <stdio.h>
#include <stdlib.h>  /* needed for ansi exit() and EXIT_FAILURE */
#include <conio.h>
#include <string.h>
#include <alloc.h>
#include <process.h>

/* it is fairly common practice to use all caps in the names of globals. */
#define  maxstring 127 /* this should be a constant expression not a const */
const lineend='\n';
const escape=27;
const null='\0';     /* Using nul for this name will cause less confusion. */
const space=' ';
const up='H';
const down='P';
const pageup='I';
const pagedown='Q';
const left='K';
const right='M';
const home='G';
const end_='O';


typedef char string[maxstring]; /* needs a constant expression, not a const */
typedef struct nodetypetag
   {
   string line;
   int linenum;
   struct nodetypetag *next,*previous;
   } nodetype;

typedef nodetype *nodetypeptr;

string line,line_,line1,bottomline;

char empty(nodetypeptr posptr)
   {
   return(posptr==NULL);
   }

void initialize(nodetypeptr *listptr)
   {
   *listptr=NULL;
   }

void add(nodetypeptr *listptr,char *fileline,int Linenum)
   {
   nodetypeptr newptr,tempptr;

   newptr=(nodetypeptr)malloc(sizeof(nodetype));
   /* need to verify allocation success */

   strcpy(newptr->line,fileline);
   newptr->linenum=Linenum;
   newptr->next=NULL;  /* no need to write this twice */
   if (*listptr==NULL)
      {
      (*listptr)=newptr;
/*      (*listptr)->next=NULL;  not needed */
      (*listptr)->previous=NULL;
      }
   else
      {
      tempptr=*listptr;
      while (tempptr->next!=NULL)
         {
         tempptr=tempptr->next;
         }
      tempptr->next=newptr;
/*      newptr->next=NULL;   not needed */
      newptr->previous=tempptr;
      }
   }

/* void remove(nodetypeptr *listptr) name is in conflict with the ansi */
/* function remove, which is prototyped in stdio.h                     */
void RemoveNode(nodetypeptr *listptr)
   {
   nodetypeptr tempptr;

   /* NULL tests missing */
   if( listptr != NULL && *listptr != NULL) /* at least 1 node exists */
      {
      tempptr=*listptr;
      *listptr=(*listptr)->next;
      (*listptr)->previous=NULL;
      free(tempptr);
      }
   }

/* This would probably work better as:                               *
*                                                                    *
*  nodetypeptr setpos( int linenum)                                  *
*                                                                    *
*  This would reduce the number of indirects and allow you to return *
*  NULL, if an invalid number manages to be passed in.               */
void setpos(nodetypeptr *posptr,int linenum)
   {
   while ((*posptr)->linenum!=linenum)
      {
      if ((*posptr)->linenum>linenum)
         {
         *posptr=(*posptr)->previous;
         }
      else
         if ((*posptr)->linenum<linenum)
            {
            *posptr=(*posptr)->next;
            }
      }
   }

void writescreenfull(char width,char height,nodetypeptr posptr,char stringpos)
   {
   char y;
   char *line__;  /* this definition was apparently left out */

   window(1,1,width,height);
   clrscr();
   window(1,1,width,height+1);
   y=1;
   while ((y<=height) && (!empty(posptr->next)))
      {
      gotoxy(1,y);
      strcpy(line_,posptr->line);
      line__=&(line_[stringpos]); /* line__ = line_ + stringpos; */
      strncpy(line,line__,width-1);
/*      strcat(line,null); someone else explained this already */
      line[maxstring - 1] = '\0'; /* this provides your safety */
      cputs(line);
      posptr=posptr->next;
      y++;
      }
   }

/* Since fgets will always append a '\0', there is no need for the    *
 * maxstrings parameter.  Just test for '\0' and '\n' or use the ansi *
 * strrchr function.                                                  */
void removelineends(char *strings,unsigned int maxstrings)
   {
   unsigned int i;

   i=0;
   while ((i<maxstrings) && (strings[i]!=lineend))
      {
      i++;
      }
     strings[i]=null;
   }

int main(int argc,char *argv[]) /* main must return int */
   {
   FILE *file;
   char x,ch,width,height,back,fore,stringpos;
   int numlines,linenum;
   struct text_info info;  /* forgot the struct */
   nodetypeptr listptr,posptr;


   if (argc<2)
      {
      cputs("\nShow what . . .\n");
      exit(EXIT_FAILURE); /* exit with failure value, when code fails */
      }
   else
      {
      file=fopen(argv[1],"rt");
      if (file==NULL)
         {
         cprintf("\nFile %s not found . . .\n",argv[1]);
         exit(EXIT_FAILURE); /* exit with failure value, when code fails */
         }
      else
         {
         rewind(file);  /* not needed, "r" opens to the beginning anyway */
         initialize(&listptr);
         linenum=0;
         while (fgets(line,maxstring,file)!=NULL)
            {
            removelineends(line,maxstring);
            add(&listptr,line,linenum);
            linenum++;
            }
         numlines=linenum--;  /* ?? */
         fclose(file);

         posptr=listptr;

/* This would make a nice 'InitScreen' function */
         gettextinfo(&info);
         fore=info.attribute&0x0f;
         back=(info.attribute&0x70)/0x10;
         height=info.screenheight;
         width=info.screenwidth;
         strcpy(bottomline,"  \30  \31  pgup  pgdn  s <string> "
                           "(search for string)  esc (quit)");
         for(x=strlen(bottomline)+1;x<width;x++)
            {
            strcat(bottomline," ");
            }
         /* look into sprintf */

         _setcursortype(_NOCURSOR);
         clrscr();
         textcolor(back);
         textbackground(fore);
         gotoxy(1,height);
         cputs(bottomline);
         textcolor(fore);
         textbackground(back);
/* end 'InitScreen' function */

         height--;
         linenum=0;   /* the first line in your list is 0, not 1 */
         stringpos=0; /* this should start at 0, not 1 */
         writescreenfull(width,height,posptr,stringpos);
         ch=space;
         while (ch!=escape)
            {
            while ((ch!=up) && (ch!=down) && (ch!=pageup) &&
                       (ch!=pagedown) && (ch!=escape) && (ch!=left) &&
                               (ch!=right) && (ch!=end_) && (ch!=home))
               {
               ch=getch();
               if (ch==null)
                  {
                  ch=getch();
                  }
               }

/* This would be much clearer using a switch statement */
            if (ch==up)
               {
               if ((linenum-1)>=0)
                  {
                  linenum--;
                  }
               else
                  {
                  linenum=0;
                  }
               setpos(&posptr,linenum);
               }
            else
               if (ch==down)
                  {
                  if ((linenum+1+height)<=numlines) /* ?? */
                     {
                     linenum++;
                     }
                  else
                     {
                     linenum=numlines-height+1;
                     }
                 setpos(&posptr,linenum);
                 }
              else
                 if (ch==pageup)
                    {
                    if ((linenum-height+1)>=1)
                       {
                       linenum=linenum-height+1;
                       }
                    else
                       {
                       linenum=1;
                       }
                    setpos(&posptr,linenum);
                    }
                 else
                    if (ch==pagedown)
                       {
                       if (((linenum+height-1)<=numlines) &&
                             ((numlines-(linenum+height-1))>=(height-1)))
                          {
                          linenum=linenum+height-1;
                          }
                       else
                          {
                          linenum=numlines-height+1;
                          }
                       setpos(&posptr,linenum);
                       }
                    else
                       if (ch==left)
                          {
                          if (stringpos>0) /* s/b 0 */
                             {
                             stringpos--;
                             }
                          }
                       else
                          if (ch==right)
                             {
                             if (stringpos<=(maxstring-width))
                                {
                                stringpos++;
                                }
                             }
                          else
                             if (ch==end_)
                                {
                                stringpos=maxstring-width+1;
                                }
                             else
                                if (ch==home)
                                   {
                                   stringpos=0; /* s/b 0, not 1 */
                                   }
            if (ch!=escape)
               {
               ch=space;
               }
            writescreenfull(width,height,posptr,stringpos);
            }
         height+=1;
         window(1,1,width,height);
         clrscr();
         _setcursortype(_NORMALCURSOR);
         while (!empty(listptr))
            {
            RemoveNode(&listptr);
            }
         }
      }
   
   return 0;
   }



-- 
John R Buchan           -:|:-     Looking for that elusive FAQ?  ftp to:
jatmon@mail.iag.net     -:|:-     rtfm.mit.edu /pub/usenet-by-group/....
Technical Details
Message-ID: <4crjh3$d71@news.iag.net>
Path: arc1-ca.pugleaf.net!news.iag.net!news
References: <4cojnn$rgd@lugb.latrobe.edu.au>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!news.iag.net!news
From: jatmon@iag.net (John R Buchan)
Newsgroups: alt.msdos.programmer,comp.lang.c
Subject: Re: Two C problems
Date: 8 Jan 1996 17:16:19 GMT
Organization: Internet Access Group, Orlando, Florida
Distribution: world
Message-ID: <4crjh3$d71@news.iag.net>
References: <4cojnn$rgd@lugb.latrobe.edu.au>
NNTP-Posting-Host: pm3-orl29.iag.net
X-Newsreader: WinVN 0.99.7