0

I'm having a problem understanding how to read in a string to a structure member array. I have a structure called 'customer' and a member called 'char last_name[20]'. I prompt the user to enter in his last name and that last name is to be stored in the 'last_name[20]' variable. The condition is that I have to use a do...while loop.

Here's the code:

void get_customer_info(struct customer *p_customer_start, int customer_num)
{
   struct customer *p_customer;

   for (p_customer = p_customer_start; (p_customer - p_customer_start) < 
        customer_num; p_customer++)
   {
      printf("\nCustomer number %d: ", (p_customer - p_customer_start) + 1);

      while (getchar() != NEW_LINE); 

      printf("\n   Enter the customer's last name: ");

      // *THIS PART IS THE PROBLEM* 
      do
      {
         p_customer->last_name = getchar();         
         p_customer->last_name++;
      } while (*p_customer->last_name != NEW_LINE);

   }
   return;
}

Problem is, with that algorithm last_name[0] does not get checked, it moves to 'last_name[1]' before it gets checked for a new line. And yes, a do...while construct must be used (this is for a class).

I appreciate anyone's thoughts.

casablanca
  • 69,683
  • 7
  • 133
  • 150
John
  • 3
  • 1
  • This won't even compile: you can't assign to or increment arrays; `last_name = ...` and `last_name++` are errors. – casablanca Nov 02 '10 at 01:25
  • Ah, sorry, for the assignment it should've been '*p_customer->last_name = getchar();' But that made me realize that constant pointers(names of arrays) can't move, I was thinking of assigning the address of last_name to a pointer, but I'm not sure how to get the address of a structure member.. – John Nov 02 '10 at 01:30
  • The increment still won't work. – casablanca Nov 02 '10 at 01:32

3 Answers3

3

I think you may have much bigger problems there than you realise, with the attempted manipulation of an array address :-)

You can probably avoid all these problems with:

int i = 0;
do {
    p_customer->last_name[i++] = getchar();         
} while (p_customer->last_name[i-1] != NEW_LINE);
p_customer->last_name[i] = '\0';

Keep in mind that this is still open to buffer overflow problems (as was your original solution) since entering a name like "Pasquale Voldemort Fortescue del Mor" is going to blow out your 20-character array.

There are ways to fix that but it probably doesn't matter for classwork that much (it will in the real world but that comes with experience):

int i = 0;
do {
    p_customer->last_name[i] = getchar();
    if (i < sizeof (p_customer->last_name) - 1)  // NEVER got to 20
        i++;
} while (p_customer->last_name[i-1] != NEW_LINE);
p_customer->last_name[i] = '\0';

If you really want a pointer version of it, that's easy:

char *p = p_customer->last_name;
do {
    *p = getchar();
    if (p != &(p_customer->last_name[sizeof(p_customer->last_name) - 1])
        p++;
} while (*(p-1) != NEW_LINE);
*p = '\0';
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I understand I can do it that way, but a do...while would then be pointless, I would've just used a for loop. I'm thinking more along the line of pointer arithmetic or some other solution not involving indexes, but thanks anyhow. – John Nov 02 '10 at 01:36
  • Well, you asked for a do...while loop, there it is :-) I see no requirement for pointers. The whole exercise is pointless (other than its educational value) since you would no doubt be using robust input functions in the real world, like this most _excellent_ one over here: http://stackoverflow.com/questions/1956687/why-does-not-the-input-of-a-string-work/1956805#1956805 :-) In any case, I've added a pointer version for you, in case you want to use it instead. – paxdiablo Nov 02 '10 at 01:50
  • Thanks, that's given me an idea of how to go about it. It is really for non-practical purposes, but I guess it helped me understand pointers and structures a bit better. – John Nov 02 '10 at 01:55
0

The code you posted won't compile. You mentioned that last_name is an array, but you can't assign to or increment arrays, so these two lines are invalid:

p_customer->last_name = getchar();         
p_customer->last_name++;

Try doing something like this, which will get rid of this error as well as solve the problem of checking if the first character is a newline:

int i = 0;
char ch;

while ((ch = getchar()) != NEW_LINE)
  p_customer->last_name[i++] = ch;

p_customer->last_name[i] = '\0';  // Don't forget the null terminator
casablanca
  • 69,683
  • 7
  • 133
  • 150
0

Ok, the solution with NO INDEXES would be;

char *pointer;

/* other code here */
pointer = p_customer->last_name 
do {
    *pointer = getchar();
    pointer += sizeof( char );
} while ( *(pointer - sizeof( char ) )!= NEW_LINE );

if you want to be sure not to go out of array bound.......simply do not use do while =) (which I always reccomend, as you must read lots of line before understanding the loop condition (and in a multinested function this is't a real readibility problem

ArtoAle
  • 2,939
  • 1
  • 25
  • 48
  • Why go through the trouble of doing `pointer += sizeof( char )` when you can just do `pointer++`? – casablanca Nov 02 '10 at 01:55
  • If I ever find someone in close physical proximity using `sizeof(char)` instead of 1, I will go biblical (as in `"wrath of ${INSERT_DEITY_OF_CHOICE_HERE}"`) on them :-) – paxdiablo Nov 02 '10 at 01:56
  • Haha, what I had in mind was to increment but somehow check for the previous addresses' contents. This fits the logic I was thinking in, and yes, doing pointer++ would complete it. – John Nov 02 '10 at 01:59
  • ok, no need to do pointer += sizeof( char ) instead of pointer++; but as long as john have some problem in understanding pointer aritmethic I tuoght that my solution would be a little bit cleaner then a (faster buy less understandable) pointer++ :] – ArtoAle Nov 02 '10 at 02:03