Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C prog: printing values from array of structures

  1. Aug 8, 2004 #1

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    Hello, I have a little function I have written that takes an array of structures as an argument

    PHP:

    void print_names(struct pers_info arr[])
    {
      printf("Here is person 1: %d %s %s %s\n", arr[0].ssn,
        arr[0].pers_name.first,arr[0].pers_name.middle, arr[0].pers_name.last);
      printf("Here is person 2: %d %s %s %s\n", arr[1].ssn,
        arr[1].pers_name.first,arr[1].pers_name.middle, arr[1].pers_name.last);
    }
     
    This is working fine - it prints a number, then a first name, middle name, and last name. The problem is that when I print the middle name I only want to print the first initial. I can't figure out how to print only the first character of the pers_name.middle character string. Thanks for your help.
     
  2. jcsd
  3. Aug 8, 2004 #2
    Try this:

    Code (Text):

    printf("%c",arr[0].pers_name.middle[0]);
     
    A string is just a character array.
     
  4. Aug 8, 2004 #3

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    Thanks! That did the trick!!
     
  5. Aug 8, 2004 #4

    plover

    User Avatar
    Homework Helper

    You can also give the string conversion maximum number of characters. (Though this is obviously more useful for numbers greater than 1...)

    PHP:
    printf("%.1s",arr[0].pers_name.middle);
     
    Last edited: Aug 8, 2004
  6. Aug 8, 2004 #5

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    hey there plover. You know, that was my first thought- that I would do some kind of a truncation thingy when I did the specifications. But I figure he wants to see us specifically access the character in the array, so I went with that.
    I am doing some alterations now to make the print function loop through all the elements in the structure array and print it one way if a middle name is found and another way if a middle name is not found. I'm not quite sure if that's the most elegant way to handle it but I'll see how it comes out and if it starts looking clunky I'll post again.
     
  7. Aug 8, 2004 #6

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    well, I got the first part of the assignment taken care of which was to pass the structure array to my printing function. At least I think I handled it right. I called the function like this:
    PHP:

    print_names(arr);
     
    and then wrote my function heading like this:
    PHP:

    void print_names(struct pers_info arr[])
     
    now, the second part of the assignment asks me to go back and modify the program by passing the structure value instead of the address this time.
    I am getting confused here. Is he asking me to pass individual elements of the structure maybe?
    :confused:
    Thanks.
     
  8. Aug 8, 2004 #7

    plover

    User Avatar
    Homework Helper

    How would you set up the function so that this call made sense?

    PHP:
    print_name(arr[n]);
    What would happen when the function was called?
     
  9. Aug 8, 2004 #8

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    well, I'm not sure. maybe I should create an argument for the number of elements in the array? like...

    void print_names(struct pers_info arr[], int n)
     
  10. Aug 8, 2004 #9
    Are you familiar with pointers? if so the following statements are equivalent

    Code (Text):

    arr[];
    *arr;
     
    When you pass them by value you will not pass a pointer to an array, you will pass an individual object (note: object is bad choice of word :P). The only way this can be achieved is by calling the function print_names as many times as the array is large.

    Just as plover was hinting at you want to do this:
    Code (Text):

    int n=0;
    for (n=0;n<size;n++){
    print_names(arr[n]);
    }
     
    You should also re-write your function above to be the same thing but instead pass a reference to the object, kinda like

    Code (Text):

    print_names(&arr[n]); //you could ultimately do it other ways, but this is conceptually simple
    //on the function prototype you would need to use a * to let the compiler know that an address was being passed.
     
    Otherwise you would have to add the size parameter as you thought of above.
     
  11. Aug 8, 2004 #10

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    hmmmm....In my current version I have a loop that sorta does that. I give it an array of structure addresses, and I display the structure contents

    PHP:

    void print_names(struct pers_info arr[])
    {
      int i;
      for (i=0;i<5;i++)
      {
        if (arr[i].pers_name.middle[i] == '\0') //no middle initial
        {
          printf("%s, %s -- %d \n",  arr[i].pers_name.last, arr[i].pers_name.first,
          arr[i].ssn);
        }
       else  //if there is a middle initial
        {
          printf("%s, %s %c. -- %d \n",  arr[i].pers_name.last,
          arr[i].pers_name.first, arr[i].pers_name.middle[0],arr[i].ssn);
        }
      }
    }
     
    Can I keep what's inside my printing function as is but just pass
    &arr to it to specify that the value should be passed rather that the address?

    Thanks.
     
  12. Aug 8, 2004 #11

    plover

    User Avatar
    Homework Helper

    C uses a method called pass-by-value when sending arguments to a function. So, if you a have a function:
    PHP:
    void uselessFunc(int n) { n += 1; }
    and later have the instructions:
    PHP:
    int a = 100;
    uselessFunc(a);
    printf("%d\n", a);
    the number printed will be 100, as the value of a is copied to the argument n (i.e. passed by value). Thus any operations on n do not affect a. This is why you pass a pointer when you want to affect the original object, because then it is the address that is value that gets copied, and a copy of the address will, of course, still de-reference to the original object.

    The same principle works if the argument is a struct rather than just an int.

    Do the questions in my previous post make more sense with this to go with them? (Also note that my function was called print_name rather than print_names.)

    It seems slightly strange to me that the teacher would imply that both of the functions you're asked to write would be able to work on the entire array at once, but perhaps I am misunderstanding something in your description.

    The follow-up that Goalie_Ca gave to my hint is correct, and in most situations his advice to pass the address would be good. However, from what I can tell of your instructions, you are being asked to not pass the address here.

    I should probably point out that I am assuming you've seen these ideas before. I'm just trying to show the context from which the problem can be answered.

    (I hope I'm not being too oblique. You should tell me if I'm just confusing you more than helping...)
     
  13. Aug 8, 2004 #12

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    I think I am understanding now. The difference is just between passing the pointer address and passing the value that is being pointed to.
    No, I think he is just asking for two different versions of the same program.
    I actually hadn't heard the term "pass by value" method before. I think initially that is all we were doing but it didn't have a special name. I get confused I think because I don't know how much the rules change (if at all) when I am working with a structure.
    And I do appreciate the help. Sorry I am not absorbing the info faster. Maybe I shoud work on a smaller simpler version of what I am trying to do and then try to apply it back to my program. Just so I'll know how to use pass by value in this case.
     
  14. Aug 8, 2004 #13

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    I made up a simpler example to see if I can get my head around this. I just have a character array and I am passing a pointer to it. Maybe someone could show me how to write this using Pass By Value? Thanks. :smile:

    PHP:

    #include <stdio.h>
    int main(void)
    {
    void print_array(char * a); //proto

    char arr[3] = {'A','B','C'};

    print_array(arr); //call printing function 
    return 0;
    }

    void print_array(char * a)
    {
        int i;
        for (i=0;i<3;i++)
        {
            printf("%c \n",a[i]);
        }
    }

     
     
  15. Aug 9, 2004 #14
    You cannot pass an array by value. An array is actually a pointer to a memory block. When you do array[3] you are essentially adding 3*data_size to the array starting address. Mmmkay.. You have to move that for loop outside the function.

    Code (Text):

    #include <stdio.h>
    void print_array(char a); //proto


    int main(void)
    {
    char arr[3] = {'A','B','C'};
    int n=0;
    for (n=0;n<3;n++)
        print_array(arr[n]); // equivalent to *(arr+3)****
    return 0;
    }

    void print_array(char a)
    {
    ********printf("%c \n",a);  
    }
     
     
  16. Aug 9, 2004 #15

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    Goalie - thank you. I remembered from examples that for arrays we had to specifically pass a pointer to a function but I was getting a little muddled on why that was.
    So you are saying use the loop to grab the value first and then pass the value off to the printing function I think? uh.. I hope I understood that..
    Anyway, I appreciate your explanations and your patience.
     
  17. Aug 9, 2004 #16

    plover

    User Avatar
    Homework Helper

    'Pass-by-value' is not something the programmer does -- it is built in to the C language. It is the method that C programs use to pass arguments to functions. (The other common method is pass-by-reference, where the function argument assumes the identity of the variable that is passed in instead of copying it. C++ uses both methods.)

    Suppose you have a struct:
    PHP:
    struct point2d {
        double x;
        double y;
    } targetCoord;
    and a function with the prototype:
    PHP:
    int swatFly(int id, struct point2d target);
    At some point in the code you have:
    PHP:
    int flyId = 666;
    targetCoord.x = 3.1415;
    targetCoord.y = 2.7183;
    int isFlyToast = swatFly(flyId, targetCoord);
    When you call swatFly, what happens? The system sets up the memory space necessary to execute a function (it's called a stack-frame -- if that's meaningless to you, don't worry about it). Included in that memory space will be spots for all of the arguments and local variables used by the function. Since C uses call-by-value, it then looks at the value of 'flyId' and copies that value to the address that will be used by the parameter 'id'. Then it looks at 'targetCoord' and copies the value of that to 'target'; since the system has already seen the definition of 'point2d', it knows that this value is two items of type 'double'.

    The slightly confusing case is arrays. If you have an array A, then an item in that array A[n] acts just like any other variable of whatever type is stored in A. But what does the symbol 'A' by itself mean? In most circumstances, the most useful meaning is to say where the array A is. So the symbol A is interpreted as the address of the first item in the array (another way to say this would be that the array is converted to a pointer). Thus when an array is passed to a function, the value that is copied by the 'pass-by-value' mechanism is the address. (The prototype of the function can specify either an array or a pointer in these cases.)

    I am glossing over a few things, but I hope this is enough information to clarify the current problem.
     
  18. Aug 9, 2004 #17

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    plover, that is very interesting - thank you. Tell me, why is targetCoord outside of the structure in

    struct point2d {
    double x;
    double y;
    } targetCoord;

    and the other thing I am not sure about (just occurred to me) is what the & symbol does here in the post by Goalie
    print_names(&arr[n]);

    Thanks rain-bird friend! :smile:
     
  19. Aug 9, 2004 #18

    plover

    User Avatar
    Homework Helper

    I'm sorry, I didn't know you hadn't seen this syntax. It is possible to include variable declarations along with the definition of a struct. Thus, targetCoord is just being declared as a variable of type struct point2d.

    In &arr[n], the '&' means "take the address of". Thus, &arr[n] passes a pointer to the array element, where arr[n] would pass the array element itself. For a large struct, you usually want to pass the pointer as that is much more efficient than copying the whole struct.
     
  20. Aug 9, 2004 #19

    Math Is Hard

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    ahhh... I see!

    Thanks. I was thinking it had something to do with the address because I had seen it used when assigning an address to a pointer like

    MyPointer = &Fred;

    to assign the address of Fred to MyPointer. But I was surprised to see it used as part of a parameter in a function call.

    Let me see if I understand. I am still not sure I have grasped it, so I will state my interpretation and you'll be able to see my thought processes on this and where I might be having trouble:

    Using this as a parameter in a function call passes a pointer to the nth element of the array
    &arr[n]
    in other words, the address of the nth element in the array.

    Using this as a parameter in a function call passes the value stored at the nth position in the array:
    arr[n]
    for instance if arr was a char array it would pass an actual character like 'A' or 'j'. It would behave the same as if you were passing over a single char variable even though it is actually a member of an array.

    Thanks. :smile:
     
  21. Aug 9, 2004 #20
    Here's something else for you to think of, if you understand this then you have a decent idea of pointers...



    char arr[3][2];

    what would arr pass?
    what would arr[2] pass?
    what would arr[2][1] pass?

    One other thing, you can also have function pointers, void pointers, and others.
     
    Last edited: Aug 9, 2004
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?



Similar Discussions: C prog: printing values from array of structures
  1. C structures (Replies: 7)

Loading...