0

I'm working (in C) with a struct that contains arrays of strings. How do I point to one of those strings?

To make it a bit clearer, consider:

struct Books {
 char title[MAX1][MAX2];
 char author[MAX1][MAX2];
} books;

How do I point to the Nth title?

Edit: as remarked below, it should be title[MAX1][MAX2] and author[MAX1][MAX2]. Corrected above.

1
  • It doesn't make sense to have 2D arrays inside the struct in the first place. If you want an array of books, then each book struct should have a 1D array title and another 1D array author. Then you make a 2D array of structs. Commented Sep 15 at 11:10

6 Answers 6

5

There are two simple ways to get a pointer to the title (or author) of a specific book in this situation.

You can take the address of the first character of the Nth title (or author):

char *t = &books.title[N][0];

Or you can take advantage of the fact that an array decays to a pointer to its first element in most expressions:

char *a = books.author[N];

author[MAX1][MAX2] is an array of arrays; presumably MAX1 represents the maximum number of books (or authors, which may not always be true), and MAX2 represents the size of the arrays containing the titles and author names. Here author[0] is the first array in this array of arrays, i.e., it contains the string representing the first author's name. But since arrays (usually) decay to pointers, author[0] will (usually) decay to a pointer to its first element.

When someone talks about a "pointer to a string" they almost always mean "a pointer to the first character of a string", not "a pointer to an array containing a string." The string-handling functions in the Standard library expect pointers to the first character of any string on which they will operate.

The address operator (&) provides one of the exceptions to this rule of array decay: &author[0] is a pointer to the array author[0] because arrays do not decay to pointers when they are the operands of the & operator. A pointer to an array is not the same thing as a pointer to the first element of that array; they have different types, and different behavior under pointer arithmetic. But author[0] will decay to a pointer in most expressions, e.g., in a function call.

In this example code I have replaced MAX1 with MAX_BOOKS, and MAX2 with MAX_STR_LEN. MAX1 and MAX2 are not descriptive enough to make the code clear to readers. Note that MAX_STR_LEN is to be interpreted as the maximum length of a title or author name string, so the arrays which contain these strings must be one byte larger to contain the null terminator that all C strings must (by definition) possess.

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

#define MAX_BOOKS    128  // maximum number of books
#define MAX_STR_LEN  255  // maximum title or author name length

struct Books {
  char title[MAX_BOOKS][MAX_STR_LEN+1];   // include space for `\0`
  char author[MAX_BOOKS][MAX_STR_LEN+1];  // in titles and author names
} books;

int main(void) {
  char *t = &books.title[0][0];
  strcpy(t, "Remembrance of Things Past");

  char *a = books.author[0];
  strcpy(a, "Proust, Marcel");

  // These are all equivalent:
  printf("%s, '%s'\n", books.author[0], books.title[0]);
  printf("%s, '%s'\n", &books.author[0][0], &books.title[0][0]);
  printf("%s, '%s'\n", a, t);
}

Program output:

Proust, Marcel, 'Remembrance of Things Past'
Proust, Marcel, 'Remembrance of Things Past'
Proust, Marcel, 'Remembrance of Things Past'
Sign up to request clarification or add additional context in comments.

Comments

2

MAX1 refers to maximum number of string elements, and MAX2 refers to the maximum size of each string(including terminating NUL byte) to be held in each element. This code demonstrates getting the nth element by parsing every element of the structure sequentially. You can stop the parsing to select any individual (nth) element you like from the arrays. This code also demonstrates how to initialize the structure at the time of declaration, should you ever need to do that -- it's very useful at times.

This code is compiled and run-tested by me just now. A runnable version lives here: https://godbolt.org/z/nvTGev6er

#include <stdio.h>

#define MAX1 5
#define MAX2 80

