формат '%s' ожидает аргумент типа 'char *'

Для тренировки своих навыков программирования на C я пытаюсь написать функцию strncpy самостоятельно. Делая это, я продолжал натыкаться на ошибки, решая большинство из них, в конце концов я застрял без дальнейшего вдохновения, чтобы продолжать.

Ошибка, которую я получаю:

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);

Дело в том, что это очень распространенная ошибка, и она также уже описана на SO, только я не могу применить советы, на которые уже указали другие люди. Я понимаю, что использую неправильный тип при печати переменной, и когда я использую формат% d, он возвращает целое число, которое, вероятно, является значением ASCII первого символа, поскольку оно не изменяется при увеличении максимального числа байтов для копирования.

Используя GDB, я обнаружил, что переменная b при выполнении итерации цикла while содержит правильную строку, но я не могу ее напечатать.

Мне, вероятно, не хватает очень фундаментальной части знаний о языке C, и я прошу прощения за этот вопрос новичка (еще раз). Также я был бы признателен, если бы вы могли оставить отзыв или указать на другие недостатки в моем коде.

#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;
}

person mjrc    schedule 20.11.2013    source источник
comment
stringb это char, а не char*.   -  person Zeta    schedule 21.11.2013
comment
stringb - это char (который повышается до int при передаче в printf()). Вам нужно будет объявить его как массив соответствующего размера. Действительно, еще раз.   -  person    schedule 21.11.2013
comment
%s требуется адрес последовательности символов, которая заканчивается нулевым символом. Вы передаете символ, а не адрес последовательности символов и, конечно же, не тот, который заканчивается нулевым символом.   -  person WhozCraig    schedule 21.11.2013


Ответы (1)


Между char и char* есть небольшая разница. Первый — это один символ, а второй — указатель на char (который может указывать на переменное количество объектов char).

Спецификатор формата %s на самом деле ожидает строку в стиле C, которая должна быть не только типа char*, но также должна завершаться нулем (см. обработка строки C). Если вы хотите напечатать один символ, используйте вместо него %c.

Что касается программы, предполагая, что то, что я думаю, вы хотите, это то, что вы хотите, попробуйте что-то вроде этого:

#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;
}

Но, честно говоря, это настолько фундаментально, что объяснение может просто привести к написанию книги по C. Так что вам будет намного лучше, если вы просто прочитаете уже написанную. Список хороших книг и ресурсов по C см. в The Definitive C Book Guide and List.

Надеюсь, поможет. Удачи!

person Community    schedule 20.11.2013
comment
Небольшой? Сорри. это заставило меня смеяться. - person WhozCraig; 21.11.2013
comment
@WhozCraig: Да, разница только в звездочке, насколько большой она может быть :) - person ; 21.11.2013
comment
Разница незначительна. :П - person ; 21.11.2013
comment
Для справки ОП потратьте некоторое время на игру со спецификаторами формата в документации для printf(). Стоит потратить время на их изучение. - person WhozCraig; 21.11.2013
comment
И вы, конечно, имели в виду указатель на char. Указатели на массивы — еще один зверь. - person ouah; 21.11.2013
comment
+1 за ваше исправление к strmycpy() ОП: требовалось исправление. Альтернативный вариант: вместо второго while (n-- > 0) ... можно использовать memset(dest, 0, n), чтобы воспользоваться оптимизацией, которую он может использовать, особенно для больших n. Ваш код в функционально правильном ИМХО. - person chux - Reinstate Monica; 21.11.2013
comment
Спасибо за все ответы, я, конечно, ценю это! Хотя я признаю, что мне не хватает знаний во всех областях, я знаю о концепции указателей, хотя на самом деле я еще не освоил их. То, что я пытался сделать: в функции strmycpy мне удалось успешно продублировать строку в указателе a в строку в указателе b, хотя при попытке напечатать ее, похоже, не распознать stringb как стиль C строка, хотя я (пытался) завершить ее NULL строкой кода b[i] = 0; - person mjrc; 21.11.2013