esrever-utf-8.c
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