simple array question

Discussion in 'C Programming' started by Michael, Aug 18, 2006.

  1. Michael

    Michael Guest

    Hi,

    I am trying to pass a function an array of strings, but I am having trouble
    getting the indexing to index the strings rather than the individual
    characters of one of the strings.
    I have declared an array as:

    char *stringArray[] = {"one","two","three","a"};

    When I pass the array using:
    CompareStringArray(*stringArray, 3, min); /*I know I have a magic number
    here*/

    Then try to access the elements with
    func(array+i, array+result); /* func(char *, char
    *) */
    the array+i is indexing through the first string, rather than through the
    array of strings.

    I dont understand why array+1 = "ne" and not "two"

    can anyone help me with this please?

    Regards

    Michael
     
    Michael, Aug 18, 2006
    #1
    1. Advertising

  2. Michael

    Michael Mair Guest

    Michael schrieb:
    > Hi,
    >
    > I am trying to pass a function an array of strings, but I am having trouble
    > getting the indexing to index the strings rather than the individual
    > characters of one of the strings.
    > I have declared an array as:
    >
    > char *stringArray[] = {"one","two","three","a"};
    >
    > When I pass the array using:
    > CompareStringArray(*stringArray, 3, min); /*I know I have a magic number
    > here*/


    Passing *stringArray is equivalent to passing stringArray[0]
    which is the start address of a string containing "one".

    > Then try to access the elements with
    > func(array+i, array+result); /* func(char *, char
    > *) */
    > the array+i is indexing through the first string, rather than through the
    > array of strings.


    If you posted actual code, then I would not have to guess whether
    func is supposed to be CompareStringArray() even though the number
    of parameters changed.

    The correct prototype for CompareStringArray() has
    "char *StringArray[]" or "char **StringArray" as first parameter.

    >
    > I dont understand why array+1 = "ne" and not "two"


    Probably because you passed the address of "one"...


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Aug 18, 2006
    #2
    1. Advertising

  3. "Michael" <> writes:
    > I am trying to pass a function an array of strings, but I am having trouble
    > getting the indexing to index the strings rather than the individual
    > characters of one of the strings.
    > I have declared an array as:
    >
    > char *stringArray[] = {"one","two","three","a"};


    That's an array of pointers.

    A "string" is really more of a data format that a data type. It's
    defined by the standard as "a contiguous sequence of characters
    terminated by and including the first null character".

    What you've declared is an array of pointers to strings (where a
    "pointer to a string" is defined as "a pointer to its initial (lowest
    addressed) character").

    > When I pass the array using:
    > CompareStringArray(*stringArray, 3, min); /*I know I have a magic number
    > here*/


    *stringArray is a value of type char*. It points to the string "one".

    > Then try to access the elements with
    > func(array+i, array+result); /* func(char *, char
    > *) */
    > the array+i is indexing through the first string, rather than through the
    > array of strings.


    Right. When you increment a pointer to FOO, the result points to the
    next FOO in memory (assuming there is one). In this case, you're
    incrementing a pointer to char (pointing to the 'o' of "one" and
    getting a pointer to the next char (pointig to the 'n' of "one").

    Your CompareStringArray function needs to have a parameter of type
    char**, and you need to pass it stringArray, not *stringArray.

    And you need to read section 6 of the comp.lang.c FAQ,
    <http://www.c-faq.com/>.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Aug 18, 2006
    #3
  4. Michael

    CBFalconer Guest

    Michael wrote:
    >
    > I am trying to pass a function an array of strings, but I am
    > having trouble getting the indexing to index the strings rather
    > than the individual characters of one of the strings.
    > I have declared an array as:
    >
    > char *stringArray[] = {"one","two","three","a"};
    >
    > When I pass the array using:
    > CompareStringArray(*stringArray, 3, min); /*I know I have a
    > magic number here*/
    >
    > Then try to access the elements with
    > func(array+i, array+result); /* func(char *, char *) */
    > the array+i is indexing through the first string, rather than
    > through the array of strings.
    >
    > I dont understand why array+1 = "ne" and not "two"
    >
    > can anyone help me with this please?


    You are not keeping the types of things clear. Keeping your
    declaration only, if we then pass that to a function:

    foo(stringarray)

    the function would be declared as:

    foo(char **arr)
    or
    foo(char *arr[])

    the point being that what foo sees is an array of pointers to char,
    identified by a pointer to the first of those, i.e. the char **.
    You can now get pointers to the various strings by dereferencing
    arr for some i from 0 to the number available.

    foo(char **arr) {
    char *p;
    int i;

    for (i = 0; i < 3; i++) {
    p = arr;
    /* operate on p to access the string */
    /* which is read-only for your declaration */
    puts(p); /* for example */
    }
    }

    It would be well to have the original declaration mark its own
    boundary by terminating it with a NULL, ie:

    char *stringArray[] = {"one", "two", "three", "a", NULL};

    --
    "The power of the Executive to cast a man into prison without
    formulating any charge known to the law, and particularly to
    deny him the judgement of his peers, is in the highest degree
    odious and is the foundation of all totalitarian government
    whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
     
    CBFalconer, Aug 18, 2006
    #4
  5. Michael

    Michael Guest

    "Michael Mair" <> wrote in message
    news:...
    > Michael schrieb:
    >> Hi,
    >>
    >> I am trying to pass a function an array of strings, but I am having
    >> trouble getting the indexing to index the strings rather than the
    >> individual characters of one of the strings.
    >> I have declared an array as:
    >>
    >> char *stringArray[] = {"one","two","three","a"};
    >>
    >> When I pass the array using:
    >> CompareStringArray(*stringArray, 3, min); /*I know I have a magic
    >> number here*/

    >
    > Passing *stringArray is equivalent to passing stringArray[0]
    > which is the start address of a string containing "one".
    >
    >> Then try to access the elements with
    >> func(array+i, array+result); /* func(char *,
    >> char *) */
    >> the array+i is indexing through the first string, rather than through the
    >> array of strings.

    >
    > If you posted actual code, then I would not have to guess whether
    > func is supposed to be CompareStringArray() even though the number
    > of parameters changed.
    >
    > The correct prototype for CompareStringArray() has
    > "char *StringArray[]" or "char **StringArray" as first parameter.
    >
    >>
    >> I dont understand why array+1 = "ne" and not "two"

    >
    > Probably because you passed the address of "one"...
    >
    >
    > Cheers
    > Michael
    > --
    > E-Mail: Mine is an /at/ gmx /dot/ de address.


    Ok, following is what I have written.

    When I originally wrote this I had **stringArray, not *stringArray in my
    function call, but the compiler complained:
    "passing arg 1 of CompareStringArray makes pointer from integer without a
    cast".
    I know I have some magic numbers and stuff, I'm really just trying to sort
    out the array stuff though.

    int main(){
    char *stringArray[] = {"one","two","three","four","five"};
    int smallest;
    int largest;

    smallest = CompareStringArray(*stringArray, 4, min);
    largest = CompareStringArray(*stringArray, 4, max);

    if(smallest > -1){
    printf("\nsmallest is %s at position
    %d",stringArray[smallest], smallest);
    }else {
    printf("\nempty array");
    }
    if(largest > -1){
    printf("\nlargest is %s at position
    %d",stringArray[largest], largest);
    }else {
    printf("\nempty array");
    }

    fgetc(stdin);
    return 0;
    }



    int max(char *string1, char *string2){
    int result = FALSE;

    if(strlen(string1) > strlen(string2)){
    result = TRUE;
    }

    return result;
    }

    int min(char *string1, char *string2){
    int result = FALSE;

    if(strlen(string1) < strlen(string2)){
    result = TRUE;
    }

    return result;
    }

    int CompareStringArray(char *array, int size, int (*func)(char*, char*)){
    int i;
    int result;

    if(!strlen(array)){
    result = 0; /*arbitrary starting point
    for result*/
    for(i = 0; i < size; i++){
    if(func(array+i, array+result)){ /*check if current is longer
    than longest found yet*/
    result = i;
    }
    }
    } else {
    result = -1; /*zero length array*/
    }
    return result;
    }
     
    Michael, Aug 18, 2006
    #5
  6. Michael

    pete Guest

    Michael wrote:
    >
    > "Michael Mair" <> wrote in message
    > news:...
    > > Michael schrieb:
    > >> Hi,
    > >>
    > >> I am trying to pass a function an array of strings, but I am having
    > >> trouble getting the indexing to index the strings rather than the
    > >> individual characters of one of the strings.
    > >> I have declared an array as:
    > >>
    > >> char *stringArray[] = {"one","two","three","a"};
    > >>
    > >> When I pass the array using:
    > >> CompareStringArray(*stringArray, 3, min); /*I know I have a magic
    > >> number here*/

    > >
    > > Passing *stringArray is equivalent to passing stringArray[0]
    > > which is the start address of a string containing "one".
    > >
    > >> Then try to access the elements with
    > >> func(array+i, array+result); /* func(char *,
    > >> char *) */
    > >> the array+i is indexing through the first string, rather than through the
    > >> array of strings.

    > >
    > > If you posted actual code, then I would not have to guess whether
    > > func is supposed to be CompareStringArray() even though the number
    > > of parameters changed.
    > >
    > > The correct prototype for CompareStringArray() has
    > > "char *StringArray[]" or "char **StringArray" as first parameter.
    > >
    > >>
    > >> I dont understand why array+1 = "ne" and not "two"

    > >
    > > Probably because you passed the address of "one"...
    > >
    > >
    > > Cheers
    > > Michael
    > > --
    > > E-Mail: Mine is an /at/ gmx /dot/ de address.

    >
    > Ok, following is what I have written.
    >
    > When I originally wrote this I had **stringArray, not *stringArray in my
    > function call, but the compiler complained:
    > "passing arg 1 of CompareStringArray makes pointer from integer without a
    > cast".
    > I know I have some magic numbers and stuff, I'm really just trying to sort
    > out the array stuff though.
    >
    > int main(){
    > char *stringArray[] = {"one","two","three","four","five"};
    > int smallest;
    > int largest;
    >
    > smallest = CompareStringArray(*stringArray, 4, min);
    > largest = CompareStringArray(*stringArray, 4, max);
    >
    > if(smallest > -1){
    > printf("\nsmallest is %s at position
    > %d",stringArray[smallest], smallest);
    > }else {
    > printf("\nempty array");
    > }
    > if(largest > -1){
    > printf("\nlargest is %s at position
    > %d",stringArray[largest], largest);
    > }else {
    > printf("\nempty array");
    > }
    >
    > fgetc(stdin);
    > return 0;
    > }
    >
    > int max(char *string1, char *string2){
    > int result = FALSE;
    >
    > if(strlen(string1) > strlen(string2)){
    > result = TRUE;
    > }
    >
    > return result;
    > }
    >
    > int min(char *string1, char *string2){
    > int result = FALSE;
    >
    > if(strlen(string1) < strlen(string2)){
    > result = TRUE;
    > }
    >
    > return result;
    > }
    >
    > int CompareStringArray(char *array, int size, int (*func)(char*, char*)){
    > int i;
    > int result;
    >
    > if(!strlen(array)){
    > result = 0; /*arbitrary starting point
    > for result*/
    > for(i = 0; i < size; i++){
    > if(func(array+i, array+result)){ /*check if current is longer
    > than longest found yet*/
    > result = i;
    > }
    > }
    > } else {
    > result = -1; /*zero length array*/
    > }
    > return result;
    > }


    /* BEGIN ptr_sort.c */
    /*
    ** lencomp() compares pointers to strings,
    ** according to string length.
    */
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    #define SORT_FUNCTIONS { \
    no_sort, "This is the original order of the test array:",\
    si_sort, "Stable insertionsort:", \
    s38sort, "Nonstable Shellsort, four is after " \
    "nine, and eight is before three:", \
    q_sort, "Standard library qsort, " \
    "unspecified ordering of equal keys:", \
    }
    #define NUMBERS { \
    {"one"},{ "two"},{"three"},{"four"},{"five"}, \
    {"six"},{"seven"},{"eight"},{"nine"},{ "ten"}, \
    }
    #define GT(A, B) (lencomp((A), (B)) > 0)
    #define NMEMB (sizeof numbers / sizeof *numbers)
    #define SORTS (sizeof s_F / sizeof *s_F)
    #define str(s) # s
    #define xstr(s) str(s)
    #define E_TYPE char *

    typedef E_TYPE e_type;

    int lencomp(const void *, const void *);
    void no_sort(e_type *, size_t);
    void si_sort(e_type *, size_t);
    void s38sort(e_type *, size_t);
    void q_sort(e_type *, size_t);

    int main(void)
    {
    size_t element, sort;
    struct sf {
    void (*function)(e_type *, size_t);
    const char *description;
    } s_F[] = SORT_FUNCTIONS;
    const e_type numbers[] = NUMBERS;
    e_type copy[NMEMB];

    puts("/* BEGIN output from ptr_sort.c */\n");
    puts("Arrays of type " xstr(E_TYPE)
    ",\nare being sorted by string length.");
    for (sort = 0; sort != SORTS; ++sort) {
    putchar('\n');
    puts(s_F[sort].description);
    memcpy(copy, numbers, sizeof copy);
    s_F[sort].function(copy, NMEMB);
    for (element = 0; element != NMEMB; ++element) {
    puts(copy[element]);
    }
    }
    puts("\n/* END output from ptr_sort.c */");
    return 0;
    }

    int lencomp(const void *a, const void *b)
    {
    const size_t a_len = strlen(*(e_type *)a);
    const size_t b_len = strlen(*(e_type *)b);

    return b_len > a_len ? -1 : a_len != b_len;
    }

    void no_sort(e_type *array, size_t nmemb)
    {
    array, nmemb;
    }

    void si_sort(e_type *array, size_t nmemb)
    {
    e_type temp, *base, *low, *high;

    if (nmemb-- > 1) {
    base = array;
    do {
    low = array++;
    if (GT(low, array)) {
    high = array;
    temp = *high;
    do {
    *high-- = *low;
    if (low == base) {
    break;
    }
    --low;
    } while (GT(low, &temp));
    *high = temp;
    }
    } while (--nmemb != 0);
    }
    }

    void s38sort(e_type *array, size_t nmemb)
    {
    e_type temp, *i, *j, *k, *after;

    after = array + nmemb;
    if (nmemb > (size_t)-1 / 3) {
    nmemb /= 3;
    }
    do {
    for (i = array + nmemb; after != i; ++i) {
    j = i - nmemb;
    if (GT(j, i)) {
    k = i;
    temp = *k;
    do {
    *k = *j;
    k = j;
    if (nmemb + array > j) {
    break;
    }
    j -= nmemb;
    } while (GT(j, &temp));
    *k = temp;
    }
    }
    nmemb = nmemb != 2 ? 3 * nmemb / 8 : 1;
    } while (nmemb != 0);
    }

    void q_sort(e_type *array, size_t nmemb)
    {
    qsort(array, nmemb, sizeof *array, lencomp);
    }

    /* END ptr_sort.c */


    --
    pete
     
    pete, Aug 18, 2006
    #6
  7. Michael

    CBFalconer Guest

    Michael wrote:
    > "Michael Mair" <> wrote in message
    >

    .... snip ...
    >>
    >> The correct prototype for CompareStringArray() has
    >> "char *StringArray[]" or "char **StringArray" as first parameter.
    >>

    REMEMBER THE ABOVE
    ... snip ...
    >
    > Ok, following is what I have written.
    >
    > When I originally wrote this I had **stringArray, not *stringArray in my
    > function call, but the compiler complained:
    > "passing arg 1 of CompareStringArray makes pointer from integer without a
    > cast".


    And remember that too.

    The following is only what I had to do to your source to make it
    compile (not run). The changes consist of proper formatting (via
    indent), judicious insertion of the 'const' keyword, and addition
    of the #includes and #defines at the start. In addition I had to
    move the function definitions so that functions are defined before
    use. The source line length is limited to something that will
    avoid wrapping on most newsreaders, and the 'void' is added to the
    definition of main.

    You are still using some nominally illegal variable names, i.e.
    "stri....". These, among others, are reserved for the
    implementation and can nip you in the butt.

    With the above 'remember's and the cleaned up compilable source,
    see if you can figure out the basic problems that remain.

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

    #define FALSE (0)
    #define TRUE (1)

    /* ----------------------- */

    int max(const char *string1, const char *string2)
    {
    int result = FALSE;

    if (strlen(string1) > strlen(string2)) {
    result = TRUE;
    }
    return result;
    }

    /* ----------------------- */

    int min(const char *string1, const char *string2)
    {
    int result = FALSE;

    if (strlen(string1) < strlen(string2)) {
    result = TRUE;
    }
    return result;
    }

    /* ----------------------- */

    int CompareStringArray(const char *array, int size,
    int (*func)(const char *, const char *))
    {
    int i;
    int result;

    if (!strlen(array)) {
    result = 0; /* arbitrary starting point for result */
    for (i = 0; i < size; i++) {
    if (func(array + i, array + result)) {
    /* check if current is longer than longest found yet */
    result = i;
    }
    }
    }
    else {
    result = -1; /* zero length array */
    }
    return result;
    }

    /* ----------------------- */

    int main(void)
    {
    const char *stringArray[] =
    { "one", "two", "three", "four", "five" };
    int smallest;
    int largest;

    smallest = CompareStringArray(*stringArray, 4, min);
    largest = CompareStringArray(*stringArray, 4, max);

    if (smallest > -1) {
    printf("\nsmallest is %s at position %d",
    stringArray[smallest], smallest);
    }
    else {
    printf("\nempty array");
    }
    if (largest > -1) {
    printf("\nlargest is %s at position %d",
    stringArray[largest], largest);
    }
    else {
    printf("\nempty array");
    }
    fgetc(stdin);
    return 0;
    }

    --
    "The power of the Executive to cast a man into prison without
    formulating any charge known to the law, and particularly to
    deny him the judgement of his peers, is in the highest degree
    odious and is the foundation of all totalitarian government
    whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
     
    CBFalconer, Aug 18, 2006
    #7
  8. Michael

    Joe Wright Guest

    Michael wrote:
    > Hi,
    >
    > I am trying to pass a function an array of strings, but I am having trouble
    > getting the indexing to index the strings rather than the individual
    > characters of one of the strings.
    > I have declared an array as:
    >
    > char *stringArray[] = {"one","two","three","a"};
    >
    > When I pass the array using:
    > CompareStringArray(*stringArray, 3, min); /*I know I have a magic number
    > here*/
    >
    > Then try to access the elements with
    > func(array+i, array+result); /* func(char *, char
    > *) */
    > the array+i is indexing through the first string, rather than through the
    > array of strings.
    >
    > I dont understand why array+1 = "ne" and not "two"
    >
    > can anyone help me with this please?
    >


    Your definition of stringArray is 'array of pointer to char'. Expressing
    stringArray will give you the first pointer. *stringArray is the first
    character of the first string. Think about it.

    --
    Joe Wright
    "Everything should be made as simple as possible, but not simpler."
    --- Albert Einstein ---
     
    Joe Wright, Aug 18, 2006
    #8
  9. Michael

    Michael Guest

    "CBFalconer" <> wrote in message
    news:...
    > Michael wrote:
    >> "Michael Mair" <> wrote in message
    >>

    > ... snip ...
    >>>
    >>> The correct prototype for CompareStringArray() has
    >>> "char *StringArray[]" or "char **StringArray" as first parameter.
    >>>

    > REMEMBER THE ABOVE
    > ... snip ...
    >>
    >> Ok, following is what I have written.
    >>
    >> When I originally wrote this I had **stringArray, not *stringArray in my
    >> function call, but the compiler complained:
    >> "passing arg 1 of CompareStringArray makes pointer from integer without a
    >> cast".

    >
    > And remember that too.
    >
    > The following is only what I had to do to your source to make it
    > compile (not run). The changes consist of proper formatting (via
    > indent), judicious insertion of the 'const' keyword, and addition
    > of the #includes and #defines at the start. In addition I had to
    > move the function definitions so that functions are defined before
    > use. The source line length is limited to something that will
    > avoid wrapping on most newsreaders, and the 'void' is added to the
    > definition of main.
    >
    > You are still using some nominally illegal variable names, i.e.
    > "stri....". These, among others, are reserved for the
    > implementation and can nip you in the butt.
    >
    > With the above 'remember's and the cleaned up compilable source,
    > see if you can figure out the basic problems that remain.
    >
    > #include <stdio.h>
    > #include <string.h>
    >
    > #define FALSE (0)
    > #define TRUE (1)
    >
    > /* ----------------------- */
    >
    > int max(const char *string1, const char *string2)
    > {
    > int result = FALSE;
    >
    > if (strlen(string1) > strlen(string2)) {
    > result = TRUE;
    > }
    > return result;
    > }
    >
    > /* ----------------------- */
    >
    > int min(const char *string1, const char *string2)
    > {
    > int result = FALSE;
    >
    > if (strlen(string1) < strlen(string2)) {
    > result = TRUE;
    > }
    > return result;
    > }
    >
    > /* ----------------------- */
    >
    > int CompareStringArray(const char *array, int size,
    > int (*func)(const char *, const char *))
    > {
    > int i;
    > int result;
    >
    > if (!strlen(array)) {
    > result = 0; /* arbitrary starting point for result */
    > for (i = 0; i < size; i++) {
    > if (func(array + i, array + result)) {
    > /* check if current is longer than longest found yet */
    > result = i;
    > }
    > }
    > }
    > else {
    > result = -1; /* zero length array */
    > }
    > return result;
    > }
    >
    > /* ----------------------- */
    >
    > int main(void)
    > {
    > const char *stringArray[] =
    > { "one", "two", "three", "four", "five" };
    > int smallest;
    > int largest;
    >
    > smallest = CompareStringArray(*stringArray, 4, min);
    > largest = CompareStringArray(*stringArray, 4, max);
    >
    > if (smallest > -1) {
    > printf("\nsmallest is %s at position %d",
    > stringArray[smallest], smallest);
    > }
    > else {
    > printf("\nempty array");
    > }
    > if (largest > -1) {
    > printf("\nlargest is %s at position %d",
    > stringArray[largest], largest);
    > }
    > else {
    > printf("\nempty array");
    > }
    > fgetc(stdin);
    > return 0;
    > }
    >
    > --
    > "The power of the Executive to cast a man into prison without
    > formulating any charge known to the law, and particularly to
    > deny him the judgement of his peers, is in the highest degree
    > odious and is the foundation of all totalitarian government
    > whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
    >
    >


    Thanks for the help, but you don't seem to have changed anything about the
    way the array is passed or handled, which is where my problem is.
    The array+i still indexes through the first element, rather than through the
    array of strings.
    I know this is to do with the way I am passing the array, but I cant figure
    out what concept I have misunderstood.

    const char *stringArray[] =
    { "one", "two", "three", "four", "five" };
    so
    stringArray[0][0] = 'o'
    stringArray[0][1] = 'n'
    stringArray[0][2] = 'e'
    correct?

    so
    stringArray[0] = 'one'
    correct?

    so
    *stringArray = 'one'
    correct?

    Regards

    Michael
     
    Michael, Aug 19, 2006
    #9
  10. Michael

    CBFalconer Guest

    Michael wrote:
    > "CBFalconer" <> wrote in message
    >> Michael wrote:
    >>> "Michael Mair" <> wrote in message
    >>>

    >> ... snip ...
    >>>>
    >>>> The correct prototype for CompareStringArray() has
    >>>> "char *StringArray[]" or "char **StringArray" as first parameter.
    >>>>

    >> REMEMBER THE ABOVE
    >> ... snip ...
    >>>
    >>> Ok, following is what I have written.
    >>>
    >>> When I originally wrote this I had **stringArray, not *stringArray
    >>> in my function call, but the compiler complained:
    >>> "passing arg 1 of CompareStringArray makes pointer from integer
    >>> without a cast".

    >>
    >> And remember that too.
    >>

    .... snip ...
    >
    > Thanks for the help, but you don't seem to have changed anything
    > about the way the array is passed or handled, which is where my
    > problem is. The array+i still indexes through the first element,
    > rather than through the array of strings.
    > I know this is to do with the way I am passing the array, but I
    > cant figure out what concept I have misunderstood.
    >
    > const char *stringArray[] =
    > { "one", "two", "three", "four", "five" };
    > so
    > stringArray[0][0] = 'o'
    > stringArray[0][1] = 'n'
    > stringArray[0][2] = 'e'
    > correct?
    >
    > so
    > stringArray[0] = 'one'
    > correct?


    No. stringArray[0] is a pointer to the char array "one\0", which
    in turn is a C string.

    I deliberately left your program fundamentally unchanged but
    readable (and compileable) so you could learn something. Look up
    at the start of this message at the two "remember"s I left about
    earlier comments for some clues.

    --
    "The power of the Executive to cast a man into prison without
    formulating any charge known to the law, and particularly to
    deny him the judgement of his peers, is in the highest degree
    odious and is the foundation of all totalitarian government
    whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
     
    CBFalconer, Aug 19, 2006
    #10
  11. Michael

    goose Guest

    CBFalconer wrote:

    <snipped>

    > You are still using some nominally illegal variable names, i.e.
    > "stri....". These, among others, are reserved for the
    > implementation and can nip you in the butt.


    AFAIK, "str..." is reserved for function names. Variable
    names starting with "str..." are safe.

    goose,
     
    goose, Aug 19, 2006
    #11
  12. Michael

    Michael Guest

    "CBFalconer" <> wrote in message
    news:...
    > Michael wrote:
    >> "CBFalconer" <> wrote in message
    >>> Michael wrote:
    >>>> "Michael Mair" <> wrote in message
    >>>>
    >>> ... snip ...
    >>>>>
    >>>>> The correct prototype for CompareStringArray() has
    >>>>> "char *StringArray[]" or "char **StringArray" as first parameter.
    >>>>>
    >>> REMEMBER THE ABOVE
    >>> ... snip ...
    >>>>
    >>>> Ok, following is what I have written.
    >>>>
    >>>> When I originally wrote this I had **stringArray, not *stringArray
    >>>> in my function call, but the compiler complained:
    >>>> "passing arg 1 of CompareStringArray makes pointer from integer
    >>>> without a cast".
    >>>
    >>> And remember that too.
    >>>

    > ... snip ...
    >>
    >> Thanks for the help, but you don't seem to have changed anything
    >> about the way the array is passed or handled, which is where my
    >> problem is. The array+i still indexes through the first element,
    >> rather than through the array of strings.
    >> I know this is to do with the way I am passing the array, but I
    >> cant figure out what concept I have misunderstood.
    >>
    >> const char *stringArray[] =
    >> { "one", "two", "three", "four", "five" };
    >> so
    >> stringArray[0][0] = 'o'
    >> stringArray[0][1] = 'n'
    >> stringArray[0][2] = 'e'
    >> correct?
    >>
    >> so
    >> stringArray[0] = 'one'
    >> correct?

    >
    > No. stringArray[0] is a pointer to the char array "one\0", which
    > in turn is a C string.
    >


    This is how I understood it. But when I try to step through the array I find
    I am stepping through the first element, so have something wrong but I
    cannot find what.

    > I deliberately left your program fundamentally unchanged but
    > readable (and compileable) so you could learn something. Look up
    > at the start of this message at the two "remember"s I left about
    > earlier comments for some clues.


    These are clues I already had.
    I have been struggling with this for some time and only posted here when I
    found I was going in circles.

    >
    > --
    > "The power of the Executive to cast a man into prison without
    > formulating any charge known to the law, and particularly to
    > deny him the judgement of his peers, is in the highest degree
    > odious and is the foundation of all totalitarian government
    > whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
    >
    >
     
    Michael, Aug 19, 2006
    #12
  13. goose wrote:
    > CBFalconer wrote:
    >
    > <snipped>
    >
    >> You are still using some nominally illegal variable names, i.e.
    >> "stri....". These, among others, are reserved for the
    >> implementation and can nip you in the butt.

    >
    > AFAIK, "str..." is reserved for function names. Variable
    > names starting with "str..." are safe.


    Extern declarations and definitions of variables of which the names start
    with str (followed by a lowercase letter) are not safe, and when <string.h>
    is included neither are static declarations and definitions with file
    scope. However, it is true that non-file scope variable names can safely
    start with str.
     
    Harald van =?UTF-8?B?RMSzaw==?=, Aug 19, 2006
    #13
  14. Michael

    CBFalconer Guest

    Michael wrote:
    > "CBFalconer" <> wrote in message
    >> Michael wrote:
    >>> "CBFalconer" <> wrote in message
    >>>> Michael wrote:
    >>>>> "Michael Mair" <> wrote in message
    >>>>>
    >>>> ... snip ...
    >>>>>>
    >>>>>> The correct prototype for CompareStringArray() has
    >>>>>> "char *StringArray[]" or "char **StringArray" as first parameter.
    >>>>>>
    >>>> REMEMBER THE ABOVE
    >>>> ... snip ...
    >>>>>
    >>>>> Ok, following is what I have written.
    >>>>>
    >>>>> When I originally wrote this I had **stringArray, not *stringArray
    >>>>> in my function call, but the compiler complained:
    >>>>> "passing arg 1 of CompareStringArray makes pointer from integer
    >>>>> without a cast".
    >>>>
    >>>> And remember that too.
    >>>>

    >> ... snip ...
    >>>
    >>> Thanks for the help, but you don't seem to have changed anything
    >>> about the way the array is passed or handled, which is where my
    >>> problem is. The array+i still indexes through the first element,
    >>> rather than through the array of strings.
    >>> I know this is to do with the way I am passing the array, but I
    >>> cant figure out what concept I have misunderstood.
    >>>
    >>> const char *stringArray[] =
    >>> { "one", "two", "three", "four", "five" };
    >>> so
    >>> stringArray[0][0] = 'o'
    >>> stringArray[0][1] = 'n'
    >>> stringArray[0][2] = 'e'
    >>> correct?
    >>>
    >>> so
    >>> stringArray[0] = 'one'
    >>> correct?

    >>
    >> No. stringArray[0] is a pointer to the char array "one\0", which
    >> in turn is a C string.
    >>

    >
    > This is how I understood it. But when I try to step through the array I find
    > I am stepping through the first element, so have something wrong but I
    > cannot find what.
    >
    >> I deliberately left your program fundamentally unchanged but
    >> readable (and compileable) so you could learn something. Look up
    >> at the start of this message at the two "remember"s I left about
    >> earlier comments for some clues.

    >
    > These are clues I already had.
    > I have been struggling with this for some time and only posted here when I
    > found I was going in circles.


    You chose the wrong way to fix those initial complaints. Start by
    passing the right parameter to CompareStringArray.

    --
    "The power of the Executive to cast a man into prison without
    formulating any charge known to the law, and particularly to
    deny him the judgement of his peers, is in the highest degree
    odious and is the foundation of all totalitarian government
    whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
     
    CBFalconer, Aug 19, 2006
    #14
  15. Michael

    Michael Mair Guest

    Michael schrieb:
    > "Michael Mair" <> wrote in message
    > news:...
    >>Michael schrieb:
    >>>I am trying to pass a function an array of strings, but I am having
    >>>trouble getting the indexing to index the strings rather than the
    >>>individual characters of one of the strings.
    >>>I have declared an array as:
    >>>
    >>>char *stringArray[] = {"one","two","three","a"};
    >>>
    >>>When I pass the array using:
    >>>CompareStringArray(*stringArray, 3, min); /*I know I have a magic
    >>>number here*/

    >>
    >>Passing *stringArray is equivalent to passing stringArray[0]
    >>which is the start address of a string containing "one".
    >>
    >>>Then try to access the elements with
    >>>func(array+i, array+result); /* func(char *,
    >>>char *) */
    >>>the array+i is indexing through the first string, rather than through the
    >>>array of strings.

    >>
    >>If you posted actual code, then I would not have to guess whether
    >>func is supposed to be CompareStringArray() even though the number
    >>of parameters changed.
    >>
    >>The correct prototype for CompareStringArray() has
    >>"char *StringArray[]" or "char **StringArray" as first parameter.

    >
    > Ok, following is what I have written.
    >
    > When I originally wrote this I had **stringArray, not *stringArray in my
    > function call, but the compiler complained:
    > "passing arg 1 of CompareStringArray makes pointer from integer without a
    > cast".
    > I know I have some magic numbers and stuff, I'm really just trying to sort
    > out the array stuff though.
    >


    missing includes

    > int main(){
    > char *stringArray[] = {"one","two","three","four","five"};
    > int smallest;
    > int largest;
    >
    > smallest = CompareStringArray(*stringArray, 4, min);
    > largest = CompareStringArray(*stringArray, 4, max);


    pass string array.

    >
    > if(smallest > -1){
    > printf("\nsmallest is %s at position
    > %d",stringArray[smallest], smallest);


    Note: Not the smallest, but one of the smallest.
    Another thing: The last character you output to a text
    stream should be a '\n', if you want to be sure that your
    output "arrives".

    > }else {
    > printf("\nempty array");
    > }
    > if(largest > -1){
    > printf("\nlargest is %s at position
    > %d",stringArray[largest], largest);
    > }else {
    > printf("\nempty array");
    > }
    >
    > fgetc(stdin);
    > return 0;
    > }
    >
    >
    >
    > int max(char *string1, char *string2){
    > int result = FALSE;
    >
    > if(strlen(string1) > strlen(string2)){
    > result = TRUE;
    > }
    >
    > return result;
    > }
    >
    > int min(char *string1, char *string2){
    > int result = FALSE;
    >
    > if(strlen(string1) < strlen(string2)){
    > result = TRUE;
    > }
    >
    > return result;
    > }
    >
    > int CompareStringArray(char *array, int size, int (*func)(char*, char*)){

    char **array
    > int i;
    > int result;
    >
    > if(!strlen(array)){

    size > 0
    > result = 0; /*arbitrary starting point
    > for result*/
    > for(i = 0; i < size; i++){
    > if(func(array+i, array+result)){ /*check if current is longer
    > than longest found yet*/


    func(array, array[result])

    > result = i;
    > }
    > }
    > } else {
    > result = -1; /*zero length array*/
    > }
    > return result;
    > }


    I added "const" where appropriate and shortened min() and max():

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

    int CompareStringArray (const char **array,
    int size,
    int (*func)(const char*, const char*));
    int min (const char *string1, const char *string2);
    int max (const char *string1, const char *string2);

    int main (void)
    {
    const char *stringArray[] = {"one","two","three","four","five"};
    int smallest;
    int largest;

    smallest = CompareStringArray(stringArray, 4, min);
    largest = CompareStringArray(stringArray, 4, max);

    if (smallest > -1) {
    printf("\nOne of the smallest is %s at position %d\n",
    stringArray[smallest],
    smallest);
    }
    else {
    printf("\nempty array\n");
    }
    if (largest > -1) {
    printf("\nOne of the largest is %s at position %d\n",
    stringArray[largest], largest);
    }
    else {
    printf("\nempty array\n");
    }

    getchar();
    return 0;
    }

    int max (const char *string1, const char *string2)
    {
    return strlen(string1) > strlen(string2);
    }

    int min (const char *string1, const char *string2)
    {
    return strlen(string1) < strlen(string2);
    }

    int CompareStringArray (const char **array,
    int size,
    int (*func)(const char*, const char*))
    {
    int i;
    int result;

    if (size <= 0) {
    result = -1;
    }
    else {
    result = 0; /*arbitrary starting point for result*/
    for (i = 0; i < size; i++) {
    if ((*func)(array, array[result])) {
    /*check if current is longer than longest found yet*/
    result = i;
    }
    }
    }

    return result;
    }


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
     
    Michael Mair, Aug 19, 2006
    #15
  16. "Michael" <> wrote in message
    news:44e6555a$0$320$...
    >
    > Thanks for the help, but you don't seem to have changed anything about the
    > way the array is passed or handled, which is where my problem is.
    > The array+i still indexes through the first element, rather than through

    the
    > array of strings.
    > I know this is to do with the way I am passing the array, but I cant

    figure
    > out what concept I have misunderstood.
    >
    > const char *stringArray[] =
    > { "one", "two", "three", "four", "five" };
    > so
    > stringArray[0][0] = 'o'
    > stringArray[0][1] = 'n'
    > stringArray[0][2] = 'e'
    > correct?
    >


    Yes.

    > so
    > stringArray[0] = 'one'
    > correct?
    >


    Yes.

    > so
    > *stringArray = 'one'
    > correct?
    >


    Yes.


    What you "misunderstood" was how to declare 'array'. This isn't your fault
    but a problem with how standard literature describes arrays in C.

    You have:
    int CompareStringArray(char *array,

    When you need:
    int CompareStringArray(char **array,

    The reason is that C doesn't actually have arrays. C only has pointers and
    values. Occasionally, you'll hear about arrays being "second class
    citizens" in C. What that means is arrays are an artificial construct in C
    which appear to be arrays but aren't arrays. So, in a declaration: "char
    mstr[10]", mstr or mstr[] is thought of as an array. But, [] is actually a
    subscript operator which functions on pointers only. Therefore, mstr is a
    pointer, not an array. Specifically, mstr is a pointer to preallocated
    storage storage of 10 char's. By definition, a is the same as
    *((a)+(b)), where a is the pointer. What this means is that "char
    array[][]" or "char *array[]" is the same as "char **array".


    Here's a sample program based on your post. You'll see your array accessed
    using both forms: a and *((a)+(b)).

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

    void pvi(char **mstr)
    {
    printf("0: %s\n",mstr[0]);
    printf("1: %s\n",mstr[1]);
    printf("2: %s\n",mstr[2]);
    printf("3: %s\n",*(mstr));
    printf("4: %s\n",*(mstr+1));
    printf("5: %s\n",*(mstr+2));
    }

    int main(void)
    {
    char *stringArray[] =
    { "one", "two", "three", "four", "five" };

    printf("%s\n",&stringArray[0][0]);
    printf("%s\n",&stringArray[0][1]);
    printf("%s\n",&stringArray[0][2]);
    printf("%s\n",stringArray[0]);
    printf("%s\n",stringArray[1]);
    printf("%s\n",stringArray[2]);
    printf("%s\n",*stringArray);
    printf("%s\n",*(stringArray+1));
    printf("%s\n",*(stringArray+2));

    pvi(stringArray);

    return(0);
    }


    Rod Pemberton
     
    Rod Pemberton, Aug 19, 2006
    #16
  17. Michael

    pete Guest

    Rod Pemberton wrote:

    > The reason is that C doesn't actually have arrays.
    > C only has pointers and values.
    > Occasionally, you'll hear about arrays being "second class
    > citizens" in C.
    > What that means is arrays are an artificial construct in C
    > which appear to be arrays but aren't arrays.


    That's a pile of crap.
    The "second class citizen" status of arrays
    has to do with expressions of array type being automaticaly
    converted to expressions of pointer type in most circumstances,
    which among other things, prevents expressions of array type
    from being left operands of the assignment operator.

    --
    pete
     
    pete, Aug 19, 2006
    #17
  18. "pete" <> wrote in message
    news:...
    > Rod Pemberton wrote:
    >
    > > The reason is that C doesn't actually have arrays.
    > > C only has pointers and values.
    > > Occasionally, you'll hear about arrays being "second class
    > > citizens" in C.
    > > What that means is arrays are an artificial construct in C
    > > which appear to be arrays but aren't arrays.

    >
    > That's a pile of crap.
    > The "second class citizen" status of arrays
    > has to do with expressions of array type being automaticaly
    > converted to expressions of pointer type in most circumstances,


    And why do you think they are being converted to expressions of pointer
    type? Reread completely:

    RP> The reason is that C doesn't actually have arrays. C only has pointers
    and
    RP> values. Occasionally, you'll hear about arrays being "second class
    RP> citizens" in C. What that means is arrays are an artificial construct
    in C
    RP> which appear to be arrays but aren't arrays. So, in a declaration:
    "char
    RP> mstr[10]", mstr or mstr[] is thought of as an array. But, [] is
    actually a
    RP> subscript operator which functions on pointers only. Therefore, mstr is
    a
    RP> pointer, not an array. Specifically, mstr is a pointer to preallocated
    RP> storage storage of 10 char's. By definition, a is the same as
    RP> *((a)+(b)), where a is the pointer. What this means is that "char
    RP> array[][]" or "char *array[]" is the same as "char **array".

    > which among other things, prevents expressions of array type
    > from being left operands of the assignment operator.



    Rod Pemberton
     
    Rod Pemberton, Aug 19, 2006
    #18
  19. Michael

    Flash Gordon Guest

    Rod Pemberton wrote:
    > "pete" <> wrote in message
    > news:...
    >> Rod Pemberton wrote:
    >>
    >>> The reason is that C doesn't actually have arrays.
    >>> C only has pointers and values.
    >>> Occasionally, you'll hear about arrays being "second class
    >>> citizens" in C.
    >>> What that means is arrays are an artificial construct in C
    >>> which appear to be arrays but aren't arrays.

    >> That's a pile of crap.
    >> The "second class citizen" status of arrays
    >> has to do with expressions of array type being automaticaly
    >> converted to expressions of pointer type in most circumstances,

    >
    > And why do you think they are being converted to expressions of pointer
    > type? Reread completely:


    Having reread it completely I am even more convinced it is crap than
    when I saw pete saying it was crap.

    > RP> The reason is that C doesn't actually have arrays. C only has pointers


    The C standard disagrees with you.

    > and
    > RP> values. Occasionally, you'll hear about arrays being "second class
    > RP> citizens" in C. What that means is arrays are an artificial construct
    > in C
    > RP> which appear to be arrays but aren't arrays. So, in a declaration:


    Wrong.

    > "char
    > RP> mstr[10]", mstr or mstr[] is thought of as an array.


    Because it is except when it is the declaration of a parameter to a
    function.

    > But, [] is
    > actually a
    > RP> subscript operator which functions on pointers only.


    True. Fortunately the name of an array gets automatically converted to a
    pointer in this situation.

    > Therefore, mstr is
    > a
    > RP> pointer, not an array.


    Wrong. Or you would be able to do:
    mstr = 0;
    Also check the value of:
    sizeof mstr
    Check the type of &mstr, this is a pointer to an array, not a pointer to
    a pointer, and it is *not* assignment compatible with a pointer to a
    pointer.

    > Specifically, mstr is a pointer to preallocated
    > RP> storage storage of 10 char's. By definition, a is the same as
    > RP> *((a)+(b)), where a is the pointer.


    Also true by definition when a is an array.

    > What this means is that "char
    > RP> array[][]" or "char *array[]" is the same as "char **array".


    Complete and utter rubish. Try compiling a program that passes an array
    of arrays to a function expecting a pointer to a pointer without using
    casts and watch the diagnostics fly. Or search the group for all the
    occasions where people have tried this or tried it the other way around
    and it has not worked. Or just read question 6.18 of the FAQ.

    >> which among other things, prevents expressions of array type
    >> from being left operands of the assignment operator.


    I suggest, Rob, that you read the comp.lang.c FAQ, specifically section
    6. You obviously don't yet understand arrays and/or pointers in C.
    Either that or you are deliberately trying to mislead.
    --
    Flash Gordon
    Still sigless on this computer.
     
    Flash Gordon, Aug 19, 2006
    #19
  20. "Rod Pemberton" <> writes:
    [...]
    > The reason is that C doesn't actually have arrays. C only has pointers and
    > values. Occasionally, you'll hear about arrays being "second class
    > citizens" in C. What that means is arrays are an artificial construct in C
    > which appear to be arrays but aren't arrays.


    Utter nonsense.

    C most certainly does have arrays. There are some serious limitations
    on what you can do with array values in expressions; specifically, any
    expression of array type is implicitly converted to the address of its
    first element *unless* it's the operand of a unary "&" or "sizeof"
    operator, or it's a string literal in an initializer used to
    initialize an array.

    In that sense, arrays are considered "second-class" types. But
    there's no rigorous definition of what "second-class" means. There
    are a number of operations you can perform on, say, integer types that
    you can't (directly) perform on array types -- but the same is true,
    to a lesser extent, for structure types. Each set of types has a
    defined set of operations that can be performed on it.

    The indexing operator takes two operands, a pointer value and an
    integer value; for it to work, the pointer value must point to the
    first element of an array object.

    Pointers are not arrays. Arrays are not pointers. Certain features
    of the language can make it difficult, but by no means impossible, to
    keep the distinction straight. Section 6 of the comp.lang.c FAQ,
    <http://www.c-faq.com/>, does an excellent job of clearing up the
    confusion. Please read it.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Aug 19, 2006
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    590
  2. Kevin Spencer

    Re: Simple Simple question!!!

    Kevin Spencer, Jun 25, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    697
    Kevin Spencer
    Jun 25, 2004
  3. Daniel Frey

    Simple Question - Simple Answer?

    Daniel Frey, Dec 28, 2004, in forum: XML
    Replies:
    4
    Views:
    873
    Daniel Frey
    Jan 12, 2005
  4. Oli

    simple simple question

    Oli, Jan 26, 2004, in forum: ASP General
    Replies:
    10
    Views:
    393
    Roland Hall
    Jan 26, 2004
  5. Peter Bailey

    simple, simple array question

    Peter Bailey, Apr 8, 2008, in forum: Ruby
    Replies:
    7
    Views:
    238
    Peter Bailey
    Apr 8, 2008
Loading...

Share This Page