How to count the number of elements of an array - c

I encountered a problem while testing a code.I define a macro for obtaining the number of elements of an array as follows:
#define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0])
This macro works fine for counting the number of elements of an array whose initializers match the storage capacity(e.g. int buf[] = {1,2,3};),but not very effective with arrays declared as : int buf[20] = {1,2,3};
Now i know counting array elements like these is pretty easy,but what about large number of elements? How do you count them? counting could be a killer,you know!
Consider the following code:
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0])
void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize);
int main(void)
{
int dst[20] = { 1,2,3 };
int src[] = { 4,5,6 };
size_t dstSize = 3; // dstSize = ARRAY_SIZE(dst) doesn't work
size_t srcSize = ARRAY_SIZE(src);
g_strcat(dst, dstSize, sizeof(int), src, srcSize);
size_t n, newSize = dstSize + srcSize;
for (n = 0; n < newSize; n++) {
printf("%d ", dst[n]);
}
putchar('\n');
return 0;
}
void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize)
{
memcpy((char *)_Dst + (dstSize * bytes), _Src, srcSize * bytes);
}

If you only partially initialize a list of primitive data types (ie: array of ints), the remaining elements get initialized to 0.
C99 Standard 6.7.8.21
If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in
a string literal used to initialize an array of known size than there
are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage
duration.
In your case, you're trying to determine the size of the initializer list. Can't really think of a valid reason to need to do this, but you could simply check when elements start being equal to zero consistently. Of course, this fails if you've deliberately set an element to zero.
The macro you wrote will work correctly (ie: return the number of elements in the array), but it will fail if you use it in a function that accepts a pointer-to-array as an argument, as pointer decay causes sizeof to act differently than one might expect.
All that being said, you can't determine the size of the initializer list in any meaningful sense, unless you do something like so, where you define the initializer list as a macro:
Code Listing
#include <stdio.h>
#define LIST {1,2,3}
int main(void)
{
int i[20] = LIST;
int t[] = LIST;
printf("elements in i: %d\n", sizeof(i)/sizeof(int));
printf("elements in t: %d\n", sizeof(t)/sizeof(int));
return 0;
}
Sample output
elements in i: 20
elements in t: 3
You can minimize wasted memory by putting the throw-away array into a new block scope, ie:
#include <stdio.h>
#define LIST {1,2,3}
int main(void)
{
int i[20] = LIST;
int initListSize = 0;
{
int t[] = LIST;
initListSize = sizeof(t) / sizeof(int);
}
printf("elements in t: %d\n", initListSize);
return 0;
}
This will limit the storage lifetime of the temporary array to the narrow scope between the braces. Again, I can see this being useful maybe as an experiment, but can't see this ever finding its way into production code.

