Two dimensional array with char pointer in c











up vote
0
down vote

favorite












In the following code I am trying for each band to get the number of band members. I've tried a number of things but nothing works. The following looks like it should but doesn't.



If any one could point out what I'm doing wrong it would be greatly appreciated.



numMembers = sizeof(bands[0]) / sizeof(bands[0].members);

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

int main(void) {
int i;
int j;
int numBands;
int numMembers;
int limit = 4;

struct band {
char name[10];
char *members[20];
};

const struct band bands =
{ {"Beatles", {"John", "George", "Paul", "Ringo", "Pete", "George"} },
{"Stones", {"Mick", "Keith", "Bill", "Charlie", "Brian"} },
{"Who", {"Pete", "Roger", "Keith", "John"} },
{"JHE", {"Jimmy", "Noel", "Mitch"} } };

numBands = sizeof(bands) / sizeof(bands[0]);

for ( i = 0; i < numBands; ++i ) {
printf ("%sn", bands[i].name);
numMembers = sizeof(bands[0]) / sizeof(bands[0].members);
for ( j = 0; j < numMembers; ++j )
printf ("t%s", bands[i].members[j]);
printf ("n");
}

return 0;
}









share|improve this question






















  • Design question: why use a fixed array size char name[10] for band names, yet a character pointer for band members? I'd expect something like char *name; char *members[20]; or char name[10]; char members[20][30];
    – chux
    Nov 7 at 23:16










  • The first line is a syntax error
    – M.M
    Nov 7 at 23:20















up vote
0
down vote

favorite












In the following code I am trying for each band to get the number of band members. I've tried a number of things but nothing works. The following looks like it should but doesn't.



If any one could point out what I'm doing wrong it would be greatly appreciated.



numMembers = sizeof(bands[0]) / sizeof(bands[0].members);

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

int main(void) {
int i;
int j;
int numBands;
int numMembers;
int limit = 4;

struct band {
char name[10];
char *members[20];
};

const struct band bands =
{ {"Beatles", {"John", "George", "Paul", "Ringo", "Pete", "George"} },
{"Stones", {"Mick", "Keith", "Bill", "Charlie", "Brian"} },
{"Who", {"Pete", "Roger", "Keith", "John"} },
{"JHE", {"Jimmy", "Noel", "Mitch"} } };

numBands = sizeof(bands) / sizeof(bands[0]);

for ( i = 0; i < numBands; ++i ) {
printf ("%sn", bands[i].name);
numMembers = sizeof(bands[0]) / sizeof(bands[0].members);
for ( j = 0; j < numMembers; ++j )
printf ("t%s", bands[i].members[j]);
printf ("n");
}

return 0;
}









share|improve this question






















  • Design question: why use a fixed array size char name[10] for band names, yet a character pointer for band members? I'd expect something like char *name; char *members[20]; or char name[10]; char members[20][30];
    – chux
    Nov 7 at 23:16










  • The first line is a syntax error
    – M.M
    Nov 7 at 23:20













up vote
0
down vote

favorite









up vote
0
down vote

favorite











In the following code I am trying for each band to get the number of band members. I've tried a number of things but nothing works. The following looks like it should but doesn't.



If any one could point out what I'm doing wrong it would be greatly appreciated.



numMembers = sizeof(bands[0]) / sizeof(bands[0].members);

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

int main(void) {
int i;
int j;
int numBands;
int numMembers;
int limit = 4;

struct band {
char name[10];
char *members[20];
};

const struct band bands =
{ {"Beatles", {"John", "George", "Paul", "Ringo", "Pete", "George"} },
{"Stones", {"Mick", "Keith", "Bill", "Charlie", "Brian"} },
{"Who", {"Pete", "Roger", "Keith", "John"} },
{"JHE", {"Jimmy", "Noel", "Mitch"} } };

numBands = sizeof(bands) / sizeof(bands[0]);

for ( i = 0; i < numBands; ++i ) {
printf ("%sn", bands[i].name);
numMembers = sizeof(bands[0]) / sizeof(bands[0].members);
for ( j = 0; j < numMembers; ++j )
printf ("t%s", bands[i].members[j]);
printf ("n");
}

return 0;
}









share|improve this question













In the following code I am trying for each band to get the number of band members. I've tried a number of things but nothing works. The following looks like it should but doesn't.



If any one could point out what I'm doing wrong it would be greatly appreciated.



numMembers = sizeof(bands[0]) / sizeof(bands[0].members);

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

