What is Best way concatenate strings and number - Performance Using C? - c

Please go down and read new/last update section.
i very try to write a code with good performance.
but also php interpreter script is more fast of my c app.
i am test this in a big loop. and i sure then speed of my concatenate code is bad.
and sure then can make this better like php script.
Complate Source(c):
for(int count=1;count<=1000000;count++)
{
results=str_int("New Item",count);
}
str_int(...) Function :
#1 :
DATA_VALUE_String *str_int(DATA_VALUE_String *s1,DATA_VALUE_Int64 s2)
{
DATA_VALUE_String *result=malloc(sizeof(s1)+sizeof(s2)+2*sizeof(DATA_VALUE_String *));
snprintf(result,sizeof(s2)+sizeof(s2),"%s%d",s1,s2);
return result;
}
Time : 0m0.135s
#2 :
DATA_VALUE_String *str_int(DATA_VALUE_String *s1,DATA_VALUE_Int64 s2)
{
DATA_VALUE_String *result=malloc(sizeof(s1)+sizeof(s2)+2*sizeof(DATA_VALUE_String *));
DATA_VALUE_String *ss2;
ss2=malloc((sizeof(s2)+2)*sizeof(DATA_VALUE_String *));
sprintf(ss2,"%"PRId64,s2);
strcat(strcpy(result,s1),ss2);
return result;
}
Time : 0m0.160s
But Php 7.1.4 : 0.081s
<?php
//$myArrays = [];
for($count=1;$count<=1000000;$count++)
{
$results="";
$results="New Item".$count;
}
//unset($myArrays);
?>
please help me to make this c file more fast...
i want make my c code better.
php have more performance in concatenate string,int.
but my c code is not like them.
how can make this better?
tank you very much. :like:
=============
New Update for Answer 1:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
void int64ToChar(char **mesg, int64_t num) {
//*mesg="..";
*(int64_t *)mesg = num;
}
int main()
{
int64_t num=4694;
char *nums=malloc(6*sizeof(char *));
int64ToChar(&nums,num);
printf("%s",nums);
return 0;
}
Error : Segmentation fault (core dumped)
New/Last Update for Bad Performance (C vs PHP)
php(last version) : http://codepad.org/9D26wLEA
$ time php arrays2.php
real 0m0.089s
user 0m0.086s
sys 0m0.004s
c : http://codepad.org/JmemaXOr
$ gcc arrays.c -o arrays -O3 -w
$ time ./arrays
real 0m0.131s
user 0m0.091s
sys 0m0.040s
How can make my C file better?

You can try to concatenate strings in C by directly adding the second string to the end of the first string in memory via pointers.
char* strConcat(char* str1,char* str2){
while (*str1) str1++;
do{
*str1++ = *str2++
}while (*str2);
return --str1; //return a pointer to the end of the new string
}
This returns a pointer to the end of the new concatenated string so you can just pass the pointer along to continue to concatenate to this current string. Alternately, if no further concatenation is necessary, you can maintain the pointer to the head of the concatenated string.

Someone gave an algorithm much faster than snprintf for converting an int to a string :
How to convert an int to string in C
This algo (I named it xitoa below) is also faster than the PHP script.
(I tested with int32, rather than int64, but it illustrates a significant improvement over snprintf)
My benchmark:
with snprintf: 1.54s
with xitoa: 0.99s
with PHP: 1.23s
These results were obtained with gcc optimization -O2 (for snprintf and xitoa).
Here is the algo that I tested (copied from the given link):
char * xitoa (int value, char *buffer, int base)
{
// check that the base if valid
if (base < 2 || base > 36) { *buffer = '\0'; return buffer; }
char* ptr = buffer, *ptr1 = buffer, tmp_char;
int tmp_value;
do {
tmp_value = value;
value /= base;
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
} while ( value );
// Apply negative sign
if (tmp_value < 0) *ptr++ = '-';
*ptr-- = '\0';
// reverse the characters, as they were stored less-significant first
while (ptr1 < ptr) {
tmp_char = *ptr;
*ptr--= *ptr1;
*ptr1++ = tmp_char;
}
return buffer;
}

Related

