Structures, Pointer and gets

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Riaan Cillié

    Structures, Pointer and gets

    Hi

    I'm trying to learn C, but I am struggling with using scanf and a struct. I
    want to define a structure and declare a variable of that type in int main.
    This has to be passed to a function and its values have to read and returned
    from this function. How do you use gets() for this? I just can't figure it
    out.

    Here is a bit of code

    typedef struct sStudent
    {
    char *Name;
    char *ID;
    } tStudent;

    void ReadStudents(tS tudent student[10])

    int main()
    {
    tStudent student[10];
    ReadStudents(st udent);
    }

    void ReadStudents(tS tudent student[10])
    {
    ????????????
    }


  • RAiN

    #2
    Re: Structures, Pointer and gets

    Well first if you want something to be sent back your function mustnt be
    void or you can use it void but call by reference (pass the address)
    Cause as you probably know if you pass a variable by value, it creates a
    copy which dies at the end of the called function itself: so or return value
    or work on the address.

    Second, in the ReadStudent prototype you should declare an array of 10
    elements. Arrays are just pointers for C. When you pass an array to a
    function in the end you just pass the location memory of the first element,
    then you access to the others with pointers arithmetics.


    struct sStudent{
    char *Name;
    char *ID;
    } tStudent[10];

    typedef struct sStudent student; //sorry i hate typedef... :)


    void ReadStudents(st udent *);

    void ReadStudents(st udent *myStud){

    printf("Plz insert your name: ");
    gets(myStud->Name);
    }



    [color=blue]
    > I'm trying to learn C, but I am struggling with using scanf and a struct.[/color]
    I[color=blue]
    > want to define a structure and declare a variable of that type in int[/color]
    main.[color=blue]
    > This has to be passed to a function and its values have to read and[/color]
    returned[color=blue]
    > from this function. How do you use gets() for this? I just can't figure it
    > out.
    >
    > Here is a bit of code
    >
    > typedef struct sStudent
    > {
    > char *Name;
    > char *ID;
    > } tStudent;
    >
    > void ReadStudents(tS tudent student[10])
    >
    > int main()
    > {
    > tStudent student[10];
    > ReadStudents(st udent);
    > }
    >
    > void ReadStudents(tS tudent student[10])
    > {
    > ????????????
    > }
    >
    >[/color]


    Comment

    • Richard Heathfield

      #3
      Re: Structures, Pointer and gets

      Riaan Cillie wrote:
      [color=blue]
      > Hi
      >
      > I'm trying to learn C, but I am struggling with using scanf and a struct.
      > I want to define a structure and declare a variable of that type in int
      > main. This has to be passed to a function and its values have to read and
      > returned from this function. How do you use gets() for this? I just can't
      > figure it out.[/color]

      For a start, you don't use gets(). Ever. It has no way to protect your
      buffer from being overrun with too much data.

      Secondly, char * is not C-speak for "string". It is merely a pointer to a
      character. It /can/ be used to point at the first of a bunch of characters
      in a row, but it doesn't actually reserve any space itself. You must either
      point it to valid space, or use a proper array instead. For now, let's use
      an array:

      [color=blue]
      >
      > Here is a bit of code[/color]

      Great! Let's take a look...
      [color=blue]
      >
      > typedef struct sStudent
      > {
      > char *Name;
      > char *ID;
      > } tStudent;[/color]

      I suggest replacing this, for the time being, with:

      #define NAME_LEN 32
      #define ID_LEN 16

      typedef struct sStudent
      {
      char Name[NAME_LEN];
      char ID[ID_LEN];
      } tStudent;
      [color=blue]
      >
      > void ReadStudents(tS tudent student[10])
      >
      > int main()
      > {
      > tStudent student[10];
      > ReadStudents(st udent);
      > }
      >
      > void ReadStudents(tS tudent student[10])
      > {
      > ????????????
      > }[/color]

      Rather than lock the ReadStudents function down to a 10-element array, why
      not pass in the size? This will entail changing the call, in main(), to:

      ReadStudents(st udent, sizeof student / sizeof student[0]);

      Here's a possible ReadStudents implementation. It's not completely robust,
      but it will show you the general idea:

      void ReadStudents(tS tudent student[], size_t NumStudents)
      {
      size_t ThisStudent = 0;

      while(ThisStude nt < NumStudents)
      {
      puts("Please enter the student's name.");
      fgets(student[ThisStudent].Name,
      sizeof student[ThisStudent].Name,
      stdin);
      student[ThisStudent].Name[strlen(student[ThisStudent].Name) - 1] = '\0';
      puts("Please enter the student's ID.");
      fgets(student[ThisStudent].ID,
      sizeof student[ThisStudent].ID,
      stdin);
      student[ThisStudent].ID[strlen(student[ThisStudent].ID) - 1] = '\0';
      ++ThisStudent;
      }
      }

      Problems I haven't discussed:

      1) fgets might fail (it returns NULL if it does).
      2) User might type in more data than the buffer can hold. Unlike gets(),
      fgets() will not allow this to overrun your buffer, but you will get
      strange results on subsequent calls (because the remaining data will be
      left in the buffer).

      --
      Richard Heathfield : binary@eton.pow ernet.co.uk
      "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
      C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
      K&R answers, C books, etc: http://users.powernet.co.uk/eton

      Comment

      • Richard Heathfield

        #4
        Re: Structures, Pointer and gets

        RAiN wrote:
        [color=blue]
        > Well first if you want something to be sent back your function mustnt be
        > void or you can use it void but call by reference (pass the address)[/color]

        There is no such thing as call by reference in C.

        As it happens, he's using an array, so it's a moot point anyway (since the
        name of an array decays into a pointer to its first element).
        [color=blue]
        > Cause as you probably know if you pass a variable by value, it creates a
        > copy which dies at the end of the called function itself: so or return
        > value or work on the address.
        >
        > Second, in the ReadStudent prototype you should declare an array of 10
        > elements. Arrays are just pointers for C.[/color]

        Not true. If it were true, arrays would have the same size as pointers, and
        they don't (except by coincidence).
        [color=blue]
        > When you pass an array to a
        > function in the end you just pass the location memory of the first
        > element, then you access to the others with pointers arithmetics.[/color]

        That, at least, is correct.

        <snip>
        [color=blue]
        > void ReadStudents(st udent *myStud){
        >
        > printf("Plz insert your name: ");
        > gets(myStud->Name);
        > }[/color]

        Undefined behaviour, guaranteed. Quite apart from using the gets() function
        (which is severely broken), you forgot to reserve any storage for Name.

        --
        Richard Heathfield : binary@eton.pow ernet.co.uk
        "Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
        C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
        K&R answers, C books, etc: http://users.powernet.co.uk/eton

        Comment

        • Mark McIntyre

          #5
          Re: Structures, Pointer and gets

          On Sat, 15 Nov 2003 17:24:07 +0200, in comp.lang.c , "Riaan Cillié"
          <riaanantispam@ tiscali.co.uk> wrote:
          [color=blue]
          >Hi
          >
          >I'm trying to learn C, but I am struggling with using scanf[/color]

          scanf is quite a dangerous function for many reasons - I think the FAQ
          talks about this. You would be better to use fgets, and then parse the
          line you read in.
          [color=blue]
          >want to define a structure and declare a variable of that type in int main.
          >This has to be passed to a function and its values have to read and returned
          >from this function.[/color]

          pass a pointer to the struct to your function doing the reading, read
          in a value from stdin via fgets, convert the read in data from a
          string to the right type for the struct element, and store.
          [color=blue]
          >How do you use gets() for this?[/color]

          NEVER use gets. Its a bug waiting to happen. The FAQ definitely talks
          about this.
          [color=blue]
          >I just can't figure it
          >out.
          >
          >Here is a bit of code
          >
          >typedef struct sStudent
          >{
          > char *Name;
          > char *ID;
          >} tStudent;[/color]

          remember that ID and Name are only pointers to chars, with no memory
          allocated. You will need to allocate memory for them as you go along.
          It would be simpler to create them fixed-length, then hope you don't
          get any students with very long names...

          struct sStudent { char Name[128]; char ID[12]};
          [color=blue]
          >void ReadStudents(tS tudent student[10])
          >
          >int main()
          >{
          > tStudent student[10];[/color]

          this creates an array of ten struct tStudents.
          [color=blue]
          > ReadStudents(st udent);[/color]

          this passes the address of the first element to ReadStudents
          [color=blue]
          >void ReadStudents(tS tudent student[10])
          >{[/color]
          for i = 0 to 9
          fgets some data
          check its valid - for example names typically
          don't begin with digits
          copy it to Name
          fgets some more data
          validate that too - can IDs begin with letters?
          copy it to ID
          next loop[color=blue]
          >}
          >[/color]

          --
          Mark McIntyre
          CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
          CLC readme: <http://www.angelfire.c om/ms3/bchambless0/welcome_to_clc. html>

          Comment

          • RAiN

            #6
            Re: Structures, Pointer and gets

            > > Well first if you want something to be sent back your function mustnt be[color=blue][color=green]
            > > void or you can use it void but call by reference (pass the address)[/color]
            >
            > There is no such thing as call by reference in C[/color]

            passing by reference = a pointer to the original..
            Sure isnt properly correct to talk of calll by reference in C but not even
            Ritchie would kill you

            [color=blue][color=green]
            > > elements. Arrays are just pointers for C.[/color]
            > Not true. If it were true, arrays would have the same size as pointers,[/color]
            and[color=blue]
            > they don't (except by coincidence).[/color]

            Same here...
            Arrays are treated by the machine as if they were pointers, this mean
            myArray[i] = *(myArray+i)

            a little more flexibility man...

            p.s. riaan the faster you get used to work using the pointers notation the
            better it is
            The more you advance the more you will find yourself working with them


            Comment

            • Al Bowers

              #7
              Re: Structures, Pointer and gets



              Riaan Cillié wrote:[color=blue]
              > Hi
              >
              > I'm trying to learn C, but I am struggling with using scanf and a struct. I
              > want to define a structure and declare a variable of that type in int main.
              > This has to be passed to a function and its values have to read and returned
              > from this function. How do you use gets() for this? I just can't figure it
              > out.
              >
              > Here is a bit of code
              >
              > typedef struct sStudent
              > {
              > char *Name;
              > char *ID;
              > } tStudent;
              >
              > void ReadStudents(tS tudent student[10])
              >
              > int main()
              > {
              > tStudent student[10];
              > ReadStudents(st udent);
              > }
              >
              > void ReadStudents(tS tudent student[10])
              > {
              > ????????????
              > }
              >[/color]

              Unless you have allocated storage for struct members Name
              and ID, they are simply char pointers without pointing
              to any storage. To keep things simple you can change the members
              from char * to char arrays.

              typedef struct sStudent
              {
              char Name[32];
              char ID[32];
              } tStudent;

              Change the function ReadStudents to:
              void ReadStudents(tS tudent *student);
              and read in each student in a loop.

              Do not use gets. It is very unsafe for user input. The
              standard has other functions, such as fgets, that you
              can safely use. Here is a example using function fgets.
              It is just an demo and a really useful application would
              not restrict the number of students in this way or
              read the input data all in one chunk.

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

              typedef struct sStudent
              {
              char Name[40];
              char ID[32];
              } tStudent;

              void ReadStudent(tSt udent *student);

              int main(void)
              {
              tStudent MathClass[5];
              int i;

              for(i = 0; i < 5;i++)
              {
              ReadStudent(&Ma thClass[i]);
              putchar('\n');
              }
              puts("\nThe students in the Math Class are");
              for(i = 0; i < 5;i++)
              printf("\tName: %s\n\tID: %s\n\n",
              MathClass[i].Name, MathClass[i].ID);
              return 0;
              }

              void ReadStudent(tSt udent *student)
              {
              char *s;

              printf("Enter student name: ");
              fflush(stdout);
              fgets(student->Name,sizeof student->Name, stdin);
              if((s = strchr(student->Name,'\n')) != NULL) *s = '\0';
              else while(getchar() != '\n');
              printf("Enter the Students ID: ");
              fflush(stdout);
              fgets(student->ID, sizeof student->ID, stdin);
              if((s = strchr(student->ID,'\n')) != NULL) *s = '\0';
              else while(getchar() != '\n');
              return;
              }

              --
              Al Bowers
              Tampa, Fl USA
              mailto: xabowers@myrapi dsys.com (remove the x to send email)
              Latest news coverage, email, free stock quotes, live scores and video are just the beginning. Discover more every day at Yahoo!


              Comment

              • Thomas Stegen

                #8
                Re: Structures, Pointer and gets

                RAiN wrote:[color=blue][color=green][color=darkred]
                >>>Well first if you want something to be sent back your function mustnt be
                >>>void or you can use it void but call by reference (pass the address)[/color]
                >>
                >>There is no such thing as call by reference in C[/color]
                >
                >
                > passing by reference = a pointer to the original..[/color]

                Not so.
                [color=blue]
                > Sure isnt properly correct to talk of calll by reference in C but not even
                > Ritchie would kill you[/color]

                Why not use correct terminology? There is a world of difference
                between passing a reference by value and passing something by
                reference. Understanding the terminology is the first step on the
                way of understanding the issues involved.
                [color=blue]
                > Arrays are treated by the machine as if they were pointers, this mean
                > myArray[i] = *(myArray+i)[/color]

                So how this does not print the same number twice?

                #include <stdio.h>

                int main(void)
                {
                int arr[10];
                int *ptr;
                printf("%u %u\n"), (unsigned)sizeo f arr, (unsigned)sizeo f ptr);
                return 0;
                }

                Arrays are converted to a pointer to the first element in the array
                when they are evaluated for their value.
                [color=blue]
                >
                > a little more flexibility man...[/color]

                No, this is an important point.

                Arrays are not just pointers. Consider arrays of arrays for example.

                --
                Thomas.

                Comment

                • Sheldon Simms

                  #9
                  Re: Structures, Pointer and gets

                  On Sat, 15 Nov 2003 17:39:04 +0000, RAiN wrote:
                  [color=blue][color=green][color=darkred]
                  >> > Well first if you want something to be sent back your function mustnt be
                  >> > void or you can use it void but call by reference (pass the address)[/color]
                  >>
                  >> There is no such thing as call by reference in C[/color]
                  >
                  > passing by reference = a pointer to the original..
                  > Sure isnt properly correct to talk of calll by reference in C but not even
                  > Ritchie would kill you[/color]

                  Richard didn't "kill you" either. He just pointed out that there is
                  no call by reference in C. He is right. You are wrong. Deal with it.
                  [color=blue][color=green][color=darkred]
                  >> > elements. Arrays are just pointers for C.[/color]
                  >> Not true. If it were true, arrays would have the same size as pointers,
                  >> and they don't (except by coincidence).[/color]
                  >
                  > Same here...
                  > Arrays are treated by the machine as if they were pointers,[/color]

                  Sometimes they are. Sometimes they aren't. The C Standard says:

                  6.3.2.1#3
                  Except when it is the operand of the sizeof operator or the unary &
                  operator, or is a string literal used to initialize an array, an
                  expression that has type array of type is converted to an expression
                  with type pointer to type that points to the initial element of the
                  array object and is not an lvalue.
                  [color=blue]
                  > a little more flexibility man...[/color]

                  Which do you prefer, flexible programs or correct programs?


                  Comment

                  • Joe Wright

                    #10
                    Re: Structures, Pointer and gets

                    RAiN wrote:[color=blue]
                    >[color=green][color=darkred]
                    > > > Well first if you want something to be sent back your function mustnt be
                    > > > void or you can use it void but call by reference (pass the address)[/color]
                    > >
                    > > There is no such thing as call by reference in C[/color]
                    >
                    > passing by reference = a pointer to the original..
                    > Sure isnt properly correct to talk of calll by reference in C but not even
                    > Ritchie would kill you
                    >[/color]
                    Not really. Languages supporting call by reference don't do the pointer
                    stuff. The reference is the actual 'thing'. C doesn't do that and DMR
                    might actually kill you.
                    [color=blue][color=green][color=darkred]
                    > > > elements. Arrays are just pointers for C.[/color]
                    > > Not true. If it were true, arrays would have the same size as pointers,[/color]
                    > and[color=green]
                    > > they don't (except by coincidence).[/color]
                    >
                    > Same here...
                    > Arrays are treated by the machine as if they were pointers, this mean
                    > myArray[i] = *(myArray+i)
                    >[/color]
                    Yes, but arrays are not pointers and pointers are not arrays. Right?
                    [color=blue]
                    > a little more flexibility man...
                    >
                    > p.s. riaan the faster you get used to work using the pointers notation the
                    > better it is
                    > The more you advance the more you will find yourself working with them[/color]

                    Yes indeed. I am of the old school that differentiates between values
                    and objects. I read pointer as an object which may hold a value which is
                    the address of another object. Others call an address value a pointer. I
                    understand but I disagree.
                    --
                    Joe Wright http://www.jw-wright.com
                    "Everything should be made as simple as possible, but not simpler."
                    --- Albert Einstein ---

                    Comment

                    • Thomas Stegen

                      #11
                      Re: Structures, Pointer and gets

                      Joe Wright wrote:
                      [color=blue]
                      > Yes indeed. I am of the old school that differentiates between values
                      > and objects. I read pointer as an object which may hold a value which is
                      > the address of another object. Others call an address value a pointer. I
                      > understand but I disagree.[/color]

                      You disagree with a standard definition? Interesting... :)

                      --
                      Thomas.

                      Comment

                      • Mark McIntyre

                        #12
                        Re: Structures, Pointer and gets

                        On Sat, 15 Nov 2003 17:39:04 GMT, in comp.lang.c , "RAiN"
                        <here.comes@the .rain.com> wrote:

                        (Someone else said)[color=blue][color=green]
                        >> There is no such thing as call by reference in C[/color]
                        >
                        >passing by reference = a pointer to the original..[/color]

                        Thats not what "pass by reference" is generally taken to mean.
                        Consider C++. What C is doing is passing the value of a pointer.
                        [color=blue]
                        >Sure isnt properly correct to talk of calll by reference in C but not even
                        >Ritchie would kill you[/color]

                        Its likely you'll confuse people, esp those familiar with C++ or other
                        languages that /do/ implement pass by reference.
                        [color=blue][color=green][color=darkred]
                        >> > elements. Arrays are just pointers for C.[/color]
                        >> Not true. If it were true, arrays would have the same size as pointers, and they don't (except by coincidence).[/color]
                        >
                        >Arrays are treated by the machine as if they were pointers, this mean
                        >myArray[i] = *(myArray+i)[/color]

                        No. Accessing an array's elements is /equivalent/ to doing pointer
                        arithmetic but that doesn't make an array the same as a pointer.
                        Consider the result of sizeof, Consider the result of trying to free()
                        an array. Consider trying to assign to an array. The list goes on.
                        [color=blue]
                        >a little more flexibility man...[/color]

                        When you are correct, you get flexibility. When you're erroneous, you
                        don't... :-(


                        --
                        Mark McIntyre
                        CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
                        CLC readme: <http://www.angelfire.c om/ms3/bchambless0/welcome_to_clc. html>

                        Comment

                        • Joe Wright

                          #13
                          Re: Structures, Pointer and gets

                          Thomas Stegen wrote:[color=blue]
                          >
                          > Joe Wright wrote:
                          >[color=green]
                          > > Yes indeed. I am of the old school that differentiates between values
                          > > and objects. I read pointer as an object which may hold a value which is
                          > > the address of another object. Others call an address value a pointer. I
                          > > understand but I disagree.[/color]
                          >
                          > You disagree with a standard definition? Interesting... :)
                          >[/color]
                          Why interesting? Does the Standard confuse value and object? Maybe.
                          Let's examine two objects..

                          char arr[10];
                          char *arp;

                          I contend that arr is an array object and arp is a pointer object. Very
                          different things. Expressing arr yields the address of arr[0]. That
                          address can be assigned..

                          arp = arr;

                          Now you can use arr and arp interchangeably in most array contexts.
                          arr[5] == arp[5] will be true. But they are not the same. arr is an
                          array and arp is a pointer. Expressing either of them in rvalue context
                          will yield the same value but they are not the same things.

                          --
                          Joe Wright http://www.jw-wright.com
                          "Everything should be made as simple as possible, but not simpler."
                          --- Albert Einstein ---

                          Comment

                          • Sheldon Simms

                            #14
                            Re: Structures, Pointer and gets

                            On Sun, 16 Nov 2003 03:01:07 +0000, Joe Wright wrote:
                            [color=blue]
                            > Thomas Stegen wrote:[color=green]
                            >>
                            >> Joe Wright wrote:
                            >>[color=darkred]
                            >> > Yes indeed. I am of the old school that differentiates between values
                            >> > and objects. I read pointer as an object which may hold a value which is
                            >> > the address of another object. Others call an address value a pointer. I
                            >> > understand but I disagree.[/color]
                            >>
                            >> You disagree with a standard definition? Interesting... :)
                            >>[/color]
                            > Why interesting? Does the Standard confuse value and object?[/color]

                            Perhaps Thomas was thinking of 6.5.3.2

                            3 The unary & operator returns the address of its operand. If the
                            operand has type "TYPE", the result has type "pointer to TYPE".


                            Comment

                            • Thomas Stegen

                              #15
                              Re: Structures, Pointer and gets

                              Joe Wright wrote:
                              [color=blue]
                              > Thomas Stegen wrote:
                              >[color=green]
                              >>Joe Wright wrote:
                              >>
                              >>[color=darkred]
                              >>>Yes indeed. I am of the old school that differentiates between values
                              >>>and objects. I read pointer as an object which may hold a value which is
                              >>>the address of another object. Others call an address value a pointer. I
                              >>>understand but I disagree.[/color]
                              >>
                              >>You disagree with a standard definition? Interesting... :)
                              >>[/color]
                              >
                              > Why interesting?[/color]

                              Because the most you can say is that the definition is flawed.
                              A definition is, by definition, correct.
                              [color=blue]
                              > Does the Standard confuse value and object? Maybe.[/color]

                              It does not. Objects can have type pointer to T. Values can have type
                              pointer to T. Sheldon quoted an appropriate from the standard with which
                              you disagree (You are saying that the address of an object is not a
                              pointer.)
                              [color=blue]
                              > Let's examine two objects..
                              >
                              > char arr[10];
                              > char *arp;[/color]

                              As your example demonstrates something different from what you were
                              saying I snipped most of it.

                              You are saying (at least said) that arp is a pointer, whereas &arp is
                              not. Note that when arr is evaluated it is converted to a value which
                              is the address of the first element in the array. This value is not
                              stored in any object and so is by your disagreement with the standard
                              not a pointer. You just have to look at clause 6.3.2.1#2 to see that
                              this value is indeed a pointer.

                              --
                              Thomas.

                              Comment

                              Working...