sorting the input

N

Nick Keighley

please include the subject in the body of your email:

"sorting the input"

1st I think of creating an array of pointers of size 100 as this is the
maximum input I intend to take. I can create a fixed size array but in the
end I want my array to expand at run-time to fit the size of input. I am
not able to come up with anyting all all and doing:

take a look at realloc(). Initally malloc() a block of pointers
and when it fills up call realloc().
   char* arr_of_pointers[100];

seems like a completely wrong idea as this is a static array. I want to
take the input and then decide how much memory I need and then malloc the
array of that size. I came up with K&R2 idea:

   1.)   read and save the input lines till the user hits the EOF
   2.)   sort them
   3.)   print them

I am pretty much confused on what to start with. Can I have your ideas in
solving this problem ? All I can think of is:

  use sort algorithm from the standard library to sort the lines.
  print the lines using %s as argument in printf().

or fputs()

sounds fine to me. Which bit are you stuck on?
 
B

Ben Bacarisse

arnuld said:
1st I think of creating an array of pointers of size 100 as this is the
maximum input I intend to take. I can create a fixed size array but in the
end I want my array to expand at run-time to fit the size of input. I am
not able to come up with anyting all all and doing:

char* arr_of_pointers[100];
...[SNIP]....


I came up with the Static Version of this function with 1 error and I
can't seem to find a way either to remove that error or to convert it to a
dynamic version of the program:


/* write a program to read a set of lines from input and sort them
* and then print them.
*
* version 1.0
*/


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

enum MAXLINES { ARRSIZE = 100 };

char* arr_of_ptr[ARRSIZE];
char arr_of_lines[ARRSIZE];

I would not link these two sizes. You need two enum constants.
int readlines( char**, char*, const int max );
void printlines( char** );


/* main() will simply call the other functions to do the job */

int main( void )
{
if( readlines( arr_of_ptr, arr_of_lines, ARRSIZE ) > 0 )
{
qsort( arr_of_ptr, ARRSIZE, sizeof( char* ) ); /* Line 26 */

OK, I see you ask about this later.
printlines( arr_of_ptr );
}
else
{
fprintf( stderr, "error: out of memory\n" );
}

return 0;
}


/* 1) read lines till we get the NULL,
* 2) store those lines into an array of characters <arr_of_lines>,
* 3) pointer of arry of pointers <arr_of_ptr> will point to the
* individual elements of array of characters <arr_of_lines>,
*
*/

int readlines( char* arr_of_ptr[], char arr_of_lines[], int max )

The second parameter has a bad name. At best it is one line.
{
int num_lines;

char temp_arr[ARRSIZE];

num_lines = 0;

while( fgets(temp_arr, max, stdin) )
{
strcpy( arr_of_lines, temp_arr );
*arr_of_ptr++ = arr_of_lines++;

This can't work. You must malloc space for the line you have just
read. There is nowhere else to put the line that will survive both
the next execution of the loop and the return from this function.
++num_lines;
}

return num_lines;
}


/* it will simply print the lines pointed to by the elements of
* arrays of pointers <arr_of_ptr>.
*
*/
void printlines( char* arr_of_ptr[] )
{
while( *arr_of_ptr != '\0' )

Correct, but confusing. '\0' is a char constant equal to zero so it
works, but I'd expect plain 0 or, better, NULL here.
{
puts( *arr_of_ptr++ );

You will get extra newlines. puts adds one and fgets retains the
newline from the input.
}
}
================ OUTPUT ====================
[arnuld@raj C]$ gcc -ansi -pedantic -Wall -Wextra 5-7.c
5-7.c: In function `main':
5-7.c:27: error: too few arguments to function `qsort'
[arnuld@raj C]$



I know that qsort needs a compare function and I found this in FAQ:

http://www.c-faq.com/lib/qsort1.html


but a statement like: *(char * const *)p1

is totally beyond my capability.

I'd stick with reading the lines in first. Deal with sorting later.
 
B

Ben Bacarisse

arnuld said:
On Tue, 22 Apr 2008 13:05:13 +0100, Ben Bacarisse wrote:

