I am trying to merge two strings of variable length in C. The result should be 1st character from str1 then 1st character from str2 then 2nd character from str1, 2nd character from str2, etc. When it reaches the end of one string it should append the rest of the other string.
For Example:
str1 = "abcdefg";
str2 = "1234";
outputString = "a1b2c3d4efg";
I'm pretty new to C, my first idea was to convert both strings to arrays then try to iterate through the arrays but I thought there might be an easier method. Sample code would be appreciated.
UPDATE:
I've tried to implement the answer below. My function looks like the following.
void strMerge(const char *s1, const char *s2, char *output, unsigned int ccDest)
{
printf("string1 is %s\n", s1);
printf("string2 is %s\n", s2);
while (*s1 != '\0' && *s2 != '\0')
{
*output++ = *s1++;
*output++ = *s2++;
}
while (*s1 != '\0')
*output++ = *s1++;
while (*s2 != '\0')
*output++ = *s2++;
*output = '\0';
printf("merged string is %s\n", *output);
}
But I get a warning when compiling:
$ gcc -g -std=c99 strmerge.c -o strmerge
strmerge2.c: In function ‘strMerge’:
strmerge2.c:41:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
And when I run it it doesnt work:
./strmerge abcdefg 12314135
string1 is abcdefg
string2 is 12314135
merged string is (null)
Why does it think argument 2 is an int and how do I fix it to be a char? If I remove the "*" off output in the printf it doesn't give a compile error but the function still doesn’t work.
The code below ensures that the strings can't overflow by making the output string as long as the two input strings, and using fgets() to ensure that there is no overflow of the input strings. One alternative design would do dynamic memory allocation (malloc() et al), at the cost of the calling code having to free() the allocated space. Another design would pass the length of the output buffer to the function so that it could ensure no overflow occurs.
The test program doesn't emit prompts: it would not be hard to add a function to do so.
Code
#include <stdio.h>
#include <string.h>
void interleave_strings(const char *s1, const char *s2, char *output)
{
while (*s1 != '\0' && *s2 != '\0')
{
*output++ = *s1++;
*output++ = *s2++;
}
while (*s1 != '\0')
*output++ = *s1++;
while (*s2 != '\0')
*output++ = *s2++;
*output = '\0';
}
int main(void)
{
char line1[100];
char line2[100];
char output[200];
if (fgets(line1, sizeof(line1), stdin) != 0 &&
fgets(line2, sizeof(line2), stdin) != 0)
{
char *end1 = line1 + strlen(line1) - 1;
char *end2 = line2 + strlen(line2) - 1;
if (*end1 == '\n')
*end1 = '\0';
if (*end2 == '\n')
*end2 = '\0';
interleave_strings(line1, line2, output);
printf("In1: <<%s>>\n", line1);
printf("In2: <<%s>>\n", line2);
printf("Out: <<%s>>\n", output);
}
}
Example output
$ ./interleave
abcdefgh
1234
In1: <<abcdefgh>>
In2: <<1234>>
Out: <<a1b2c3d4efgh>>
$
char* getMerged(const char* str1, const char* str2) {
char* str = malloc(strlen(str1)+strlen(str2)+1);
int k=0,i;
for(i=0;str1[i] !='\0' && str2[i] !='\0';i++) {
str[k++] = str1[i];
str[k++] = str2[i];
}
str[k]='\0';
if (str1[i] != '\0') {
strcpy(&str[k], &str1[i]);
} else if (str2[i] != '\0') {
strcpy(&str[k], &str2[i]);
}
return str;
}
Your strMerge prints null because, you print the valueAt(*)output which was assigned null the previous step.
#include<stdio.h>
#include<string.h>
//strMerge merges two string as per user requirement
void strMerge(const char *s1, const char *s2, char *output)
{
printf("string1 is %s\n", s1);
printf("string2 is %s\n", s2);
while (*s1 != '\0' && *s2 != '\0')
{
*output++= *s1++;
*output++ = *s2++;
}
while (*s1 != '\0')
*output++=*s1++;
while (*s2 != '\0')
*output++ = *s2++;
*output='\0';
}
int main()
{
char *str1="abcdefg";
char *str2="1234";
char *output=malloc(strlen(str1)+strlen(str2)+1); //allocate memory 7+4+1 = 12 in this case
strMerge(str1,str2,output);
printf("%s",output);
return 0;
}
OUTPUT:
string1 is abcdefg
string2 is 1234
a1b2c3d4efg
In C, both strings are already arrays that can be accessed by their pointers. You just need to create a new buffer that's large enough, then copy into it.
E.g. something like this:
int str1Length = strlen(str1);
int str2Length = strlen(str2);
char* output = (char*) malloc(str1Length + str2Length + 1);
int j = 0;
for (int i = 0; i < str1Length; i++)
{
output[j++] = str1[i];
if (str2Length < i)
output[j++] = str2[i];
}
if (str2Length > str1Length)
{
for (int i = str2Length - str1Length; i < str2Length; i++)
{
output[j++] = str2[i];
}
}
Related
The goal is to take two strings(30 character maximum), for example "cat" and "dog", and print out "cdaotg"(alternate between strings). If one string is longer, it should print the rest of the longer string.
I am getting a segementation fault(core dumped) error either while writing the string or printing it, here is the relevant code.
#include <stdio.h>
int main(int argc, char *argv[])
{
char str1[30], str2[30], newstr[61] = { '\0' }; //declarations
printf("Please enter a maximum 30 characters: "); //user input
scanf("%s", str1);
printf("Please enter a maximum 30 characters: ");
scanf("%s", str2);
if (*argv[1] == 'i') { //if statement to check if command argument is 'i'
char *newstr; //declare pointer to first element of array "newstr"
while (*str1 != '\0') { // while the first string is not NULL
*newstr = *str1; //value at newstr=value at str1
newstr++; //increment pointer
*newstr = *str2; //value at newstr=value at str2
}
*newstr = '\0'; //set the rest of newstr to null
printf("The combined string is: %s", newstr); //print out combined string
}
else //if command argument!='i', just print out nope
printf("nope");
}
You have to fix some of the errors mentioned in the top comments.
But, do not use the sub-scoped char *newstr;. It hides the char newstr[61] definition above (which you do want to use).
Your merge code needs some work:
char *dst = newstr;
const char *s1 = str1;
const char *s2 = str2;
for (; (*s1 != 0) && (*s2 != 0); ++s1, ++s2) {
*dst++ = *s1;
*dst++ = *s2;
}
for (; *s1 != 0; ++s1)
*dst++ = *s1;
for (; *s2 != 0; ++s2)
*dst++ = *s2;
*dst = 0;
I want to make my own strcmp function, like the one in C.
int my_cmp(const char* str1, const char* str2)
{
int index;
for (index = 0; str1[index] != '\0' && str2[index] != '\0'; index++)
if (str1[index] != str2[index])
return (str1[index] - str2[index]);
return 0;
}
Am I right?
I know that not all the strings have the same length.
I'm not sure about condition of for statement.
Here is one of the Official implemention.
int strcmp(const char *s1, const char *s2)
{
for ( ; *s1 == *s2; s1++, s2++)
if (*s1 == '\0')
return 0;
return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
}
Update:
Problems of your code:
your code works fine for string of the same length, the other cases it will false.
For Extended ASCII(range between 128~255), you use sign char, so their value would overflow to an negative value, then you may get a wrong value.
fix version:
int my_cmp(const char* str1, const char* str2)
{
int index;
for (index = 0; str1[index] != '\0' && str2[index] != '\0'; index++)
if (str1[index] != str2[index])
return ((*(unsigned char *)str1 < *(unsigned char *)str2) ? -1 : +1);
// here is the fix code.
if (str1[index] != '\0') {
return 1;
} else if (str2[index] != '\0') {
return -1;
}
return 0;
}
the following code snippet shows you how you could implement an "strcmp" function:
int myStrCmp (const char *s1, const char *s2) {
const unsigned char *p1 = (const unsigned char *)s1;
const unsigned char *p2 = (const unsigned char *)s2;
while (*p1 != '\0') {
if (*p2 == '\0') return 1;
if (*p2 > *p1) return -1;
if (*p1 > *p2) return 1;
p1++;
p2++;
}
if (*p2 != '\0') return -1;
return 0;
}
Am I right? I know that not all the strings have the same length. I'm not sure about condition of for statement.
You are almost right. Your if statement
if (str1[index] != str2[index])
return (str1[index] - str2[index]);
is basically correct (though the characters should be subtracted as unsigned chars), but the for loop itself
for (index = 0; str1[index] != '\0' && str2[index] != '\0'; index++)
is wrong. Specifically the condition:
str1[index] != '\0' && str2[index] != '\0'
This is wrong because it checks to make sure that both characters at the given index are not '\0', rather than either character. This can be fixed by replacing && with ||.
Here's how a seasoned C programmer might write the strcmp function (I wrote this :p (EDIT: #chux suggested an improvement)):
int strcmp(const char *s1, const char *s2) {
for (; *s1 && (*s1 == *s2); s1++, s2++) {}
return (unsigned char)(*s1) - (unsigned char)(*s2);
}
Is it possible to use strtok or some other string function to cut the string until the point where last delimiter is found.
Specific example would be date; I would like to transform "4.1.2017." to "4.1.2017" - without the dot at the end.
If you have a single delimiter, use strrchr to find its last occurrence in the string:
char str[] = "quick.brown.fox";
char *ptr = strrchr(str, '.');
if (ptr) {
*ptr = '\0';
}
printf("%s\n"' str);
This produces the following output:
quick.brown
Like I explained in My comment (if you don't want to use strrchr or you cannot for some reasons) I'll create a Function which checks the position of that delimiter like this:
int my_strrchr(const char *ptr, const char delimiter){
if (ptr == NULL ){
printf("Error, NULL Pointer\n");
return -1;
}
if ( *ptr == '\0' ){
printf("Error, the Buffer is Empty\n");
return 0;
}
int i = 0;
int ret = 0;
while( ptr[i] != '\0' ){
if ( ptr[i] == delimiter ){
ret = i;
}
i++;
}
return ret;
}
And use it Like this:
#include <stdio.h>
int main(void){
char arr[] = "4.1.2017.";
char delimiter = '.';
int len;
if( (len = my_strrchr(arr, delimiter)) > 0){
while ( arr[len] != '\0'){
arr[len] = '\0';
}
printf("%s\n", arr);
}
}
See DEMO.
Any way this is only to get you an Idea and as you can see I use no standard Functions here.
I want to split a String in C.
My String is defined by my Struct:
struct String
{
char *c;
int length;
int maxLength;
}
Then I have a function that does the splitting. Perhaps C has something that does this, but although I wanted my own, I have not found anything that will do it so far.
String ** spliter(String *s)
{
if(s == NULL)
return NULL;
// set of splitters: {'\n', ' '}
}
Input looks something like this: This is Sparta.
Then I want to return a pointer to each character array.
*p1 = This
*p2 = is
*p3 = Sparta.
If that makes any sense, I want an array of pointers, and each pointer points to a character array.
I will have to realloc the String as I increment the size of each character array. Probably my biggest problem is imagining how the pointers work.
Similar problem: c splitting a char* into an char**
So, how do I go about doing this?
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
string test = "aa aa bbc cccd";
vector<string> strvec;
string strtemp;
string::size_type pos1, pos2;
pos2 = test.find(' ');
pos1 = 0;
while (string::npos != pos2)
{
strvec.push_back(test.substr(pos1, pos2 - pos1));
pos1 = pos2 + 1;
pos2 = test.find(' ', pos1);
}
strvec.push_back(test.substr(pos1));
vector<string>::iterator iter1 = strvec.begin(), iter2 = strvec.end();
while (iter1 != iter2)
{
cout << *iter1 << endl;
++iter1;
}
return 0;
}
Have you looked at strtok? It should be possible to do this using strtok.
here is a exemple :
String ** spliter(String *s)
{
int i;
int j;
char *p1;
char *p2;
char *p3;
i = 0;
j = 0;
if(s == NULL)
return NULL;
p1 = malloc(sizeof(*p1) * strlen(s));
p2 = malloc(sizeof(*p2) * strlen(s));
p3 = malloc(sizeof(*p3) * strlen(s));
while (s[i] != ' ')
{
p1[j++] = s[i];
i++;
}
i++;
j = 0;
while (s[i] != ' ')
{
p2[j++] = s[i];
i++;
}
i++;
j = 0;
while (s[i] != '\0')
{
p3[j++] = s[i];
i++;
}
printf("%s\n", p1);
printf("%s\n", p2);
printf("%s\n", p3);
}
You're looking for strtok, check out man 3 strtok, or here if you're not on *nix.
You would use it like this: (Assuming that you can write the add_string code yourself.)
String ** spliter(String *s)
{
if(s == NULL)
return NULL;
String **return_strings = NULL;
char *delim = " \n";
char *string = strtok(s, delim);
int i = 0;
for(i = 0; add_string(return_strings, string, i) != -1; i++) {
string = strtok(NULL, delim);
}
return strings;
}
Note that if you need to save the original string (strtok modifies the string it works on), you'll need to call strdup on the original string, then operate on the copy.
EDIT: OP said he was having trouble thinking about the pointers. With the above code sample, add_string only has to worry about dealing with a string of characters, as opposed to an array of pointers to pointers to characters. So it might look something like this:
int add_string(String **strings, char *s, int len)
{
if(s == NULL)
return -1;
String *current_string = NULL;
strings = realloc(strings, sizeof(String) * (len + 1));
current_string = strings[len];
/* fill out struct fields here */
}
add strdup and strtok can work on a copy of the string. The split() call is more generic than the other spliter() examples, but does the same thing with strtok on a duplicate.
char **
split(char **result, char *w, const char *src, const char *delim)
{
int i=0;
char *p;
strcpy(w,src);
for(p=strtok(w, delim) ; p!=NULL; p=strtok('\0', delim) )
{
result[i++]=p;
result[i]=NULL;
}
return result;
}
void display(String *p)
{
char *result[24]={NULL};
char *w=strdup(p->c);
char **s=split(result, w, p->, "\t \n"); split on \n \t and space as delimiters
for( ; *s!=NULL; s++)
printf("%s\n", *s);
free(w);
}
I have a string as const char *str = "Hello, this is an example of my string";
How could I get everything after the first comma. So for this instance: this is an example of my string
Thanks
You can do something similar to what you've posted:
char *a, *b;
int i = 0;
while (a[i] && a[i] != ',')
i++;
if (a[i] == ',') {
printf("%s", a + i + 1);
} else {
printf("Comma separator not found");
}
Alternatively, you can take a look at strtok and strstr.
With strstr you can do:
char *a = "hello, this is an example of my string";
char *b = ",";
char *c;
c = strstr(a, b);
if (c != NULL)
printf("%s", c + 1);
else
printf("Comma separator not found");
Since you want a tail of the original string, there's no need to copy or modify anything, so:
#include <string.h>
...
const char *result = strchr(str, ',');
if (result) {
printf("Found: %s\n", result+1);
} else {
printf("Not found\n");
}
If you want ideas how to do it yourself (useful if you later want to do something similar but not identical), take a look at an implementation of strchr.
const char *result;
for(result = str; *result; result++)
if(*result == ',')
{
result++;
break;
}
//result points to the first character after the comma
After this code, result points to the string starting right after the comma. Or to the final '\0' (empty string), if there is no comma in the string.
You have the right idea, the following programs is one way to do it:
#include <stdio.h>
#include <string.h>
static char *comma (char *s) {
char *cpos = strchr (s, ',');
if (cpos == NULL)
return s;
return cpos + 1;
}
int main (int c, char *v[]) {
int i;
if (c >1 )
for (i = 1; i < c; i++)
printf ("[%s] -> [%s]\n", v[i], comma (v[i]));
return 0;
}
It produced the following output:
$ commas hello,there goodbye two,commas,here
[hello,there] -> [there]
[goodbye] -> [goodbye]
[two,commas,here] -> [commas,here]