add initial scramble
authorJoey Hess <joey@gnu.kitenet.net>
Sat, 11 Jul 2009 20:03:50 +0000 (16:03 -0400)
committerJoey Hess <joey@gnu.kitenet.net>
Sat, 11 Jul 2009 20:03:50 +0000 (16:03 -0400)
scramble.c [new file with mode: 0644]

diff --git a/scramble.c b/scramble.c
new file mode 100644 (file)
index 0000000..978e06e
--- /dev/null
@@ -0,0 +1,205 @@
+/* Scramble the "inner" letters of each word in the input into a random order, and output the result. Non-word (that is, non-alphabetical) characters, and the first and last letters of each word, are left alone.
+ * Output to something other than stdout will append to the file instead of overwriting it - this may be undesirable, and can be changed if so.
+ */
+
+/* Copyright 2009-07-11 Andrew J. Buehler.
+ */
+
+/*   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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <ctype.h> // for isalpha()
+#include <stdlib.h> // for malloc()/calloc()/realloc()/free() and rand()/srand()
+#include <string.h> // for strlen()
+#include <time.h> // for time()
+
+#define ALLOW_FILE_IO 1
+
+
+/* strips 'reduction' characters from the end of the input string and returns the result
+ * works only if strlen(string> >= reduction, which is the case in the only place it is presently called
+ */
+char *shorten_string(char *string, int reduction) {
+  int i;
+  
+  i = strlen(string);
+  
+  for (; reduction > 0; reduction--, i--) {
+    string[i-1] = '\0'; // would it work to use an 'i-reduction' approach instead, similar to what was later done in narrow_string()?
+  }
+  
+  return string;
+}
+
+/* strips 'reduction' characters from the beginning and the end of the input string and returns the result
+ * works only if(strlen(string) >= 2*reduction), which is the case in the only place it is presently called
+ */
+char *narrow_string(char *string, int reduction) {
+  int i = reduction;
+  
+  while(string[i]) {
+    string[i-reduction] = string[i];
+    i++;
+  }
+  string[i-reduction] = '\0';
+  
+  return shorten_string(string, reduction);
+}
+
+int all_one_letter(char *string) {
+  char c;
+  int i;
+  
+  c = string[0];
+  for(i = 1; string[i] != '\0'; i++) {
+    if(c != string[i]) {
+      return 0; // a nonduplicate letter has been found
+    }
+    c = string[i];
+  }
+  
+  return 1; // reached the end of the string having found only duplicate letters, so it's all one letter
+}
+
+/* randomly reorders the contents of the string
+ * WARNING: frees the input string and returns a replacement
+ */
+char *scramble_string(char *string) {
+  char *ret, *tmpstr;
+  int len, i, j;
+  
+  len = strlen(string);
+  if(len < 2) return string; // can't scramble a 1-character string or an empty string!
+  if(all_one_letter(string)) return(string); // can't scramble a string which consists entirely of one letter!
+  
+  ret = strdup(string);
+  
+  while(strcmp(string, ret) == 0) {
+    j = 0;
+    tmpstr = strdup(string);
+    while(len > 0) {
+      i = rand() % len;
+      ret[j] = tmpstr[i];
+      j++;
+      while(tmpstr[i] != '\0') {
+        tmpstr[i] = tmpstr[i+1];
+        i++;
+      }
+      len--;
+    }
+    free(tmpstr);
+    len = strlen(string);
+  }
+  
+  
+  free(string);
+  return ret;
+}
+
+char *clear_string(char *string) {
+  int i;
+  
+  i = strlen(string);
+  
+  for(; i >= 0 ; i--) {
+    string[i] = '\0';
+  }
+  
+  return string;
+}
+
+int main(int argc, char **argv) {
+  int word_length;
+  char c, tempchar, *word;
+  FILE *infile, *outfile;
+  
+#if ALLOW_FILE_IO
+ /* open files, if any other than stdin and stdout */
+  if(argc > 1) {
+    if(!strcmp(argv[1], "--help") ||
+       !strcmp(argv[1], "-h")) {
+      printf("Usage: %s [INPUT_FILENAME] [OUTPUT_FILENAME]\n", argv[0]);
+      printf("If INPUT_FILENAME is omitted or is '-', read from standard input\nIf OUTPUT_FILENAME is omitted or is '-', print to standard output\n");
+      return 0;
+    }
+    
+    if(strcmp(argv[1], "-")) {
+      infile = fopen(argv[1], "r");
+      if(infile == NULL) {
+        fprintf(stderr, "Unable to open input file %s for reading\n", argv[1]);
+        return 1;
+      }
+    } else {
+      infile = stdin;
+    }
+    
+    if(argc > 2) {
+      if(strcmp(argv[2], "-")) {
+        outfile = fopen(argv[2], "a");
+        if(outfile == NULL) {
+          fprintf(stderr, "Unable to open output file %s for writing\n", argv[2]);
+          return 2;
+        }
+      } else {
+        outfile = stdout;
+      }
+    }
+  } else { // no arguments specified
+    infile = stdin;
+    outfile = stdout;
+  }
+#else
+  infile = stdin;
+  outfile = stdout;
+#endif
+
+  srand(time(NULL)); // needed for scramble_string() to actually be random
+  
+  word_length = 0;
+  word = malloc(sizeof(char));
+  word[0] = '\0';
+  c = fgetc(infile);
+  
+  if(feof(infile)) {
+    printf("Reached EOF while reading the first character of the input file!\n");
+    return 4;
+  }
+  
+  while(!feof(infile)) {
+    if(isalpha(c)) {
+      word = realloc(word, word_length+2); // one for the new character, one for the null
+      word[word_length] = c;
+      word[word_length + 1] = '\0'; // duplicate addition with the next line, but possibly more readable
+      word_length++;
+    } else {
+      if(word_length) {
+        word_length--;
+        fputc(word[0], outfile);
+        if(word_length) {
+          tempchar = word[word_length];
+          word = scramble_string(narrow_string(word, 1));
+          fprintf(outfile, "%s", word);
+          fputc(tempchar, outfile);
+        }
+        word = clear_string(word);
+        word_length = 0;
+      }
+      fputc(c, outfile);
+    }
+    fflush(outfile);
+    c = fgetc(infile);
+  }
+  
+  free(word);
+  return 0;
+}
This page took 0.014935 seconds and 4 git commands to generate.