struct Books {
 char title[MAX1][MAX2];
 char author[MAX1][MAX2];
} books =
{
    {   /* Book Titles: */
        {"To Eat a Mockingbird" },
        {"Tails of the Shrew" },
        {"Beswain the Nights" },
        {"Earstwhile Earnest" },
        {"Yes, the Foghorn Knows" }
    },
    {   /* Authors: */
        {"Francis Cunningham" },
        {"Bable Sonorius" },
        {"Cooker M. J." },
        {"Earnest Hummingway" },
        {"Toys R Us" }
    }
};


int main()
{
    int iii;

    for(iii=0; iii < MAX1; iii++)
        printf("Title:  %s \tAuthor: %s\n", books.title[iii], books.author[iii]); 

    return 0;
}

Output:

Title:  To Eat a Mockingbird    Author: Francis Cunningham 
Title:  Tails of the Shrew      Author: Bable Sonorius     
Title:  Beswain the Nights      Author: Cooker M. J.       
Title:  Earstwhile Earnest      Author: Earnest Hummingway 
Title:  Yes, the Foghorn Knows  Author: Toys R Us          

Comments

0

Your struct does not contain 2 arrays of strings but 2 arrays of chars, so basically two strings. If you want a string array, you need to create a char[n][MAX], where n is the ammount of strings and MAX the length of each string. Pointing to the Nth title would look like this:
char* title = books->title[n];

1 Comment

char* title = books->title[n]; has two problems: books is not a pointer to a struct in OP code, and with char title[n][MAX] title[n] is an out-of-bounds access. Perhaps you meant books.title[N] where N < n and books is a struct.
0

To make it a bit clearer, consider:

struct Books {
 char title[MAX1][MAX2];
 char author[MAX1][MAX2];
} books;

How do I point to the Nth title?

As you declare title it is an array of arrays, so you can point to any i title (assume b is declared as a struct Books type) by just using b.title[i] This will return you the pointer to the first character you need to manage it as a string. The same works for b.author[i] which is the i-est array of the matrix.

Comments

0

As many have pointed out, the correct way to get the nth title would be

struct Books {
    char title[MAX1][MAX2];
    char author[MAX1][MAX2];
} books;
char *nth_title = books.title[N];

But your current implementation uses parallel arrays, which make it hard to create a pointer to one book.

As mentioned in the comment section, it is better practice to rewrite books as an array of structs.

Look at the following:

struct book {
    char title[MAX2];
    char author[MAX2];
} books[MAX1];

Now we can get the Nth title using books[N].title but we can also create a pointer to a book using:

struct book *nth_book = &books[N];

And for completeness:

char *nth_title = nth_book->title;

This also has the added benefit of making it very clear that MAX2 is the maximum length of each element and that MAX1 is the maximum number of books.

Comments

0

How do I point to the Nth title?

If you have an array as for example

T a[MAX];

where T is some type of elements of the array then to access the N-th element of the array you can use the subscript operator like

a[N]

In you example you have two-dimensional arrays

struct Books {
 char title[MAX1][MAX2];
 char author[MAX1][MAX2];
} books;

The element type of the arrays is char[MAX2]. So to access the N-th element of any array you can write as shown above

title[N]

or

author[N]

To make the approach similar to the access of the one-dimensional array you can introduce a typedef name for the array element type of the arrays like

typedef char T[MAX2];

and then declare the object books like

struct Books {
 T title[MAX1];
 T author[MAX1];
} books;

and correspondingly to access the N-th element of the arrays you again can write

title[N]

or

author[N]

If you need a pointer to the N-th element of the arrays then you could declare a pointer to an element of the arrays the following way

T *ptr =title + N;

or

T *ptr = author + N;

Or without using the typedef you can write

char ( *ptr )[MAX2] = title + N;

or

char ( *ptr )[MAX2] = author + N;

and then write for example in a call of printf like

printf( "%s\n", *ptr );

provided that elements of the arrays contain strings.

It is the same as to write

printf( "%s\n", title[N] );

or

printf( "%s\n", author[N] );

Pay attention to that the expression title[N] or author[N] are equivalent to expressions *( title + N ) or *( author + N ).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.