Segmentation fault with -O3 flag [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Edit: I am really sorry if I have wasted time of your guys, I was running out of time when posting this problem. Here comes the code that I have done my best to minimize it
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum Error {
ERROR_UNRESOLVED_NAME = 1,
ERROR_CANNOT_OPEN_FILE,
ERROR_NO_ARGV,
ERROR_UNRECOGNIZED_SYMBOL,
ERROR_UNCOMPLETED_SENTENCE,
ERROR_RECURSIVE_SELF
};
struct _Piece;
typedef struct _Piece *(*PieceFunc)(struct _Piece *, void *);
struct _Piece {
PieceFunc function;
void *backpack;
};
typedef struct _Piece Piece;
Piece *piece_create(PieceFunc func, void *pack) {
Piece *piece = malloc(sizeof(Piece));
piece->function = func;
piece->backpack = pack;
return piece;
}
typedef struct _Record {
char *name;
int name_len;
Piece *piece;
struct _Record *previous;
} Record;
Record *record_register(Record *pre, char *name, int name_len, Piece *piece) {
Record *record = malloc(sizeof(Record));
record->name = name;
record->name_len = name_len;
record->piece = piece;
record->previous = pre;
return record;
}
typedef struct {
char *file_name;
char *source;
int length;
int current;
int line;
int column;
} Source;
Source *source_create(char *s, int len, char *file_name) {
Source *source = malloc(sizeof(Source));
source->source = s;
source->file_name = file_name;
source->length = len;
source->current = 0;
source->line = source->column = 1;
return source;
}
Piece *apply(Piece *caller, Piece *callee) {
return caller->function(callee, caller->backpack);
}
// Part 3, internals
Piece *internal_self(Piece *callee, void *backpack) {
if (callee->function == internal_self) {
fprintf(stderr,
"recursive `self` calling between two pieces\n"
"piece 1 backpack: %p\n"
"piece 2: %p backpack: %p",
backpack, callee, callee->backpack);
exit(ERROR_RECURSIVE_SELF);
}
return apply(callee, piece_create(internal_self, backpack));
}
Piece *internal_put(Piece *callee, void *backpack) {
int *p_char = callee->backpack;
putchar(*p_char);
return piece_create(internal_self, NULL);
}
Source *main_create_source(char *file_name) {
FILE *source_file = fopen(file_name, "r");
if (!source_file) {
fprintf(stderr, "cannot open file \"%s\"\n", file_name);
exit(ERROR_CANNOT_OPEN_FILE);
}
char *source = NULL;
int length = 0;
while (true) {
char *line = NULL;
int line_len = 0;
line_len = (int)getline(&line, (size_t *)&line_len, source_file);
if (line_len < 0) {
break;
}
if (source == NULL) {
source = line;
} else {
source = realloc(source, sizeof(char) * (length + line_len + 1));
strcat(source, line);
// free(line);
}
length += line_len;
}
fclose(source_file);
return source_create(source, length, file_name);
}
#define MAIN_REGISTER_INTERNAL(record, name, func) \
record = record_register(record, name, sizeof(name) - 1, \
piece_create(func, NULL)); \
printf("%p %p\n", record, record->previous);
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf(stderr, "please specify source file by command line argument\n");
exit(ERROR_NO_ARGV);
}
Record *r = NULL;
MAIN_REGISTER_INTERNAL(r, "put", internal_put);
printf("main %p\n", r);
Source *s = main_create_source(argv[1]);
printf("main %p\n", r);
}
At first, the program crashed with a segmentation fault, I located the bad access code line, which have been deleted in this code demo. I figure out the original bug is that variable r in main would unexpected change after an unrelated calling to main_create_source, which would be demonstrated like this (save this code file as foo.c)
$ cc -O0 -g foo.c
$ ./a.out futaba_test.ftb
0x7fc0024025b0 0x0
main 0x7fc0024025b0
main 0x7fc0024025b0
$ cc -O3 -g foo.c
$ ./a.out futaba_test.ftb
0x7fe861c025b0 0x0
main 0x7fe861c025b0
main 0x7fe800000000
The behavior varied when changing optimization level. It has nothing todo with EOF since I have removed it, and in my opinion the memory for strcat's destination is rich enough. Thanks for any help.
By the way if there is any requirement to point out the purpose of this snippet. This is an interpreter for a minimal language I am working on. It is able to evaluate small source code snippet at the time and this is the first time I have tried to build it with -O3. The bug will only disappear without any level optimization.
(The following is the original post and is able to be ignored.)
I have this code file. When compiling with cc -O0 futaba.c, and running it with ./a.out futaba_test.ftb, the result will be
0x7fba60c025b0 0x0
0x7fba60c025e0 0x7fba60c025b0
0x7fba60c02610 0x7fba60c025e0
0x7fba60c02640 0x7fba60c02610
0x7fba60c02670 0x7fba60c02640
0x7fba60c026b0 0x7fba60c02670
0x7fba60c026d0 0x7fba60c026b0
0x7fba60c02700 0x7fba60c026d0
0x7fba60c02730 0x7fba60c02700
main 0x7fba60c02730
main 0x7fba60c02730
A%
(Zsh add the postfix %) everything is going well. But when compiling with -O3 rather than -O0, than result will be
0x7f8f274025b0 0x0
0x7f8f274025e0 0x7f8f274025b0
0x7f8f27402610 0x7f8f274025e0
0x7f8f27402640 0x7f8f27402610
0x7f8f27402670 0x7f8f27402640
0x7f8f274026b0 0x7f8f27402670
0x7f8f274026d0 0x7f8f274026b0
0x7f8f27402700 0x7f8f274026d0
0x7f8f27402730 0x7f8f27402700
main 0x7f8f27402730
main 0x7f8f00000000
[1] 27811 segmentation fault ./a.out futaba_test.ftb
The last two main line print different address, and the second one is not valid, which cause the stack overflow bug later in record_resolve function.
What is the problem?
That's a lot of code, but here's at least a flag:
char source_fetch(Source *s) {
return s->current == s->length ? EOF : s->source[s->current];
}
This forces EOF into a char, which is a very bad idea. That's why all standard C functions that can return EOF (like getchar() return int.
No idea what an optimizing compiler can make out of that, but once you factor in code that waits for EOF using that ... it's smelly.
Note: this is perhaps bad form as an answer; but it's pointing out a concrete problem with the code.
Also none of the heap allocations seems to have code looking for NULL being returned; that's a bit scary too.

