14

I have to build a nested structure to store some basic information about some person (name, age, address). So I created a structure called "info" and to hold the address I created another nested structure inside "info" called "address". But whenever I prompt to store the values using a for loop, I get errors. What is the problem here and how can I solve it?

[Error] 'struct Info' has no member named 'address'
[Warning] declaration does not declare anything [enabled by default]

#include <stdio.h>

int main(){

    struct Info{
        char name[30];
        int age;
        struct address{
            char area_name[39];
            int house_no;
            char district[39];
        };
    };

    struct Info Person[10];

    int i;
    for(i=0;i<10;i++){

        printf("enter info of person no %d\n",i);
        printf("enter name\n");
        scanf("%s",&Person[i].name);
        printf("enter age\n");
        scanf("%d",&Person[i].age);
        printf("enter address :\n");
        printf("enter area name :\n");
        scanf("%s",&Person[i].address.area_name);
        printf("enter house no : \n");
        scanf("%d",&Person[i].address.house_no);
        printf("enter district : \n");
        scanf("%s",&Person[i].address.district);
    }
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
AL-zami
  • 8,902
  • 15
  • 71
  • 130
  • Note that you should not prefix the string members with an `&` in the call to `scanf()`. If you do include the `&`, the type passed is `char (*)[30]` rather than `char *`, but the `%s` format expects a `char *`. If the compiler is set fussy enough (`-Wall` should be sufficient), it will tell you about the type mismatch — and you should heed it. (Yes, in actual practice on most actual machines, it does work OK — but it is somewhat by coincidence; there is a type mismatch and you should avoid those.) – Jonathan Leffler Mar 08 '16 at 15:37

5 Answers5

20

You declared a type struct address in the structure Info but not a data member of this type.

You can write for example

struct Info{
    char name[30];
    int age;
    struct address{
        char area_name[39];
        int house_no;
        char district[39];
    } address;
      ^^^^^^^^
};
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
10

What you have at the moment is just a declaration of a structure called address, but you'll need a variable called address in struct Info to use the Person[i].address syntax.

What you need is to move the word address a bit:

struct Info{
    char name[30];
    int age;
    struct {
        char area_name[39];
        int house_no;
        char district[39];
    } address; // <<< here it is now
};

Another option is to use the following:

struct Info{
    char name[30];
    int age;
    struct addr{ // as noted by @JonathanLeffler,
                 // it's not necessary to change the 
                 // name of a struct
        char area_name[39];
        int house_no;
        char district[39];
    };
    struct addr address; // <<< a variable of type struct addr
};
ForceBru
  • 43,482
  • 10
  • 63
  • 98
  • 2
    Why the name change? Structure tags are in a separate namespace from structure elements, so `struct address { … } address; is perfectly valid C. – Jonathan Leffler Mar 08 '16 at 15:04
  • @JonathanLeffler, I wasn't quite sure about that then. Still, it amy help to avoid confusion when reading the following: `struct address address;` – ForceBru Mar 08 '16 at 15:14
4

The structure Info have a nested structure named address, but not a member variable named address.

You should do

struct Info
{
    ...
    struct
    {
        ...
    } address;
};
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    There is a `struct address` in the outer `struct`. But that is just an anonymous struct member without a name. This is legal syntax since C99. – too honest for this site Mar 08 '16 at 14:40
  • 1
    @Olaf: The standard says (ISO/IEC 9899:2011 §6.7.2.1 ¶13) _An unnamed member whose type specifier is a structure specifier with no tag is called an anonymous structure; an unnamed member whose type specifier is a union specifier with no tag is called an anonymous union. The members of an anonymous structure or union are considered to be members of the containing structure or union. This applies recursively if the containing structure or union is also anonymous._ In the original declaration in the question, `struct address` has a tag, so it is not an anonymous struct member. – Jonathan Leffler Mar 08 '16 at 15:27
  • @JonathanLeffler: Hmm, you are correct. I use it in conjunction with gcc `-fplan9-extensions` (wish it would make it into the standard) which interestingly includes a Microsoft extension which allows such constructs (along with using a `typedef` or external struct definition). Sorry, I always forget how useless the standard-compliant version actually is due to these restrictions. – too honest for this site Mar 08 '16 at 15:33
  • @Olaf: Interesting that it is allowed anywhere. It changes the meaning of a valid (but obscure) C89 program if the tagged structure declaration is treated as an anonymous member. That's likely why it is not in the standard. – Jonathan Leffler Mar 08 '16 at 15:39
  • @JonathanLeffler: Can you elaborate? I have not used C89 since long time. OTOH, it is way too useful for OOP to not use it (you have to enable it explicitly, though) - Iff you have it well documented, of course. See [here](https://gcc.gnu.org/onlinedocs/gcc-4.9.3/gcc/Unnamed-Fields.html#Unnamed-Fields). – too honest for this site Mar 08 '16 at 15:55
  • @Olaf: A full exposition on it would be painful to fit into comments. The compiler warning ('declaration does not declare anything') is accurate; it declares a type but the type is not immediately used. In C, you could create a structure of type `struct address` after (outside, separately from) the structure `struct Info`, but C++ has nested scopes. It is an eccentric way of defining `struct address;`, but syntactically legitimate. Usually, you'd have `struct address { … } address;` within the definition of `struct Info`, which would not incur the warning. _[…continued…]_ – Jonathan Leffler Mar 08 '16 at 18:01
  • _[…continuation…]_ You could write `struct address { … }; struct address address;` within `struct Info`; that would probably incur the warning. These were all valid in C89/90. I had to double-check the rules on anonymous structure and union types before writing my initial comment — I wasn't sure what the wording was that ruled either way. I can see there might be uses for the alternative, but the fact remains that it changes the meaning of syntactically valid (albeit unorthodox) existing programs, which the standards committee generally tries to avoid. – Jonathan Leffler Mar 08 '16 at 18:05
  • @JonathanLeffler: Thanks, I think I got your point. "Unorthodox" sounds linke an euphemism for such a construct. But I really think it is high time to cut out old wood from the C standard. If someone still has such code, she should use C90 compatibility mode. Otherwise C will never become a modern language. An alternative would be to standardise a true successor with the same minimum/no runtime overhead. But there is none in sight either. – too honest for this site Mar 08 '16 at 18:15
1

From http://www.c4learn.com/c-programming/c-nested-structure/ it looks like you should "dub" your address structure, i.e.

struct address{
    char area_name[39];
    int house_no;
    char district[39];
} adr_;

Then to set house number:

&Person[i].adr_.house_no
J. Chomel
  • 8,193
  • 15
  • 41
  • 69
0

Here is the updated code using anonymous structure. I enabled C11 for compiling this.

#include <stdio.h>

int main(){

    struct Info{
        char name[30];
        int age;
        struct {
            char area_name[39];
            int house_no;
            char district[39];
        };
    };

    struct Info Person[10];

    int i;
    for(i=0;i<10;i++){

        printf("enter info of person no %d\n",i);
        printf("enter name\n");
        scanf(" %s",Person[i].name);
        printf("enter age\n");
        scanf("%d",&Person[i].age);
        printf("enter address :\n");
        printf("enter area name :\n");
        scanf(" %s",Person[i].area_name);
        printf("enter house no : \n");
        scanf("%d",&Person[i].house_no);
        printf("enter district : \n");
        scanf(" %s",Person[i].district);
    }
}
Rajesh
  • 1,085
  • 1
  • 12
  • 25