Обратный ввод каждые два символа

avatar
user9613239
7 апреля 2018 в 23:13
40
1
0

Я пытался написать программу, которая берет адрес и переворачивает его для каждых двух символов. Пример ввода будет "0xefba5896", а в идеале вывод будет "\x96\x58\xba\xef". Проблема, с которой я сталкиваюсь, заключается в том, что первые несколько байтов работают, но последний не печатается. Мой код ниже:

     int i;
     char *add =  argv[1];
     char rev[8];
     char xa[2];
     strncpy(rev, &add[2], strlen(add));   
     for (i = strlen(rev) - 2; i > -2; i-=2) {
                if (i == 0) {
                    strncpy(xa, &rev[0], 2);
                 } else {
                    strncpy(xa, &rev[i], 2);
                    xa[2] = '\0';
            }
                printf("\\x%s", xa);
     }

Если я ввожу "0xefba5896", мой вывод:

\x96\x58\xba\x

Если для кого-то ответ очевиден, пожалуйста, простите меня. Я изучаю C всего около недели. Будем очень признательны за любую помощь!

Источник
Iharob Al Asimi
7 апреля 2018 в 23:16
1

Почему вы пытаетесь это сделать? Как вы думаете, это квалифицируется как Проблема XY? Если да, то чем на самом деле вы хотите заниматься? Изменить порядок байтов целого числа?

r3mainer
7 апреля 2018 в 23:17
0

for (i = strlen(rev) - 2; i > -2; i-=2) — это rev вход? Было бы полезно, если бы вы дали своим переменным более осмысленные имена. В любом случае, что происходит, когда strlen(rev) является нечетным числом?

Iharob Al Asimi
7 апреля 2018 в 23:20
0

Также обратите внимание: 1. strncpy() — сложная функция, иногда она пропускает разделитель null, и в большинстве случаев вы можете заменить его на memcpy(), если знаете, что делаете. 2. Вы злоупотребили strncpy(), потому что, чтобы просто скопировать 2 байта, вы можете просто сделать это, назначив их напрямую.

Pablo
7 апреля 2018 в 23:26
1

Нет смысла передавать strlen(add) в качестве ограничивающего фактора в strncpy, если add длиннее 8, вы все равно переполнитесь rev! Вы должны передать размер места назначения, а не размер источника. Таким образом, правильный вызов strncpy(rev, add +2, sizeof rev);

Ответы (1)

avatar
Pablo
7 апреля 2018 в 23:43
0

Не имеет смысла передавать strlen(add) в качестве ограничивающего фактора strncpy, если add длиннее 10, вы все равно переполнитесь rev!

Вы должны передать размер места назначения, а не размер источника. Таким образом, правильный вызов

strncpy(rev, add+2, sizeof rev);
rev[sizeof(rev) - 1] = 0;

Также обратите внимание, что strncpy не обязательно записывает '\0'-завершающий байт если пункт назначения недостаточно длинный, поэтому всегда следует устанавливать '\0'-заканчивающий байт самостоятельно.

Также обратите внимание, что xa[2] = '\0'; переполняет xa, поскольку размер xa равен 2, поэтому максимальный индекс 1. Если вы хотите сохранить 2 символа в xa, то xa должен иметь как минимум размерность 3. То же самое касается rev. Итак, вы должны объявить xa следующим образом:

char rev[9];
char xa[3];

Поэтому, когда вы используете strncpy, вы должны использовать его следующим образом:

char dest[8];
strncpy(dest, src, sizeof dest);
dest[sizeof(dest) - 1] = 0;

Таким образом, вы можете переписать свою программу следующим образом:

int main(int argc, char **argv)
{
    if(argc != 2)
    {
        fprintf(stderr, "usage: %s address\n", argv[0]);
        return 1;
    }

    size_t len;
    char *add =  argv[1];
    char rev[9];
    char xa[3];  

    strncpy(rev, add + 2, sizeof rev);
    rev[sizeof(rev) - 1] = 0;

    len = strlen(rev);

    if(len & 1)
    {
        fprintf(stderr, "Invalid length of address, needs an even number of characters\n");
        return 1;
    }

    for(size_t i = len - 2; i >= 0; i -= 2)
    {
        strncpy(xa, rev + i, sizeof xa);
        xa[sizeof(xa) - 1] = 0;

        printf("\\x%s", xa);
        fflush(stdout);
    }

    putchar('\n');

    return 0;
}
user9613239
11 апреля 2018 в 02:23
0

Спасибо! Как оказалось, все, что мне было нужно, это расширить мои массивы на единицу.