440,928 Members | 1,210 Online Need help? Post your question and get tips & solutions from a community of 440,928 IT Pros & Developers. It's quick & easy.

# K&R2 exercise 1.19 "reversing a character array"

 P: n/a i have created a solutions myself. it compiles without any trouble and runs but it prints some strange characters. i am not able to find where is the trouble. --------------------------------- PROGRAMME -------------------------------- /* K&R2 section 1.9 exercise 1.19 STATEMENT: write a function "reverse(s)" that reverses the character string "s". use it to to write a programme that reverses its input a line at a time. it works like this: 1.) "main" takes input from user and creates a char array from that. 2.) then "main" calls "reverse_them" to reverse the char array it created. 3.) "reverse_them", 1st, calls "arr_size" on the array "main" created. 4.) 2nd, "reverse them", then revrses the characters of 1st array by putting the array into in a 2nd array(a new array) in reverse order. */ #include #define MAXLINE 1000 int arr_size(char arr[]); void reverse_them(char to[], char from[]); int main(void) { char my_array[MAXLINE]; char reversed_array[MAXLINE]; int i, c; /* now we will take some input and feed it into array */ for(i = 0; ((c = getchar()) != EOF) && i < MAXLINE; ++i) my_array[i] = c; my_array[i] = '\0'; /* '\0' is required in the end */ printf("array size: %d\n", arr_size(my_array)); reverse_them(my_array, reversed_array); return 0; } /* this function "reverses:" the 1st array into 2nd */ void reverse_them(char from[], char to[]) { int i, asize, li; asize = arr_size(from); /* get input array size */ li = asize - 1; /* because of last '\0' element */ for(i = 0; (to[li] = from[i]) != '\0'; ++i) --li; printf("\nthe original input: %s\n", from); printf("reversed input: %s\n", to); } /* this function gets the size of an array */ int arr_size(char ar[]) { int i; for(i = 0; (ar[i] != '\0') == 1; ++i) ; return i; } ------------------------------- OUTPUT ----------------------- [arch@voodo kr2]\$ ./a.out like this K&R2 array size: 17 the original input: like this K&R2 reversed input: 2R&K siht ekil??? [arch@voodo kr2]\$ Mar 11 '07 #1