int main(void) {
int i;
int j;
int numBands;
int numMembers;
int limit = 4;

struct band {
char name[10];
char *members[20];
};

const struct band bands =
{ {"Beatles", {"John", "George", "Paul", "Ringo", "Pete", "George"} },
{"Stones", {"Mick", "Keith", "Bill", "Charlie", "Brian"} },
{"Who", {"Pete", "Roger", "Keith", "John"} },
{"JHE", {"Jimmy", "Noel", "Mitch"} } };

numBands = sizeof(bands) / sizeof(bands[0]);

for ( i = 0; i < numBands; ++i ) {
printf ("%sn", bands[i].name);
numMembers = sizeof(bands[0]) / sizeof(bands[0].members);
for ( j = 0; j < numMembers; ++j )
printf ("t%s", bands[i].members[j]);
printf ("n");
}

return 0;
}






c arrays pointers struct char






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 7 at 21:54









Griffau

103




103












  • Design question: why use a fixed array size char name[10] for band names, yet a character pointer for band members? I'd expect something like char *name; char *members[20]; or char name[10]; char members[20][30];
    – chux
    Nov 7 at 23:16










  • The first line is a syntax error
    – M.M
    Nov 7 at 23:20


















  • Design question: why use a fixed array size char name[10] for band names, yet a character pointer for band members? I'd expect something like char *name; char *members[20]; or char name[10]; char members[20][30];
    – chux
    Nov 7 at 23:16










  • The first line is a syntax error
    – M.M
    Nov 7 at 23:20
















Design question: why use a fixed array size char name[10] for band names, yet a character pointer for band members? I'd expect something like char *name; char *members[20]; or char name[10]; char members[20][30];
– chux
Nov 7 at 23:16




Design question: why use a fixed array size char name[10] for band names, yet a character pointer for band members? I'd expect something like char *name; char *members[20]; or char name[10]; char members[20][30];
– chux
Nov 7 at 23:16












The first line is a syntax error
– M.M
Nov 7 at 23:20




The first line is a syntax error
– M.M
Nov 7 at 23:20












3 Answers
3






active

oldest

votes

















up vote
1
down vote



accepted










You don't have a "two dimensional array". What you have is a simple array of struct band which contains two simple character arrays as its members.



There is actually no need to compute the number of "members" in each bands. All you need to compute is the number of bands, e.g.



    int nbands = sizeof bands / sizeof *bands;


Since you have declared members as an array of pointers and have used an initializer to initialize the first four, the remaining pointers will have all bytes set 0 resulting in each being NULL. You can simply loop for the members with while (bands[i].members[j]), incrementing j each iteration, e.g.



#include <stdio.h>

struct band {
char name[10];
char *members[20];
};

int main(void) {

const struct band bands = {
{"Beatles", {"John", "George", "Paul", "Ringo", "Pete", "George"} },
{"Stones", {"Mick", "Keith", "Bill", "Charlie", "Brian"} },
{"Who", {"Pete", "Roger", "Keith", "John"} },
{"JHE", {"Jimmy", "Noel", "Mitch"} } };

int nbands = sizeof bands / sizeof *bands;

for (int i = 0; i < nbands; i++) {
int j = 0;
puts (bands[i].name);
while (j < 20 && bands[i].members[j])
printf (" %s", bands[i].members[j++]);
putchar ('n');
}
}


(note addition of j < 20, which as pointed out by @chux in the comments, the test of while (bands[i].members[j]) alone could result in Undefined Behavior in the case where there were additional bands added bands after initialization and all 20 pointers of the members struct member were filled)



Example Use/Output



$ ./bin/bandmembers
Beatles
John George Paul Ringo Pete George
Stones
Mick Keith Bill Charlie Brian
Who
Pete Roger Keith John
JHE
Jimmy Noel Mitch


Additionally, don't use magic numbers in your code. Instead, If you need a constant, #define one (or more), e.g.



#define MAXNM 10
#define MAXMB 20


or use a global enum to do the same thing, e.g.



enum { MAXNM = 10, MAXMB = 20 };


That will allow you to eliminate the magic numbers, e.g.



struct band {
char name[MAXNM];
char *members[MAXMB];
};


This becomes very important for maintainability as your code length grows.