This will do it if we can assume that the last initialized element is not zero (because that's indistinguishable from being implicitly initialized to zero):
size_t trailing_zero_bytes(const void* data, size_t size) {
for (; size > 0; size--) {
if (((const char*)data)[size - 1] != 0) {
break;
}
}
return size;
}
#define ARRAY_SIZE(arr) \
((sizeof(arr) - trailing_zero_bytes(arr, sizeof(arr)) + sizeof(arr[0]) + 1) / sizeof(arr[0]))
If you want to count these two cases differently, you're completely out of luck (unless you parse the code using Clang or GCC-XML or whatever):
int s1[5] = { 4,5,6 }; // 2 zeros implied
int s2[5] = { 4,5,6,0 }; // 1 zero implied
Both of the above will give 3 with my approach, and there is nothing that can be done about it.

Your macro is working fine. The statement:
int dst[20] = { 1,2,3 };
Creates the following in stack memory:
|1|2|3|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
The array size is still 20 even if it has only been initialized with the first three values
Regarding your question in the comments: How will i concatenate to the array? The array must be big enough to hold the other string:
If you are working with strings (and not number arrays) the string function int len = strlen(string); can be used to test the existing usage of a string variable before concatenating.
Unlike the sizeof macro, strlen is a function that looks for the first NULL character in an array of characters:
char string[20] = {"yes"};
Creates the following in memory:
|y|e|s|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
strlen starts at the address of string and counts characters until it encounters the first NULL. (or 0):
int len strlen(string); //will yield a len of 3
you can then use strncat(string, newStr, count); to concatenate a specified numbers of characters, count, to a string of a known capacity, thus avoiding a buffer overflow.
Keep in mind that a string variable of size == 20 for example is limited to containing a string of length == 19. The 20th position must be reserved for the NULL character.

If you want to determine the number of initializers of an array,declare an array to hold the initializers elements and apply the macro ARRAY_SIZE() on it.Then use memcpy() to copy the initializers to the dst[20] array.
Now you have the number of elements without hassle.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0])
void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize);
int main(void)
{
int dst[20], src[] = { 4,5,6 };
int initializer_list[] = { 1,2,3 };
size_t init_size = ARRAY_SIZE(initializer_list);
memcpy(dst, initializer_list, init_size * sizeof(int));
size_t dstSize = init_size;
size_t srcSize = ARRAY_SIZE(src);
g_strcat(dst, dstSize, sizeof(int), src, srcSize);
dstSize += srcSize;
size_t n;
for (n = 0; n < dstSize; n++) {
printf("%d ", dst[n]);
}
putchar('\n');
return 0;
}
void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize)
{
memcpy((char *)_Dst + (dstSize * bytes), _Src, srcSize * bytes);
}

Related

How do you return the last element in an array in C?

How do I return the last element in an array? I thought this function would work, as it worked for a similar function that returned the first element.
int END(int arr[]) {
int last;
size_t s = sizeof(arr) / sizeof(arr[0]);
if (s != 0) {
last = arr[s - 1];
return last;
} else {
return -1 ; //END(arr);
}
}
int END(int arr[]) is adjusted to int END(int* arr), since you can't pass arrays as arguments in C. This means that sizeof(arr) is sizeof(int*), and your calculation for s is wrong.
You can use a macro for this, as the macro argument won't be turned into a pointer implicitly:
#define END(ARR) (ARR)[(sizeof(ARR) / sizeof((ARR)[0])) - 1u]
(Note that there are no arrays of size 0, so your -1 case is redundant)
You cannot use sizeof inside a function because sizeof(arr) will return the size of the pointer which is generally 8 bytes on a x86_64 architecture. I would not use -1 is an error value because -1 can be an element of the given array. I would prefer the C++ way of npos, returning the maximum value of the data type according to the system architecture.
I would recommend you to get the length of the array as a parameter of the function. Like this:
#include <stdio.h>
#include <limits.h>
int END(int *arr, size_t length); // fix prototype error
/*
#brief Returns the last element of the array `arr`.
#param arr array
#param length array's length
#returns If `arr` is NULL or empty returns INT_MAX, otherwise the last element.
*/
int END(int *arr, size_t length)
{
if (!arr || length == 0) // if arr is NULL
return INT_MAX;
else
return arr[length - 1]; // 0 based indexing system in C
}
int main(void)
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
size_t length = sizeof(arr) / sizeof(*arr);
printf("Last element of the array: %d\n", END(arr, length));
return 0;
}
Output:
Last element of the array: 10

How to return an array from function A and then function B takes this array