8 Replies

 P: n/a arnuld wrote: i have created a solutions myself. it compiles without any trouble and runs but it prints some strange characters. i am not able to find where is the trouble. --------------------------------- PROGRAMME -------------------------------- /* K&R2 section 1.9 exercise 1.19 STATEMENT: write a function "reverse(s)" that reverses the character string "s". use it to to write a programme that reverses its input a line at a time. it works like this: 1.) "main" takes input from user and creates a char array from that. 2.) then "main" calls "reverse_them" to reverse the char array it created. 3.) "reverse_them", 1st, calls "arr_size" on the array "main" created. 4.) 2nd, "reverse them", then revrses the characters of 1st array by putting the array into in a 2nd array(a new array) in reverse order. */ #include #define MAXLINE 1000 int arr_size(char arr[]); A better return type would be unsigned or size_t. void reverse_them(char to[], char from[]); int main(void) { char my_array[MAXLINE]; char reversed_array[MAXLINE]; int i, c; /* now we will take some input and feed it into array */ for(i = 0; ((c = getchar()) != EOF) && i < MAXLINE; ++i) my_array[i] = c; my_array[i] = '\0'; /* '\0' is required in the end */ If the for loop breaks because the maximum array length was reached, your subsequent suffix of a null character will write to memory beyond the array. To fix it, store at most MAXLINE - 1 characters into the array. printf("array size: %d\n", arr_size(my_array)); reverse_them(my_array, reversed_array); If reverse array is to be reusable function, it should not attempt to print the output. Rather that task should be delegated to the calling function, (in this case main.) Also, since you've already computed your string's length before the call to reverse_them, you could just pass the value into reverse_them instead of calling arr_size again inside reverse_them. return 0; } /* this function "reverses:" the 1st array into 2nd */ void reverse_them(char from[], char to[]) { int i, asize, li; asize = arr_size(from); /* get input array size */ li = asize - 1; /* because of last '\0' element */ for(i = 0; (to[li] = from[i]) != '\0'; ++i) --li; This is a very compilcated way of doing it. I would simply do it as: i = 0; while ( to[li--] = from[i++] ); printf("\nthe original input: %s\n", from); printf("reversed input: %s\n", to); } /* this function gets the size of an array */ int arr_size(char ar[]) { int i; for(i = 0; (ar[i] != '\0') == 1; ++i) Simply writing ar[i] != '\0' would do. ; return i; Here you're returning the length of the string in ar _including_ the terminating null character, unlike the Standard library's strlen. Your program seems to work fine here. Mar 11 '07 #2

 P: n/a On 10 Mar 2007 23:51:55 -0800, "arnuld" i have created a solutions myself. it compiles without any troubleand runs but it prints some strange characters. i am not able to findwhere is the trouble. --------------------------------- PROGRAMME--------------------------------/* K&R2 section 1.9 exercise 1.19STATEMENT: write a function "reverse(s)" that reverses the character string "s". use it to to write a programme that reverses its input a line at a time. it works like this:1.) "main" takes input from user and creates a char array from that.2.) then "main" calls "reverse_them" to reverse the char array itcreated.3.) "reverse_them", 1st, calls "arr_size" on the array "main" created.4.) 2nd, "reverse them", then revrses the characters of 1st array byputting the array into in a 2nd array(a new array) in reverse order.*/#include #define MAXLINE 1000int arr_size(char arr[]);void reverse_them(char to[], char from[]);int main(void) { char my_array[MAXLINE]; char reversed_array[MAXLINE]; int i, c; /* now we will take some input and feed it into array */ for(i = 0; ((c = getchar()) != EOF) && i < MAXLINE; ++i) my_array[i] = c; my_array[i] = '\0'; /* '\0' is required in the end */ Let's assume the input was abc followed by EOF. At this point, my_array contains 'a', 'b', 'c', and '\0' > printf("array size: %d\n", arr_size(my_array)); arr_size returns 3. reverse_them(my_array, reversed_array); return 0;} /* this function "reverses:" the 1st array into 2nd */void reverse_them(char from[], char to[]){ int i, asize, li; asize = arr_size(from); /* get input array size */ asize is now 3. li = asize - 1; /* because of last '\0' element */ li is now 2. > for(i = 0; (to[li] = from[i]) != '\0'; ++i) --li; In iteration 1, li is 2, i is 0, and to is set to 'a'. In iteration 2, li is 1, i is 1, and to is set to 'b'. In iteration 3, li is 0, i is 2, and to is set to 'c'. In iteration 4, li is -1, i is 3, and you attempt to set to[-1] to '\0'. This invokes undefined behavior. Once you fix the for loop so it doesn't attempt to store into a nonexistent member of to, you still have the problem that the contents of to are not a string because they are not terminated with a '\0' in to. It contains 'c', 'b', 'a', and a number of indeterminate (uninitialized) values. > printf("\nthe original input: %s\n", from); printf("reversed input: %s\n", to);} /* this function gets the size of an array */int arr_size(char ar[]){ int i; for(i = 0; (ar[i] != '\0') == 1; ++i) The second clause is no different than ar[i] != '\0'; which is simpler, more common, and easier to understand. ; return i;}------------------------------- OUTPUT -----------------------[arch@voodo kr2]\$ ./a.outlike this K&R2array size: 17the original input: like this K&R2reversed input:2R&K siht ekil???[arch@voodo kr2]\$ Remove del for email Mar 11 '07 #3

 P: n/a On Mar 11, 1:57 pm, "santosh"

 P: n/a arnuld wrote: On Mar 11, 1:57 pm, "santosh" = to a short, but must be at least 16 bits. A long must be >= an int and must be a minimum of 32 bits. A long long type must be >= a long and at least of 64 bits. Other types are derived from these basic types. http://c-faq.com/decl/inttypes.html This is a C99 header that specifies various macros for portably using printf and scanf family of functions with the extended integer types in stdint.h. If reverse array is to be reusable function, it should not attempt to print the output. Rather that task should be delegated to the calling function, (in this case main.) you are right on this but how will "reverse_them" will return an array ? i am on chapter 1 and all return types i see are "int", "char" or "float". IIRC, both your arrays are local to the calling function, (which in your case is main); you're simply passing pointers to their first element to the reverse function. So you can print the reversed string from main. It's generally a good programming practise to delegate user interface and other "higher-level" decisions to higher level functions. Lower level functions should generally perform their allotted task and return. Also, since you've already computed your string's length before the call to reverse_them, you could just pass the value into reverse_them instead of calling arr_size again inside reverse_them. this will introduce one more variable into the programme: int j; j = arr_size(my_array) then i can use "j" at 2 places i used "arr_size(my_array)" what is the benefit of introducing an extra variable ? An extra variable, especially so simple a one as an int, is computationally, far less expensive than an extra function call. Since you know that the string does not change between the two points, scanning for it's length again is redundant and with long strings, could become noticeably slower. This is a very compilcated way of doing it. I would simply do it as: i = 0; while ( to[li--] = from[i++] ); i did so and got this warning message: [arch@voodo kr2]\$ gcc -Wall -Wextra 19-ex-1-19.c 19-ex-1-19.c: In function 'reverse_them': 19-ex-1-19.c:57: warning: suggest parentheses around assignment used as truth value gcc is warning because of a very common mistake newbies make, writing: while(x = y) when they meant while(x == y) In our case, the warning is not applicable, since we _did_ mean to assign rather than compare for equality. PS. Barry spotted an error I didn't. Be sure to read his post elsethread. Mar 11 '07 #5

 P: n/a ok this is what, finally, i have got and it works :-( because i *cheat* by using /char*/ in creating the solution. at chapter 1 i am not supposed to use /char*/. can nybody do the same without using /pointers/ ? --------------- PROGRAMME ------------------------- /* K&R2 section 1.9 exercise 1.19 STATEMENT: write a function "reverse(s)" that reverses the character string "s" use it to to write a programme that reverses its input a line at a time. it works like this: 1.) "main" takes input from user and creates a char array from that. 2.) then "main" calls "reverse_them" to reverse the char array it created. 3.) "reverse_them", 1st, calls "arr_size" on the array "main" created. 4.) 2nd, "reverse them", then revrses the characters of 1st array by putting the array into in a 2nd array(a new array) in reverse order. */ #include #define MAXLINE 1000 int arr_size(char arr[]); char* reverse_them(char to[], char from[]); /* declarations first */ int main(void) { char my_array[MAXLINE]; char reversed_array[MAXLINE]; int i, c; /* now we will take some input and feed it into array */ for(i = 0; ((c = getchar()) != EOF) && i < MAXLINE - 1; ++i) my_array[i] = c; my_array[i] = '\0'; /* '\0' is required in the end */ printf("array size: %d\n", arr_size(my_array)); printf("%s\n", reverse_them(my_array, reversed_array)); return 0; } /* this function "reverses:" the 1st array into 2nd */ char* reverse_them(char from[], char to[]) { int i, asize, li; asize = arr_size(from); /* get input array size */ li = asize - 1; /* because of last '\0' element */ for(i = 0; li >= 0; ++i) to[li--] = from[i]; return to; } /* this function gets the size of an array */ int arr_size(char ar[]) { int i; for(i = 0; ar[i] != '\0'; ++i) ; return i; } ----------------- OUTPUT --------------------------- [arch@voodo kr2]\$ gcc -std=c99 -Wall -Wextra 19-ex-1-19.c [arch@voodo kr2]\$ ./a.out like Richar Heathfield array size: 25 dleifhtaeH rahciR ekil [arch@voodo kr2]\$ Mar 11 '07 #6

 P: n/a arnuld wrote: ok this is what, finally, i have got and it works :-( because i *cheat* by using /char*/ in creating the solution. at chapter 1 i am not supposed to use /char*/. You are not understanding the mechanics of arrays as function arguments. When an array is used as a function argument, what is actually passed to the function is simply a pointer to the first element of the array. If you like, you can think of arrays as always being passed to functions by reference, though, strictly speaking, this is not correct. So your string reversing function actually gets two pointer values to the start of the 'from' and 'to' arrays. It manipulates these arrays, (whose scope is in the calling function), *directly*, through these pointers, though you use array indexing notation with the pointer objects rather than the more traditional pointer notation. So your first example did solve the problem fine without using pointer explicit pointer notation, though pointers *cannot* be eliminated when arrays are used in C. That's just the way C is built. In your second attempt, you're unnecessarily returning a pointer to the 'to' array. This is not necessary since both the arrays are local to the calling function, (main.) It always has access to it. can nybody do the same without using /pointers/ ? /* 05.c - copy a string to an array in reversed order. */ #include #define MAXLINE 1024 unsigned long length(const char str[]) { unsigned long int len = 0; while (str[len] != '\0') len++; return len; } void revstr(char to[], const char from[]) { unsigned long int ctr, end = length(from); for (ctr = 0; end != 0; end--, ctr++) to[ctr] = from[end - 1]; to[ctr] = '\0'; return; } int main(void) { char line[MAXLINE], reversed[MAXLINE]; int c; unsigned long int ctr = 0; printf("Enter some text:\n"); while (ctr < (MAXLINE - 1) && (c = getchar()) != EOF && c != '\n') line[ctr++] = c; line[ctr] = '\0'; revstr(reversed, line); printf("%s\n", reversed); return 0; } Mar 11 '07 #7

 P: n/a On Mar 11, 7:07 pm, "santosh" #define MAXLINE 1024 unsigned long length(const char str[]) { unsigned long int len = 0; while (str[len] != '\0') len++; return len; } void revstr(char to[], const char from[]) { unsigned long int ctr, end = length(from); for (ctr = 0; end != 0; end--, ctr++) to[ctr] = from[end - 1]; to[ctr] = '\0'; return; } int main(void) { char line[MAXLINE], reversed[MAXLINE]; int c; unsigned long int ctr = 0; printf("Enter some text:\n"); while (ctr < (MAXLINE - 1) && (c = getchar()) != EOF && c != '\n') line[ctr++] = c; line[ctr] = '\0'; revstr(reversed, line); printf("%s\n", reversed); return 0; } after understanding your programme, which was not fully clear to me. i wrote my own without looking at anything and it runs BUT the same problem, its OUTPUTs are wrong: 1) size is always "original size + 1" 2) it never prints the "reversed array" it has been nearly 2 hours i am banging my head with this programme and it still has "2 semantic errors" :-( ----------------- PROGRAMME ------------------- /* this programmes prints all the input in reverse order */ #include #define MAXLINES 1000 void reverse_str(char from[], char to[]); int size_of_str(char arr[]); int main(void) { int i, ichar; char current_line[MAXLINES]; char reversed[MAXLINES]; i = 0; while( ((ichar = getchar()) != EOF) && (i < MAXLINES - 1) ) current_line[i++] = ichar;; current_line[i] = '\0'; reverse_str(current_line, reversed); printf("\nSize of input: %d\n", size_of_str(current_line)); printf("\n%s\n", reversed); return 0; } void reverse_str(char from[], char to[]) { int from_end; int from_begin; from_end = size_of_str(from) - 1; for(from_begin = 0; from_end >= 0; ++from_begin) to[from_begin] = from[from_end--]; to[from_begin] = '\0'; } int size_of_str(char arr[]) { int i = 0; while(arr[i++] != '\0'); return i; } ----------------- OUTPUT ------------------------ [arch@voodo kr2]\$ gcc -std=c99 -Wall -Wextra testing.c [arch@voodo kr2]\$ ./a.out like this Size of input: 11 [arch@voodo kr2]\$ Mar 11 '07 #8

 P: n/a arnuld wrote: On Mar 11, 7:07 pm, "santosh" #define MAXLINE 1024 unsigned long length(const char str[]) { unsigned long int len = 0; while (str[len] != '\0') len++; return len; } void revstr(char to[], const char from[]) { unsigned long int ctr, end = length(from); for (ctr = 0; end != 0; end--, ctr++) to[ctr] = from[end - 1]; to[ctr] = '\0'; return; } int main(void) { char line[MAXLINE], reversed[MAXLINE]; int c; unsigned long int ctr = 0; printf("Enter some text:\n"); while (ctr < (MAXLINE - 1) && (c = getchar()) != EOF && c != '\n') line[ctr++] = c; line[ctr] = '\0'; revstr(reversed, line); printf("%s\n", reversed); return 0; } after understanding your programme, which was not fully clear to me. i wrote my own without looking at anything and it runs BUT the same problem, its OUTPUTs are wrong: 1) size is always "original size + 1" 2) it never prints the "reversed array" it has been nearly 2 hours i am banging my head with this programme and it still has "2 semantic errors" :-( You might want to go back a few pages in K&R and start again. Your main confusion is with C's semantics for arrays. ----------------- PROGRAMME ------------------- /* this programmes prints all the input in reverse order */ #include #define MAXLINES 1000 void reverse_str(char from[], char to[]); int size_of_str(char arr[]); int main(void) { int i, ichar; char current_line[MAXLINES]; char reversed[MAXLINES]; i = 0; while( ((ichar = getchar()) != EOF) && (i < MAXLINES - 1) ) current_line[i++] = ichar;; current_line[i] = '\0'; reverse_str(current_line, reversed); printf("\nSize of input: %d\n", size_of_str(current_line)); printf("\n%s\n", reversed); return 0; } void reverse_str(char from[], char to[]) { int from_end; int from_begin; from_end = size_of_str(from) - 1; for(from_begin = 0; from_end >= 0; ++from_begin) to[from_begin] = from[from_end--]; Try: to[from_begin] = from[--from_end]; to[from_begin] = '\0'; } int size_of_str(char arr[]) { int i = 0; while(arr[i++] != '\0'); return i; } Mar 11 '07 #9

### This discussion thread is closed

Replies have been disabled for this discussion. 