...[SNIP]...

This can't work. You must malloc space for the line you have just
read. There is nowhere else to put the line that will survive both
the next execution of the loop and the return from this function.


I did not get what exactly you mean. That array is created already with
reserved space, then I am copying its contents to another place then I
don't care what fgets() puts into it on next call, because I will copy
that away too. It exists for temporary saving of input for single call to
while().

In total your program had an array of 100 char pointers. One array of
100 characters (the "global" one) and a local array of 100 characters.
That just can't be enough "in general". Where are the characters of
the second line stored?

Did you intend that the whole file should fit into one 100 character
array, with the each start of line pointer to by one of the 100
character pointers? If that was your plan, then the error was one of
detail -- you were not doing that, but your code could be corrected to
do that. The trouble is that such fixed-size solutions are almost
never worth getting right -- you need allocated storage when you don't
know the data size in advance.
Though as you advised, I changed it to malloc but the "why the malloc" is
not clear to me.



..[SNIP].....
I'd stick with reading the lines in first. Deal with sorting later.

ok, I removed the sorting routines and any calls to it. This program now
compiles and runs with strange output:


/* write a program to read a set of lines from input and sort them
* and then print them.
*
* version 1.0
*/


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

enum MAXLINES { ARR_SIZE = 100, STR_SIZE = 1000 };

char* arr_of_ptr[ARR_SIZE];
char arr_of_char[STR_SIZE];

int readlines( char**, char*, const int max );
void printlines( char** );


/* main() will simply call the other functions to do the job */

int main( void )
{
if( readlines( arr_of_ptr, arr_of_char, STR_SIZE ) > 0 )
{
/* qsort( arr_of_ptr, ARR_SIZE, sizeof( char* )); */
printlines( arr_of_ptr );
}
else
{
fprintf( stderr, "error: out of memory\n" );
}

return 0;
}


/* 1) read lines till we get the NULL,
* 2) store those lines into an array of characters <arr_of_lines>,
* 3) pointer of arry of pointers <arr_of_ptr> will point to the
* individual elements of array of characters <arr_of_lines>,
*
*/

int readlines( char* arr_of_ptr[], char arr_of_char[], int max )
{
int num_lines;
char *p;

p = malloc( max * sizeof( char* ));

Not what I intended. I assumed you continue to use a local array for
the line:

char one_line[SOME_SIZE];
num_lines = 0;

while( fgets(p, max, stdin) )

and read into that:

while( fgets(one_line, sizeof one_line, stdin) )

and do the malloc here, to save the line. At this point we know how
long it is (if we use strlen(one_line)) and we call allocate a copy
the line.
strcpy( arr_of_char, p );
*arr_of_ptr++ = arr_of_char++;

and we'd store the pointer in arr_or_ptr[num_lines] (I prefer that
style to your *arr_of_ptr++ = ... one).
 
N

Nick Keighley

I did not get what exactly you mean.

so I see! Say you have 10 lines you need 10 lumps
of memory to store the lines.
That array is created already with
reserved space, then I am copying its contents to another place

you read into the malloc()ed memory. Good. *Then* you copy it to
static memory and ignore the malloc()ed memory!

then I
don't care what fgets() puts into it on next call, because I will copy
that away too. It exists for temporary saving of input for single call to
while().

re-read your code it isn't doing what you think it is.

Though as you advised, I changed it to malloc but the "why the malloc" is
not clear to me.

I don't understand

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

enum MAXLINES { ARR_SIZE = 100, STR_SIZE = 1000 };

char*  arr_of_ptr[ARR_SIZE];
char   arr_of_char[STR_SIZE];

int readlines(  char**, char*,  const int max );
void printlines( char** );

you could avoid these by putting main() at the end

int main( void )
{
  if( readlines( arr_of_ptr, arr_of_char, STR_SIZE ) > 0 )
    {
      /*      qsort( arr_of_ptr, ARR_SIZE, sizeof( char* ));  */
      printlines( arr_of_ptr );      
    }
  else
    {
      fprintf( stderr, "error: out of memory\n" );

well no. It might be an empty file

    }

  return 0;

}

