Jonathan's initial suggestion
This code implements what I suggested in a comment essentially verbatim. It accepts either x or X as a valid marker because the examples in the question do too.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void map_x(const char *str)
{
size_t xloc = strcspn(str, "xX");
if (str[xloc] == '\0')
printf("%s\n", str);
else
{
char *copy = strdup(str);
copy[xloc] = '0';
map_x(copy);
copy[xloc] = '1';
map_x(copy);
free(copy);
}
}
int main(void)
{
char buffer[4096];
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
buffer[strcspn(buffer, "\n")] = '\0';
map_x(buffer);
}
return 0;
}
The main() function is essentially the same in all three variants. The use of strcspn() is a standard idiom that trims everything from the first newline onwards, or overwrites the end of the string if there is no newline in it.
Note that this solution is safe even if a read-only string literal is passed to the function; it does not modify the string that it is passed. The following solutions will both crash or otherwise fail if the initial string is in fact a read-only string literal.
It would be possible to determine the string length, allocate a VLA (variable length array) to take the string copy, and copy the string into the VLA. That would dramatically reduce the cost of allocating memory for the string (VLA allocation is much simpler than a general purpose memory allocator).
Gene's Suggestion
This code implements what Gene suggested in a comment. It will be more efficient because it does no extra memory allocation, an expensive operation on most systems.
#include <stdio.h>
#include <string.h>
static void map_x(char *str)
{
size_t xloc = strcspn(str, "xX");
if (str[xloc] == '\0')
printf("%s\n", str);
else
{
char letter = str[xloc];
str[xloc] = '0';
map_x(str);
str[xloc] = '1';
map_x(str);
str[xloc] = letter;
}
}
int main(void)
{
char buffer[4096];
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
buffer[strcspn(buffer, "\n")] = '\0';
map_x(buffer);
}
return 0;
}
Mildly optimized variant
This optimizes the work by not rescanning the prefix that is already known to be free of x's.
/* SO 4764-4683 */
#include <stdio.h>
#include <string.h>
static void map_x(char *str, size_t offset)
{
size_t xloc = strcspn(&str[offset], "xX") + offset;
if (str[xloc] == '\0')
printf("%s\n", str);
else
{
char letter = str[xloc];
str[xloc] = '0';
map_x(str, xloc);
str[xloc] = '1';
map_x(str, xloc);
str[xloc] = letter;
}
}
int main(void)
{
char buffer[4096];
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
buffer[strcspn(buffer, "\n")] = '\0';
map_x(buffer, 0);
}
return 0;
}
The difference in performance is probably not measurable on almost any input simply because the I/O time will dominate.
With all due respect to chux, I think that the code in the answer is more complex than necessary. The extra data structure seems like overkill.
x's. The recursive function finds the nextx, replaces it with0, and calls itself. Upon return, it replaces the same0with1and calls itself again. Then it restores thexand returns.