My goal is to write a program that reads up to 100 characters from an input sentence, then from that stored data it will output 3 things. The reverse of that input sentence, the odd-numbered elements of the array, and even-numbered elements of the array. Therefore I have 3 printf functions. I have 2 separate codes to do this and can not figure out how to combine the two.
#include <stdio.h> int main(void){ int i, j; char str[100]; printf("Enter Stringn"); fgets(str, sizeof str, stdin); printf("nString in Reverse Ordern"); i = 0; while(str[i] != '') { if(str[i] == ' ' || str[i] == 'n') { for(j = i - 1; j >= 0 && str[j] != ' '; j--) printf("%c", str[j]); printf(" "); } i++; } printf("n"); return 0; }
My second Code is:
#include <stdio.h> #include <string.h> int main() { char string[100], even[100], odd[100], i, j, k; i = j = k = 0; printf("Enter your input string:"); fgets(string, 100, stdin); string[strlen(string) - 1] = ''; while (string[i] != '') { if (i % 2 == 0) { odd[j++] = string[i]; } else { even[k++] = string[i]; } i++; } odd[j] = even[k] = ''; printf("Characters at odd position: %sn", odd); printf("Characters at even position: %sn", even); return 0; }
Any input will be greatly appreciated!
So I have been messing around with it and taking all of your input. The code I have so far is below. I am getting the Odd and Even to work but when I input ‘Hello’ the String in Reverse Order says : ‘eH lleH’.. I’be been trying to break it down to see where that issue is arising but I think I am missing something.
#include <stdio.h> #include <string.h> int main() { int m; char string[100], even[100], odd[100], i, j, k; i = j = k = 0; //get the input string from the user printf("Enter your input string:"); fgets(string, 100, stdin); printf("nString in Reverse Ordern"); string[strlen(string) - 1] = ''; while(string[i] != ''){ if(string[i] == ' ' || string[i] == 'n' || i % 2 == 0) { for(m = i - 1; m >= 0 && string[m] != ' '; m--) printf("%c", string[m]); printf(" "); odd[j++] = string[i]; } else { even[k++] = string[i]; } i++; } //terminating even and odd string with NULL odd[j] = even[k] = ''; printf("n"); //print the charactersa at odd position and even positions printf("Characters at odd position: %sn", odd); printf("Characters at even position: %sn", even); return 0; }
Advertisement
Answer
As suggested, transferring a comment into an answer, and extending it (no 600-character limit in an answer).
You have code to read a line and chop off the newline; package that as function 1. Pass the array and array size into the function from the main program; return the length of the string that was read.
You have code to print the string in reverse; that can be simpler because you don’t need to worry about the newline any more because function 1 removed it. Package that as function 2.
You have code to find and print the odd-elements and even-elements of the string; package that as function 3. Again, you can pass the array and the string length into the function, which makes it easier to write.
Then your main program declares the variables and calls the functions. You should use more meaningful names for the functions that I specified — but in the code below, when I used functions, I stuck with the numeric names so you can see what corresponds to what clearly.
This is more or less the way to work with any code. You write functions that do separate identifiable tasks, and then you arrange for other code to call those functions in an appropriate sequence. You learn how to pass arguments to functions and return suitable values from functions and use those to guide the code. To some extent you’re already familiar with the process of using functions to do tasks. You use fgets()
and strlen()
, for example: they each have a different job to do, but the code is reusable, so it is provided by the standard C library. Your code won’t be quite as reusable, so it is unlikely to be part of the standard C library, but sometimes you’ll write code that is reusable enough that it should go in your own personal library.
Look at function 3. It does two jobs; maybe it should be split into two separate functions, one for the odd elements and one for the even elements. Or maybe there’s a general function lurking under there: print every Nth element of the string starting at the Mth element. Or maybe the function should simply copy N/M elements into a new array (passed to the function) and a coordinating function should call the extraction code and then print the code. It is often good to separate the I/O from the rest of the algorithm. Functions that mix the two are frequently less reusable. (Function 2 might also benefit from the separation of algorithm and I/O. A general purpose string reverser could be useful.)
Note, too, that there isn’t a single right result. A lot depends on context. But given the sample code, I think that three functions plus main is probably a suitable balance between competing interests. But it is important not to be scared of creating — and using — functions.
With all due respect, your proposed solution mixes up the processing and makes the code unnecessarily complex. This is what I meant by the three functions:
combo1.c
#include <stdio.h> #include <string.h> static int function_1(char *buffer, size_t buflen) { printf("Enter your input string: "); if (fgets(buffer, buflen, stdin) == 0) return 0; int len = strlen(buffer); if (len > 0) buffer[--len] = ''; return len; } static void function_2(char *string, int len) { printf("String in Reverse Order: "); for (int i = len; i >= 0; i--) putchar(string[i]); putchar('n'); } static void function_3(char *string, int len) { char even[100]; char odd[100]; int j = 0; int k = 0; for (int i = 0; i < len; i++) { if (i % 2 == 0) even[k++] = string[i]; else odd[j++] = string[i]; } odd[j] = even[k] = ''; // print the characters at odd position and even positions printf("Characters at odd position: %sn", odd); printf("Characters at even position: %sn", even); } int main(void) { char string[100]; int len; while ((len = function_1(string, sizeof(string))) != 0) { function_2(string, len); function_3(string, len); } putchar('n'); return 0; }
Sample run
$ ./combo1 Enter your input string: Hello World! String in Reverse Order: !dlroW olleH Characters at odd position: el ol! Characters at even position: HloWrd Enter your input string: AManAPlanACanalPanama String in Reverse Order: amanaPlanaCAnalPAnaMA Characters at odd position: MnPaAaaPnm Characters at even position: AaAlnCnlaaa Enter your input string: ^D $
On my Mac, the terminal is set to echo control characters, which is why the ^D
appears where I typed Control-D to indicate the end of input. The final putchar('n');
is there to place the prompt on the next line.
combo2.c
Doing the combination as you did, you should still simplify the code (but making the code loop over multiple inputs is harder than in the code with functions, primarily because you have to get the prompt as well as the validation into the loop conditions — it is a primary reason for using functions). This code only does one cycle:
#include <stdio.h> #include <string.h> int main(void) { char string[100]; printf("Enter your input string: "); if (fgets(string, sizeof(string), stdin) == 0) { putchar('n'); return 0; } int len = strlen(string); if (len > 0) { string[--len] = ''; printf("String in Reverse Order: "); for (int i = len; i >= 0; i--) putchar(string[i]); putchar('n'); char even[100]; char odd[100]; int j = 0; int k = 0; for (int i = 0; i < len; i++) { if (i % 2 == 0) even[k++] = string[i]; else odd[j++] = string[i]; } odd[j] = even[k] = ''; // print the characters at odd position and even positions printf("Characters at odd position: %sn", odd); printf("Characters at even position: %sn", even); } return 0; }
Sample run
$ ./combo2 Enter your input string: AManAPlanACanalPanama String in Reverse Order: amanaPlanaCAnalPAnaMA Characters at odd position: MnPaAaaPnm Characters at even position: AaAlnCnlaaa $
combo3.c
And if you are adamant that you must do just one loop of the string once read, you can combine the two loops into one more cleanly like this:
#include <stdio.h> #include <string.h> int main(void) { char string[100]; printf("Enter your input string: "); if (fgets(string, sizeof(string), stdin) == 0) { putchar('n'); return 0; } int len = strlen(string); if (len > 0) { string[--len] = ''; char even[100]; char odd[100]; int j = 0; int k = 0; printf("String in Reverse Order: "); for (int i = 0; i < len; i++) { putchar(string[len - i]); if (i % 2 == 0) even[k++] = string[i]; else odd[j++] = string[i]; } putchar('n'); odd[j] = even[k] = ''; printf("Characters at odd position: %sn", odd); printf("Characters at even position: %sn", even); } return 0; }
Sample run
$ ./combo3 Enter your input string: A Man, A Plan, A Canal, Panama! String in Reverse Order: !amanaP ,lanaC A ,nalP A ,naM Characters at odd position: a,APa,ACnl aaa Characters at even position: AMn ln aa,Pnm! $
combo4.c
Going back to the original function-based version, I can rename the functions and provide some better separation of duty by controlling the output in the main()
program and then reusing the functions. Note that I can use the print_reversed_string()
three times, and for two of the uses, the string is not at the end of the line, even.
#include <stdio.h> #include <string.h> static int read_line(const char *prompt, char *buffer, size_t buflen) { printf("%s: ", prompt); fflush(stdout); if (fgets(buffer, buflen, stdin) == 0) return 0; int len = strlen(buffer); if (len > 0) buffer[--len] = ''; return len; } static void print_reversed_string(char *string, int len) { for (int i = len; i >= 0; i--) putchar(string[i]); } static void extract_odd_even(char *string, int len, char *odd, char *even) { int j = 0; int k = 0; for (int i = 0; i < len; i++) { if (i % 2 == 0) even[k++] = string[i]; else odd[j++] = string[i]; } odd[j] = even[k] = ''; } int main(void) { char string[100]; char even[100]; char odd[100]; int len; while ((len = read_line("Enter your input string", string, sizeof(string))) != 0) { printf("String in Reverse Order: "); print_reversed_string(string, len); putchar('n'); extract_odd_even(string, len, odd, even); printf("Characters at odd position: %sn", odd); printf("Characters at even position: %sn", even); printf("Reversed even characters: ["); print_reversed_string(odd, strlen(odd)); printf("]n"); printf("Reversed odd characters: ["); print_reversed_string(odd, strlen(odd)); printf("]n"); } putchar('n'); return 0; }
Example run
$ ./combo4 Enter your input string: A Man, A Plan, A Canal, Panama! String in Reverse Order: !amanaP ,lanaC A ,nalP A ,naM A Characters at odd position: a,APa,ACnl aaa Characters at even position: AMn ln aa,Pnm! Reversed even characters: [aaa lnCA,aPA,a ] Reversed odd characters: [aaa lnCA,aPA,a ] Enter your input string: Gratuitous Display of Lunacy String in Reverse Order: ycanuL fo yalpsiD suotiutarG Characters at odd position: rtiosDslyo uay Characters at even position: Gautu ipa fLnc Reversed even characters: [yau oylsDsoitr] Reversed odd characters: [yau oylsDsoitr] Enter your input string: ^D $
This is how functions make life easier. There is room to separate reverse_string()
into a function that doesn’t print:
static void reverse_string(const char *i_buff, int i_len, char *o_buff) { for (i = 0; i < i_len; i++) o_buff[i] = i_buff[i_len - i]; o_buff[len] = ''; }
And then you can reverse a string and use the reversed value multiple times. You might even use:
static char *reverse_string(const char *i_buff, int i_len, char *o_buff) { for (i = 0; i < i_len; i++) o_buff[i] = i_buff[i_len - i]; o_buff[len] = ''; return o_buff; }
so you could embed the reversal in a call to printf()
:
char rev[100]; printf("Reversed odd characters: [%s]n", reverse_string(odd, strlen(odd), rev));
All these are valid variant designs on your original problem.