/* 1) read lines till we get the NULL,
 * 2) store those lines into an array of characters <arr_of_lines>,
 * 3) pointer of arry of pointers <arr_of_ptr> will point to the
 *    individual elements of array of characters <arr_of_lines>,
 *
 */

int readlines( char* arr_of_ptr[], char arr_of_char[], int max )
{
  int num_lines;
  char *p;

  p = malloc( max * sizeof( char* ));

don't you mean sizeof(char)? Or since sizeof(char)
is 1 just omit it. You don't check the return
value of malloc(). Your malloc() should be in the loop.

  num_lines = 0;

  while( fgets(p, max, stdin) )

you read it into the malloced buffer
    {
      strcpy( arr_of_char, p );

then you copy to a static buffer. Why?

      *arr_of_ptr++ = arr_of_char++;

what does this do? When the loop ends

aop[0] = aoc[0]
aop[1] = aoc[1]
aop[2] = aoc[2]

suppose aoc contains "ao...love"
then your print routine will print

ao...love
o...love
...love

      ++num_lines;
    }

  return num_lines;

}

/* it will simply print the lines pointed to by the elements of
 * arrays of pointers <arr_of_ptr>.
 *
 */
void printlines( char* arr_of_ptr[] )
{
  printf("\n-------------------------\n");
  while( *arr_of_ptr )
    {
      printf("%s", *arr_of_ptr++ );
    }

}

=========== OUTPUT ==============
[arnuld@raj C]$ gcc -ansi -pedantic -Wall -Wextra 5-7.c
[arnuld@raj C]$ ./a.out
and
oye
...love
 
B

Ben Bacarisse

you meant this ?


int readlines( char* arr_of_ptr[], const int max )
{
int num_lines, size_arr;
char *p;
char temp_arr[STR_SIZE];

num_lines = 0;

while( fgets(temp_arr, max, stdin) && num_lines < max )
{
size_arr = strlen( temp_arr );
if( (p = malloc( size_arr * sizeof( char* ))) )

You need size_arr + 1. You are storing chars, not char *s.
{
strcpy( p, temp_arr );
*arr_of_ptr++ = p;
++num_lines;
}

}

return num_lines;
}

and we'd store the pointer in arr_or_ptr[num_lines] (I prefer that
style to your *arr_of_ptr++ = ... one).


That's the style I want to use but I don't use it as that lies to me
about the very basic fact of C. At some point I will also stop using []
notation in function arguments as it fakes the array, it lies that it is
not a pointer, that it is a box of characters we call array and we are
using it directly but we are not, in fact, it is a pointer that is
manipulating the array and hence this distinction is the source of most
troubles I have and this trouble is intensively painful than the troubles
I get by not using array indexing.

Sorry, I can't follow that. It was a matter of style not correctness,
so I am not sure it is worth pursuing.
 
J

Joachim Schmitz

arnuld said:
and what I am supposed to do with last element ?
You need It for the string terminating \0.
strlen gives the lengh without the terminating \0, so you need to add it to
the size you malloc
I think NULL should be the last element but I can't find a way
to add it.
\0, not NULL and the "strcpy( p, temp_arr );" in your next line whill do
that for you.

Bye, Jojo
 
B

Ben Bacarisse

arnuld said:
and what I am supposed to do with last element ?

I think NULL should be the last element but I can't find a way
to add it.

the strcpy (now snipped from the quote) copies the string including
the final '\0' bytes. That is what the +1 is for.
 
A

arnuld

1st I think of creating an array of pointers of size 100 as this is the
maximum input I intend to take. I can create a fixed size array but in the
end I want my array to expand at run-time to fit the size of input. I am
not able to come up with anyting all all and doing:

char* arr_of_pointers[100];

seems like a completely wrong idea as this is a static array. I want to
take the input and then decide how much memory I need and then malloc the
array of that size. I came up with K&R2 idea:


1.) read and save the input lines till the user hits the EOF
2.) sort them
3.) print them

