My assignment is that code takes a string as input, and if there are x's in the string replace them with either a 0 or a 1, and print out all the possible string combinations. We have to use recursion for this as well. For example, if the input string was "1x0X" the output would be:
1000
1001
1100
1101
I'm really struggling with how I'm supposed to find all the permutations of the string without having the complete string yet. I have a series of function that combine to print out all permutations of a list of numbers, but I don't know how to make a function where it only permutes certain elements of a list.
Does anyone have any suggestions on how to accomplish this?
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.
Recursion is best used when the recursive depth is limited and not too big.
Yet setting aside that axiom, below is a double recursive solution. Its eats up stack space quickly (that is its biggest constraint) and so is not a robust solution. Yet it gets the job.
For "code takes a string as input,", use fgets() - not shown.
Yet in the spirit of recursion why not recurse the input too? The print_combo() recursion produces a linked list (LL) of characters and keeps track of the number of 'x' read. Once an end-of-line/end-of-file occurs, it is time to print and the linked-list starts with the last character.
The foo() recursion prints the LL in reverse order, passing in a binary mask to direct the x substitution of 0 or 1. The unsigned binary mask is good for typically 32 x's. That is another restriction.
If you must, mouse over for the code.
typedef struct node {
const struct node *prev;
int ch;
} node;
// Print the line
void foo(const node *prev, unsigned mask) {
if (prev) {
if (prev->ch == 'x' || prev->ch == 'X') {
foo(prev->prev, mask >> 1);
putchar("01"[mask & 1]);
} else {
foo(prev->prev, mask);
putchar(prev->ch);
}
}
}
// Read, form the LL and then print
void print_combo(const node *prev, unsigned xcount) {
node n = {.prev = prev, .ch = getchar()};
if (n.ch == '\n' || n.ch == EOF) {
for (unsigned mask = 0; mask < (1u << xcount); mask++) {
foo(prev, mask);
putchar('\n');
}
} else {
print_combo(&n, xcount + (n.ch == 'x' || n.ch == 'X'));
}
}
int main(void) {
print_combo(NULL, 0);
}
Input
00x01x10x11
Output
00001010011
00001010111
00001110011
00001110111
00101010011
00101010111
00101110011
00101110111
I would do something a bit simpler. Just use a position parameter to iterate over the input string. Whenever you hit the 'x' character recurse twice, once for '0' and once for '1'. Make sure to reset the character back to 'x' after you return. Whenever you hit the digit character just recurse once. Increment the position parameter each time you recurse. When you hit the end of the string, print it out. With this idea, you'd get something like this:
#include <stdio.h>
void print_combo(char *str, int pos) {
char c;
c = str[pos];
switch (c) {
case '0':
case '1':
print_combo(str, pos+1);
break;
case 'x':
case 'X':
str[pos] = '0';
print_combo(str, pos+1);
str[pos] = '1';
print_combo(str, pos+1);
str[pos] = c;
break;
case '\0':
printf("%s\n", str);
break;
default:
printf("bad input\n");
break;
}
}
int main() {
char str[10];
strcpy(str, "1x0x");
printf("printing %s\n", str);
print_combo(str, 0);
strcpy(str, "0x01x");
printf("printing %s\n", str);
print_combo(str, 0);
strcpy(str, "0x01x0X1");
printf("printing %s\n", str);
print_combo(str, 0);
return 0;
}
My output looks like this:
printing 1x0x
1000
1001
1100
1101
printing 0x01x
00010
00011
01010
01011
printing 0x01x0X1
00010001
00010011
00011001
00011011
01010001
01010011
01011001
01011011
Related
I'm trying to write a C program that only prints the last occurrence of repeating letters of a string. I have that part done but I want to store all those chars in a string. What I have so far is:
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
bool isLast(char *arg1, char ch, int p) {
p++;
while (arg1[p] != '\0') {
if ((arg1[p]) == ch) {
return false;
}
p++;
}
return true;
}
int main() {
char *word = "kaax";
char *vals = "1235";
char *result = "";
for (int i = 0; word[i] != '\0'; i++) {
if (isLast(word, word[i], i)) {
result += vals[i];
}
}
printf("%s", result);
}
I want:
printf("%s",result);
to print:
fxkav
Since that is the logical result of my program and what the output should be.
How to phrase it ... Not at all.
Your "empty string" is a string literal of size 1 (containing only '\0'. It cannot be changed and even lesss extended.
If you need to manipulate "strings" (which in C is not really an existing concept) you need to represent them as sequences of characters, which are stored in a data structure which allows to change the contained characters and, in your case, also has space for more characters.
In cases where you can determine a maximum size (MAXSIZE) you could define an array of characters of that size like this
char SizedCharArray[MAXSIZE];
As Above.
#include<stdio.h>
#include<string.h>
char str[10000],s,s1[1000],s2[1000],s3;
char *dict[1000];
int main()
{
memset(dict,0,sizeof(dict));
for(;;)
{
scanf("%s",s1);
if (s1[0] == '*')
{
break;
}
scanf("%s",s2);
dict[s1[0]] = (char*)s2;
}
printf("%s\n",dict['A']);
return 0;
}
I type:
A .-
B --
if right,it should print .-,and it can get s1[0] = 'A' and s2 = ".-" rightly,but I get -- as result.
You store all of the input strings in s2. The following iterations overwrite the input from the previous iteration. All pointers of dict point to s2.
Either the dict should be an array of arrays of char so that it can store the strings themselves, or s2 should be so that the inputs can be stored separately.
Minor notes:
(char*)s2
Avoid C style casts. They often hide bugs that the compiler would see. In this case, the cast is completely redundant and can be removed.
memset(dict,0,sizeof(dict));
This is redundant, since objects with static storage are zero initialised at the start of the program.
This coding would have been more easier in c++ (your's is C). Here's a way to do that in C way. You can also implement a search in the dictionary:
char s1[10], s2[10]; // max word length 10
char dict[1000][2][10]; // 1000 (dict entries) 2 (word + meaning) 10(max word length)
int main()
{
int idx = 0;
for (;;)
{
scanf("%s", s1); // word
if (s1[0] == '*')
{
break;
}
scanf("%s", s2); // describing word
strcpy(dict[idx][0], s1);
strcpy(dict[idx][1], s2);
idx++;
}
printf("%s %s\n", dict[0][0], dict[0][1]); // printing dict first entries
return 0;
}
I'd like a reliable method to read the characters from a character array and put them in a string. This will happen till a \r is found. I can iterate through the array but have no good way to put that in a string. I am afraid to use malloc since, at times, puts garbage value in a string.
Here payload is the HTTP data from a TCP packet. \r\n\r\n indicates the end of the payload.
My code so far to iterate through the character array:
void print_payload(const unsigned char *payload, int len) {
int i;
const unsigned char *ch = payload;
for (i = 0; i < len; i++) {
if (strncmp((char*) ch, "\r\n\r\n", 4) == 0) {
// Indicates end of payload data.
break;
} else if (strncmp((char*) ch, "\r\n", 2) == 0) {
//Indicates EOL
printf("\r\n");
ch++;
i++;
} else if(strncmp((char*) ch, "Host:", 5) == 0){
printf("Host: ");
const unsigned char *del = ch + 6;
int i = 0;
while (del[i] != 13 ){
/*
*13 is decimal value for '\r'.
* The characters below are to be inserted
* in a string. Not sure how though.
*/
printf("%c",del[i]);
i++;
}
} else if(strncmp((char*) ch, "User-Agent: ", 11) == 0){
/*
* It has to implemented here as well.
* And in every case where my string matches.
*/
printf("UserAgent: ");
const unsigned char* del = ch + 11;
int i = 0;
while(del[i] != 13){
printf("%c")
}
}
ch++;
}
printf("\r\n\r\n");
printf("\n");
return;
}
Can somebody help me achieve this? I know this is basic but I'm still learning C Programming and am not sure how to do this. Thank in advance.
You have a few options. First, if you can limit the size of the string, and do not need it outside of the function, then a char array would work:
#define STRING_MAX_LEN 999//chux mentions this is better then just putting "1000" in the array[] - 1000 needs to make sense in terms of the program, or something you wish to enforce (and checked!)
char newString[STRING_MAX_LEN+1] = {0};//Initialize to NULL value.
There is no reason to fear malloc though - just remember to work safely and free, and you should be fine:
char *newString = malloc(sizeof(char)*(len+1)); //Better limit on needed space - +1 for a final '\0'.
if (!newString) //Oh no! hard fail.
//do Something
}
memset(newString,0,sizeof(char)*(len+1)); //No garbage in my new string anymore!
...
...
free(newString);
//Finish up with program
You will not even have to append a '\0' - you are already sure the buffer is full of them, so you a valid C string. Note sizeof(char) may be redundant but I like to keep it anyway, in case one day it will not equal 1.
Note if you have to return the new string for some reason you must use a dynamically allocated array, using malloc. Finally, if you only need to check/hold one sub-string at a time, then re-using the same string is preferable.
void print_payload(const unsigned char *payload, int len)
{
int i;
char c;
char *p;
p = (char*)payload;
for(i=0;i<len;i++) {
if(!strncmp(&p[i],"\r\n\r\n",4)) {
c = p[i+4];
p[i+4] = 0;
break;
}
}
if(i==len) {
return;
}
printf("%s\n",p);
p[i+4] = c;
}
I m trying to do this little programm with defensive programming but its more than difficult for me to handle this avoiding the Loop-Goto as i know that as BAD programming. I had try with while and do...while loop but in one case i dont have problem. Problem begins when i m going to make another do...while for the second case ("Not insert space or click enter button"). I tried and nested do...while but here the results was more complicated.
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i;
int length;
char giventext [25];
Loop:
printf("String must have 25 chars lenght:\n");
gets(giventext);
length = strlen(giventext);
if (length > 25) {
printf("\nString has over %d chars.\nMust give a shorter string\n", length);
goto Loop;
}
/* Here i trying to not give space or nothing*/
if (length < 1) {
printf("You dont give anything as a string.\n");
goto Loop;
} else {
printf("Your string has %d\n",length);
printf("Letter in lower case are: \n");
for (i = 0; i < length; i++) {
if (islower(giventext[i])) {
printf("%c",giventext[i]);
}
}
}
return 0;
}
Note that your code is not defensive at all. You have no way to avoid a buffer overflow because,
you check for the length of the string after it has been input to your program so after the buffer overflow has already occurred and
you used gets() which doesn't check input length and thus is very prone to buffer overflow.
Use fgets() instead and just discard extra characters.
I think you need to understand that strlen() doesn't count the number of characters of input but instead the number of characters in a string.
If you want to ensure that there are less than N characters inserted then
int
readinput(char *const buffer, int maxlen)
{
int count;
int next;
fputc('>', stdout);
fputc(' ', stdout);
count = 0;
while ((next = fgetc(stdin)) && (next != EOF) && (next != '\n')) {
// We need space for the terminating '\0';
if (count == maxlen - 1) {
// Discard extra characters before returning
// read until EOF or '\n' is found
while ((next = fgetc(stdin)) && (next != EOF) && (next != '\n'))
;
return -1;
}
buffer[count++] = next;
}
buffer[count] = '\0';
return count;
}
int
main(void)
{
char string[8];
int result;
while ((result = readinput(string, (int) sizeof(string))) == -1) {
fprintf(stderr, "you cannot input more than `%d' characters\n",
(int) sizeof(string) - 1);
}
fprintf(stdout, "accepted `%s' (%d)\n", string, result);
}
Note that by using a function, the flow control of this program is clear and simple. That's precisely why goto is discouraged, not because it's an evil thing but instead because it can be misused like you did.
Try using functions that label logical steps that your program needs to execute:
char * user_input() - returns an input from the user as a pointer to a char (using something other than get()! For example, look at scanf)
bool validate_input(char * str_input) - takes the user input from the above function and performs checks, such as validate the length is between 1 and 25 characters.
str_to_lower(char * str_input) - if validate_input() returns true you can then call this function and pass it the user input. The body of this function can then print the user input back to console in lower case. You could use the standard library function tolower() here to lower case each character.
The body of your main function will then be much simpler and perform a logical series of steps that tackle your problem. This is the essence of defensive programming - modularising your problem into separate steps that are self contained and easily testable.
A possible structure for the main function could be:
char * user_input();
bool validate_input(char *);
void str_to_lower(char *);
int main()
{
char * str_input = user_input();
//continue to get input from the user until it satisfies the requirements of 'validate_input()'
while(!validate_input(str_input)) {
str_input = user_input();
}
//user input now satisfied 'validate_input' so lower case and print it
str_to_lower(str_input);
return 0;
}
I am trying to write a program that gets several strings until it gets the 'Q' string (this string basically stops the scanf).
Each one of the strings is sent to a function that romoves everything except the letters. For example if I scan 'AJUYFEG78348' the printf should be 'AJUYFEG'.
The problem is that the function has to be void.
I have tried several ways to make the "new array with only letters" printed, but none of them worked.
(Is is not allowed to use strlen function)
#include <stdio.h>
void RemoveNonAlphaBetChars(char*);
int main()
{
int flag=1;
char array[100]={0};
while (flag == 1)
{
scanf("%s", &array);
if(array[0] == 'Q' && array[1] =='\0') {
flag=0;
}
while (flag == 1)
{
RemoveNonAlphaBetChars(array);
}
}
return 0;
}
void RemoveNonAlphaBetChars(char* str)
{
int i=0, j=0;
char new_string[100]={0};
for (i=0; i<100; i++)
{
if (((str[i] >= 'a') && (str[i] <= 'z')) || ((str[i] >= 'A') && (str[i] <= 'Z')))
{
new_string[j] = str[i];
j++;
}
}
printf("%s", new_string);
return;
}
The fact that the function has only one argument, non-const char pointer, hints at the fact that the string is going to be changed in the call (better document it anyway), and it's perfectly all right.
A few fixes to your code can make it right:
First, don't loop to the end of the buffer, just to the end of the string (without strlen, it's probably faster too):
for (i=0; str[i] != '\0'; i++)
then don't forget to nul-terminate the new string after your processing:
new_string[j] = '\0';
Then, in the end (where you're printing the string) copy the new string into the old string. Since it's smaller, there's no risk:
strcpy(str,new_string);
now str contains the new stripped string.
Another approach would be to work in-place (without another buffer): each time you encounter a character to remove, copy the rest of the string at this position, and repeat. It can be inefficient if there are a lot of characters to remove, but uses less memory.
The key here is that you are never inserting new characters into the string. That guarantees that the input buffer is large enough to hold the result. It also makes for an easy in-place solution, which is what the void return type is implying.
#include <ctype.h>
#include <stdio.h>
...
void RemoveNonAlphaBetChars(char* str)
{
char *from, *to;
for(from = to = str; *from; from++) {
if(isalpha(*from)) {
if(from > to) *to = *from;
to++;
}
}
*to = *from;
printf("%s\n", str);
return;
}
The pointer from steps along the string until it points to a NUL character, hence the simple condition in the loop. to only receives the value of from if it is a character. The final copy after the loop ensures NUL termination.
Update
If you are dealing with 1) particularly large strings, and 2) you have long stretches of letters with some numbers in between, and 3) your version of memmove is highly optimized compared to copying things manually (e.g. with a special processor instruction), you can do the following:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
...
void RemoveNonAlphaBetChars(char* str)
{
char *from, *to, *end;
size_t len;
for(from = to = str; *from; from = end) {
for(; *from && !isalpha(*from); from++) ;
for(end = from; *end && isalpha(*end); end++) ;
len = end - from;
if(from > to) {
if(len > 1) {
memmove(to, from, len);
} else {
*to = *from;
}
}
to += len;
}
*to = *end;
printf("%s\n", str);
return;
}
The general idea is to find the limits of each range of letters (between from and end), and copy into to block by block. As I stated before though, this version should not be used for the general case. It will only give you a boost when there is a huge amount of data that meets particular conditions.
void return type is a common approach to making functions that produce C string results. You have two approaches to designing your API:
Make a non-destructive API that takes output buffer and its length, or
Make an API that changes the the string in place.
The first approach would look like this:
void RemoveNonAlphaBetChars(const char* str, char *result, size_t resultSize) {
...
}
Use result in place of new_string, and make sure you do not go past resultSize. The call would look like this:
if (flag == 1) { // if (flag == 1), not while (flag == 1)
char result[100];
RemoveNonAlphaBetChars(array, result, 100);
printf("%s\n", result);
}
If you decide to use the second approach, move printf into main, and use strcpy to copy the content of new_string back into str:
strcpy(str, new_string);