tags:

views:

182

answers:

4

I'm pretty new at this, so I tried compiling the main on page 119 (§5.11) along w/ its dependencies. I managed to get a clean build with this:

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

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

int getline(char *, int);
char *alloc(int);
char *lineptr[MAXLINES];

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

void qsort(void *lineptr[], int left, int right, 
           int (*comp)(void *, void *));

int numcmp(char *, char *);

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


/* getline:  read a line, return length */
int getline(char *line, int max)
{
   if (fgets(line, max, stdin) == NULL)
      return 0;
   else
      return strlen(line);
}


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


/* readlines:  read input lines */
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'; /* delete newline */
         strcpy(p, line);
         lineptr[nlines++] = p;
      }
   return nlines;
}


/* writelines:  write output lines */
void writelines(char *lineptr[], int nlines)
{
   int i;

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


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

   temp = v[i];
   v[i] = v[j];
   v[j] = temp;   
}


/* qsort:  sort v[left]...v[right] into increasing order */
void qsort(void *v[], int left, int right,
           int (*comp)(void *, void *))
{
   int i, last;
   void swap(void *v[], int, int);

   if (left >= right)
      right;
   swap(v, left, (left + right)/2);
   last = left;
   for(i = left+1; i <= right; i++)
      if((*comp)(v[i], v[left]) < 0)
         swap(v, ++last, 1);
   swap(v, left, last);
   qsort(v, left, last-1, comp);
   qsort(v, last+1, right, comp);
}


#include <stdlib.h>

/* numcmp:  compare s1 and s2 numerically */
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;
}


/* strcmp01:  return <0 if s<t , 0 if s==t, >0 if s>t */
int strcmp01(char *s, char *t)
{
   for( ; *s == *t; s++, t++)
      if(*s == '\0')
         return 0;
   return *s - *t;
}


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

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

But when I run it in a DOS Window (Win 7 for what it's worth), the cursor command prompt accepts multiple lines of key entry input, and... . And what exactly? After I type in a few lines of greeking, nothing happens. I just Ctrl C out of it and I'm back to a command prompt.

Alternatively I composed a few lines of stuff into a test.txt file and tried running

[DIR\]mybuild.exe <[DIR\]test.txt

That just throws an error (a Win 7 dialog appears that says "mybuild.exe has stopped working"). It does find the test.txt file; it just "stop[s] working."

What can I do to run this program successfully? (I'm just trying this never having seen it run anywhere before.) Thanks, everyone, for your help.

A: 

If you are just trying to test qsort then you could just have an array of strings, and just pass that in, with your known test case.

If you want to read from a file you will need to use something like fopen to open the file:

http://msdn.microsoft.com/en-us/library/z5hh6ee9%28VS.80%29.aspx

Once you open it, you can read in the words using fread.

This example shows opening, writing, reading, closing a file:

http://msdn.microsoft.com/en-us/library/kt0etdcs%28VS.100%29.aspx

I would go with just having a static array though, to start with, just to test out your qsort implementation.

James Black
Thank you. Before I found the < redirection in the book, I was sensing something like fopen was gonna need to be employed. Guessing that adding that to a library function would be a no no, even if just to get something going, I was, and still am, unsure of how to place that into the code I've already copied over from the book. I'd like to even hard code a file path into it, but am unsure into which snip it should be.
You could just put it into the main, that way you can then test the rest of your code, as you will then just call your library functions normally, since you have the info you need.
James Black
Thanks James...
A: 

Add some printf()s in strategic places to see what your program is up to.

To start with, try find out whether it is stuck inside readlines(), qsort(), or writelines().

So, add some printf()s to main, just before calling each of those functions. Once you know which of these the computer is stuck in, you can repeat this technique on that function itself, perhaps displaying the value of local variables to help you understand what is happening.

Artelius
Thanks, I think that's a great idea. I ordinarily apply that principle to languages I'm more familiar with (think "MsgBox"). But I have no idea what to write inside printf() in this particular situation. An example would honestly help.
Let's suppose you know the program is stuck inside `qsort()`. You notice that there is a `for` loop inside qsort. You also notice that `qsort()` calls other functions, including itself. Put `printf("for starting\n");` before the loop and `printf("for ending\n");` after the loop to check if the loop is running forever. If not, try to determine which of the functions you are calling doesn't return. This is actually a rather tricky problem to fix, but if you work on it long enough you will find the answer, and the more often you do this the faster you will learn.
Artelius
Thanks. This helps.
+4  A: 
  1. press F6 or Ctrl+Z to end the input in a console.

  2. by add the fprintf(stderr,...) to your code, i found that the program actually runs out of stack. you probably got the qsort wrong. like

if (left >= right) right;

void qsort(void *v[], int left, int right,
           int (*comp)(void *, void *))
{
   int i, last;
   void swap(void *v[], int, int);

fprintf(stderr, "left %d  right %d\n", left, right);
   if (left >= right)
      right;
   swap(v, left, (left + right)/2);
   last = left;
   for(i = left+1; i <= right; i++)
      if((*comp)(v[i], v[left]) < 0)
         swap(v, ++last, 1);
   swap(v, left, last);
   qsort(v, left, last-1, comp);
   qsort(v, last+1, right, comp);
}
Yin Zhu
Yin, wow, thanks! Is that awesome? It works now.
One more question, per Artelius's suggestion to me below: What was the rest of the printf() that you wrote? Just to get me started so that I can use that technique in the future.Thanks again. And to James Black and Artelius, I'll study further what you've helpfully suggested. Thanks all.
use printf() at the places like:after the input: to make sure you load the data correctlyat the beginning of a recursive function or any functions you are not sure...
Yin Zhu
@unknown (yahoo) Now it's your job to upvote this answer and accept it :)
atv
Yin, thank you.atv:Every time I try to up-vote, add reps, I get this popup: "Vote Up requires 15 reputation (click on this box to dismiss)." Wish I could with all of the responses I've received.
A: 
if (left >= right)
    right;

did you mean

if (left >= right)
    return;

?

Artelius
Yes. Yin said same. Thank you both.I have another question if it's not too much to ask, though: The thing prints out, whcih is all I was really after in the final analysis, but...it's not sorting. I can't say this sorts. It does something, but it's not in accordance with any sort pattern I can recognize, numerically or alphabetically, ascending or descending. (I can't say it's random either, but it's not sorting according to the classical definition of such).
Whoops, I just found I had a "1" where an "i" should have been in the qsort function. That's a relief; everything sorts perfectly now. Thanks again to all.