3

For exercising my programming skills in C I'm trying to write the strncpy function by myself. Doing that I kept hitting errors, solving most of them eventually I'm stuck with no further inspiration to go on.

The error I receive is:

ex2-1.c:29:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
   printf("The copied string is: %s.\n", stringb);

The thing is that it's a very common error and that it's also already described on SO, only I can't seem to apply the tips other people have already pointed out. I get that I'm using a wrong type when printing the variable, and when I use the %d format it will return an integer which is probably the ASCII value of the first character, as it doesn't change when increasing the max number of bytes to copy.

Using GDB I've found out that the b variable when done iterating through the while loop holds the correct string, still I can't seem to print it.

I'm probably lacking a very fundamental part of knowledge about the C language and I apologise for asking this novice question (once again). Also I would appreciate it if you could give feedback or point out other flaws in my code.

#include <stdlib.h>
#include <stdio.h>

void strmycpy(char **a, char *b, int maxbytes) {
  int i = 0;
  char x = 0;

  while(i!=maxbytes) {
  x = a[0][i];
  b[i] = x;
  i++;
  }

  b[i] = 0;

}


int main (int argc, char **argv) {
  int maxbytes = atoi(argv[2]);
  //char stringa;
  char stringb;
  if (argc!=3 || maxbytes<1) {
        printf("Usage: strmycpy <input string> <numberofbytes>. Maxbytes has to be more than or equal to 1 and keep in mind for the NULL byte (/0).\n");
        exit(0);
     } else {

  strmycpy(&argv[1], &stringb, maxbytes);
  printf("The copied string is: %s.\n", stringb);

  }

  return 0;
}
BenMorel
  • 34,448
  • 50
  • 182
  • 322
mjrc
  • 43
  • 1
  • 1
  • 5
  • 2
    `stringb` is a `char`, not a `char*`. – Zeta Nov 20 '13 at 23:10
  • 1
    `stringb` is a char (which is promoted to an int when passed to `printf()`). You'll need to declare it as an appropriately-sized array. Indeed, "once again". –  Nov 20 '13 at 23:10
  • `%s` requires the address of a character sequence that terminates with a nul-char. You're passing a character, not the address of a character sequence, and certainly not one that terminate with a nul-char. – WhozCraig Nov 20 '13 at 23:10

1 Answers1

6

There is a slight difference between char and char*. The first is a single character whereas the later is a pointer to char (which can point to variable number of char objects).

The %s format specifier really expects a C-style string, which should not only be of type char* but is also expected to be null-terminated (see C string handling). If you want to print a single character, then use %c instead.

As for the program, assuming that what I think you want is what you want, try something like this:

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

static void strmycpy(char *dest, const char *src, size_t n) {
    char c;
    while (n-- > 0) {
        c = *src++;
        *dest++ = c;
        if (c == '\0') {
            while (n-- > 0)
                *dest++ = '\0';
            break;
        }
    }
}

int main(int argc, char *argv[]) {
    size_t maxbytes;
    char *stringb;

    if (argc != 3 || !(maxbytes = atoll(argv[2]))) {
        fprintf(
            stderr,
            "Usage: strmycpy <input string> <numberofbytes>.\n"
            "Maxbytes has to be more than or equal to 1 and keep "
            "in mind for the null byte (\\0).\n"
        );
        return EXIT_FAILURE;
    }

    assert(maxbytes > 0);
    if (!(stringb = malloc(maxbytes))) {
        fprintf(stderr, "Sorry, out of memory\n");
        return EXIT_FAILURE;
    }

    strmycpy(stringb, argv[1], maxbytes);
    printf("The copied string is: %.*s\n", (int)maxbytes, stringb);
    free(stringb);

    return EXIT_SUCCESS;
}

But frankly speaking, this is so fundamental that explaining might just result in writing a book on C. So you will be a lot better off if you just read one already written. For a list of good C books and resources, see The Definitive C Book Guide and List

Hope it helps. Good Luck!

Community
  • 1
  • 1
  • 3
    *Slight*? Sry. that made me laugh. – WhozCraig Nov 20 '13 at 23:11
  • 2
    @WhozCraig: Yeah, the difference is only in asterisk, how big can it be right :) –  Nov 20 '13 at 23:12
  • 1
    The difference is negligible. :P –  Nov 20 '13 at 23:13
  • 1
    For the OP's reference, spend some time playing with the format specifiers in the [documentation for `printf()`](http://en.cppreference.com/w/c/io/fprintf). Its worth the time to learn them. – WhozCraig Nov 20 '13 at 23:14
  • And you certainly meant a pointer to a `char`. Pointers to arrays are another kind of beast. – ouah Nov 20 '13 at 23:15
  • +1 for your correction to OP's `strmycpy()`: a correction was needed. Alternate: instead of 2nd `while (n-- > 0) ...`, `memset(dest, 0, n)` could be used to take advantage of optimizations it may use, especially for large `n`. Your code in functionally correct IMHO. – chux - Reinstate Monica Nov 20 '13 at 23:54
  • Thanks for all the replies, I certainly appreciate it! Though I admit I'm lacking knowledge in all different parts, I know about the concept of pointers though indeed I haven't mastered them yet. The point I was trying to make: Within the function strmycpy I've been succesfully able to duplicate the string in pointer a into the string in pointer b, though when trying to print it it doesn't seem to recognise stringb as a C styled string, although I've (tried to) NULL terminate it by the line of code "b[i] = 0;" – mjrc Nov 21 '13 at 14:56