1

I think this snippet of code is enough to get the idea of what I'm doing. I'm using getline to read input data from a text file that has lines that might look something like this: The cat is fat/And likes to sing

From searching around the internet I was able to get it working, but I'd like to better understand WHY it is working. My primary question is how the

memcpy(id, buffer, temp - buffer); 

line is working. I read what memcpy() does but do not understand how the temp - buffer part is working. So from my understanding I'm setting *temp to the '/' in that line. Then I'm copying the line up until the '/' into it. But how does the temp, which is at '/' minus the buffer (which is the whole line from getline) work out to just be The cat is fat?

Hopefully that made some sense.

#define MAX_SIZE    255

char buffer[MAX_SIZE + 1] = { 0 };
cin.getline(buffer, MAX_SIZE);

memset(id, 0, 256);
memset(title, 0, 256);

char* temp = strchr(buffer, '/');
memcpy(id, buffer, temp - buffer);
temp++;
strcpy(title, temp);

Also, if I can double dip, why would MAX_SIZE be defined at 255 but MAX_SIZE+1 is often used. Does this have to do with a delimiter or white space at the end of a line? Thanks for the help.

1
  • I'm not sure your title is what you intended. The memset calls in this code are most straight-forward: "fill this memory region at this starting address with this octet for this many repetitions". I would think the temp-buffer in the memcpy call would be more interesting (and its a pointer-difference calculation, worth googling). Commented Oct 17, 2014 at 7:16

4 Answers 4

2

In my opinion it is simply a bad code.:) I would write it like

const size_t MAX_SIZE = 256

char buffer[MAX_SIZE] = {};

std::cin.getline( buffer, MAX_SIZE );

id[0] = '\0';
title[0] = '\0';

if ( char* temp = strchr( buffer, '/' ) )
{
    std::memcpy( id, buffer, temp - buffer );
    id[temp - buffer] = '\0';
    std::strcpy( title, temp + 1 );
}
else
{
    std::strcpy( id, buffer );
}

As for memcpy in this statement

memcpy(id, buffer, temp - buffer);

then it copies temp - buffer bytes from buffer to id. As id was previously set to zeroes then after memcpy it will contain a string with terminating zero.

Sign up to request clarification or add additional context in comments.

Comments

2

You're question concerns pointer-difference calculation, part of the family of arithmetic operations that are done in pointer-arithmetic.

Most beginners don't have too much trouble grasping how pointer-addition works. Given this:

char buffer[256];
char *p = buffer + 10;

it is usually clear that p points to the 10th slot in the buffer char array. But you need to remember that the pointer type is important. The same construct you see above also works for more complicated data types:

struct Something
{
    char name[128];
    int ident;
    int supervisor;
} people[64];

struct Something *p = people+10; // NOTE: same line, different types

Just as before, p points to the tenth element in the array, but note the arithmetic; the size of the underlying type is used to calculate the relevant memory offset. You don't need to do it yourself. No sizeof required here.

So why do you care? Because just like regular math, pointer math has certain properties, one of them being the following:

char buffer[256];
char *p = buffer+10;   // p addresses the 10th slot in the array
size_t len = p-buffer  // len is the typed-difference between p and buffer.

In this case, len will be 10, the same as the offset of p. So how does this relate to your question? Well...

char* temp = strchr(buffer, '/');
memcpy(id, buffer, temp - buffer);

The horrid nature of this code aside (if there is no '/' in the buffer array the result is temp being NULL, and the ensuing memcpy will all-but-guarantee a massive segfault). This code finds the location in the string where '/' resides. Once it has that, the calculation temp - buffer uses pointer arithmetic (specifically pointer differencing) to calculate the distance between the address in temp and the address as the base of the array. The result is the element count not including the slash itself. Therefore this code copies up-to, but not including, the discovered slash, into the id buffer. The rest of the id buffer retains all the 0 values populated with the memset and therefore the string is terminated (which is way more work than you need to do, btw).

After that line, the remainder:

temp++;
strcpy(title, temp);

post-increments the temp pointer, which says "move to the next element in the array". Then the strcpy copies the remaining chars of the null-terminated buffer string into title. Worth noting this could have simply been:

strcpy(title, ++temp);

And likewise:

strcpy(title, temp+1);

which retains temp at the '/' position. In all of the above, the result in title will be the same: all chars after the slash, but not including it.

I hope that explains what is going on. Best of luck.

Comments

1
MAX_SIZE+1 is reserving space for the null terminator at the end of the string ('\0')

memcpy(id, buffer, temp - buffer) 

This is copying (temp-buffer) bytes from buffer to id. Since strchr finds the '/' character in the input, temp is pointing inside buffer (assumiing it's found). So for example assume buffer points to a location in memory:

buffer = 0x781230001

and the third byte is the '/', after strchr, you have

temp = 0x781230003

temp - buffer therefore is 2.

HOWEVER: If the '/' is not found, then temp will not work and the code will crash. You should check the result of strchr before doing the pointer arithmetic.

Comments

1

There you calculate position of first / in buffer.

char* temp = strchr(buffer, '/');

Now temp points to / in buffer. If you want to copy this part of buffer, its enough to get pointer to start and length of string. So temp - buffer evaluates to length.

=================================
The cat is fat/And likes to sing
=================================
^             ^
buffer        temp

|    length   | = temp - buffer

End of null terminated string determinated by \0 (or simply 0). So if you need to store N chars you need to allocate N+1 buffer size.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.