how to best achieve string to number mapping in a c program

I have a definite set of strings and its corresponding numbers:
kill -> 1
live -> 2
half_kill -> 3
dont_live -> 4
List is of 30 such strings and their number mapping.
If user enters "kill", I need to return 1 and if he enters "dont_live" I need to return 4.
How should I achieve this in c program? I am looking for an efficient solution because this operation needs to be done 100s of times.
should I put them in #define in my .h file?
Thanks in advance.
Sort your table, and use the standard library function bsearch to perform a binary search.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct entry {
char *str;
int n;
};
/* sorted according to str */
struct entry dict[] = {
"dont_live", 4,
"half_kill", 3,
"kill", 1,
"live", 2,
};
int compare(const void *s1, const void *s2)
{
const struct entry *e1 = s1;
const struct entry *e2 = s2;
return strcmp(e1->str, e2->str);
}
int
main (int argc, char *argv[])
{
struct entry *result, key = {argv[1]};
result = bsearch(&key, dict, sizeof(dict)/sizeof(dict[0]),
sizeof dict[0], compare);
if (result)
printf("%d\n", result->n);
return 0;
}
Here's what you get when you run the program.
$ ./a.out kill
1
$ ./a.out half_kill
3
$ ./a.out foo
<no output>
PS: I reused portions of sidyll's program. My answer should now be CC BY-SA compliant :p
A possible solution:
#include <stdio.h>
#include <string.h>
struct entry {
char *str;
int n;
};
struct entry dict[] = {
"kill", 1,
"live", 2,
"half_kill", 3,
"dont_live", 4,
0,0
};
int
number_for_key(char *key)
{
int i = 0;
char *name = dict[i].str;
while (name) {
if (strcmp(name, key) == 0)
return dict[i].n;
name = dict[++i].str;
}
return 0;
}
int
main (int argc, char *argv[])
{
printf("enter your keyword: ");
char s[100]; scanf("%s", s);
printf("the number is: %d\n", number_for_key(s));
return 0;
}
Here's one approach:
int get_index(char *s)
{
static const char mapping[] = "\1.kill\2.live\3.half_kill\4.dont_live";
char buf[sizeof mapping];
const char *p;
snprintf(buf, sizeof buf, ".%s", s);
p = strstr(mapping, buf);
return p ? p[-1] : 0;
}
The . mess is to work around kill being a substring of half_kill. Without that issue you could simply search for the string directly.
If it is a very short list of strings then a simple block of ifs will be more than sufficient
if (0 == strcmp(value, "kill")) {
return 1;
}
if (0 == strcmp(value, "live")) {
return 2;
}
...
If the number approach 10 I would begin to profile my application though and consider a map style structure.
if you have a fixed set of strimgs, you have two options: generate a perfect hashing function (check gperf or cmph) or create a trie so that you never have to check charcters more than once.
Compilers usually use perfect hashes to recognize a language keyword, in your case I would probably go with the trie, it should be the fastest way (but nothing beats direct measurement!)
Is it really a bottleneck? You should worry about efficiency only if the simple solution proves to be too slow.
Having said that, possible speed improvements are checking the lengths first:
If it's 4 characters then it could be "kill" or "live"
If it's 9 characters then it could be "half_kill" or "dont_live"
or checking the first character in a switch statement:
switch (string[0]) {
case 'k':
if (strcmp(string, "kill") == 0)
return 1;
return 0;
case 'l':
...
default:
return 0;
}
Use hashmap/ hashtable i think this would be the best solution.
Can you use an Enumunerator?
int main(void) {
enum outcome { kill=1, live, half_kill, dont_live };
printf("%i\n", kill); //1
printf("%i\n", dont_live); //4
printf("%i\n", half_kill); //3
printf("%i\n", live); //2
return 0;
}
Create a list of const values:
const int kill = 1;
const int live = 2;
const int half_kill = 3;
etc