I have two functions in my main function.
I've tried to accomplish this problem with pointers, but as a beginner, it is very complicated to work with this.
int main(){
int *p;
p = function_A();
function_B(p);
return 0;
}
int function_A(){
static int myArray[3];
myArray[0] = 11;
myArray[1] = 22;
myArray[2] = 33;
return myArray;
}
int function_B(int *myPointer){
// Here I just want to print my array I've got from function_A() to the
// console
printf("%d", *myPointer)
return 0;
}
function_A should return a array and function_B should take this array.
Thanks!
There are some issues your compiler will already have told you.
First, you should define the functions before calling them, or at least forward declare them.
Second, to return an array, you need to return a pointer to the first element of this array, i.e. return type is int * and not int.
Third, as FredK pointed out, when you receive just a pointer, you have no chance to determine how many elements are in the array it points to. You can either terminate the array with a specific value, e.g. 0, or you need to return the size of the array, too.
See the following adaptions made to your program:
int* function_A(int *size){
static int myArray[3];
myArray[0] = 11;
myArray[1] = 22;
myArray[2] = 33;
if (size) {
*size = 3;
}
return myArray;
}
void function_B(int *myPointer, int size){
for (int i=0; i<size; i++) {
printf("%d\n", myPointer[i]);
}
}
int main(){
int *p;
int size=0;
p = function_A(&size);
function_B(p,size);
return 0;
}
Note: a reference to an array degrades to the address of the first byte of the array.
the following proposed code:
cleanly compiles
incorporates the comments to the question
assumes the programmer already knows the size of the array
performs the desired functionality
appended '\n' to format string of calls to printf() so output on separate lines
and now, the proposed code:
#include <stdio.h>
int * function_A( void );
void function_B(int *myPointer);
int main( void )
{
int *p;
p = function_A();
function_B(p);
return 0;
}
int * function_A()
{
static int myArray[3];
myArray[0] = 11;
myArray[1] = 22;
myArray[2] = 33;
return myArray;
}
void function_B(int *myPointer)
{
printf("%d\n", myPointer[0]);
printf("%d\n", myPointer[1]);
printf("%d\n", myPointer[2]);
}
a run of the program produces the following output:
11
22
33
Let's say you have a function that creates an array of ints:
int *create_int_array(const size_t num)
{
int *iarray;
size_t i;
if (num < 1)
return NULL; /* Let's not return an empty array. */
iarray = malloc(num * sizeof iarray[0]);
if (!iarray)
return NULL; /* Out of memory! */
/* Fill in the array with increasing integers. */
for (i = 0; i < num; i++)
iarray[i] = i + 1;
return iarray;
}
Let's say tou have a function that calculates the sum of the integers in the array. If we ignore any overflow issues, it could look like this:
int sum_int_array(const int *iarray, const size_t num)
{
int sum = 0;
size_t i;
/* Sum of an empty array is 0. */
if (num < 1)
return 0;
for (i = 0; i < num; i++)
sum += iarray[i];
return sum;
}
Note that sizeof is not a function, but a C language keyword. Its argument is only examined for its size. Thus, sizeof iarray[0] yields the size of each element in iarray, and is completely safe and valid even if iarray is undefined or NULL at that point. You see that idiom a lot in C programs; learn to read it as "size of first element of iarray", which is the same as "size of each element in iarray", because all C array elements have the exact same size.
In your main(), you could call them thus:
#ifndef NUM
#define NUM 5
#endif
int main(void)
{
int *array, result;
array = create_int_array(NUM);
if (!array) {
fprintf(stderr, "Out of memory!\n");
exit(EXIT_FAILURE);
}
result = sum_int_array(array, NUM);
printf("Sum is %d.\n", result);
free(array);
return EXIT_SUCCESS;
}
As you can see, there is really not much to it. Well, you do need to get familiar with the pointer syntax.
(The rule I like to point out is that when reading pointer types, read the specifiers from right to left, delimited by * read as a pointer to. Thus, int *const a reads as "a is a const, a pointer to int", and const char **b reads as "b is a pointer to a pointer to const char".)
In this kind of situations, a structure describing an array makes much more sense. For example:
typedef struct {
size_t max; /* Maximum number of elements val[] can hold */
size_t num; /* Number of elements in val[] */
int *val;
} iarray;
#define IARRAY_INIT { 0, 0, NULL }
The idea is that you can declare a variable of iarray type just as you would any other variable; but you also initialize those to an empty array using the IARRAY_INIT macro. In other words, thus:
iarray my_array = IARRAY_INIT;
With that initialization, the structure is always initialized to a known state, and we don't need a separate initialization function. We really only need a couple of helper functions:
static inline void iarray_free(iarray *array)
{
if (array) {
free(array->val);
array->max = 0;
array->num = 0;
array->val = NULL;
}
}
/* Try to grow the array dynamically.
Returns the number of elements that can be added right now. */
static inline size_t iarray_need(iarray *array, const size_t more)
{
if (!array)
return 0;
if (array->num + more > array->max) {
size_t max = array->num + more;
void *val;
/* Optional: Growth policy. Instead of allocating exactly
as much memory as needed, we allocate more,
in the hopes that this reduces the number of
realloc() calls, which tend to be a bit slow.
However, we don't want to waste too much
memory by allocating and then not using it. */
if (max < 16) {
/* Always allocate at least 16 elements, */
max = 16;
} else
if (max < 65536) {
/* up to 65535 elements add 50% extra, */
max = (3*max) / 2;
} else {
/* then round up to next multiple of 65536, less 16. */
max = (max | 65535) + 65521;
}
val = realloc(array->val, max * sizeof array->val[0]);
if (!val) {
/* We cannot grow the array. However, the old
array is still intact; realloc() does not
free it if it fails. */
return array->max - array->num;
}
/* Note: the new elements in array->val,
array->val[array->max] to
array->val[max-1], inclusive,
are undefined. That is fine, usually,
but might be important in some special
cases like resizing hash tables or such. */
array->max = max;
array->val = val;
}
return array->max - array->num;
}
/* Optional; same as initializing the variable to IARRAY_INIT. */
static inline void iarray_init(iarray *array)
{
array->max = 0;
array->num = 0;
array->val = NULL;
}
The static inline bit means that the functions are only visible in this compilation unit, and the compiler is free to implement the function directly at the call site. Basically, static inline is used for macro-like functions and accessor functions. If you put the structure in a header file (.h), you'd put the related static inline helper functions in it as well.
The growth policy part is only an example. If you omit the growth policy, and always reallocate to array->num + more elements, your code will call realloc() very often, potentially for every int appended. In most cases, doing it that often will slow down your program, because realloc() (as well as malloc(), calloc()) is kind-of slow. To avoid that, we prefer to pad or round up the allocation a bit: not too much to waste allocated but unused memory, but enough to keep the overall program fast, and not bottlenecked on too many realloc() calls.
A "good growth policy" is very much up to debate, and really depends on the task at hand. The above one should work really well on all current operating systems on desktop machines, laptops, and tablets, when the program needs only one or only a handful of such arrays.
(If a program uses many such arrays, it might implement an iarray_optimize() function, that reallocates the array to exactly the number of elements it has. Whenever an array is unlikely to change size soon, calling that function will ensure not too much memory is sitting unused but allocated in the arrays.)
Let's look at an example function that uses the above. Say, the obvious one: appending an integer to the array:
/* Append an int to the array.
Returns 0 if success, nonzero if an error occurs.
*/
int iarray_append(iarray *array, int value)
{
if (!array)
return -1; /* NULL array specified! */
if (iarray_need(array, 1) < 1)
return -2; /* Not enough memory to grow the array. */
array->val[array->num++] = value;
return 0;
}
Another example function would be one that sorts the ints in an array by ascending or descending value:
static int cmp_int_ascending(const void *ptr1, const void *ptr2)
{
const int val1 = *(const int *)ptr1;
const int val2 = *(const int *)ptr2;
return (val1 < val2) ? -1 :
(val1 > val2) ? +1 : 0;
}
static int cmp_int_descending(const void *ptr1, const void *ptr2)
{
const int val1 = *(const int *)ptr1;
const int val2 = *(const int *)ptr2;
return (val1 < val2) ? +1 :
(val1 > val2) ? -1 : 0;
}
static void iarray_sort(iarray *array, int direction)
{
if (array && array->num > 1) {
if (direction > 0)
qsort(array->val, array->num, sizeof array->val[0],
cmp_int_ascending);
else
if (direction < 0)
qsort(array->val, array->num, sizeof array->val[0],
cmp_int_descending);
}
}
Many new programmers do not realize that the standard C library has that nifty and quite efficient qsort() function for sorting arrays; all it needs is a comparison function. If the direction is positive for iarray_sort(), the array is sorted in ascending order, smallest int first; if direction is negative, then in descending order, largest int first.
A simple example main() that reads in all valid ints from standard input, sorts them, and prints them in ascending order (increasing value):
int main(void)
{
iarray array = IARRAY_INIT;
int value;
size_t i;
while (scanf(" %d", &value) == 1)
if (iarray_append(&array, value)) {
fprintf(stderr, "Out of memory.\n");
exit(EXIT_FAILURE);
}
iarray_sort(&array, +1); /* sort by increasing value */
for (i = 0; i < array.num; i++)
printf("%d\n", array.val[i]);
iarray_free(&array);
return EXIT_SUCCESS;
}
If size of array is indeed 3 (or other small fixed value), then you can simply use structs as values, something like:
struct ints3 {
int values[3];
// if needed, can add other fields
}
int main(){
struct ints3 ints;
ints = function_A();
function_B(&ints);
return 0;
}
// note about function_A signature: void is important,
// because in C empty () means function can take any arguments...
struct ints3 function_A(void) {
// use C designated initialiser syntax to create struct value,
// and return it directly
return (struct ints3){ .values = { 11, 22, 33 } };
}
int function_B(const struct ints3 *ints) {
// pass struct as const pointer to avoid copy,
// though difference to just passing a value in this case is insignificant
// could use for loop, see other answers, but it's just 3 values, so:
printf("%d %d %d\n", ints->values[0], ints->values[1], ints->values[2]);
return 0; // does this function really need return value?
}