I am pretty much confused on what to start with. Can I have your ideas in
solving this problem ? All I can think of is:


use sort algorithm from the standard library to sort the lines.
print the lines using %s as argument in printf().
 
A

arnuld

1st I think of creating an array of pointers of size 100 as this is the
maximum input I intend to take. I can create a fixed size array but in the
end I want my array to expand at run-time to fit the size of input. I am
not able to come up with anyting all all and doing:

char* arr_of_pointers[100];
...[SNIP]....


I came up with the Static Version of this function with 1 error and I
can't seem to find a way either to remove that error or to convert it to a
dynamic version of the program:


/* write a program to read a set of lines from input and sort them
* and then print them.
*
* version 1.0
*/


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

enum MAXLINES { ARRSIZE = 100 };

char* arr_of_ptr[ARRSIZE];
char arr_of_lines[ARRSIZE];

int readlines( char**, char*, const int max );
void printlines( char** );


/* main() will simply call the other functions to do the job */

int main( void )
{
if( readlines( arr_of_ptr, arr_of_lines, ARRSIZE ) > 0 )
{
qsort( arr_of_ptr, ARRSIZE, sizeof( char* ) ); /* Line 26 */
printlines( arr_of_ptr );
}
else
{
fprintf( stderr, "error: out of memory\n" );
}

return 0;
}


/* 1) read lines till we get the NULL,
* 2) store those lines into an array of characters <arr_of_lines>,
* 3) pointer of arry of pointers <arr_of_ptr> will point to the
* individual elements of array of characters <arr_of_lines>,
*
*/

int readlines( char* arr_of_ptr[], char arr_of_lines[], int max )
{
int num_lines;

char temp_arr[ARRSIZE];

num_lines = 0;

while( fgets(temp_arr, max, stdin) )
{
strcpy( arr_of_lines, temp_arr );
*arr_of_ptr++ = arr_of_lines++;
++num_lines;
}

return num_lines;
}


/* it will simply print the lines pointed to by the elements of
* arrays of pointers <arr_of_ptr>.
*
*/
void printlines( char* arr_of_ptr[] )
{
while( *arr_of_ptr != '\0' )
{
puts( *arr_of_ptr++ );
}
}
================ OUTPUT ====================
[arnuld@raj C]$ gcc -ansi -pedantic -Wall -Wextra 5-7.c
5-7.c: In function `main':
5-7.c:27: error: too few arguments to function `qsort'
[arnuld@raj C]$



I know that qsort needs a compare function and I found this in FAQ:

http://www.c-faq.com/lib/qsort1.html


but a statement like: *(char * const *)p1

is totally beyond my capability.
 
A

arnuld

...[SNIP]...
This can't work. You must malloc space for the line you have just
read. There is nowhere else to put the line that will survive both
the next execution of the loop and the return from this function.


I did not get what exactly you mean. That array is created already with
reserved space, then I am copying its contents to another place then I
don't care what fgets() puts into it on next call, because I will copy
that away too. It exists for temporary saving of input for single call to
while().

Though as you advised, I changed it to malloc but the "why the malloc" is
not clear to me.



..[SNIP].....
I'd stick with reading the lines in first. Deal with sorting later.

ok, I removed the sorting routines and any calls to it. This program now
compiles and runs with strange output:


/* write a program to read a set of lines from input and sort them
* and then print them.
*
* version 1.0
*/


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

enum MAXLINES { ARR_SIZE = 100, STR_SIZE = 1000 };

char* arr_of_ptr[ARR_SIZE];
char arr_of_char[STR_SIZE];

int readlines( char**, char*, const int max );
void printlines( char** );


/* main() will simply call the other functions to do the job */

int main( void )
{
if( readlines( arr_of_ptr, arr_of_char, STR_SIZE ) > 0 )
{
/* qsort( arr_of_ptr, ARR_SIZE, sizeof( char* )); */
printlines( arr_of_ptr );
}
else
{
fprintf( stderr, "error: out of memory\n" );
}

return 0;
}


