Question

My university advised me to learn C as a Java-programmer from this document: “C for Java Programmers” by J. Maassen.

On page 46 (PDF-page 47), Maassen tries to implement his own version of C’s strcpy function, called my_strcpy

char *my_strcpy(char *destination, char *source)
{
    char*p = destination;
    while (*source != '\0')
    {
        *p++ = *source++;
    }
    *p = '\0';
    return destination;
}

I’ve tried to write a program with this function.
Take a look at page 45 (PDF-page 46). Here, Maassen has introduced his first version of a strcpy-method. He included stdio.h and copied strA to strB.

So, the following program should work, shouldn’t it?

#include <stdio.h>

char strA[80] = "A string to be used for demonstration purposes";
char strB[80];

int main(void)
{
    my_strcpy(strB, strA);
    puts(strB);
}

char *my_strcpy(char *destination, char *source)
{
    char*p = destination;
    while (*source != '\0')
    {
        *p++ = *source++;
    }
    *p = '\0';
    return destination;
}

Well, actually it doesn’t.
Because every time I’m compiling this program, I get the following errors:

PROGRAM.c:12:7: error: conflicting types for ‘my_strcpy’
 char *my_strcpy(char *destination, char *source)
       ^
PROGRAM.c:8:5: note: previous implicit declaration of ‘my_strcpy’ was here
 mystrcpy(strB, strA);
 ^

Why isn’t this program working? I mean, it should work, shouldn’t it?
I’ve seen a similar implementation of a strcpy function here. And that implementation isn’t working either! I’m getting the same errors!

What’s wrong?

Était-ce utile?

La solution

When the compiler sees line 8 of your program, it has no idea what types my_strcpy takes or returns. Either switch the order of main and my_strcpy in the source file or add a prototype of my_strcpy before main.

Autres conseils

Unlike Java where methods can be used before they are declared textually, C requires a prototype for each function that you call. In case you do not provide a prototype, C uses default rules, requiring prototype-less functions to take parameters matching the type of whatever you pass for the first time, and return an int.

To fix this, add this line ahead of main:

char *my_strcpy(char *, char *);

Note: the real strcpy allows pointers to constants to be passed as the second parameter. This lets you make calls like this:

my_strcpy(dest, "quick brown fox");

I suggest that you change the declaration and the definition as follows:

char *my_strcpy(char *, const char *);

char *my_strcpy(char *destination, const char *source)
{
      char* p = destination;
      while (*source != '\0')
      {
          *p++ = *source++;
      }
      *p = '\0';
     return destination;
}

Another thing to note is that you could do with destination the same thing that you did with the source, avoiding p. You can also use the implied comparison to zero - another thing not available in Java:

char *my_strcpy(char *destination, const char *source)
{
      while (*source) // Removed comparison to zero
      {
          *destination++ = *source++;
      }
      *destination = '\0';
     return destination;
}

Finally, to avoid the assignment of zero at the end of your loop, you could go for a body-less one-liner implementation:

char *my_strcpy(char *destination, const char *source)
{
      while (*destination++ = *source++)
          ;
     return destination;
}

When you use my_strcpy the first time, the compiler hasn't seen it yet and has no prototype for it. So it (possibly) defines it automatically as a function returning int.

You need to either supply a prototype before the call:

char *my_strcpy(char *destination, char *source);

int main(void)
{
    my_strcpy(strB, strA);
    puts(strB);
}

char *my_strcpy(char *destination, char *source)
{
    ...

or define the call before actually calling it (i.e. placing main() at bottom).

For large projects you would place all of your prototypes in an external file that you would then include:

#include "my_functions.h"

BTW, main usually is passed arguments from the command line, so you would define it as

int main(int argc, char **argv) {


    return 0;
}

returning a valid return code (e.g. 0 if all went well). You may use *pragma*s to tell the compiler that some arguments aren't really needed in the called code.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top