inz

anagrep.c (raw)

  1. #include <string.h>
  2. #include <unistd.h>
  3. #include <fcntl.h>
  4. #include <stdbool.h>
  5. #include <stdlib.h>
  6.  
  7. static void calcchars(int *counts, const char *buf)
  8. {
  9. for (; *buf; buf++)
  10. if ((*buf & ~0x20) >= 'A' &&
  11. (*buf & ~0x20) <= 'Z')
  12. counts[(*buf & ~0x20) - 'A']++;
  13. }
  14.  
  15. static int calccmp(int *target, int *candidate)
  16. {
  17. int i;
  18. for (i = 0; i <= 'Z' - 'A'; i++)
  19. if (target[i] < candidate[i])
  20. return false;
  21. return true;
  22. }
  23.  
  24. struct result {
  25. char *str;
  26. size_t sl;
  27. };
  28.  
  29. int rescmp(const void *a, const void *b)
  30. {
  31. const struct result *ar = a;
  32. const struct result *br = b;
  33.  
  34. if (ar->sl - br->sl)
  35. return br->sl - ar->sl;
  36. return strcmp(ar->str, br->str);
  37. }
  38.  
  39. static void processfd(int *counts, int fd)
  40. {
  41. char buffer[8192];
  42. size_t used = 0;
  43. int r;
  44. struct result *results = NULL;
  45. size_t nres = 0;
  46.  
  47. while ((r = read(fd, buffer + used, sizeof(buffer) - used)) > 0) {
  48. char *nlp;
  49. used += r;
  50. while ((nlp = memchr(buffer, '\n', used))) {
  51. int lcounts['Z' - 'A' + 1] = { 0 };
  52. int cmp;
  53. *nlp = '\0';
  54. calcchars(lcounts, buffer);
  55. if (calccmp(counts, lcounts)) {
  56. results = realloc(results, ++nres * sizeof(*results));
  57. results[nres - 1].str = strdup(buffer);
  58. results[nres - 1].sl = nlp - buffer;
  59. }
  60. memmove(buffer, nlp + 1, used - (nlp - buffer) - 1);
  61. used -= (nlp - buffer) + 1;
  62. }
  63. }
  64. qsort(results, nres, sizeof(*results), rescmp);
  65. for (r = 0; r < nres; r++) {
  66. results[r].str[results[r].sl] = '\n';
  67. write(STDOUT_FILENO, results[r].str, results[r].sl + 1);
  68. free(results[r].str);
  69. }
  70. free(results);
  71. }
  72.  
  73. int main(int argc, char **argv)
  74. {
  75. int what['Z' - 'A' + 1] = { 0 };
  76. int i;
  77.  
  78. calcchars(what, argv[1]);
  79. if (argc > 2) {
  80. for (i = 2; i < argc; i++) {
  81. int fd = open(argv[i], O_RDONLY);
  82. if (fd >= 0) {
  83. processfd(what, fd);
  84. close(fd);
  85. }
  86. }
  87. } else {
  88. processfd(what, STDIN_FILENO);
  89. }
  90.  
  91. return 0;
  92. }
  93.