Get count of an array from within a function

I'm trying to write a function that prints the elements of a given array. However, I don't understand how I can count the elements of the array which is passed into my function. Here's the code:
In this example, I am trying to get the count from within my function, though this only returns 1.
#include <stdio.h>
void first_function(int ages[], char *names[]) {
int i = 0;
int count = sizeof(*ages) / sizeof(int);
for(i = 0; i < count; i++) {
printf("%s has lived %d years.\n", names[i], ages[i]);
}
}
int main(int argc, char *argv[])
{
int ages[] = { 7, 32, 36 };
char *names[] = {
"Tiger", "Sandy",
"Ryan"
};
first_function(ages, names);
printf("---\n");
return 0;
}
In this example, I give the function an extra parameter (count), then get the count from within main. Is this the normal way to do it? It seems unclean somehow.
#include <stdio.h>
void first_function(int ages[], char *names[], int count) {
int i = 0;
for(i = 0; i < count; i++) {
printf("%s has lived %d years.\n", names[i], ages[i]);
}
}
int main(int argc, char *argv[])
{
int ages[] = { 7, 32, 36 };
char *names[] = {
"Tiger", "Sandy",
"Ryan"
};
int count = sizeof(ages) / sizeof(int);
first_function(ages, names, count);
printf("---\n");
return 0;
}
Your so-called unclean way is the normal way. (The sizeof idiom does not work if the array parameter has decayed to a pointer type). Although consider using a size_t type for the count, not an int.
Another approach is to use a particular value to signal the end of the array. Effectively this is how the string library functions work in C; with NUL signalling the end of the string.
According to the C Standard (6.7.6.3 Function declarators (including prototypes))
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’, where the type qualifiers (if any)
are those specified within the [ and ] of the array type
derivation....
So this function declaration
void first_function(int ages[], char *names[]);
is equivalent to the following declaration after adjusting the corresponding parameters declared like arrays.
void first_function( int *ages, char **names );
That is the parameters ages and names have pointer types within the function.
As result this expression
int count = sizeof(*ages) / sizeof(int);
(I think you mean
int count = sizeof(ages) / sizeof(int);
^^^^
nevertheless)
is equivalent to
int count = sizeof( int) / sizeof(int);
because the type of the sub-expression *ages is int.
If you will write the expression like
int count = sizeof(ages) / sizeof(int);
then it is equivalent to
int count = sizeof(int *) / sizeof(int);
and again will not yield the size of the array passed as the argument.
For such arrays that do not have a sentinel value you have to pass also their sizes to functions if it is required.
Thus the function should be declared like
void first_function(int ages[], char *names[], size_t n);
and called like
size_t count = sizeof(ages) / sizeof(*ages);
first_function(ages, names, count);
Pay attention to that there is no need to initialize the variable i within the function two times. The function can look like
void first_function(int ages[], char *names[], size_t count)
{
for ( size_t i = 0; i < count; i++)
{
printf("%s has lived %d years.\n", names[i], ages[i]);
}
}
Yes you can't use sizeof here to get the length of the array in the called function. Because array decays into pointer here in the called function. And that's why it will return sizeof pointer not size of array.
Solution- you need to pass another parameter specifying the size of the array or keeping a place holder like NULL or some value to mark the end of the array. (Well you have followed that in your second solution - which is perfectly fine and it works).
Return value of sizeof is size_t. Use size_t instead of int.
It's the right way to handle what sizeof operator returns.

