Поменять местами N первых и N последних символов заданной строки

Задача: Дана строка символов. Поменять местами N первых и N последних символов заданной строки. Написал код:

#include <stdio.h>
#include <string.h>
 
int mystrlen(char *s) {
    int len = 0;
    
    while (s[len]) {
        len++;
    }
    
    return len - 1;
}
 
int main() {
    char s[256];
    int n, len;
    
    printf("input string: ");
    fgets(s, 256, stdin);
    
    printf("N = ");
    scanf("%d", &n);
    
    if (n <= (len = mystrlen(s)) / 2) {
        for (int i = 0; i < n; i++) {
            s[i] += s[len - i - 1];
            s[len - i - 1] = s[i] - s[len - i - 1];
            s[i] -= s[len - i - 1];
        }
        
        printf("changed string:\n%s", s);
    } else {
        printf("bad data, try again!");
        return 1;
    }
 
    return 0;
}

Судя по всему допустил ошибку в цикле с условием. Примерный ввод: мамочка мыла раму. Должно выводить: а рамуа мылмамочк. У меня выводит: �Ѽа�очка мыла р�ам�. Еще хочется узнать, как убрать эти символы в словах? Нужно подключить кириллицу как-то?


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

length определяет число символов в кодировке UTF-8. position вычисляет смещение символа с заданным номером. reverse переворачивает байты в интервале задом-наперёд. swap меняет местами два сегмента строки:

#include <stdio.h>

int length(const char *s) {
    int len = 0;
    for (const char *p = s; *p != '\0'; ++p) {
        if ((*p & 0xC0) != 0x80) {
            ++len;
        }
    }
    return len;
}

int position(const char *s, int n) {
    int i = 0;
    const char *p;
    for (p = s; *p != '\0'; ++p) {
        if ((*p & 0xC0) != 0x80) {
            if (i >= n) {
                break;
            }
            ++i;
        }
    }
    return p - s;
}

void reverse(char *s0, char *s1) {
    const int n = s1 - s0;
    for (int i = 0, j = n - 1; i < j; ++i, --j) {
        char tmp = s0[i];
        s0[i] = s0[j];
        s0[j] = tmp;
    }
}

void swap(char *s0, char *s1, char *s2) {
    reverse(s0, s1);
    reverse(s1, s2);
    reverse(s0, s2);
}

#define SIZE 256

int main() {
    char s[SIZE];
    puts("string:");
    if (fgets(s, SIZE, stdin) == NULL) {
        return 1;
    }

    int n;
    puts("n:");
    if (scanf("%d", &n) != 1) {
        return 1;
    }

    const int len = length(s) - 1;
    if (n > len / 2) {
        return 1;
    }
    const int pos1 = position(s, n);
    const int pos2 = position(s, len - n);
    const int pos3 = position(s, len);
    swap(s, s + pos1, s + pos3);
    swap(s, s + pos2 - pos1, s + pos3 - pos1);

    printf("changed string:\n%s", s);
}
$ gcc -std=c11 -pedantic -Wall -Wextra -Werror swap-chars.c 

$ ./a.out 
string:
Hello, world!
n:
3
changed string:
ld!lo, worHel

$ ./a.out 
string:
Привет, мир!
n:
3
changed string:
ир!вет, мПри

$ ./a.out 
string:
Привет, world!
n:
3
changed string:
ld!вет, worПри

$ ./a.out 
string:
Hello, мир!
n:
3
changed string:
ир!lo, мHel
→ Ссылка