share|improve this answer



















  • 1




    while (bands[i].members[j]) printf (" %s", bands[i].members[j++]); this is UB when the initialization had 20 band members. Maybe while (j < MAXMB && bands[i].members[j])?
    – chux
    Nov 7 at 23:04












  • David many thanks. Your points on magic numbers are noted.
    – Griffau
    Nov 7 at 23:05










  • I don't think the MAXNM and MAXNB improve the code . It's obvious what the numbers mean in their original context, and the use of sizeof avoids the possibility of errors due to code duplication
    – M.M
    Nov 7 at 23:22










  • @chux while the check for j < MAXMB is a fine addition, the check as it sits is while (bands[i].members[j] != NULL) which is not UB based on the initialization rules. See § 6.7.9 Initialization (p10) and § 6.7.9 Initialization (p19)
    – David C. Rankin
    Nov 8 at 0:33










  • @M.M agreed for this short snippet. The addition was to address future programming where the "code length grows". I try to address all points and what could become bad habits. Sometimes what seems obvious to veterans is useful information for those just learning.
    – David C. Rankin
    Nov 8 at 0:37


















up vote
1
down vote














what I'm doing wrong




Wrong numMembers calculation



numMembers should be the number of elements in the array. (20)



Each bands[i].member has 20 elements given char *members[20]. Several elements are populated with pointers to string literals. Most elements remain 0 (NULL).



// numMembers = sizeof(bands[0]) / sizeof(bands[0].members);
numMembers = sizeof(bands[0].members) / sizeof(bands[0].members[0]);




Attempting to print NULL as a string



printf ("t%s", bands[i].members[j]); not valid when bands[i].members[j] is NULL.



Not all bands[i].members[j] are set to a non-NULL value.



numBands = sizeof(bands) / sizeof(bands[0]);

for ( i = 0; i < numBands; ++i ) {
printf ("%sn", bands[i].name);
numMembers = sizeof(bands[i].members) / sizeof(bands[i].members[0]);

for ( j = 0; j < numMembers; ++j ) {
if (bands[i].members[j]) {
printf ("t%s", bands[i].members[j]);
}
}

printf ("n");
}
}




Deeper:



