expand.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. //This is a trivial C program that takes as input a string of the
  2. //form: "[a-zA-Z0-9]-[a-zA-Z0-9]". It then expands. eg:
  3. // "a-e2-4" will expand into "abcde234"
  4. // We will hereafter refer to any three length strength of the form:
  5. // "[a-zA-Z0-9]-[a-zA-Z0-9]" a sequence.
  6. //This exercise is taken from "The C Programming Language" p. 63
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #define ALLOCATE_SEQUENCE() (struct sequence_t *) \
  12. malloc (sizeof (struct sequence_t))
  13. /* This would expand the sequence "a-e" into "abcde". This macro
  14. works on one sequence at a time. So it will not process two
  15. sequences like "a-e4-6" at once. It returns a pointer to the
  16. expanded string. */
  17. #define EXPAND_SEQUENCE_TO_STRING(loop_str) \
  18. for (char c = sequence->beginning_char; \
  19. c <= sequence->end_char; c++, i++) \
  20. *(loop_str + i) = c; \
  21. *(loop_str + i) = '\0';
  22. #define IS_CHAR_A_DIGIT(c) (c >= '0' && c <= '9') ? 1 : 0
  23. #define EXIT_IF_INVALID_SEQUENCE(a, b) \
  24. if ((isalpha (a) && !(isalpha (b))) \
  25. || (isdigit (a) && !(isdigit (b))) \
  26. || (isupper (a) && (islower (b))) \
  27. || (islower (a) && (isupper (b)))) \
  28. { \
  29. fprintf (stderr, "Input String \"%c-%c\" is not valid\n", \
  30. a, b); \
  31. fprintf (stderr, \
  32. "Sequences are of the form ([a-bA-B0-9]-[a-bA-B0-9])+.\n"); \
  33. exit (EXIT_FAILURE); \
  34. }
  35. /* This is the number of sequences the inputted string has. */
  36. int sequences = 0;
  37. /* sequence_t will store the information from an encoded string the
  38. ** encoded strings looks like "[a-zA-Z0-9]-[a-zA-Z0-9]". So an
  39. ** encoded string of "a-z", represents the whole alphabet. */
  40. //A struct of
  41. //sequence_t = {beginning_char = 'a', end_char = 'z', next
  42. // = sequence_t { beginning_char = '0', end_char = '9', next = 0 }}
  43. // represents a string that contains the alphabet followed by the
  44. // numbers 1-9. The original string would have been "a-z0-9".
  45. struct sequence_t
  46. {
  47. char beginning_char, end_char;
  48. unsigned int sequence_length;
  49. struct sequence_t *next;
  50. };
  51. void *
  52. xmalloc (size_t size)
  53. {
  54. void *value = malloc (size);
  55. if (value == 0)
  56. {
  57. fprintf (stderr, "virtual memory exhausted\n");
  58. exit (EXIT_FAILURE);
  59. }
  60. return value;
  61. }
  62. /* This function parses the string of sequences into numerous struct
  63. sequence_t. It returns the pointer to the first sequence. */
  64. struct sequence_t * parse_string (char * input_string)
  65. {
  66. int str_len = strlen (input_string);
  67. if (str_len % 3)
  68. {
  69. fprintf
  70. (stderr,
  71. "Sequences are of the form ([a-bA-B0-9]-[a-bA-B0-9])+.\n");
  72. exit (EXIT_FAILURE);
  73. }
  74. // This is the number of sequences that we have. (reminder "a-c0-9"
  75. //is 2 sequences).
  76. extern int sequences;
  77. sequences = str_len / 3;
  78. struct sequence_t * sequence = ALLOCATE_SEQUENCE ();
  79. struct sequence_t * loop_sequence = sequence;
  80. for (int i, j = 0; j < sequences; i++, j++)
  81. {
  82. loop_sequence->beginning_char = *(input_string + i);
  83. i += 2; //skip the '-'
  84. loop_sequence->end_char = *(input_string + i);
  85. EXIT_IF_INVALID_SEQUENCE
  86. (sequence->beginning_char, sequence->end_char);
  87. loop_sequence->next = ALLOCATE_SEQUENCE ();
  88. loop_sequence = loop_sequence->next;
  89. }
  90. return sequence;
  91. }
  92. /* This function returns expanded sequences from the inputted string
  93. of sequences. */
  94. char * expand (char * input_string)
  95. {
  96. struct sequence_t * sequence = parse_string (input_string);
  97. extern int sequences;
  98. //this is using way too much memory. For the sequence "a-b", 32
  99. //chars are allocated for it.
  100. char * return_string = (char *) xmalloc (sizeof (char) * 32 * sequences);
  101. int return_string_len = 0;
  102. int i;
  103. //this should work in place of the next line...memset (loop_str, 0, 32);
  104. char * loop_str = (char *) xmalloc (sizeof (char) * 32);
  105. while (sequence)
  106. {
  107. i = 0;
  108. EXPAND_SEQUENCE_TO_STRING (loop_str);
  109. strcpy ((return_string + return_string_len), loop_str);
  110. return_string_len += i;
  111. sequence = sequence->next;
  112. }
  113. free (loop_str);
  114. return return_string;
  115. }
  116. int main ()
  117. {
  118. char * expanded_string = expand ("1-3a-gM-T3-5");
  119. printf ("%s\n", expanded_string);
  120. return 0;
  121. }