/* 1) read lines till we get the NULL,
* 2) store those lines into an array of characters <arr_of_lines>,
* 3) pointer of arry of pointers <arr_of_ptr> will point to the
* individual elements of array of characters <arr_of_lines>,
*
*/

int readlines( char* arr_of_ptr[], char arr_of_char[], int max )
{
int num_lines;
char *p;

p = malloc( max * sizeof( char* ));

num_lines = 0;

while( fgets(p, max, stdin) )
{
strcpy( arr_of_char, p );
*arr_of_ptr++ = arr_of_char++;
++num_lines;
}

return num_lines;
}




/* it will simply print the lines pointed to by the elements of
* arrays of pointers <arr_of_ptr>.
*
*/
void printlines( char* arr_of_ptr[] )
{
printf("\n-------------------------\n");
while( *arr_of_ptr )
{
printf("%s", *arr_of_ptr++ );
}
}


=========== OUTPUT ==============
[arnuld@raj C]$ gcc -ansi -pedantic -Wall -Wextra 5-7.c
[arnuld@raj C]$ ./a.out
and
oye
....love
 
A

arnuld

In total your program had an array of 100 char pointers. One array of
100 characters (the "global" one) and a local array of 100 characters.
That just can't be enough "in general". Where are the characters of
the second line stored?

:-O


and read into that:

while( fgets(one_line, sizeof one_line, stdin) )
and do the malloc here, to save the line. At this point we know how
long it is (if we use strlen(one_line)) and we call allocate a copy
the line.


you meant this ?


int readlines( char* arr_of_ptr[], const int max )
{
int num_lines, size_arr;
char *p;
char temp_arr[STR_SIZE];

num_lines = 0;

while( fgets(temp_arr, max, stdin) && num_lines < max )
{
size_arr = strlen( temp_arr );
if( (p = malloc( size_arr * sizeof( char* ))) )
{
strcpy( p, temp_arr );
*arr_of_ptr++ = p;
++num_lines;
}

}

return num_lines;
}

and we'd store the pointer in arr_or_ptr[num_lines] (I prefer that
style to your *arr_of_ptr++ = ... one).


That's the style I want to use but I don't use it as that lies to me
about the very basic fact of C. At some point I will also stop using []
notation in function arguments as it fakes the array, it lies that it is
not a pointer, that it is a box of characters we call array and we are
using it directly but we are not, in fact, it is a pointer that is
manipulating the array and hence this distinction is the source of most
troubles I have and this trouble is intensively painful than the troubles
I get by not using array indexing.
 
A

arnuld

You need size_arr + 1. You are storing chars, not char *s.


and what I am supposed to do with last element ?

I think NULL should be the last element but I can't find a way
to add it.

Sorry, I can't follow that. It was a matter of style not correctness,
so I am not sure it is worth pursuing.

okay :)
 
A

arnuld

I would not link these two sizes. You need two enum constants.

it is done.

The second parameter has a bad name. At best it is one line.

sorry, my mistake


I'd stick with reading the lines in first. Deal with sorting later.


okay, I am done with reading and printing lines now. It is working now, I
need to understand the sorting part now:


/* write a program to read a set of lines from input and sort them
* and then print them.
*
* version 1.0
*/


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

enum MAXLINES { ARR_SIZE = 100, STR_SIZE = 1000 };

char* arr_of_ptr[ARR_SIZE];
char arr_of_char[STR_SIZE];

int readlines( char**, const int );
void printlines( char** );


/* main() will simply call the other functions to do the job */

int main( void )
{
if( readlines( arr_of_ptr, ARR_SIZE ) > 0 )
{
/* qsort( arr_of_ptr, ARR_SIZE, sizeof( char* )); */
printlines( arr_of_ptr );
}
else
{
fprintf( stderr, "error: out of memory\n" );
}

return 0;
}


/* 1) read lines till we get the NULL,
* 2) store those lines into an array of characters <arr_of_lines>,
* 3) pointer of arry of pointers <arr_of_ptr> will point to the
* individual elements of array of characters <arr_of_lines>,
*
*/