const struct band bands = { {"Beatles", ... forms bands and sizes bands based on the number of initializers.



char *members[20]; is a fixed size even if the initialization did not supply 20 strings. The first elements members[20] are initialized per the list, the remaining elements have a pointer value of 0.






share|improve this answer























  • Chux many thanks for your input it is greatly appreciated.
    – Griffau
    Nov 7 at 23:07




















up vote
0
down vote













For numMembers = sizeof(bands[0]) / sizeof(bands[0].members);



sizeofband(bands[0]) will give the size of one band struct - that is the 10 bytes for name, and then 20 * the size of a pointer.



sizeof(bands[0].members); will give 20*thesizeof a pointer



Not what you want, as sizeof doesn't take into consideration the content of whatever the pointer points to.



It also doesn't take into consideration that some of those members pointers will be NULL so you don't want to count them.



Perhaps better doing:



for ( j = 0; j < 20 &&  bands[i].members[j] != NULL; ++j )
printf ("t%s", bands[i].members[j]);





share|improve this answer





















  • @loastbard, many thanks for you help.
    – Griffau
    Nov 7 at 23:08











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53198424%2ftwo-dimensional-array-with-char-pointer-in-c%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










You don't have a "two dimensional array". What you have is a simple array of struct band which contains two simple character arrays as its members.



There is actually no need to compute the number of "members" in each bands. All you need to compute is the number of bands, e.g.



    int nbands = sizeof bands / sizeof *bands;


Since you have declared members as an array of pointers and have used an initializer to initialize the first four, the remaining pointers will have all bytes set 0 resulting in each being NULL. You can simply loop for the members with while (bands[i].members[j]), incrementing j each iteration, e.g.



#include <stdio.h>

struct band {
char name[10];
char *members[20];
};

int main(void) {

const struct band bands = {
{"Beatles", {"John", "George", "Paul", "Ringo", "Pete", "George"} },
{"Stones", {"Mick", "Keith", "Bill", "Charlie", "Brian"} },
{"Who", {"Pete", "Roger", "Keith", "John"} },
{"JHE", {"Jimmy", "Noel", "Mitch"} } };

int nbands = sizeof bands / sizeof *bands;

for (int i = 0; i < nbands; i++) {
int j = 0;
puts (bands[i].name);
while (j < 20 && bands[i].members[j])
printf (" %s", bands[i].members[j++]);
putchar ('n');
}
}


(note addition of j < 20, which as pointed out by @chux in the comments, the test of while (bands[i].members[j]) alone could result in Undefined Behavior in the case where there were additional bands added bands after initialization and all 20 pointers of the members struct member were filled)



Example Use/Output



$ ./bin/bandmembers
Beatles
John George Paul Ringo Pete George
Stones
Mick Keith Bill Charlie Brian
Who
Pete Roger Keith John
JHE
Jimmy Noel Mitch


Additionally, don't use magic numbers in your code. Instead, If you need a constant, #define one (or more), e.g.



#define MAXNM 10
#define MAXMB 20


or use a global enum to do the same thing, e.g.



enum { MAXNM = 10, MAXMB = 20 };


That will allow you to eliminate the magic numbers, e.g.



struct band {
char name[MAXNM];
char *members[MAXMB];
};


This becomes very important for maintainability as your code length grows.






share|improve this answer



















  • 1




    while (bands[i].members[j]) printf (" %s", bands[i].members[j++]); this is UB when the initialization had 20 band members. Maybe while (j < MAXMB && bands[i].members[j])?
    – chux
    Nov 7 at 23:04












  • David many thanks. Your points on magic numbers are noted.
    – Griffau
    Nov 7 at 23:05










  • I don't think the MAXNM and MAXNB improve the code . It's obvious what the numbers mean in their original context, and the use of sizeof avoids the possibility of errors due to code duplication
    – M.M
    Nov 7 at 23:22










  • @chux while the check for j < MAXMB is a fine addition, the check as it sits is while (bands[i].members[j] != NULL) which is not UB based on the initialization rules. See § 6.7.9 Initialization (p10) and § 6.7.9 Initialization (p19)
    – David C. Rankin
    Nov 8 at 0:33










  • @M.M agreed for this short snippet. The addition was to address future programming where the "code length grows". I try to address all points and what could become bad habits. Sometimes what seems obvious to veterans is useful information for those just learning.
    – David C. Rankin
    Nov 8 at 0:37















up vote
1
down vote



accepted










You don't have a "two dimensional array". What you have is a simple array of struct band which contains two simple character arrays as its members.



There is actually no need to compute the number of "members" in each bands. All you need to compute is the number of bands, e.g.



    int nbands = sizeof bands / sizeof *bands;


Since you have declared members as an array of pointers and have used an initializer to initialize the first four, the remaining pointers will have all bytes set 0 resulting in each being NULL. You can simply loop for the members with while (bands[i].members[j]), incrementing j each iteration, e.g.



#include <stdio.h>

struct band {
char name[10];
char *members[20];
};

int main(void) {

const struct band bands = {
{"Beatles", {"John", "George", "Paul", "Ringo", "Pete", "George"} },
{"Stones", {"Mick", "Keith", "Bill", "Charlie", "Brian"} },
{"Who", {"Pete", "Roger", "Keith", "John"} },
{"JHE", {"Jimmy", "Noel", "Mitch"} } };

int nbands = sizeof bands / sizeof *bands;

for (int i = 0; i < nbands; i++) {
int j = 0;
puts (bands[i].name);
while (j < 20 && bands[i].members[j])
printf (" %s", bands[i].members[j++]);
putchar ('n');
}
}


(note addition of j < 20, which as pointed out by @chux in the comments, the test of while (bands[i].members[j]) alone could result in Undefined Behavior in the case where there were additional bands added bands after initialization and all 20 pointers of the members struct member were filled)



Example Use/Output



$ ./bin/bandmembers
Beatles
John George Paul Ringo Pete George
Stones
Mick Keith Bill Charlie Brian
Who
Pete Roger Keith John
JHE
Jimmy Noel Mitch


Additionally, don't use magic numbers in your code. Instead, If you need a constant, #define one (or more), e.g.



#define MAXNM 10
#define MAXMB 20


or use a global enum to do the same thing, e.g.



enum { MAXNM = 10, MAXMB = 20 };


That will allow you to eliminate the magic numbers, e.g.



struct band {
char name[MAXNM];
char *members[MAXMB];
};


This becomes very important for maintainability as your code length grows.






share|improve this answer



















  • 1




    while (bands[i].members[j]) printf (" %s", bands[i].members[j++]); this is UB when the initialization had 20 band members. Maybe while (j < MAXMB && bands[i].members[j])?
    – chux
    Nov 7 at 23:04












  • David many thanks. Your points on magic numbers are noted.
    – Griffau
    Nov 7 at 23:05










  • I don't think the MAXNM and MAXNB improve the code . It's obvious what the numbers mean in their original context, and the use of sizeof avoids the possibility of errors due to code duplication
    – M.M
    Nov 7 at 23:22










  • @chux while the check for j < MAXMB is a fine addition, the check as it sits is while (bands[i].members[j] != NULL) which is not UB based on the initialization rules. See § 6.7.9 Initialization (p10) and § 6.7.9 Initialization (p19)
    – David C. Rankin
    Nov 8 at 0:33










  • @M.M agreed for this short snippet. The addition was to address future programming where the "code length grows". I try to address all points and what could become bad habits. Sometimes what seems obvious to veterans is useful information for those just learning.
    – David C. Rankin
    Nov 8 at 0:37













up vote
1
down vote



accepted







up vote
1
down vote



accepted






You don't have a "two dimensional array". What you have is a simple array of struct band which contains two simple character arrays as its members.



There is actually no need to compute the number of "members" in each bands. All you need to compute is the number of bands, e.g.



    int nbands = sizeof bands / sizeof *bands;


Since you have declared members as an array of pointers and have used an initializer to initialize the first four, the remaining pointers will have all bytes set 0 resulting in each being NULL. You can simply loop for the members with while (bands[i].members[j]), incrementing j each iteration, e.g.



#include <stdio.h>

struct band {
char name[10];
char *members[20];
};

int main(void) {

const struct band bands = {
{"Beatles", {"John", "George", "Paul", "Ringo", "Pete", "George"} },
{"Stones", {"Mick", "Keith", "Bill", "Charlie", "Brian"} },
{"Who", {"Pete", "Roger", "Keith", "John"} },
{"JHE", {"Jimmy", "Noel", "Mitch"} } };

int nbands = sizeof bands / sizeof *bands;

for (int i = 0; i < nbands; i++) {
int j = 0;
puts (bands[i].name);
while (j < 20 && bands[i].members[j])
printf (" %s", bands[i].members[j++]);
putchar ('n');
}
}


(note addition of j < 20, which as pointed out by @chux in the comments, the test of while (bands[i].members[j]) alone could result in Undefined Behavior in the case where there were additional bands added bands after initialization and all 20 pointers of the members struct member were filled)



Example Use/Output



$ ./bin/bandmembers
Beatles
John George Paul Ringo Pete George
Stones
Mick Keith Bill Charlie Brian
Who
Pete Roger Keith John
JHE
Jimmy Noel Mitch


Additionally, don't use magic numbers in your code. Instead, If you need a constant, #define one (or more), e.g.



#define MAXNM 10
#define MAXMB 20


or use a global enum to do the same thing, e.g.



enum { MAXNM = 10, MAXMB = 20 };


That will allow you to eliminate the magic numbers, e.g.



struct band {
char name[MAXNM];
char *members[MAXMB];
};


This becomes very important for maintainability as your code length grows.






share|improve this answer














You don't have a "two dimensional array". What you have is a simple array of struct band which contains two simple character arrays as its members.



There is actually no need to compute the number of "members" in each bands. All you need to compute is the number of bands, e.g.



    int nbands = sizeof bands / sizeof *bands;


Since you have declared members as an array of pointers and have used an initializer to initialize the first four, the remaining pointers will have all bytes set 0 resulting in each being NULL. You can simply loop for the members with while (bands[i].members[j]), incrementing j each iteration, e.g.



#include <stdio.h>

struct band {
char name[10];
char *members[20];
};

int main(void) {

const struct band bands = {
{"Beatles", {"John", "George", "Paul", "Ringo", "Pete", "George"} },
{"Stones", {"Mick", "Keith", "Bill", "Charlie", "Brian"} },
{"Who", {"Pete", "Roger", "Keith", "John"} },
{"JHE", {"Jimmy", "Noel", "Mitch"} } };

int nbands = sizeof bands / sizeof *bands;

for (int i = 0; i < nbands; i++) {
int j = 0;
puts (bands[i].name);
while (j < 20 && bands[i].members[j])
printf (" %s", bands[i].members[j++]);
putchar ('n');
}
}


(note addition of j < 20, which as pointed out by @chux in the comments, the test of while (bands[i].members[j]) alone could result in Undefined Behavior in the case where there were additional bands added bands after initialization and all 20 pointers of the members struct member were filled)



Example Use/Output



$ ./bin/bandmembers
Beatles
John George Paul Ringo Pete George
Stones
Mick Keith Bill Charlie Brian
Who
Pete Roger Keith John
JHE
Jimmy Noel Mitch


Additionally, don't use magic numbers in your code. Instead, If you need a constant, #define one (or more), e.g.



#define MAXNM 10
#define MAXMB 20


or use a global enum to do the same thing, e.g.



enum { MAXNM = 10, MAXMB = 20 };


That will allow you to eliminate the magic numbers, e.g.



struct band {
char name[MAXNM];
char *members[MAXMB];
};


This becomes very important for maintainability as your code length grows.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 8 at 0:54

























answered Nov 7 at 22:26









David C. Rankin

39.2k32546




39.2k32546








  • 1




    while (bands[i].members[j]) printf (" %s", bands[i].members[j++]); this is UB when the initialization had 20 band members. Maybe while (j < MAXMB && bands[i].members[j])?
    – chux
    Nov 7 at 23:04












  • David many thanks. Your points on magic numbers are noted.
    – Griffau
    Nov 7 at 23:05










  • I don't think the MAXNM and MAXNB improve the code . It's obvious what the numbers mean in their original context, and the use of sizeof avoids the possibility of errors due to code duplication
    – M.M
    Nov 7 at 23:22










  • @chux while the check for j < MAXMB is a fine addition, the check as it sits is while (bands[i].members[j] != NULL) which is not UB based on the initialization rules. See § 6.7.9 Initialization (p10) and § 6.7.9 Initialization (p19)
    – David C. Rankin
    Nov 8 at 0:33










  • @M.M agreed for this short snippet. The addition was to address future programming where the "code length grows". I try to address all points and what could become bad habits. Sometimes what seems obvious to veterans is useful information for those just learning.
    – David C. Rankin
    Nov 8 at 0:37














  • 1




    while (bands[i].members[j]) printf (" %s", bands[i].members[j++]); this is UB when the initialization had 20 band members. Maybe while (j < MAXMB && bands[i].members[j])?
    – chux
    Nov 7 at 23:04












  • David many thanks. Your points on magic numbers are noted.
    – Griffau
    Nov 7 at 23:05










  • I don't think the MAXNM and MAXNB improve the code . It's obvious what the numbers mean in their original context, and the use of sizeof avoids the possibility of errors due to code duplication
    – M.M
    Nov 7 at 23:22










  • @chux while the check for j < MAXMB is a fine addition, the check as it sits is while (bands[i].members[j] != NULL) which is not UB based on the initialization rules. See § 6.7.9 Initialization (p10) and § 6.7.9 Initialization (p19)
    – David C. Rankin
    Nov 8 at 0:33










  • @M.M agreed for this short snippet. The addition was to address future programming where the "code length grows". I try to address all points and what could become bad habits. Sometimes what seems obvious to veterans is useful information for those just learning.
    – David C. Rankin
    Nov 8 at 0:37








1




1




while (bands[i].members[j]) printf (" %s", bands[i].members[j++]); this is UB when the initialization had 20 band members. Maybe while (j < MAXMB && bands[i].members[j])?
– chux
Nov 7 at 23:04






while (bands[i].members[j]) printf (" %s", bands[i].members[j++]); this is UB when the initialization had 20 band members. Maybe while (j < MAXMB && bands[i].members[j])?
– chux
Nov 7 at 23:04














David many thanks. Your points on magic numbers are noted.
– Griffau
Nov 7 at 23:05




David many thanks. Your points on magic numbers are noted.
– Griffau
Nov 7 at 23:05












I don't think the MAXNM and MAXNB improve the code . It's obvious what the numbers mean in their original context, and the use of sizeof avoids the possibility of errors due to code duplication
– M.M
Nov 7 at 23:22




I don't think the MAXNM and MAXNB improve the code . It's obvious what the numbers mean in their original context, and the use of sizeof avoids the possibility of errors due to code duplication
– M.M
Nov 7 at 23:22












@chux while the check for j < MAXMB is a fine addition, the check as it sits is while (bands[i].members[j] != NULL) which is not UB based on the initialization rules. See § 6.7.9 Initialization (p10) and § 6.7.9 Initialization (p19)
– David C. Rankin
Nov 8 at 0:33




@chux while the check for j < MAXMB is a fine addition, the check as it sits is while (bands[i].members[j] != NULL) which is not UB based on the initialization rules. See § 6.7.9 Initialization (p10) and § 6.7.9 Initialization (p19)
– David C. Rankin
Nov 8 at 0:33












@M.M agreed for this short snippet. The addition was to address future programming where the "code length grows". I try to address all points and what could become bad habits. Sometimes what seems obvious to veterans is useful information for those just learning.
– David C. Rankin
Nov 8 at 0:37




@M.M agreed for this short snippet. The addition was to address future programming where the "code length grows". I try to address all points and what could become bad habits. Sometimes what seems obvious to veterans is useful information for those just learning.
– David C. Rankin
Nov 8 at 0:37












up vote
1
down vote














what I'm doing wrong




Wrong numMembers calculation



numMembers should be the number of elements in the array. (20)



Each bands[i].member has 20 elements given char *members[20]. Several elements are populated with pointers to string literals. Most elements remain 0 (NULL).



// numMembers = sizeof(bands[0]) / sizeof(bands[0].members);
numMembers = sizeof(bands[0].members) / sizeof(bands[0].members[0]);




Attempting to print NULL as a string



printf ("t%s", bands[i].members[j]); not valid when bands[i].members[j] is NULL.



Not all bands[i].members[j] are set to a non-NULL value.



numBands = sizeof(bands) / sizeof(bands[0]);

for ( i = 0; i < numBands; ++i ) {
printf ("%sn", bands[i].name);
numMembers = sizeof(bands[i].members) / sizeof(bands[i].members[0]);

for ( j = 0; j < numMembers; ++j ) {
if (bands[i].members[j]) {
printf ("t%s", bands[i].members[j]);
}
}

printf ("n");
}
}




Deeper:



const struct band bands = { {"Beatles", ... forms bands and sizes bands based on the number of initializers.



char *members[20]; is a fixed size even if the initialization did not supply 20 strings. The first elements members[20] are initialized per the list, the remaining elements have a pointer value of 0.






share|improve this answer























  • Chux many thanks for your input it is greatly appreciated.
    – Griffau
    Nov 7 at 23:07

















up vote
1
down vote














what I'm doing wrong




Wrong numMembers calculation



numMembers should be the number of elements in the array. (20)



Each bands[i].member has 20 elements given char *members[20]. Several elements are populated with pointers to string literals. Most elements remain 0 (NULL).



// numMembers = sizeof(bands[0]) / sizeof(bands[0].members);
numMembers = sizeof(bands[0].members) / sizeof(bands[0].members[0]);




Attempting to print NULL as a string



printf ("t%s", bands[i].members[j]); not valid when bands[i].members[j] is NULL.



Not all bands[i].members[j] are set to a non-NULL value.



numBands = sizeof(bands) / sizeof(bands[0]);

for ( i = 0; i < numBands; ++i ) {
printf ("%sn", bands[i].name);
numMembers = sizeof(bands[i].members) / sizeof(bands[i].members[0]);

for ( j = 0; j < numMembers; ++j ) {
if (bands[i].members[j]) {
printf ("t%s", bands[i].members[j]);
}
}

printf ("n");
}
}




Deeper:



const struct band bands = { {"Beatles", ... forms bands and sizes bands based on the number of initializers.



char *members[20]; is a fixed size even if the initialization did not supply 20 strings. The first elements members[20] are initialized per the list, the remaining elements have a pointer value of 0.






share|improve this answer























  • Chux many thanks for your input it is greatly appreciated.
    – Griffau
    Nov 7 at 23:07















up vote
1
down vote










up vote
1
down vote










what I'm doing wrong




Wrong numMembers calculation



numMembers should be the number of elements in the array. (20)



Each bands[i].member has 20 elements given char *members[20]. Several elements are populated with pointers to string literals. Most elements remain 0 (NULL).



// numMembers = sizeof(bands[0]) / sizeof(bands[0].members);
numMembers = sizeof(bands[0].members) / sizeof(bands[0].members[0]);




Attempting to print NULL as a string



printf ("t%s", bands[i].members[j]); not valid when bands[i].members[j] is NULL.



Not all bands[i].members[j] are set to a non-NULL value.



numBands = sizeof(bands) / sizeof(bands[0]);

for ( i = 0; i < numBands; ++i ) {
printf ("%sn", bands[i].name);
numMembers = sizeof(bands[i].members) / sizeof(bands[i].members[0]);

for ( j = 0; j < numMembers; ++j ) {
if (bands[i].members[j]) {
printf ("t%s", bands[i].members[j]);
}
}

printf ("n");
}
}




Deeper:



const struct band bands = { {"Beatles", ... forms bands and sizes bands based on the number of initializers.



char *members[20]; is a fixed size even if the initialization did not supply 20 strings. The first elements members[20] are initialized per the list, the remaining elements have a pointer value of 0.






share|improve this answer















what I'm doing wrong




Wrong numMembers calculation



numMembers should be the number of elements in the array. (20)



Each bands[i].member has 20 elements given char *members[20]. Several elements are populated with pointers to string literals. Most elements remain 0 (NULL).



// numMembers = sizeof(bands[0]) / sizeof(bands[0].members);
numMembers = sizeof(bands[0].members) / sizeof(bands[0].members[0]);




Attempting to print NULL as a string



printf ("t%s", bands[i].members[j]); not valid when bands[i].members[j] is NULL.



Not all bands[i].members[j] are set to a non-NULL value.



numBands = sizeof(bands) / sizeof(bands[0]);

for ( i = 0; i < numBands; ++i ) {
printf ("%sn", bands[i].name);
numMembers = sizeof(bands[i].members) / sizeof(bands[i].members[0]);

for ( j = 0; j < numMembers; ++j ) {
if (bands[i].members[j]) {
printf ("t%s", bands[i].members[j]);
}
}

printf ("n");
}
}




Deeper:



const struct band bands = { {"Beatles", ... forms bands and sizes bands based on the number of initializers.



char *members[20]; is a fixed size even if the initialization did not supply 20 strings. The first elements members[20] are initialized per the list, the remaining elements have a pointer value of 0.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 7 at 22:20

























answered Nov 7 at 22:01









chux

78.8k869145




78.8k869145












  • Chux many thanks for your input it is greatly appreciated.
    – Griffau
    Nov 7 at 23:07




















  • Chux many thanks for your input it is greatly appreciated.
    – Griffau
    Nov 7 at 23:07


















Chux many thanks for your input it is greatly appreciated.
– Griffau
Nov 7 at 23:07






Chux many thanks for your input it is greatly appreciated.
– Griffau
Nov 7 at 23:07












up vote
0
down vote













For numMembers = sizeof(bands[0]) / sizeof(bands[0].members);



sizeofband(bands[0]) will give the size of one band struct - that is the 10 bytes for name, and then 20 * the size of a pointer.



sizeof(bands[0].members); will give 20*thesizeof a pointer



Not what you want, as sizeof doesn't take into consideration the content of whatever the pointer points to.



It also doesn't take into consideration that some of those members pointers will be NULL so you don't want to count them.



Perhaps better doing:



for ( j = 0; j < 20 &&  bands[i].members[j] != NULL; ++j )
printf ("t%s", bands[i].members[j]);





share|improve this answer





















  • @loastbard, many thanks for you help.
    – Griffau
    Nov 7 at 23:08















up vote
0
down vote













For numMembers = sizeof(bands[0]) / sizeof(bands[0].members);



sizeofband(bands[0]) will give the size of one band struct - that is the 10 bytes for name, and then 20 * the size of a pointer.



sizeof(bands[0].members); will give 20*thesizeof a pointer



Not what you want, as sizeof doesn't take into consideration the content of whatever the pointer points to.



It also doesn't take into consideration that some of those members pointers will be NULL so you don't want to count them.



Perhaps better doing:



for ( j = 0; j < 20 &&  bands[i].members[j] != NULL; ++j )
printf ("t%s", bands[i].members[j]);





share|improve this answer





















  • @loastbard, many thanks for you help.
    – Griffau
    Nov 7 at 23:08













up vote
0
down vote










up vote
0
down vote









For numMembers = sizeof(bands[0]) / sizeof(bands[0].members);



sizeofband(bands[0]) will give the size of one band struct - that is the 10 bytes for name, and then 20 * the size of a pointer.



sizeof(bands[0].members); will give 20*thesizeof a pointer



Not what you want, as sizeof doesn't take into consideration the content of whatever the pointer points to.



It also doesn't take into consideration that some of those members pointers will be NULL so you don't want to count them.



Perhaps better doing:



for ( j = 0; j < 20 &&  bands[i].members[j] != NULL; ++j )
printf ("t%s", bands[i].members[j]);





share|improve this answer












For numMembers = sizeof(bands[0]) / sizeof(bands[0].members);



sizeofband(bands[0]) will give the size of one band struct - that is the 10 bytes for name, and then 20 * the size of a pointer.



sizeof(bands[0].members); will give 20*thesizeof a pointer



Not what you want, as sizeof doesn't take into consideration the content of whatever the pointer points to.



It also doesn't take into consideration that some of those members pointers will be NULL so you don't want to count them.



Perhaps better doing:



for ( j = 0; j < 20 &&  bands[i].members[j] != NULL; ++j )
printf ("t%s", bands[i].members[j]);






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 7 at 21:59









lostbard

2,7551311




2,7551311












  • @loastbard, many thanks for you help.
    – Griffau
    Nov 7 at 23:08


















  • @loastbard, many thanks for you help.
    – Griffau
    Nov 7 at 23:08
















@loastbard, many thanks for you help.
– Griffau
Nov 7 at 23:08




@loastbard, many thanks for you help.
– Griffau
Nov 7 at 23:08


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53198424%2ftwo-dimensional-array-with-char-pointer-in-c%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Tangent Lines Diagram Along Smooth Curve

Yusuf al-Mu'taman ibn Hud

Zucchini