1
votes

I have a question that reads as follows:

Write a function int tokenCopy(char* dest, const char* src, int destSize) which copies characters from the given source string src into the given destination buffer dest, which is of size destSize, until either:

the end of the source string occurs, or

the destination buffer is full (allowing for the terminator that will be needed), or

a space character is found in the input string

whichever comes first. If the copying finishes because a space is found, the space is not copied. The destination string must always be correctly terminated. If there is insufficient space in the destination for the source string, the destination string must be a correctly terminated leading substring of the source string.

The return value is the number of characters copied, not including the terminating null byte.

This is my attempt so far:

   int tokenCopy(char* dest, const char* src, int destSize)
   {
        int the_slab = 0;
        for (; *src != ('\0' | ' '); the_slab++) 
        {   
            if ( *src == (32 | 0)) 
            {
                *dest = '\0';
                return the_slab;
            }
            *dest = *src;
            dest++;
            src++;  
         }
        *dest = '\0';
        return the_slab;      
       }

However it fails when tested by:

char buff[10];
int n = tokenCopy(buff, "This", 10);
printf("%d '%s'\n", n, buff);

Because it returns the number 7 as opposed to 4. why is it not terminating after it's processed the first four letters? I don't understand why src doesn't have a terminating byte?

What have I done wrong? What don't I understand conceptually?

Thanks!

4
Although, the proposed duplicate looks like a duplicate, the answers there are really mess and doesn't address a simple issue. Worse, the example compares c-strings such "x" with == operator!P.P
Who cares? The problem is with basic language constructs, and would get closed for some other reason if not dup. There are many. many dups of such misunderstanding of the basics of compound conditionals.Martin James

4 Answers

4
votes

*src != ('\0' | ' ') doesn't do what you think it does.

You need to split it into two:

*src != '\0' && *src!= ' '

The same with:

  if ( *src == (32 | 0)) 

It should be:

 if ( *src == ' ' || *src )

It's always better to use the character representation ' ' than assuming/relying on ASCII values.

In fact, the whole condition inside the loop is reduntant:

   if ( *src == (32 | 0)) 
        {
            *dest = '\0';
            return the_slab;
        }

That's what you test in the for loop condition already.

2
votes

The | operator performs a bitwise "OR" operation on the two operands-- not at all what you want.

C bitwise OR operations

Your test should use the logical OR operator, ||:

if (*src == ' ' || *src == '\0')
2
votes

This is really a comment, but comments don't allow for proper code formatting. I agree with the answers of @JohnPirie and @BlueMoon.

This is an example where using array index is cleaner then using pointers, as shown by the code below:

int tokenCopy(char* dest, const char* src, int destSize)
{
    int i;
    if (dest == NULL || source == NULL || destSize < 1) {
        // invalid input!
        return -1;
    }
    for (i = 0; i < (destSize-1) && src[i] != '\0' && src[i] != ' '; i++) {   
        dest[i] = src[i];
    }
    dest[i] = '\0';
    return i;
}
0
votes

the operator | is bitwize (OR) operator. the instruction if ( *src == (32 | 0)) is same as if ( *src == 32 ) . because 32|0==32; remember logical table?:

0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1=  1

bitwize operator compare every bit of source with the one of dest, and because 0 has all bits off, every bit in 32 remain unchanged

you have to do this so that it works:

if ( (*src == 32) || (*src== 0)) { ...