int readlines( char* arr_of_ptr[], const int max )
{
char *p, **p_arrptr;
int num_lines, size_arr;
char temp_arr[STR_SIZE];

num_lines = 0;
p_arrptr = arr_of_ptr;

while( fgets(temp_arr, max, stdin) && num_lines < max )
{
size_arr = strlen( temp_arr ) + 1;
if( (p = malloc( size_arr * sizeof( char ))) )
{
strcpy( p, temp_arr );
*p_arrptr++ = p;
++num_lines;
}

}

return num_lines;
}




/* it will simply print the lines pointed to by the elements of
* arrays of pointers <arr_of_ptr>.
*
*/
void printlines( char* arr_of_ptr[] )
{
printf("\n-------------------------\n");
while( *arr_of_ptr )
{
printf("%s", *arr_of_ptr++ );
}
}

============= OUTPUT ===================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra 5-7.c
/home/arnuld/programs/C $ ./a.out
Ben & Richard
both are helping
C newbie.... arnuld
 
B

Ben Bacarisse

arnuld said:
okay, I am done with reading and printing lines now. It is working
now,

Sorry, not quite.
I need to understand the sorting part now:

I think you need to show your best attempt at the sort call and people
will help you get the details right.
/* write a program to read a set of lines from input and sort them
* and then print them.
*
* version 1.0
*/
enum MAXLINES { ARR_SIZE = 100, STR_SIZE = 1000 };

char* arr_of_ptr[ARR_SIZE];
char arr_of_char[STR_SIZE];