length of array with repeated '\0', not strlen

If I need to find out length of a array with repeated '\0' character, what should I do? strlen won't be of use as it will simply stop with '\0'. In that case what is the best solution?
For example I have a buf;
now I don't know the length. I need to find out the length so that I can read whole data in it.
EDIT:
unsigned char buf[4096];
This buf has '\0' character in it. But it occurs in between data.I need to read the data even with '\0' character. strlen won't solve the purpose. So what is the way?
This is the part question from here : lzss decoding EOF character issue
Code is there. Please look at it.
There are 3 possibilities to determine array size in my mind:
The array is declared as array. The sizeof operator can be used. (Nice, it's comile-time resolved.)
The array is passed as pointer. The size cannot be determined from type. It has to be provided another way.
The array length can be determined by its contents. This is used for C strings but can be used for other types also. (Consider, that the end-marker consumes an element itself. Thus, the maximum length is one less than the capacity.)
Sample code test-array-size.c:
#include <stdio.h>
/* an array */
static int a[5] = { 0, 0, 0, 0, -1 };
/* a function */
void func(int a1[], int len1, int *a2)
{
/* size of a1 is passed as len1 */
printf("a1 has %d elements.\n", len1);
/* len of a2 is determined with end marker */
int len2;
for (len2 = 0; a2[len2] >= 0; ++len2);
printf("a2 has (at least) %d elements.\n", len2 + 1);
}
/* HOW IT DOES NOT WORK: */
void badFunc(int a3[5])
{
int len = sizeof a3 / sizeof a3[0]; /* number of elements */
printf("a3 seems to have %d elements.\n", len);
}
/* the main function */
int main()
{
/* length of a can be determined by sizeof */
int size = sizeof a; /* size in bytes */
int len = sizeof a / sizeof a[0]; /* number of elements */
printf("a has %d elements (consuming %d bytes).\n", len, size);
/* Because this is compile-time computable it can be even used for
* constants:
*/
enum { Len = sizeof a / sizeof a[0] };
func(a, Len, a);
badFunc(a);
/* done */
return 0;
}
Sample session:
$ gcc -std=c11 -o test-array-size test-array-size.c
test-array-size.c: In function 'badFunc':
test-array-size.c:19:20: warning: 'sizeof' on array function parameter 'a3' will return size of 'int *' [-Wsizeof-array-argument]
int len = sizeof a3 / sizeof a3[0]; /* number of elements */
^
test-array-size.c:17:18: note: declared here
void badFunc(int a3[5])
^
$ ./test-array-size.exe
a has 5 elements (consuming 20 bytes).
a1 has 5 elements.
a2 has (at least) 5 elements.
a3 seems to have 1 elements.
$

What does happen when we equation two pointer in C?

This is a C code to sort the substrings of a large string starting from each index but I cannot understand how can we sort the array a in the code.
As far as I understand:
we refer a[i] to &c[i] and thus it created n arrays but doesn't
&a[i][1] == &a[i+1][0]?
Since a[i] = &c[i], is it true that &a[i][0] == &c[i]?
If not, this looks like a faster way to create n(length of original
string) arrays, without actually copying it. Is that true?
My code
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define M 1
#define MAXN 5000000
char c[MAXN], *a[MAXN];
int pstrcmp(char **p, char **q){
return strcmp(*p, *q);
}
int main(){
int i, ch, n = 0, maxi, maxlen = -1;
while ((ch = getchar()) != EOF) {
a[n] = &c[n];
c[n++] = ch;
}
c[n] = 0;
qsort(a, n, sizeof(char *), pstrcmp);
printf("%s",a[1]);
return 0;
}
I'm guessing pstrcmp is a wrapper around strcmp that compares two pointers to char pointers. Something like:
int pstrcmp(const void *a, const void *b) {
return strcmp(*(char**)a, *(char**)b);
}
To answer your questions,
Yes, &a[i][1] == &a[i+1][0]. They both point to the i + 1-st character of c.
Yes, &a[i][0] == &c[i].
You are indeed creating pointers to n strings, but there is a catch: if you altered any string (say, the last character), you would be altering more strings. So these strings are not independent.
Conceptually, a[i] is a pointer to the suffix of c starting at position i. The program then sorts a according to the values of the strings they point to. So, for c = "abacaba", you would get { "a", "aba", "abacaba", "acaba", "ba", "bacaba", "caba" }.
Please note that there are faster ways to build suffix arrays.
In this code, I don't see sub-strings, as you don't build any.
Technically, a is an array of pointers of type char that could make it an array of strings, but the way you link c to a, effectively a is an index of c.
Inside the loop, you fill the index char by char. Later when you sort a, you sort the index.
The problem with the index is, that you can't really print it out as a string, as it is not a char * that the %s printf format modifier expects, but a char **. This alone should warn you about something spooky. I see that you evaded this problem as hard coding a[1] as parameter, but the sole problem of what index to use, tells, that you are going in the wrong way.
I've slightly edited your code, how it would print out the sorted array. If you think it is not doing what you want, there is a misunderstanding between what you want and what your code does (except the last printf).
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAXN 5000000
// This is an array of characters:
char c[MAXN];
// This is an array of pointers pointing to individual characters. Essentially, this is an index.
char *a[MAXN];
static int pstrcmp(const void *p1, const void *p2){
// wrapper between strcmp and qsort's compare signature.
// See: man 3 qsort -- http://linux.die.net/man/3/qsort
return strcmp(* (char * const *) p1, * (char * const *) p2);
}
int main() {
int ch;
size_t n = 0;
while ((ch = getchar()) != EOF) {
// In this loop, you systematically build up an index, where a[i] points to c[i].
a[n] = &c[n];
c[n] = ch;
n++;
}
c[n] = 0;
qsort(a, n, sizeof(char *), pstrcmp); // Now, you sort the _index_.
printf("\nc: %s\n", c); // Print Original array.
printf("a: "); // Print Ordered array:
for (size_t i = 0; i < n; i++)
printf("%c", *a[i]); // Look at the indirection
printf("\n");
return 0;
}

Resources