Fastest way to print a certain number of characters to stdout in C

I have to print a certain number of blank spaces to stdout, but this number is not fixed. I'm using putchar(), but I'm not sure if this is fast. What is the fastest way to print a certain number of characters to stdout in C? Also, I cannot use system functions.
Thanks for you help!
I would just use fwrite. Simple. Correct. Easy.
void put_spaces(int n)
{
static const char SPACES[32] = " ";
for (; n >= 32; n -= 32)
fwrite(SPACES, 32, 1, stdout);
if (n)
fwrite(SPACES, n, 1, stdout);
}
Note, however, that the naive version is also quite fast:
void put_spaces(int n)
{
while (n--)
putchar(' ');
}
Why is it fast? On most systems, putchar is a macro which writes directly into a buffer most of the time. If you're not sure it's fast, the correct answer is profile your application, not "optimize first".
Stay away from malloc (it's just unnecessary), puts (which adds a '\n' every time you call it), and printf (it's too complicated for such a simple task).
I would try to use the system commands instead of making my own.
something like:
void print_spaces(unsigned int number_of_spaces) {
char* spaces = malloc(sizeof(char)*number_of_spaces + 1);
memset (spaces,' ',number_of_spaces);
spaces[number_of_spaces] = '\0';
printf("%s",spaces);
free(spaces);
}
would do the trick.
printf() allows you to adjust the number of spaces to be print, but this has to be stated in the format string. Se here for reference.
char format[256];
sprintf(format, "%%%ds", number_of_spaces); // creates the format string
printf(format, " ");
I'm assuming by "system functions", you mean non-standard extensions. In which case, it all depends on whether you mean fastest to write or fastest to execute?
If the former, and assuming there's an upper limit, you can just use something like:
void outSpaces (unsigned int num) {
static char *lotsaSpaces = " ";
printf ("%*.*s", num, num, lotsaSpaces);
}
If the latter, something like this should be a good starting point:
void outSpaces (unsigned int num) {
static char *hundredSpaces = "<<insert 100 spaces here>>";
while (num >= 100) {
puts (hundredSpaces);
num -= 100;
}
printf ("%*.*s", num, num, hundredSpaces);
}
You need to be aware that function calls can be expensive, even with output buffering. In that case, it may be best to call puts once to output a hundred characters rather than call putchar a hundred times.
Perhaps:
void PrintSpaces (int num_spaces)
{
char *spaces = " "; /* twenty spaces */
while (num_spaces > 20)
{
puts (spaces);
num_spaces -= 20;
}
if (num_spaces)
{
puts (&spaces [19 - num_spaces]);
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
int main() {
const size_t size = 5;
char* const data = (char*)malloc(size * sizeof(char) + 1);
if (!data) {
return EXIT_FAILURE;
}
memset(data, ' ', size);
data[size] = '\0'; // not needed (in this case)
fwrite(data, sizeof(char), size, stdout);
free(data);
return EXIT_SUCCESS;
}
(If the number of spaces isn't outrageous)
I don't known c, but here is the basic idea.
create an array of size 8192, and completely fill that particular array with spaces, now you can use puts or write system call or use something which is efficient, and then print this array.
Here I have a code snippet in go, but if you prefer c, you can see an example of how you do it, its actually GNU's yes program which is freaking fast at printing things, there is followed up explanation over there.
package main
import (
"bufio"
"os"
)
func main() {
t := []byte{'y', '\n'}
var used int
const tot = 8192
buf := make([]byte, 0, tot)
for used < tot {
buf = append(buf, t...)
used += 2
}
//Filled complete array named as buf with "y\n"
w := bufio.NewWriter(os.Stdout)
for {
w.Write(buf) //using write system call to print.
}
w.Flush()
}
//syscall.Write({without buf}) : 1.40MiB/s
//syscall.Write(buf) : 1.5GiB/s

Another C question

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.

Recursion problem in C

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;
}

Resources