Advertisement
dmilicev

c_strings_pointers_and_dynamic_allocation_of_memory_space.c

Oct 29th, 2019
1,057
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 32.42 KB | None
  1. /*
  2.  
  3.  c_strings_pointers_and_dynamic_allocation_of_memory_space.c
  4.  
  5. The idea is that this program should cover everything about strings,
  6. pointers and dynamic allocation of memory space.
  7.  
  8. The program has many comments because it is intended for beginners.
  9.  
  10. I want to encourage beginners in programming to study this program
  11. regardless of the fact that it consists of almost 1000 lines.
  12. Half of these lines belong to the comments and explanations.
  13.  
  14. The point of the functions is to divide a big problem
  15. into several smaller problems.
  16. Each function should solve only one problem and nothing more.
  17. Functions should therefore not have more than a couple dozen lines of code.
  18. The features of the functions are arguments (parameters, input values)
  19. and the value returned by the function to the part of the program
  20. from which it was called.
  21. If we pass to the function the pointers to the variables as arguments,
  22. function then has the ability to change the value of the arguments
  23. beyond its scope, and in that case it does not even have to have
  24. its own return value.
  25. Our conversations should soon come down to questions about how to write
  26. a function that receives those arguments and has that return value.
  27.  
  28. Please understand that English is not my native language and
  29. please feel free to correct me about it.
  30.  
  31. Feel free to let me know if you think I left out something about it,
  32. or if you find some bugs in this program.
  33.  
  34. This program will be updated according to your suggestions.
  35.  
  36. Author Dragan Milicev
  37. https://www.facebook.com/dmilicev
  38. You can find all my C programs at Dragan Milicev's pastebin:
  39. https://pastebin.com/u/dmilicev
  40.  
  41. An example of C strings
  42. https://www.tutorialspoint.com/cprogramming/c_strings.htm
  43.  
  44. An example of dynamically allocating memory space
  45. https://www.tutorialspoint.com/cprogramming/c_memory_management.htm
  46.  
  47. An example of working with pointers, explanation of **variable.
  48. https://www.tutorialspoint.com/cprogramming/c_pointers.htm
  49.  
  50. // While * means the address of a variable in C programming language,
  51. // what does ** mean then?
  52. // https://www.quora.com/While-*-means-the-address-of-a-variable-in-C-programming-language-what-does-**-mean-then#
  53. // **x is a pointer to a pointer:
  54. //  *x points to an address
  55. // **x is the value at that address.
  56.  
  57. int *ptr1;
  58. means to declare "pointer to int 'ptr1', where ptr1 is the name of the pointer.
  59. int **ptr2;
  60. means to declare "pointer to pointer to int 'ptr2'." ptr2 still only holds one address in it.
  61. What the stars signify is that the address in ptr2 points to another address,
  62. which you may want to dereference to get a value, or put a value.
  63.  
  64.  
  65. // ----------Functions for working with characters (ctype.h)-----------------
  66.  
  67. int isalpha(int c)
  68. // checks if the passed character is alphabetic (letter)
  69. https://www.tutorialspoint.com/c_standard_library/c_function_isalpha.htm
  70.  
  71. int isdigit(int c)
  72. // checks if the passed character is a decimal digit character (digit)
  73. https://www.tutorialspoint.com/c_standard_library/c_function_isdigit.htm
  74.  
  75. int isalnum(int c)
  76. // checks if the passed character is alphanumeric (letter or digit)
  77. https://www.tutorialspoint.com/c_standard_library/c_function_isalnum.htm
  78.  
  79. int isspace(char c)
  80. // checks whether the passed character is white-space.
  81. // examines whether c is any of the following characters:
  82. // ' ' , '\t' , '\n' , '\v' , '\f' , '\r'
  83. https://www.tutorialspoint.com/c_standard_library/c_function_isspace.htm
  84.  
  85. int isupper(int c)
  86. // checks whether the passed character is uppercase letter (capital letter)
  87. https://www.tutorialspoint.com/c_standard_library/c_function_isupper.htm
  88.  
  89. int islower(int c)
  90. // checks whether the passed character is a lowercase letter
  91. https://www.tutorialspoint.com/c_standard_library/c_function_islower.htm
  92.  
  93. int ispunct(int c)
  94. // checks whether the passed character is a punctuation character.
  95. // A punctuation character is any graphic character (as in isgraph)
  96. // that is not alphanumeric (as in isalnum).
  97. https://www.tutorialspoint.com/c_standard_library/c_function_ispunct.htm
  98.  
  99. int tolower(int c)
  100. // converts a given letter to lowercase
  101. https://www.tutorialspoint.com/c_standard_library/c_function_tolower.htm
  102.  
  103. int toupper(int c)
  104. // converts lowercase letter to uppercase
  105. https://www.tutorialspoint.com/c_standard_library/c_function_toupper.htm
  106.  
  107.  
  108. // ----------Functions for working with strings (string.h)-------------------
  109.  
  110. char *strcpy(char *dest, const char *src)
  111. // copies the string pointed to, by src to dest,
  112. // assuming in advance that there is enough space in string dest    !!! VERY IMPORTANT !!!
  113. https://www.tutorialspoint.com/c_standard_library/c_function_strcpy.htm
  114. If the destination of the strcpy call doesn't have enough memory
  115. to contain the result, strcpy cals lead to severe bugs.
  116.  
  117. char *strcat(char *dest, const char *src)
  118. // appends the string pointed to by src to the end of the string pointed to by dest
  119. // assuming in advance that there is enough space in string dest    !!! VERY IMPORTANT !!!
  120. // (ConcATenate)
  121. https://www.tutorialspoint.com/c_standard_library/c_function_strcat.htm
  122. Implementation of strcat()
  123. https://www.programiz.com/c-programming/examples/concatenate-string
  124. If the destination of the strcat call doesn't have enough memory
  125. to contain the result, strcat cals lead to severe bugs.
  126. A better example of using strcat is to allocate an array dynamically.
  127. https://www.stev.org/post/csomesimpleexamplesofusingstrcat
  128.  
  129. char *strncat(char *dest, const char *src, size_t n)
  130. // appends the string pointed to by src to the end of the string
  131. // pointed to by dest up to n characters long
  132. // dest is pointer to the destination array, which should contain a C string,
  133. // and should be large enough to contain the concatenated resulting string
  134. // which includes the additional null-character.    !!! VERY IMPORTANT !!!
  135. https://www.tutorialspoint.com/c_standard_library/c_function_strncat.htm
  136.  
  137. int strcmp(const char *str1, const char *str2)
  138. // compares the string pointed to, by str1 to the string pointed to by str2.
  139. // compares strings a and b and returns:
  140.                 //  -1 if a<b
  141.                 //   0 if a=b
  142.                 //   1 if a>b
  143. // (CoMPare)
  144. https://www.tutorialspoint.com/c_standard_library/c_function_strcmp.htm
  145.  
  146. int strncmp(const char *str1, const char *str2, size_t n)
  147. //  compares at most the first n bytes of str1 and str2.
  148. https://www.tutorialspoint.com/c_standard_library/c_function_strncmp.htm
  149.  
  150. int strcmpi(const char * str1, const char * str2 )
  151. // same as strcmp function
  152. // only that all the letters are converted to lowercase for comparison
  153. https://www.geeksforgeeks.org/strcmpi-function-in-c/
  154.  
  155. char *strchr(const char *str, int c)
  156. // searches for the first occurrence of the character c (an unsigned char)
  157. // in the string pointed to by the argument str.
  158. // returns a pointer to the first occurrence of the character c in the string str,
  159. // or NULL if the character is not found.
  160. https://www.tutorialspoint.com/c_standard_library/c_function_strchr.htm
  161.  
  162. char *strstr(const char *haystack, const char *needle)
  163. // finds the first occurrence of the substring needle in the string haystack.
  164. // The terminating '\0' characters are not compared.
  165. https://www.tutorialspoint.com/c_standard_library/c_function_strstr.htm
  166.  
  167. size_t strlen(const char *str)
  168. // computes the length of the string str up to,
  169. // but not including the terminating null character.
  170. // (LENght)
  171. https://www.tutorialspoint.com/c_standard_library/c_function_strlen.htm
  172.  
  173. char *strpbrk(const char *str1, const char *str2)
  174. // finds the first character in the string str1 that matches any character
  175. // specified in str2. This does not include the terminating null-characters.
  176. // If there are none, return NULL.
  177. https://www.tutorialspoint.com/c_standard_library/c_function_strpbrk.htm
  178.  
  179.  
  180. // ----------Functions for dynamic allocation of memory space----------------
  181.  
  182. void *malloc(size_t size)
  183. // allocates the requested memory and returns a pointer to it.
  184. https://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm
  185.  
  186. void *calloc(size_t nitems, size_t size)
  187. // allocates the requested memory and returns a pointer to it.
  188. // The difference in malloc and calloc is that malloc does not set
  189. // the memory to zero where as calloc sets allocated memory to zero.
  190. https://www.tutorialspoint.com/c_standard_library/c_function_calloc.htm
  191.  
  192. void *realloc(void *ptr, size_t size)
  193. //attempts to resize the memory block pointed to by ptr that was
  194. // previously allocated with a call to malloc or calloc.
  195. https://www.tutorialspoint.com/c_standard_library/c_function_realloc.htm
  196.  
  197. void free(void *ptr)
  198. // golden rule - for every call to malloc, there should be a corresponding free
  199. // deallocates the memory previously allocated by a call to calloc, malloc, or realloc.
  200. https://www.tutorialspoint.com/c_standard_library/c_function_free.htm
  201.  
  202. // ----------Begin of program------------------------------------------------
  203.  
  204. */
  205.  
  206.  
  207. #include <stdio.h>
  208. #include <stdlib.h>     // for malloc(), calloc(), realloc(), free()
  209. #include <conio.h>      // for _getch() i _getche()
  210. #include <string.h>     // for string functions
  211. #include <ctype.h>      // for char functions
  212.  
  213. #define MAX_SIZE 100
  214.  
  215.  
  216. // choice_1, copy string source to string destination
  217. // string_copy() is a safe function because it takes care that
  218. // the destination string has enough memory space
  219. // to be copied to it the entire source string
  220. char *string_copy( char **destination, char **source ) {
  221.  
  222. // Pointers ...
  223. // While * means the address of a variable in C programming language,
  224. // what does ** mean then?
  225. // https://www.quora.com/While-*-means-the-address-of-a-variable-in-C-programming-language-what-does-**-mean-then#
  226. // **x is a pointer to a pointer:
  227. //  *x points to an address
  228. // **x is the value at that address.
  229. // We use ** destination to allow this function
  230. // to change the value of the destination variable
  231. // in the part of the program from which it was called.
  232.  
  233. // !!! VERY IMPORTANT NOTE !!!
  234. // function strcpy() copies the source to destination,
  235. // assuming in advance that there is enough space
  236. // in destination for whole source.
  237.  
  238. // In our example, this is not the case.
  239.  
  240. // We are copying source to destination and because of that,
  241. // and we don't need a value of destination any more.
  242. // Because of that, we can to perform dynamic allocation of memory space
  243. // of destination to fit the entire source.
  244. // Let's do it:
  245.  
  246.     *destination = (char *)malloc( strlen( *source ) + 2 * sizeof(source) );
  247.  
  248. // *destination is value of **destination.
  249. // After allocating memory space, it must be checked that allocation has succeeded!
  250. // If malloc() returned a value of NULL, this is an indication of a failed allocation.
  251.  
  252.     if( *destination == NULL )
  253.     {
  254.         fprintf(stderr, "\n\n malloc() error! \n\n");
  255.         exit(EXIT_FAILURE);
  256.     }
  257.  
  258. // Only now the pointer *destination points to a memory space
  259. // large enough to fit the entire *source
  260. // and only now can we copy *source to *destination
  261.  
  262.     strcpy( *destination, *source );
  263.  
  264.     return ( *destination );
  265. }
  266.  
  267.  
  268. // choice_2, concatenate source to destination
  269. // string_concatenate() is a safe function because it takes care that
  270. // the destination string has enough memory space
  271. // to be copied to it the entire source string and destination string
  272. char *string_concatenate( char **destination, char **source ) {
  273.  
  274. // Pointers ...
  275. // While * means the address of a variable in C programming language,
  276. // what does ** mean then?
  277. // https://www.quora.com/While-*-means-the-address-of-a-variable-in-C-programming-language-what-does-**-mean-then#
  278. // **x is a pointer to a pointer:
  279. //  *x points to an address
  280. // **x is the value at that address.
  281. // We use **destination to allow this function
  282. // to change the value of the variable destination
  283. // in the part of the program from which it was called.
  284.  
  285. // !!! VERY IMPORTANT NOTE !!!
  286. // function strcat() concatenate source to destination,
  287. // assuming in advance that there is enough space
  288. // in destination to fit destination and source.
  289.  
  290. // In our example, this is not the case, and so
  291.  
  292. // We are concatenate source to destination,
  293. // and we need a value of destination.
  294. // Because of that, let's first declare a new variable mem_string_1
  295. // which does not currently point to anything, so we initialize it to NULL.
  296.  
  297.     char *mem_string_1 = NULL;
  298.  
  299. // Pointer mem_string_1 points to a memory space of 0 bytes.
  300. // We want it to point to a memory space of sufficient size to store destination
  301.  
  302.     mem_string_1 = malloc( strlen(*destination) + 1 * sizeof(**destination) );
  303.  
  304. // Instead of counting the characters in the new string, we use function strlen().
  305. // Let's check if dynamic memory allocation for variable mem_string_1 succeeded
  306.  
  307.     if (mem_string_1 == NULL)
  308.     {
  309.         fprintf(stderr, "\n\n malloc() error ! \n\n");
  310.         exit(EXIT_FAILURE);
  311.     }
  312.  
  313. // Let's remember value of destination in the new variable mem_string_1
  314. // ( instead of standard function strcpy() we may use our safe function
  315. // string_copy() and in that case there is no need to worry about
  316. // the destination having enough memory for the entire source
  317. // and in that case you can ignore (put in comment or delete)
  318. // the following code lines that are between // -------------------- //)
  319.  
  320.     strcpy(mem_string_1, *destination);
  321.  
  322. // ----------------------------------------------------------------------- //
  323.  
  324. // *destination is value of **destination.
  325. // *destination means value that is on the address destination.
  326. // Now we have value of *destination in mem_string_1,
  327. // so we can perform dynamic memory reallocation for destination
  328.  
  329. // Let's expand the memory space of variable destination with dynamic memory allocation
  330. // to fit value of destination and value of source
  331. // There are two ways to do this:
  332.  
  333.     // *destination = malloc( strlen(*destination) + strlen(*source) + 1 * sizeof(**destination) );
  334.  
  335. // or
  336.  
  337.     *destination = realloc( *destination, strlen(*destination) + strlen(*source) + 1 * sizeof(**destination) );
  338.  
  339. // Let's check if dynamic memory allocation for variable mem_string_1 succeeded
  340.  
  341.     if (*destination == NULL)
  342.     {
  343.         fprintf(stderr, "\n\n malloc() or realloc() error ! \n\n");
  344.         exit(EXIT_FAILURE);
  345.     }
  346.  
  347. // ----------------------------------------------------------------------- //
  348.  
  349.  
  350. // Let's return the value from mem_string_1 to the extended *destination
  351.  
  352.     strcpy( *destination, mem_string_1 );
  353.  
  354.  
  355. // Let's concatenate the value of *source to *destination
  356.  
  357.     strcat(*destination, *source);
  358.  
  359. // The mem_string_1 variable is no longer needed, so remember to free up it's memory space !
  360.  
  361.     free(mem_string_1); // golden rule - for every call to malloc, there should be a corresponding free
  362.  
  363.     return( *destination );
  364. }
  365.  
  366.  
  367. // choice_3, concatenate n characters of source to destination
  368. // string_n_concatenate() is a safe function because it takes care that
  369. // the destination string has enough memory space to be copied to it
  370. // the entire source string and first n characters of destination string
  371. char *string_n_concatenate( char **destination, char **source, int n ) {
  372.  
  373. // Pointers ...
  374. // While * means the address of a variable in C programming language,
  375. // what does ** mean then?
  376. // https://www.quora.com/While-*-means-the-address-of-a-variable-in-C-programming-language-what-does-**-mean-then#
  377. // **x is a pointer to a pointer:
  378. //  *x points to an address
  379. // **x is the value at that address.
  380. // We use **destination to allow this function
  381. // to change the value of the variable destination
  382. // in the part of the program from which it was called.
  383.  
  384. // !!! VERY IMPORTANT NOTE !!!
  385. // function strncat() appends the string pointed to by src to the end of the string
  386. // pointed to by dest up to n characters long.
  387. // dest is pointer to the destination array, which should contain a C string,
  388. // and should be large enough to contain the concatenated resulting string
  389. // which includes the additional null-character.    !!! VERY IMPORTANT !!!
  390.  
  391. // In our example, this is not the case, and so
  392.  
  393. // We are concatenate first n characters from source to destination,
  394. // and we need a value of destination.
  395. // Because of that, let's first declare a new variable mem_string_1
  396. // which does not currently point to anything, so we initialize it to NULL.
  397.  
  398.     char *mem_string_1 = NULL;
  399.  
  400. // Pointer mem_string_1 points to a memory space of 0 bytes.
  401. // We want it to point to a memory space of sufficient size to store destination
  402.  
  403.     mem_string_1 = malloc( strlen(*destination) + 1 * sizeof(**destination) );
  404.  
  405. // Instead of counting the characters in the new string, we use function strlen().
  406. // Let's check if dynamic memory allocation for variable mem_string_1 succeeded
  407.  
  408.     if (mem_string_1 == NULL)
  409.     {
  410.         fprintf(stderr, "\n\n malloc() error ! \n\n");
  411.         exit(EXIT_FAILURE);
  412.     }
  413.  
  414. // Let's remember value of destination in the new variable mem_string_1
  415.  
  416.     strcpy(mem_string_1, *destination);
  417.  
  418. // *destination means value that is on the address destination.
  419. // Now we have value of *destination in mem_string_1,
  420. // so let's expand the memory space of variable destination with dynamic memory allocation
  421. // to fit value of destination and first n characters from source
  422. // There are two ways to do this:
  423.  
  424.     //*destination = malloc( strlen(*destination) + n * sizeof(**source) );
  425.  
  426. // or
  427.  
  428.     *destination = realloc( *destination, strlen(*destination) + n * sizeof(**source) );
  429.  
  430. // Let's check if dynamic memory allocation for variable mem_string_1 succeeded
  431.  
  432.     if (*destination == NULL)
  433.     {
  434.         fprintf(stderr, "\n\n malloc() or realloc() error ! \n\n");
  435.         exit(EXIT_FAILURE);
  436.     }
  437.  
  438. // Let's return the value from mem_string_1 to the extended *destination
  439.  
  440.     strcpy(*destination, mem_string_1);
  441.  
  442. // Concatenate first n characters of *source to *destination
  443.  
  444.     strncat(*destination, *source, (size_t)n );
  445.  
  446. // The mem_string_1 variable is no longer needed, so remember to free up it's memory space !
  447.  
  448.     free(mem_string_1); // golden rule - for every call to malloc, there should be a corresponding free
  449.  
  450.     return( *destination );
  451. }
  452.  
  453.  
  454. // choice_7, convert upper case to lower case and vice versa with own meny
  455. // argument char *string_1 is not necessary
  456. void choice_7( char *string_1, char *string_2 ) {
  457.  
  458.     int i=0;
  459.     char choice;
  460.  
  461.   printf("\n\n 1. Convert uppercase and lowercase in string_2 ");
  462.     printf("\n 2. Convert string_2 to lowercase ");
  463.     printf("\n 3. Convert string_2 to uppercase ");
  464.   printf("\n\n    Choose (1-3)  ?  ");
  465.  
  466.     choice = _getche();
  467.  
  468.     switch(choice) {
  469.         case '1':                       // Convert uppercase and lowercase in string_2
  470.  
  471.             while( string_2[i] != '\0') {
  472.                 if ( isupper(string_2[i] ))
  473.                     string_2[i] = tolower( string_2[i] );
  474.                 else
  475.                     string_2[i] = toupper( string_2[i] );
  476.  
  477.                 i++;
  478.             }
  479.             break;
  480.  
  481.         case '2':                       // Convert string_2 to lowercase
  482.             while( string_2[i] != '\0') {
  483.                 if ( isupper(string_2[i] ))
  484.                     string_2[i] = tolower( string_2[i] );
  485.  
  486.                 i++;
  487.             }
  488.             break;
  489.  
  490.         case '3':                       // Convert string_2 to uppercase
  491.  
  492.             while( string_2[i] != '\0') {
  493.                 if ( islower(string_2[i] ))
  494.                     string_2[i] = toupper( string_2[i] );
  495.                 i++;
  496.             }
  497.             break;
  498.  
  499.         default:
  500.             printf("\n\n You have to choose (1-3) ! \n\n");
  501.     }
  502. }
  503.  
  504.  
  505. // choice_8, character testing in string_2
  506. // argument char *string_1 is not necessary
  507. void choice_8( char *string_1, char *string_2 ) {
  508.  
  509.     int i=0;
  510.  
  511. //`` This is for displaying all ascii characters,
  512. // for example of working with pointers
  513. // and for example of dynamically allocating memory space.
  514. // Turn off next lines for default string_2     ( put next lines in comment / *      * /  )
  515. // Note that such nested comments are not allowed !
  516. // Also don't forget to put in comment line at the end of this function
  517. //  free(p_all_ascii_characters);
  518.  
  519. // We declare pointer p_all_ascii_characters which does not currently point to anything,
  520. // so we initialize it to NULL.
  521.     char *p_all_ascii_characters = NULL;
  522.  
  523. // Pointer p_all_ascii_characters points to a memory space of 0 bytes.
  524. // We want it to point to a memory space of sufficient size to place
  525. // our string with all ascii characters in that memory space.
  526. // That is why we dynamically allocate such space (there are two ways to do that):
  527.  
  528. // 1. we need to reserve memory space
  529. // Instead of counting the characters in the new string, we use function strlen().
  530.  
  531.     p_all_ascii_characters = (char *)malloc( strlen( "`1234567890-=~!@#$%^&*()_+qwertyuiop[]\\QWERTYUIOP{}|asdfghjkl;'ASDFGHJKL:""zxcvbnm,./ZXCVBNM<>? ┘░▒▓" ) + 2 );
  532.  
  533. // 2. or we need to reallocate (change) memory space
  534. // Instead of counting the characters in the new string, we use function strlen().
  535.  
  536.     //p_all_ascii_characters = (char *)realloc( (char *)p_all_ascii_characters, strlen( "`1234567890-=~!@#$%^&*()_+qwertyuiop[]\\QWERTYUIOP{}|asdfghjkl;'ASDFGHJKL:""zxcvbnm,./ZXCVBNM<>? ┘░▒▓" ) + 2 );
  537.  
  538. // After allocating memory space, it must be checked that allocation has succeeded !
  539. // If malloc() or realloc() returned a value of NULL, this is an indication of a failed allocation.
  540.  
  541.     if( p_all_ascii_characters == NULL )
  542.     {
  543.         fprintf(stderr, "\n\n malloc() or realloc() error ! \n\n");
  544.         exit(EXIT_FAILURE);
  545.     }
  546.  
  547. // The memory space whose address is pointer p_all_ascii_characters can now be filled with our string
  548.     strcpy( p_all_ascii_characters, "`1234567890-=~!@#$%^&*()_+qwertyuiop[]\\QWERTYUIOP{}|asdfghjkl;'ASDFGHJKL:""zxcvbnm,./ZXCVBNM<>? ┘░▒▓" );
  549.  
  550. // let string_2 point to that same memory space p_all_ascii_characters
  551.  
  552.     string_2 = p_all_ascii_characters;
  553.  
  554. // Now is
  555. // string_2 = "`1234567890-=~!@#$%^&*()_+qwertyuiop[]\\QWERTYUIOP{}|asdfghjkl;'ASDFGHJKL:""zxcvbnm,./ZXCVBNM<>? ┘░▒▓"
  556. // but this is only in this function because string_2 is here a local variable.
  557. // When we exit this function, string_2 will again have its old value,
  558. // which it had before calling this function.
  559. // This is a property of a local variable.
  560.  
  561. //`` This was for displaying all ascii characters,
  562. // for example of working with pointers
  563. // and for example of dynamically allocating memory space.
  564. // Turn off above lines for default string_2    ( put them in comment / *      * /  )
  565. // Also don't forget to put in comment line at the end of this function
  566. //  free(p_all_ascii_characters);
  567.  
  568.     printf("\n\n");
  569.  
  570.     while( string_2[i] != '\0' ) {
  571.         if(isalpha( string_2[i] ) )
  572.             printf("\n  %4d   %c  letter \n", string_2[i], string_2[i] );
  573.         else if( isdigit( string_2[i] ) )
  574.             printf("\n  %4d   %c  digit \n", string_2[i], string_2[i] );
  575.         else if(isalnum(string_2[i]))
  576.             printf("\n  %4d   %c  letter or digit \n", string_2[i],  string_2[i] );
  577.         else if(isspace(string_2[i]))
  578.             printf("\n  %4d   %c   space \n", string_2[i], string_2[i] );
  579.         else if(isupper(string_2[i]))
  580.             printf("\n  %4d   %c  capital letter \n", string_2[i], string_2[i] );
  581.         else if(islower(string_2[i]))
  582.             printf("\n  %4d   %c  lowercase letter \n", string_2[i], string_2[i] );
  583.         else if(ispunct(string_2[i]))
  584.             printf("\n  %4d   %c  punctuation mark \n", string_2[i], string_2[i] );
  585.         else
  586.             printf("\n  %4d   %c  none of the above \n", string_2[i], string_2[i] );
  587.  
  588.         i++;
  589.     }
  590.  
  591.     printf("\n\n");
  592.  
  593. // Don't forget to free up dynamically allocated memory space !
  594.     free(p_all_ascii_characters); // golden rule - for every call to malloc, there should be a corresponding free
  595.  
  596.     system("PAUSE");
  597. }
  598.  
  599.  
  600.  
  601. // The main meny
  602. char meny( char *string_1, char *string_2 ) {
  603.  
  604.     int n, length_string_1, length_string_2;
  605.     char which_string[MAX_SIZE];
  606.     char ch;
  607.     char choice;
  608.  
  609.     while( 1 ) {    // endless loop, press 0 or Escape to exit
  610.  
  611.         //system("CLS");          // clear (erase) console screen
  612.  
  613.         //length_string_1 = strlen(string_1);
  614.         //length_string_2 = strlen(string_2);
  615.  
  616.         //printf("\n\n string_1 (%d): %s \n", length_string_1, string_1);
  617.         //printf("\n string_2 (%d): %s \n", length_string_2, string_2);
  618.  
  619. //ruler
  620. printf("\n                             1         2         3         4         5");
  621. printf("\n    ruler           12345678901234567890123456789012345678901234567890");
  622.     printf("\n p_string_1 (%2d) = |%s| ", strlen(string_1), string_1 );
  623.     printf("\n p_string_2 (%2d) = |%s| ", strlen(string_2), string_2 );
  624.  
  625.     printf("\n\n +---------------------------------------------------------------------------+ \n");
  626.         printf(" |           THE MAIN MENU                                                   | \n");
  627.         printf(" +---------------------------------------------------------------------------+ \n");
  628.         printf(" |  1.  Copy string_2 to string_1                                            | \n");
  629.         printf(" |  2.  Concatenate string_2 to string_1                                     | \n");
  630.         printf(" |  3.  Concatenate n characters of string_2 to string_1                     | \n");
  631.         printf(" |  4.  Find the first occurrence of character c in string_2                 | \n");
  632.         printf(" |  5.  Find the first occurrence of string t in string_2                    | \n");
  633.         printf(" |  6.  Find the first occurrence of any character from string t in string_2 | \n");
  634.         printf(" |  7.  Convert upper case to lower case and vice versa                      | \n");
  635.         printf(" |  8.  Character testing in string_2                                        | \n");
  636.         printf(" |  9.  Reset both strings to their initial values                           | \n");
  637.         printf(" |  0.  End of work ( or Escape )                                            | \n");
  638.         printf(" +---------------------------------------------------------------------------+ \n");
  639.         printf("    Choose (0-9)  ?  ");
  640.  
  641.         switch( choice = _getche() ) {  // based on the choices we call the appropriate functions
  642.  
  643.             case '1' :      // Copy string_2 to string_1
  644.  
  645. // Arguments of function string_copy() are addresses of variables so that it can
  646. // change them and keep that change even after exiting string_copy()
  647.  
  648.                     string_copy( &string_1, &string_2 );
  649.                     break;
  650.  
  651.             case '2' :      // Concatenate string_2 to string_1
  652.  
  653. // Arguments of function string_concatenate() are addresses of variables so that it can
  654. // change them and keep that change even after exiting string_concatenate()
  655.  
  656.                     string_concatenate( &string_1, &string_2 );
  657.                     break;
  658.  
  659.             case '3' :      // Concatenate n characters of string_2 to string_1
  660.  
  661.                     printf("\n\n How many characters from string_2 do you want to concatenate to string_1 ? ");
  662.                     scanf("%d", &n);
  663.  
  664. // Arguments of function string_n_concatenate() are addresses of variables so that it can
  665. // change them and keep that change even after exiting string_n_concatenate()
  666.  
  667.                     string_n_concatenate( &string_1, &string_2, n );
  668.                     break;
  669.  
  670.             case '4' :      // Find the first occurrence of character c in string_2
  671.  
  672.                     printf("\n\n What character are you looking for in string_2  ?   ");
  673.                     scanf("%c", &ch);
  674.                     strcpy( string_1, strchr( string_2, ch ) );
  675.                     break;
  676.  
  677.             case '5' :      // Find the first occurrence of string t in string_2
  678.  
  679.                     printf("\n\n What string are you looking for in string_2  ?   ");
  680.                     scanf("%s", which_string);
  681.                     strcpy(string_1, strstr( string_2, which_string ) );
  682.                     break;
  683.  
  684.             case '6' :      // Find the first occurrence of any character from string t in string_2    // choice_6
  685.  
  686.                     printf("\n\n Enter the string with the characters you are looking for in string_2  ?   ");
  687.                     scanf("%s", which_string);
  688.                     strcpy(string_1, strpbrk(string_2, which_string ) );
  689.                     break;
  690.  
  691.             case '7' :      // Convert upper case to lower case and vice versa with own meny
  692.  
  693.                     choice_7( string_1, string_2 );
  694.                     break;
  695.  
  696.             case '8' :      // Character testing in string_2
  697.  
  698.                     choice_8( string_1, string_2 );
  699.                     break;
  700.  
  701.             case '9' :      // Reset both strings to their initial values
  702.  
  703.                     strcpy( string_1, "First string.");
  704.                     strcpy( string_2, "My name is Dragan Milicev.");
  705.                     break;
  706.  
  707.             case '0' :      // End of work ( 0 )
  708.  
  709.                     printf(" The key %c , code %d , is pressed \n\n", choice , choice);
  710.                     return(choice);
  711.                     break;
  712.  
  713.             case 27  :      // End of work ( Escape )
  714.  
  715.                     printf(" The Escape key whose code is %d , is pressed \n\n", choice );
  716.                     return(choice);
  717.                     break;
  718.  
  719.             case  0  :      // if a function key is pressed
  720.  
  721.                     choice = _getche();     // let's empty that 0
  722.                     printf(" The function key %c , code %d , is pressed \n\n", choice, choice );
  723.                     system("PAUSE");
  724.                     break;
  725.  
  726.             case -32 :      // if a special function key is pressed
  727.  
  728.                     choice = _getche();     // let's empty that 0 or -32
  729.                     printf(" The special function key %c , code %d , is pressed \n\n", choice, choice );
  730.                     system("PAUSE");
  731.                     break;
  732.  
  733.             default:
  734.  
  735.                     printf(" The key %c , code %d , is pressed \n\n", choice , choice);
  736.                     if( choice < '0' || choice > '9' ) {    // if no digit is entered
  737.                         printf("\n\n You have to choose (0-9) !!! \n\n");
  738.                         system("PAUSE");
  739.                     }
  740.                     break;
  741.  
  742.         } // end of switch( choice )
  743.  
  744.     } // end of while( 1 )
  745.  
  746.     return(choice);
  747. }
  748.  
  749.  
  750.  
  751.  
  752.  
  753. int main(void) {
  754.  
  755.     printf("\n LET'S LEARN C STRINGS, POINTERS AND DYNAMIC ALLOCATION OF MEMORY SPACE \n");
  756.  
  757. // p_string_1 is a pointer to char, which does not currently point to anything.
  758. // So we initialize it to NULL. Same p_string_2.
  759.     char *p_string_1 = NULL;
  760.     char *p_string_2 = NULL;
  761.  
  762. // Example of dynamic allocation of memory space for 10 characters (here not necessary)
  763.     // p_string_1 = (char *) malloc( 10 * sizeof(char) );
  764.     // p_string_2 = (char *) malloc( 10 * sizeof(char) );
  765.  
  766. // Because we want to copy 14 characters into the first string "First string." ( 14th is '\0'),
  767. // we need to make or reallocate (change) memory space.
  768. // Instead of counting the characters in the new string, we use function strlen().
  769.  
  770.     p_string_1 = (char *)malloc( strlen( "First string." ) + 2 * sizeof(char) );
  771.  
  772. // or
  773.  
  774.     //p_string_1 = (char *)realloc( (char *)p_string_1, strlen( "First string." ) + 2 );
  775.  
  776. // We want to copy 27 characters into the second string "My name is Dragan Milicev." ( 27th is '\0'),
  777. // we need to make or reallocate (change) memory space.
  778. // Instead of counting the characters in the new string, we use function strlen().
  779.  
  780.     p_string_2 = (char *)malloc( strlen( "My name is Dragan Milicev." ) + 2 * sizeof(char) );
  781.  
  782. // or
  783.  
  784.     //p_string_2 = (char *)realloc ( (char *)p_string_2, strlen( "My name is Dragan Milicev." ) + 2 );
  785.  
  786. // After allocating memory space, it must be checked that allocation has succeeded!
  787. // If malloc returned a value of NULL, this is an indication of a failed allocation.
  788.  
  789.     if( p_string_1 == NULL )
  790.     {
  791.         fprintf(stderr, "\n\n malloc() or realloc() error! \n\n");
  792.         exit(EXIT_FAILURE);
  793.     }
  794.  
  795.     if( p_string_2 == NULL )
  796.     {
  797.         fprintf(stderr, "\n\n malloc() or realloc() error! \n\n");
  798.         exit(EXIT_FAILURE);
  799.     }
  800.  
  801. // We now have a reserved memory space large enough to fit our strings.
  802. // Let's put them in:
  803.  
  804.     strcpy( p_string_1, "First string." );
  805.     strcpy( p_string_2, "My name is Dragan Milicev." );
  806.  
  807. // and start our work with them:
  808.  
  809.     meny( p_string_1, p_string_2 );      // we invoke the main program meny
  810.  
  811. // Don't forget to free up dynamically allocated memory space !
  812. // golden rule - for every call to malloc, there should be a corresponding free
  813.     free( p_string_1 );
  814.     free( p_string_2 );
  815.  
  816.     return 0;
  817. }
Advertisement
RAW Paste Data Copied
Advertisement