A few days ago I wrote a program that writes its reversed input to output. Here’s an UTF-8 version of that program. Beware, this program is not non-UTF-8 safe. Have fun. On second thoughts, maybe the source file should be named 8-ftu-esrever.c.

/*
 esrever-utf-8.c -- Write the reversed input to output.

 Copyright © 2015 Trond Endrestøl <Trond.Endrestol@ximalas.info>

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>

static char *strrev(char *p);

int main(int argc, char **argv)
{
  FILE *in = stdin, *out = stdout;

  if (argc >= 2) {
    if ((in = fopen(argv[1], "r")) == NULL) {
      fprintf(stderr,
              "%s:%s:%d: fopen(\"%s\", \"r\") = %s (%d) \n",
              argv[0], __FILE__, __LINE__, argv[1], strerror(errno), errno);
      return 1;
    } // if

    if (argc >= 3) {
      if ((out = fopen(argv[2], "w")) == NULL) {
        fprintf(stderr,
                "%s:%s:%d: fopen(\"%s\", \"w\") = %s (%d) \n",
                argv[0], __FILE__, __LINE__, argv[2], strerror(errno), errno);
        return 1;
      } // if
    } // if
  } // if

  do {
    char buffer[4096], *p;

    if (fgets(buffer, sizeof(buffer), in) == NULL) {
      if (ferror(in) && !feof(in)) {
        fprintf(stderr,
                "%s:%s:%d: ferror() on \"%s\", possibly %s (%d) \n",
                argv[0], __FILE__, __LINE__, (in == stdin) ? "/dev/stdin" : argv[1], strerror(errno), errno);
        return 1;
      } // if
    } // if

    if (feof(in))
      break;

    if ( (p = strchr(buffer, '\n')) != NULL)
      *p = '\0'; // Change newline to NUL terminator

    strrev(buffer);

    if (p != NULL)
      *p = '\n'; // Put newline back.

    if (fputs(buffer, out) == EOF) {
      if (ferror(out)) {
        fprintf(stderr,
                "%s:%s:%d: ferror() on \"%s\", possibly %s (%d) \n",
                argv[0], __FILE__, __LINE__, (out == stdout) ? "/dev/stdout" : argv[2], strerror(errno), errno);
        return 1;
      } // if
    } // if
  } while (!ferror(in) && !ferror(out)); // do-while

  return 0;
} // main()

char *strrev(char *p)
{
  size_t start = 0, end;

  if (p == NULL || (end = strlen(p)) == 0)
    return NULL;

  end--; // Leave the NUL terminator alone.

  while (start < end) {
    p[start] ^= p[end];
    p[end]   ^= p[start];
    p[start] ^= p[end];

    start++;
    end--;
  } // while

  // Fixup any UTF-8 character sequences. This is not non-UTF-8 safe!
  start = 0;
  while (p[start] != '\0') {
    if (p[start] & 0x80 && p[start + 1] & 0x80) {
      p[start]     ^= p[start + 1];
      p[start + 1] ^= p[start];
      p[start]     ^= p[start + 1];
    } // if

    start++;
  } // while

  return p;
} // strrev()

// esrever-utf-8.c