This second array seem not to be used now (that is as I would expect)
so you should get rid of it.
if( readlines( arr_of_ptr, ARR_SIZE ) > 0 )
int readlines( char* arr_of_ptr[], const int max )
{
char *p, **p_arrptr;
int num_lines, size_arr;
char temp_arr[STR_SIZE];

num_lines = 0;
p_arrptr = arr_of_ptr;

while( fgets(temp_arr, max, stdin) && num_lines < max )
^^^?

Safe (because max happens to be less that STR_SIZE) but not correct.
{
size_arr = strlen( temp_arr ) + 1;
if( (p = malloc( size_arr * sizeof( char ))) )

You can omit sizeof(char). It is 1 by definition. I can see why some
people might want a size there, but if you are one of them then you
should use the c.l.c-approved idiom:

if( (p = malloc(size_arr * sizeof *p)) )
 
S

santosh

arnuld said:
where is "p" pointing to ? nowhere . so you can't dereference it yet.

That's perfectly legal. Sizeof is a compile time operator and no actual
deferencing of the pointer is done.
 
A

arnuld

Sorry, not quite.

I have shown you the output and it seems ok to me. Did you find something
wrong ?


I think you need to show your best attempt at the sort call and people
will help you get the details right.


I can't understand the 13.8 of FAQs: http://c-faq.com/lib/qsort1.html

/* compare strings via pointers */
int pstrcmp(const void *p1, const void *p2)
{
return strcmp(*(char * const *)p1, *(char * const *)p2);
}


parameters are made void* but in fact we are passing char**, which is 2 levels of
indirection. and what about the cast:

(char* const*)p1


we are casting a <pointer to void> to <pointer to a const pointer to char>
, right ?


char* arr_of_ptr[ARR_SIZE];
char arr_of_char[STR_SIZE];
This second array seem not to be used now (that is as I would expect)
so you should get rid of it.

okay

^^^?

Safe (because max happens to be less that STR_SIZE) but not correct.


incorrect ?


If the user enters the 1001 characters then program will crash or behave
strangely or something but I can't do anything here as the array-size has
to be there at compile-time. Even if I do malloc() for array then for user
input I use fgets() I will still need a limit to read the characters.



You can omit sizeof(char). It is 1 by definition.

you mean, by default, if I type: <malloc( size_arr )> then it will be
converted to <malloc(size_arr * 1)> ?



I can see why some
people might want a size there, but if you are one of them then you
should use the c.l.c-approved idiom:

if( (p = malloc(size_arr * sizeof *p)) )

okay
 
B

Barry Schwarz

where is "p" pointing to ? nowhere . so you can't dereference it yet.

Since sizeof does not evaluate its operand (except for VLA), the *p
does not involve a dereference. *p simply identifies the type that
sizeof should operate on.


Remove del for email
 
B

Barry Schwarz

I have tried the strcmp function from FAQ:

http://c-faq.com/lib/qsort1.html

it fails to do its job. It Segfaults :( . If I remove its call from the
program, my program compiles and runs fine:

Is sorting important to your program or not? If not, leave it out. If
it is, then your program does not run fine without it. The output
will not be sorted.
/* write a program to read a set of lines from input and sort them
* and then print them.

One might infer that sorting is important.
*
* version 1.0
*/


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

enum MAXLINES { ARR_SIZE = 100, STR_SIZE = 1000 };

char* arr_of_ptr[ARR_SIZE];
/* char arr_of_char[STR_SIZE]; */

int readlines( char**, const int );
void printlines( char** );
int p_strcmp( const void*, const void* );


/* main() will simply call the other functions to do the job */
int main( void )
{
if( readlines( arr_of_ptr, ARR_SIZE ) > 0 )
{
qsort( arr_of_ptr, ARR_SIZE, sizeof( char* ), p_strcmp );

The second argument to qsort is the number of array elements to
process. While there are ARR_SIZE elements, most of them contain NULL
and should not be processed. readlines told you how many elements to
process but you threw that information away.
printlines( arr_of_ptr );
}


return 0;
}


/* 1) read lines till we get the NULL,
* 2) store those lines into an array of characters <arr_of_lines>,
* 3) pointer of arry of pointers <arr_of_ptr> will point to the
* individual elements of array of characters <arr_of_lines>,
*
*/

int readlines( char* arr_of_ptr[], const int max )
{
char *p, **p_arrptr;
int num_lines, size_arr;
char temp_arr[STR_SIZE];

num_lines = 0;
p_arrptr = arr_of_ptr;

while( fgets(temp_arr, max, stdin) && num_lines < max )

People have already told you that max is not appropriate in the call
to fgets. If you won't listen, why post?
{
size_arr = strlen( temp_arr ) + 1;

It is a nit but this will include the '\n' that fgets inserts for a
line shorter than the buffer. Most seem to think it is worth
eliminating.
if( (p = malloc( size_arr * sizeof( char ))) )
{
strcpy( p, temp_arr );
*p_arrptr++ = p;
++num_lines;
}

}

return num_lines;
}



/* it will simply print the lines pointed to by the elements of
* arrays of pointers <arr_of_ptr>.
*
*/
void printlines( char* arr_of_ptr[] )
{
printf("\n-------------------------\n");
while( *arr_of_ptr )
{
printf("%s", *arr_of_ptr++ );
}
}


/* compare 2 strings using pointers */
int p_strcmp( const void* pv1, const void* pv2 )
{
return strcmp( *(char* const*)pv1, *(char* const*)pv2 );

When either v1 or v2 is NULL, this invoked undefined behavior. A
segfault is one of the nicer manifestations of same.


Remove del for email
 
I

Ian Collins

arnuld said:
so, sizeof() operator does not evaluate its operands. It finds the number
of bytes without evaluating anything ?
It is evaluating the size of a type, at compile time.
 
R

Richard Tobin

He isn't dereferencing it: sizeof does not evaluate its operand (except
for one tiny corner-case in C99 that doesn't apply here), so no
dereferencing is taking place.
[/QUOTE]
so, sizeof() operator does not evaluate its operands. It finds the number
of bytes without evaluating anything ?

In effect, it instructs the compiler to find the number of bytes
used by the argument. That depends on the *type* of the argument,
not its value. And you don't need to evaluate an expression to
determine its type: if a and b are ints, a+b is an int regardless
of the values of a and b; if x is an array of doubles, x[5] is always
a double, and so on.

The compiler does some calculations to determine the type and hence
the size, so you could say it evaluates *something*, but it doesn't
evaluate the argument itself.

-- Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top