I'm a beginner programmer. I was trying out the problem of reversing vowels in a string.
Ex: input: zabedfigu, output: zubidfega
When I run the following code, I get a runtime error. I've tried to change the conditions within incrementing the pointer pc1 upto only upto the middle index etc., but that either gives me a runtime error or doesn't give me the required output. I'd like some help on what to do to make my code work as well as any new way of solving the problem. TIA.
#include<stdio.h>
char* reverseVowels(char* str)
{
char *pc1, *pc2;
int i;
pc1 = &str[0];
for(i=0; str[i]!='\0';++i)
;
pc2 = &str[i-1];
while(pc1!=pc2)
{
if((*pc1=='a')||(*pc1=='e')||(*pc1=='i')||(*pc1=='o')||(*pc1=='u'))
{
while(pc2!=pc1)
{
if((*pc2=='a')||(*pc2=='e')||(*pc2=='i')||(*pc2=='o')||(*pc2=='u'))
{
char temp;
temp = *pc1;
*pc1 = *pc2;
*pc2 = temp;
++pc2;
break;
}
else
++pc2;
}
++pc1;
}
else
++pc1;
}
//return str;
return NULL;
}
int main()
{
char string[20], *pstr;
scanf("%s", string);
//pstr = reverseVowels(string);
//printf("%s", pstr);
reverseVowels(string);
printf("%s", string);
return 0;
}
You have several answers and comments pointing out the fundamental flaw in your code — that you're incrementing pc2 instead of decrementing it. However, I think your algorithm is more complicated than need be. You could:
Subject at all times to pc1 < pc2:
If pc1 is not pointing at a vowel, increment it
If pc2 is not pointing at a vowel, decrement it
If the pointers are different, swap the vowels and adjust the pointers
With test code, and with the addition of an is_vowel() function which detects both upper-case and lower-case vowels, I ended up with:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
static inline int is_vowel(int c)
{
c = tolower(c);
return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u');
}
static void reverse_vowels(char *string)
{
char *p1 = string;
char *p2 = p1 + strlen(p1); // '\0' is not a vowel
while (p1 < p2)
{
while (p1 < p2 && !is_vowel((unsigned char)*p1))
p1++;
while (p1 < p2 && !is_vowel((unsigned char)*p2))
p2--;
if (p1 != p2)
{
char c = *p1;
*p1++ = *p2;
*p2-- = c;
}
}
}
int main(void)
{
#ifdef INTERACTIVE
char line[1024];
while (fgets(line, sizeof(line), stdin) != NULL)
{
line[strcspn(line, "\n")] = '\0';
printf("Input: [%s]\n", line);
reverse_vowels(line);
printf("Output: [%s]\n", line);
}
#else
char strings[][40] =
{
"",
"a",
"b",
"ab",
"abe",
"abeci",
"nnnnummmmmmmmmmmmippppoqq",
"AbleWasIEreISawElba",
"A Man, A Plan, A Canal - Panama!"
};
enum { NUM_STRINGS = sizeof(strings) / sizeof(strings[0]) };
for (int i = 0; i < NUM_STRINGS; i++)
{
printf("Input: [%s]\n", strings[i]);
reverse_vowels(strings[i]);
printf("Output: [%s]\n", strings[i]);
}
#endif /* INTERACTIVE */
return 0;
}
You can compile it with -DINTERACTIVE to give you an interactive test, or by default it gives a fixed set of tests.
Default output:
Input: []
Output: []
Input: [a]
Output: [a]
Input: [b]
Output: [b]
Input: [ab]
Output: [ab]
Input: [abe]
Output: [eba]
Input: [abeci]
Output: [ibeca]
Input: [nnnnummmmmmmmmmmmippppoqq]
Output: [nnnnommmmmmmmmmmmippppuqq]
Input: [AbleWasIEreISawElba]
Output: [ablEWasIerEISawelbA]
Input: [A Man, A Plan, A Canal - Panama!]
Output: [a Man, a Plan, a CAnal - PAnamA!]
Sample interactive session (my program was called rv61):
$ rv61
Input: []
Output: []
a
Input: [a]
Output: [a]
b
Input: [b]
Output: [b]
ab
Input: [ab]
Output: [ab]
ae
Input: [ae]
Output: [ea]
abcde
Input: [abcde]
Output: [ebcda]
ablewasiereisawelba
Input: [ablewasiereisawelba]
Output: [ablewasiereisawelba]
palindromic nonsense
Input: [palindromic nonsense]
Output: [pelendromic nonsinsa]
vwlsmssng
Input: [vwlsmssng]
Output: [vwlsmssng]
AManAPlanACanal-Panama!
Input: [AManAPlanACanal-Panama!]
Output: [aManaPlanaCAnal-PAnamA!]
a big and complex sentence with multiple words of a number of lengths and so on
Input: [ a big and complex sentence with multiple words of a number of lengths and so on ]
Output: [ o bog and cemplox sentunca woth moltepli wurds if e nember ef longths and si an ]
$
Note that the testing tests a number of degenerate cases — an empty string, a string with no vowels, a string with one vowel, etc. The palindromic tests benefit from supporting mixed case — it's hard to spot that vowels have been swapped if they're all lower case and the text is a palindrome.
Another test that could be applied is to reverse the vowels twice; the output should be the same as the input. Conservation tests can be important. (If you had a sort which didn't preserve all the elements in the array but added random new ones and/or dropped initial ones, you wouldn't be happy. But that's a topic for another day.)
Having a simple test harness along the lines shown can be helpful for library functions. Many of my library functions have a #ifdef TEST … #endif at the end to allow them to be tested for sanity. The best tests verify that the result is what is expected; these ones are lazy and leave it to visual inspection to validate the output. If it was a library function, there'd be a header to declare the function which would be #included in the source, and the function would not be static. (My default compilation options require either a declaration of the function before it is defined, or the function must be static. I make functions static in sample code like this since there's no other file referencing the function, so there's no need for a header to declare the function, and only headers should declare externally visible functions.)
Note too that the is_vowel name is carefully chosen to avoid the reserved names in the C standard:
Function names that begin with either is or to, and a lowercase letter may be added to the declarations in the <ctype.h> header.
Using isVowel() would have been OK too; using isvowel() would be using a reserved name.
Bill Woodger commented:
Why the comment about '\0' not being a vowel? …
With the code as shown, after the initialization of p2, it is true that *p2 == '\0'. The observation the '\0' is not a vowel matters if the string is non-empty because if it matched the is_vowel() predicate, the null byte could be moved to some point earlier in the string, truncating it.
Suppose the function was reverse_controls() instead of reverse_vowels() and the test used iscntrl() instead of is_vowel(). Then the code would have to handle it differently for a non-zero length string because the null byte would be reported as a control character and that would send things awry — it would be swapped with the first other control character (if there was another) in the string, truncating the string. That is not what's intended.
The problem here is that you are incrementing both pointers the one in the 0 position, and the one in the end position. The first pointer should increment, and the second one should decrement, thus instead of doing this:
++pc2;
You should do this
--pc2;
The problem is occurring when you are going to increment the pointer variable value of pc2, instead of decrementing the pointer variable pc2 value like this --pc.
Updated
According to cleblanc's comment, my previous answer was not working for an input like abade, so then I changed the code to fix that problem.
#include <stdio.h>
char* reverseVowels(char* str)
{
char *pc1, *pc2;
int i;
pc1 = &str[0];
for(i=0; str[i]!='\0';++i)
;
pc2 = &str[i-1];
while(pc1<pc2)
{
if((*pc1=='a')||(*pc1=='e')||(*pc1=='i')||(*pc1=='o')||(*pc1=='u'))
{
while(pc2!=pc1)
{
if((*pc2=='a')||(*pc2=='e')||(*pc2=='i')||(*pc2=='o')||(*pc2=='u'))
{
char temp;
temp = *pc1;
*pc1 = *pc2;
*pc2 = temp;
--pc2;
break;
}
else
--pc2;
}
++pc1;
}
else
++pc1;
}
//return str;
return NULL;
}
int main()
{
char string[20], *pstr;
scanf("%s", string);
//pstr = reverseVowels(string);
//printf("%s", pstr);
reverseVowels(string);
printf("%s\n", string);
return 0;
}
Related
Can't get any of the if statements to trigger and print something in the main. I am confused on what to do from here.
Can you please find where I have gone wrong for this problem. I need to count the number of dots and dashes (I've simplified it to work on the dots first).
The question must be solved using pointer arithmetic and the function has been provided
void analyse(char* code, int* p_dots, int* p_dashes);
^
#include <stdio.h>
#include <string.h>
void analyse(char* code, int* p_dots)
{
char *current = code;
int k = 0;
if ((*current + k) == '.')
{
p_dots++;
k++;
}
if ((*current + k) == '-')
{
//p_dashes++;
k++;
}
if ((*current + k) ==' ')
{
//p_dashes++;
k++;
}
}
int main(void)
{
char* morse[] =
{
"... --- ..." // SOS
// "-- --- .-. ... .", // MORSE
// "-.-. --- -.. .", // CODE
// "-.-. --- -- .--. ..... ----- -----", // COMP500
// ". -. ... . ..... ----- .----" // ENSE501
};
char* code = *morse;
int*p_dots=0;
//int*p_dashes = 0;
analyse(code, p_dots);
printf("Line 1 has %d dots", *p_dots);
return 0;
}
Here's another approach:
#include <stdio.h>
void analyse(char *code, int *p_dots, int *p_dashes)
{
for( ; *code ; ++code)
{
if (*code == '.')
*p_dots += 1;
if (*code == '-')
*p_dashes += 1;
}
}
int main(void)
{
int dots;
int dashes;
char *morse[] =
{
"... --- ...", // SOS
"-- --- .-. ... .", // MORSE
"-.-. --- -.. .", // CODE
"-.-. --- -- .--. ..... ----- -----", // COMP500
". -. ... . ..... ----- .----" // ENSE501
};
for(int i = 0 ; i < sizeof(morse) / sizeof(char *) ; ++i)
{
dots = 0;
dashes = 0;
analyse(morse[i], &dots, &dashes);
printf("Line %d ('%s') has %d dots and %d dashes\n", i, morse[i], dots, dashes);
}
return 0;
}
A pointer is a variable which contains the address of something. Using a pointer you can look at and/or change the thing it points to. If you increment the pointer, you're changing the address in the pointer, and thus you're changing what it points to.
In this code all of the pointer arithmetic is done in the for loop for( ; *code ; ++code) in the analyse function. What we're saying here is that A) there's no initialization section (there's no code before the first ; in the for statement); B) we want to continue as long as what's being pointed at the the code pointer is not zero *code in the "test" portion of the for statement; and C) after each pass through the loop we want to increment the code pointer (++code in the "increment" section of the for statement).
If you wanted to you could replace the for loop in analyse with:
while(*code <> 0)
{
if (*code == '.')
*p_dots += 1;
if (*code == '-')
*p_dashes += 1;
code += 1;
}
When looking at code like this I find it useful to mentally say "object of pointer" whenever I see an asterisk used with a pointer variable - so I'd read the first line of the code above as
While object of pointer "code" is not equal to zero...
then the next lines read as
if object of pointer "code" is equal to the character "period"
then add one to object of pointer "p_dots"
if object of pointer "code" is equal to the character "dash"
then add one to object of pointer "p_dashes"
add one to the variable "code"
Instead of "object of pointer" maybe you could read it as "target of pointer" to remind yourself that the pointer is pointing to something, and you're manipulating what the pointer points to, or in other words you're manipulating the pointers "target".
I find this kind of thing helps me understand pointer-based code a little bit more. Perhaps that'll help you too.
Change all occurrences of this:
(*current + k) == '-'
to this:
*(current + k) == '-'
(which means the same as the following:)
current[k] = '-'
Also in main() your code needs to update the value of an int, so just create a regular int, then pass it's address:
int p_dots = 0;
...
analyse(code, &p_dots);//sends the address so the value can be updated
Also, to get all of the values summed properly in the void analyse(char* code, int* p_dots) analyze function, a while loop is necessary: The following is your code with a while loop, and some simplifications: (it only tracks p_dots)
void analyse(char* code, int* p_dots)
{
char *current = code;
int k = 0;
while(*current)//check for NULL character
{
if (*current == '.')
{
(*p_dots)++;
}
if (*current == '-')
{
k++;
}
if (*current ==' ')
{
k++;
}
current++; //increment pointer to next position
}
}
By the way, one way to track each of the symbols ( ., -. ) is to create a struct, then pass it's address to update the member values. The example code for this is below:
typedef struct {
int dot;
int dash;
int space;
} count_s;
void analyse(char* code, count_s *c)//new prototype to track `.`, `-` and ` `
{
char *current = code;
int k = 0;
while(*current)
{
if (*current == '.')
{
(*c).dot++;
}
if (*current == '-')
{
(*c).dash++;
}
if (*current ==' ')
{
(*c).space++;
}
current++;
}
}
int main(void)
{
char* morse[] =
{
"... --- ..." // SOS
// "-- --- .-. ... .", // MORSE
// "-.-. --- -.. .", // CODE
// "-.-. --- -- .--. ..... ----- -----", // COMP500
// ". -. ... . ..... ----- .----" // ENSE501
};
char* code = *morse;
//int p_dots;
count_s count;
//int*p_dashes = 0;
analyse(code, &count);
printf("Line 1 has %d dots\n", count.dot);
printf("Line 1 has %d dashes\n", count.dash);
printf("Line 1 has %d spaces\n", count.space);
return 0;
}
EDIT to address question in comments: How would I go about doing it for the following lines that I've commented out?
Create an array of string literals
const char *morse[] = {{"... --- ..."},
{"-- --- .-. ... ."},
{"-.-. --- -.. ."},
{"-.-. --- -- .--. ..... ----- -----"},
{". -. ... . ..... ----- .----"}};
New main()...
int main(void)
{
char* code = NULL;//will be used to point to each array line.
count_s count = {0};//instance of struct with accumulators
// place declaration of const char *morse[] here as illustrated above
for(int i=0;i<sizeof(morse)/sizeof(morse[0]);i++)
{
code = morse[i];//set pointer to successive array elements 0-4
analyse(code, &count);//count will accumulate values as loop progresses.
}
printf(" %d dots\n", count.dot);
printf(" %d dashes\n", count.dash);
printf(" %d spaces\n", count.space);
return 0;
}
You have issue on the increment of dots and on scanning the string, see p_dots update on main.
I change p_dots to an int to have it on the stack (should be renamed I think). On your code you need to allocate some memory.
To scan the string:
Just increment the pointer to read char by char in an infinite loop, use a switch for the future of scanning '-', stop on null char.
code is pointing to the beginning of the string, switch (*code++) will read the current char and move pointer to the next one.
Start:
"... --- ..."
^
code
Read . and move code
"... --- ..."
^
code
and so on
#include <stdio.h>
#include <string.h>
void analyse(char* code, int* p_dots)
{
while (42) {
switch (*code++) {
case '.':
(*p_dots)++;
break;
case '-':
break;
case '\0':
return;
default:
break;
}
}
}
int main(void)
{
char* morse[] =
{
"... --- ..." // SOS
// "-- --- .-. ... .", // MORSE
// "-.-. --- -.. .", // CODE
// "-.-. --- -- .--. ..... ----- -----", // COMP500
// ". -. ... . ..... ----- .----" // ENSE501
};
char* code = *morse;
int p_dots=0;
//int*p_dashes = 0;
analyse(code, &p_dots);
printf("Line 1 has %d dots\n", p_dots);
return 0;
}
I am new to C, and I have been going through the CS50 course to learn some basics. I have been trying to solve the challenge which requires you to make a simple password cracker, but I ran into a problem which prevents me from writing a function program: every time I call the crypt function in my for loop, it somehow breaks my password string that I am iterating through.
I have tried making a copy of the password string, and passing that as an argument to crypt; I have also tried moving the crypt call into a separate function and calling that from the loop (as well as the combination of the two)
#define _XOPEN_SOURCE
#include <unistd.h>
#include <cs50.h>
#include <stdio.h>
#include <string.h>
string buildLetterDictionary();
int main(int argc, string argv[])
{
if (argc == 2)
{
printf("Two arguments, starting test...\n");
char password[2];
string letters = buildLetterDictionary();
for(int i = 0; i < 5; i++)
{
password[0] = letters[i];
password[1] = '\0';
printf("Password: %s\n", password);
string hashed = crypt(password, "50");
printf("\n%i\nOriginal: %s\nHashed: %s\n", i, password, hashed);
}
return 0;
}
else
{
printf("Usage: ./crack hash");
return 1;
}
}
string buildLetterDictionary()
{
char letters[27];
for(int i = 65; i < 91; i++)
{
letters[i-65] = i;
}
letters[26] = '\0';
string letter = letters;
return letter;
}
if I comment out the lines:
string hashed = crypt(password, "50");
printf("\n%i\nOriginal: %s\nHashed: %s\n", i, password, hashed);
The code works as expected, and produces the output:
A
B
C
D
E
But if I leave those lines in, the password is printed out as 'A' with the hash "50pe4e2XTIS/g" the first time, but every subsequent time is printed out as "" with the hash "50sXZPq5euCxs"
Please let me know what the underlying problem is, so that I may work towards resolving it! Thanks for any help in advance!
I am guessing here that cs50.h contains some definitions like a type alias from char * to string that the professor is giving you for simplicity.
If that is true, then buildLetterDictionary() cannot work, because you are doing:
char letters[27];
...
char * letter = letters;
return letter;
This means you are returning the address of a local variable, which will be destroyed as soon as you leave the function.
I'm trying to print an array of structs that contain two strings. However my print function does not print more than two indices of the array. I am not sure why because it seems to me that the logic is correct.
This is the main function
const int MAX_LENGTH = 1024;
typedef struct song
{
char songName[MAX_LENGTH];
char artist[MAX_LENGTH];
} Song;
void getStringFromUserInput(char s[], int maxStrLength);
void printMusicLibrary(Song library[], int librarySize);
void printMusicLibraryTitle(void);
void printMusicLibrary (Song library[], int librarySize);
void printMusicLibraryEmpty(void);
int main(void) {
// Announce the start of the program
printf("%s", "Personal Music Library.\n\n");
printf("%s", "Commands are I (insert), S (sort by artist),\n"
"P (print), Q (quit).\n");
char response;
char input[MAX_LENGTH + 1];
int index = 0;
do {
printf("\nCommand?: ");
getStringFromUserInput(input, MAX_LENGTH);
// Response is the first character entered by user.
// Convert to uppercase to simplify later comparisons.
response = toupper(input[0]);
const int MAX_LIBRARY_SIZE = 100;
Song Library[MAX_LIBRARY_SIZE];
if (response == 'I') {
printf("Song name: ");
getStringFromUserInput(Library[index].songName, MAX_LENGTH);
printf("Artist: ");
getStringFromUserInput(Library[index].artist, MAX_LENGTH);
index++;
}
else if (response == 'P') {
// Print the music library.
int firstIndex = 0;
if (Library[firstIndex].songName[firstIndex] == '\0') {
printMusicLibraryEmpty();
} else {
printMusicLibraryTitle();
printMusicLibrary(Library, MAX_LIBRARY_SIZE);
}
This is my printing the library function
// This function will print the music library
void printMusicLibrary (Song library[], int librarySize) {
printf("\n");
bool empty = true;
for (int i = 0; (i < librarySize) && (!empty); i ++) {
empty = false;
if (library[i].songName[i] != '\0') {
printf("%s\n", library[i].songName);
printf("%s\n", library[i].artist);
printf("\n");
} else {
empty = true;
}
}
}
I think the problem is caused due to setting : empty = true outside the for loop and then checking (!empty) which will evaluate to false. What I am surprised by is how is it printing even two indices. You should set empty = false as you are already checking for the first index before the function call.
The logic has two ways to terminate the listing: 1) if the number of entries is reached, or 2) if any entry is empty.
I expect the second condition is stopping the listing before you expect. Probably the array wasn't built as expected (I didn't look at that part), or something is overwriting an early or middle entry.
you gave the definition as:
typedef struct song
{
char songName[MAX_LENGTH];
char artist[MAX_LENGTH];
}Song;
the later, you write if (library[i].songName[i] != '\0') which really seems strange: why would you index the songname string with the same index that the lib?
so I would naturally expect your print function to be:
// This function will print the music library
void printMusicLibrary (Song library[], int librarySize) {
for (int i = 0; i < librarySize; i ++) {
printf("%s\n%s\n\n", library[i].songName,
library[i].artist);
}
}
note that you may skip empty song names by testing library[i].songName[0] != '\0' (pay attention to the 0), but I think it would be better not to add them in the list (does an empty song name make sens?)
(If you decide to fix that, note that you have an other fishy place: if (Library[firstIndex].songName[firstIndex] == '\0') with the same pattern)
I have a piece of code shown below
#include <stdio.h>
#include <stdlib.h>
void Advance_String(char [2],int );
int Atoi_val;
int Count_22;
int Is_Milestone(char [2],int P2);
char String[2] = "0";
main()
{
while(1)
{
if(Is_Milestone(String,21)==1)
{
if(atoi(String)==22)
{
Count_22 = Count_22 + 1;
}
}
Atoi_val = atoi(String);
Advance_String(S,Atoi_val);
}
}
int Is_Milestone(char P1[2],int P2)
{
int BoolInit;
char *Ptr = P1;
int value = atoi(Ptr);
BoolInit = (value > P2);
return BoolInit;
}
void Advance_String(char P1[2],int Value)
{
if(Value!=7)
{
P1[1] = P1[1]+1;
}
else
{
P1[1] = '0';
P1[0] = P1[0]+1 ;
}
}
Now my problem is Count_22 never increments as the char increments never achieves the value 21 or above.Could anyone please tell me the reason for this unexpected behaviour?My question here is to find the value of Count_22.Is there any problem with the code?
Thanks and regards,
Maddy
Your code is probably one of the worst pieces of C code i've ever seen (no offense, everybody has to learn sometime).
It has syntax errors (maybe copy/paste problem), logical problems, meaningless obfuscation, bad practices (globals), buffer overflow (atoi used on a char where there is no place to store the terminating zero byte), uninitialized values (Count_22), surprising naming convention (mixed CamelCase and underscore, variables and functions beginning with capital letter), infinite loop, no header and I forget some.
More, if you want anyone to help you debug this code, you should at list say what it is supposed to do...
To answer to the original question: why Count_22 is never incremented ?
Because Is_Milestone is always false (with or without #Jay change). Is_Milestone intend seems to be to compare the decimal value of the string "22" with the integer 21 (or 1, boolean result of 21 == 1) depending on the version).
It's logical because of Advance_String behavior. both because String has bad initial value (should probably be char String[3] = "00";) and because of the Value != 7 test. I guess what you wanted was comparing the digit with 7, but atoi works with a full string. Another minor change to achieve that Atoi_val = atoi(String+1); in the body of your loop. Then again you won't see much as the loop never stop and never print anything.
If it is a first attempt at an exercice given by some teacher (something like "programming a two digit counter in base 7" or similar). You should consider not using atoi at all and converting characters digit to value using something like:
digit_value = char_value - '0';
example:
char seven_as_char = '7';
int seven_as_int = seven_as_char - '0';
If you can explain what you are really trying to do, we may be able to show you some simple sample code, instead of the horror you are trying to debug.
EDIT
It is really more simple with original code...
After reading the Ada source, I can confirm it is indeed an Ascii based octal counter. The original code is allready of poor quality, and that explains part of the bad quality of the resulting C code.
A possible direct port could be as following (but still need a serious cleanup to look like native C code... and is quite dumb anyway as it prints a constant):
#include <stdio.h>
#include <stdlib.h>
void Advance_String(char * P1)
{
if((P1[1]-'0') != 7){
P1[1]++;
}
else{
P1[1] = '0';
P1[0]++ ;
}
}
int Is_Milestone(char * P1, int P2)
{
return (atoi(P1) > P2);
}
main()
{
int Count_11 = 0;
int Count_22 = 0;
int Count_33 = 0;
int Count_44 = 0;
char S[3] = "00";
int cont = 1;
while(cont)
{
if(Is_Milestone(S, 10)){
if(atoi(S) == 11){
Count_11 = Count_11 + 1;
}
if(Is_Milestone(S, 21)){
if(atoi(S) == 22){
Count_22 = Count_22 + 1;
}
if(Is_Milestone(S, 32)){
if(atoi(S) == 33){
Count_33 = Count_33 + 1;
}
if(Is_Milestone(S, 43)){
if(atoi(S) == 44){
Count_44 = Count_44 + 1;
}
if (atoi(S) == 77){
cont = 0;
}
}
}
}
}
Advance_String(S);
}
printf("result = %d\n", Count_11 + Count_22 + Count_33 + Count_44);
}
This statement
if(Is_Milestone(S,21==1) // Braces are not matching. If statement is not having the closing brace. Compilation error should be given.
should be
if(Is_Milestone(S,21)==1)
I guess.
Also, the code you have posted doesn't seem to be correct. It will surely give compilation errors. You have declared Count22, but are using Count_22.
Please check.
I've been trying to solve this problem for a few days now but it seems I haven't grasped the concept of recursion,yet.
I have to build a program in C (recursion is a must here but loops are allowed as well) which does the following:
The user inputs 2 different strings.For example:
String 1 - ABC
String 2 - DE
The program is supposed to print strings which are combined of the ones the user has entered.
the rule is that the inner order of the letters in each string (1&2) must remain.
That's the output for string1=ABC & string2=DE ":
abcde
abdce
abdec
adbce
adbec
adebc
dabce
dabec
daebc
deabc
If anyone could give me a hand here, it would be great.
Thanks guys.
Here is a partial solution in Java: it should be instructive:
public class Join { // prints:
static void join(String s, String s1, String s2) { // ABCde
if (s1.isEmpty() || s2.isEmpty()) { // ABdCe
System.out.println(s + s1 + s2); // ABdeC
} else { // AdBCe
join(s + s1.charAt(0), s1.substring(1), s2); // AdBeC
join(s + s2.charAt(0), s1, s2.substring(1)); // AdeBC
} // dABCe
} // dABeC
public static void main(String[] args) { // dAeBC
join("", "ABC", "de"); // deABC
}
}
How it works
Basically you have String s, the "output stream", and String s1, s2, the "input stream". At every opportunity, you first take from s1, and later you try again and take from s2, exploring both options recursively.
If at any time either "input stream" is empty, then you're left with no other choice but take whatever's left (if any).
Here it is in C, based on the same idea #polygenelubricants used. It's not that I stole his idea, it's that this is a classical problem and this is the simplest approach :).
#include <stdio.h>
#include <string.h>
void solve(const char *str1, const char *str2,
const int length1, const int length2,
char *output, int pozOut, int pozIn1, int pozIn2)
{
if (pozIn1 == length1 && pozIn2 == length2)
{
printf("%s\n", output);
return;
}
if (pozIn1 < length1)
{
output[pozOut] = str1[pozIn1];
solve(str1, str2, length1, length2, output, pozOut + 1, pozIn1 + 1, pozIn2);
}
if (pozIn2 < length2)
{
output[pozOut] = str2[pozIn2];
solve(str1, str2, length1, length2, output, pozOut + 1, pozIn1, pozIn2 + 1);
}
}
int main()
{
char temp[100]; // big enough to hold a solution.
solve("ABC", "12", strlen("ABC"), strlen("12"), temp, 0, 0, 0);
return 0;
}
This can be improved. For example, how would you get rid of some of the parameters?
Also, this has a bug: you should make sure that output contains a '\0' at the end before printing it, otherwise you might get unexpected results. I'll leave that for you to fix.
I don't feel like I want to write down the whole algorithm. However, here are some leads that might help you.
Basically, you must merge two strings, keeping the characters order. It's like you have 2 stacks of possibly different sizes.
In your example:
stack #1: A B C
stack #2: D E
You also know that the resulting string will have as length the sum of the length of the two input strings. (So you know already how much length to allocate)
If you proceed character by character: each turn you can choose wether to pop one character from either the stack #1 or the stack #2, then continue. (Here could be the recursion). If you roll up all the possible calls you'll have all the resulting strings.
I use to like problems like that when I was in college: it can seem difficult sometimes, but it is so rewarding when you solve it by yourself !
Feel free to comment if you need more clues.
The same algorithm as IVlad, but dynamically allocating the result array, and using pointers rather than indexes making it a bit clearer I think.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void solve(const char* result, const char* x0, const char* x1, char* p) {
if (!*x0 && !*x1) printf("%s\n", result);
if (*x0) {
*p = *x0;
solve(result, x0 + 1, x1, p + 1);
}
if (*x1) {
*p = *x1;
solve(result, x0, x1 + 1, p + 1);
}
}
int main(int argc, char* argv[]) {
if (argc >= 3) {
size_t total_length = strlen(argv[1]) + strlen(argv[2]) + 1;
char *result = malloc(total_length);
if (result) {
result[total_length - 1] = '\0';
solve(result, argv[1], argv[2], result);
free(result);
}
}
return 0;
}