Concatenate four string constants into one - c++

I have two string constants const char * like this:
const char * p1 = "abcd";
const char * p2 = "efgh";
I want to convert these into a single string so that it becomes a file name:
const char * filename = "abcd_efgh.txt";
I tried to concatenate the char * but failed. Kindly guide me as to how to do this.
Thanks

char* are pointers, i.e they hold the address of the memory segment where the data is stored. You need to allocate a new, large enough buffer and then use the strcat() function to concatenate the strings.
This is really the C way to do this, not the C++ way. In C++ you should use a string class, such as std::string which handles all the buffer allocation stuff for you.

I would go with sprintf()
char buffer[strlen(p1) + strlen(p2) + 6];
sprintf(buffer, "%s_%s.txt", abcd, efgh);
(You're adding 6 for the _, .txt, and the \0 to terminate the string; 1 + 4 + 1)

You could use the strcat function:
/* strcat example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[80];
strcpy (str,"these ");
strcat (str,"strings ");
strcat (str,"are ");
strcat (str,"concatenated.");
puts (str);
return 0;
}

You have declared the filename string const, which is too restrictive for what you want to do at runtime, but can be done by the pre-processor at compile time, using the adjacent string rule:
#define PART1 "abcd"
#define PART2 "efgh"
const char* p1 = PART1 ;
const char* p2 = PART2 ;
const char* filename = PART1 "_" PART2 ".txt"
However if you don't need filename to be a const use one of the already proposed solutions.

const std::string p1 = "abcd";
const std::string p2 = "efgh";
std::string filename = p1 + "_" + p2 + ".txt";

Try this:
char name1[] = "my_demo";
char name2[] = "_file.txt";
char* filename = (char*) malloc(sizeof(char) * (strlen(name1) + strlen(name2) + 1));
strcpy(filename, name1);
strcat(filename, name2);
printf("Filename is: %s \n", filename);
free(filename);
Outputs:
Filename is: my_demo_file.txt

Related

Copying char* with char symbol

I am trying to copy a char* and char symbol into a new char* , however the desired result after copying is wrong.
char* name = "someData";
char symbol ='!';
int size1 = strlen(name);
int size2 = 1;
int newSize = size1 + size2 + 1;
char* res = new char[newSize];
strcpy(res,name);
const char* symbolPointer = &symbol;
strcat(res, symbolPointer);
cout<<*res;
I expect the result to be "someData!" , however it is only "s" , where is my mistake?
char* name = "someData";
This is an ill-formed conversion in C++ (since C++11). I recommend to not point to string literals with pointer to non-const.
const char* symbolPointer = &symbol;
strcat(res, symbolPointer);
Both arguments of std::strcat must be null terminated. symbolPointer is not a pointer to a null terminated string. Because the pre-condition of std::strcat is violated, the behaviour of the program is undefined.
cout<<*res;
res is a pointer to the first character of the string. By indirecting through the pointer to first character, you get the first character. That is why you see the first character (in case the undefined behaviour hasn't caused the program to do something completely different).
Lastly, the program leaks the allocated res.
Here is a fixed example:
std::string name = "someData";
name += '!';
std::cout << name;
The problem is the following:
cout<<*res;
This is equivalent to:
cout << res[0];
It prints just the first character of the output. Use
cout<<res;
Try it this way:
const string name = "someData";
const char symbol ='!';
string res = name + symbol;
cout << res;
You should avoid the legacy C nul-terminated string handling functions. You should avoid using new directly in your code.
The observed result you are asking about is due to you writing *res (a single character) instead of res (a pointer to the first character) in the output statement. But the code was buggy besides that, as strcat will copy until it finds the terminator, so it will overwrite some unknown amount of memory beyond what you allocated.
symbolPointer should end with null character, because strcat requires 0-terminated string.
So if you want to continue on your way,
(not a good idea but)
You can add this before strcat.
*(symbolPointer+1) = 0;
#include <iostream>
#include <cstring>
int main() {
char name[] = "someData";
char symbol ='!';
int size1 = strlen(name);
int size2 = 1;
int newSize = size1 + size2 + 1;
char* res = new char[newSize];
strcpy(res,name);
char* symbolPointer = &symbol;
*(symbolPointer + 1) = 0;
strcat(res, symbolPointer);
cout<<res;
return 0;
}

Copy specific range of 2 Dimensional Char[][] Array to char * or std::string

Assuming you read the title, here's a little example in pseudo code:
char inputChar[5][20];
{put data in array obviously}
char * outputChar;
copy(inputChar[2][7], inputChar[2][18], outputChar);
printf("%s", outputChar);
or optionally (although I prefer the above version):
char inputChar[5][20];
{put data in array obviously}
std::string outputString;
copy(inputChar[2][7], inputChar[2][18], outputString);
cout outputString; //I don't know how to use std::strings with printf
I've tried std::copy and memcpy but I can't get it to work. The result either gives me random characters that aren't part of the string, or just results in compiler errors due to me not understanding the syntax fully.
EDIT:
Here is the actual code I'm using:
(assume for this example that storeMenu already has data assigned to it)
int line = 0
int frame5 = 11;
char storeMenu[9][13];
char * temp1 = new char[12];
char * temp2 = new char[12];
std::copy(&storeMenu[line+1][0], &storeMenu[line+1][frame5-10], temp1);
std::copy(&storeMenu[line][frame5-10], &storeMenu[line][12], temp2);
To use std::copy you need a pointer to the location of the character, you are passing the character itself here. You also need to initialize outputChar.
char inputChar[5][20] = {"abc","def","ghi01234567890","jkl"};
char * outputChar = new char[20];
auto last = copy(&inputChar[2][0], &inputChar[2][5], outputChar);
*last = '\0';
printf("%s\n", outputChar);
Alternatively using std::string:
char inputChar[5][20] = {"abc","def","ghi01234567890","jkl"};
string outputChar;
copy(&inputChar[2][0], &inputChar[2][5], back_inserter(outputChar));
printf("%s\n", outputChar.c_str());
Using inputs as std::string too:
string inputChar[5] = {"abc","def","ghi01234567890","jkl"};
int fromChar = 2; // from (inclusive) ^ ^
int toChar = 5; // to (exclusive) ^
string outputChar;
copy(inputChar[2].begin()+fromChar, inputChar[2].begin()+toChar, back_inserter(outputChar));
printf("%s\n", outputChar.c_str());
cout << outputChar << endl;

Using sscanf for the dynamic delimiters (inputted by users) in parsing an input string in C?

I'm encountering a problem in parsing a string using sscanf() function.
My function gets 2 string parameters. One for input string and another one for a dynamic list of delimiters. How can I use sscanf to parse the input string with the defined delimiters inputted by users.
For example:
Myfunction(char * input_string, char * delimiter_list){
scanf("%s", input_string);
scanf("%s", delimiter_list);
sscanf(input_string, ???...);
................
}
Use sprintf to create a scanf format string dynamically:
char fmt[256];
sprintf(fmt, "%%[^%250s]", delimiter_list);
sscanf(input_string, fmt, result);
Alternatively, consider using something like strpbrk instead:
const char *end;
size_t len;
end = strpbrk(input_string, delimiter_list);
if (end != NULL)
len = end - input_string;
else
len = strlen(input_string);
memcpy(result, input_string, len);
result[len] = 0;
What you are looking for is strtok:
//makes the assumption that tokens has enought storage to hold all the substrings.
void Myfunction(char * input, char * delimiters, char **tokens){
char *str = strdup(input); //not necessicary if you can modify input_string.
char **tp = tokens;
for(str=strtok(str, delemeters)); str; str=strtok(NULL, delimeters)){
*(tp++) = str;
}
*tp = NULL;
}
You will want to refrain from using strtok for several reasons. With the most important reason being that it alters the source string.
It's also not thread-safe, because it allows you to do this:
char source[] = "Testing, 1 2 3";
char *occurrence= strtok(source, ",");
while (occurrence!= NULL) {
occurrence = strok(NULL, ",");
}
A good alternative would be to use strpbrk, as demonstrated in one of the earlier answers.
It looks like you want something like strtok. look at this: http://www.cplusplus.com/reference/clibrary/cstring/strtok/
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
Still, it is not clear if what you want is this.

C++ String and char * c stype strings

I have a c library which use char arrays as strings and i want to use c++ std::string on my code,
could someone help me how can i convert between char * c style strings and STL library strings ?
for example i have :
char *p="abcdef";
string p1;
and
string x="abc";
char *x1;
how can i convert p to p1 and x to x1
Use string's assignment operator to populate it from a char *:
p1 = p;
Use string's c_str() method to return a const char *:
x1 = x.c_str();
From char* to std::string :
char p[7] = "abcdef";
std::string s = p;
From std::string to char* :
std::string s("abcdef");
const char* p = s.c_str();
You can construct a std::string from a C string thus:
string p1 = p;
You can get a const char * from a std::string thus:
const char *x1 = x.c_str();
If you want a char *, you'll need to create a copy of the string:
char *x1 = new char[x.size()+1];
strcpy(x1, x.c_str());
...
delete [] x1;
string has a constructor and an assignment operator that take a char const* as an argument, so:
string p1(p);
or
string p1;
p1 = p;
Should work. The other way around, you can get a char const* (not a char*) from a string using its c_str() method. That is
char const* x1 = x.c_str();
#include <string.h>
#include <stdio.h>
// Removes character pointed to by "pch"
// from whatever string contains it.
void delchr(char* pch)
{
if (pch)
{
for (; *pch; pch++)
*pch = *(pch+1);
}
}
void main()
{
// Original string
char* msg = "Hello world!";
// Get pointer to the blank character in the message
char* pch = strchr(msg, ' ');
// Delete the blank from the message
delchr(pch);
// Print whatever's left: "Helloworld!"
printf("%s\n", msg);
}

Add 2 chars without using strncpy?

How would I manually concatenate two char arrays without using the strncpy function?
Can I just say char1 + char2?
Or would I have to write a for loop to get individual elements and add them like this:
addchar[0] = char1[0];
addchar[1] = char1[1];
etc
etc
addchar[n] = char2[0];
addchar[n+1] = char2[1];
etc
etc
To clarify, if
char1 = "happy"
char2 = "birthday"
I want addchar to = happybirthday
For a C-only solution use strncat:
char destination[80] = "";
char string1[] = "Hello";
char string2[] = " World!";
/* Copy string1 to destination */
strncat(destination, string1, sizeof(destination));
/* Append string2 to destination */
strncat(destination, string2, sizeof(destination) - sizeof(string1));
Note that the strn* family of string functions are safer than the ones without n, because they avoid the possibility of buffer overruns.
For a C++ solution, simply use std::string and operator+ or operator+=:
std::string destination("Hello ");
destination += "World";
destination += '!';
If you consider two trivial loops to be "manual", then yes, without using the standard library this is the only way.
char *append(const char *a, const char *b) {
int i = 0;
size_t na = strlen(a);
size_t nb = strlen(b);
char *r = (char*)calloc(na + nb + 1, 1);
for (i = 0; i < na; i++) {
r[i] = a[i];
}
for (i = 0; i < nb; i++) {
r[na + i] = b[i];
}
return r;
}
Remember to call free.
If you're using c++ just use an std::string. With std::strings, the + operator is supported, so you can do string1+string2.
Without using library functions, here is the procedure:
1. Point to the first character in string1.
2. While the current character at the pointer is not null, increment the pointer.
3. Create a "source" pointer pointing to string2.
4. While the character at the "source" location is not null:
4.1. Copy the character from the "source" location to the location pointed to by the String1 pointer.
4.2. Increment both pointers.
Unless this is homework, use C++ std::string for your text.
If you must use C style strings, use the library functions.
Library functions are optimized and validated, reducing your development time.
Alright, you want something like this:
char1 + char2
First, let's see the insane solution:
C:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length_left = strlen(a_Left);
unsigned int length_right = strlen(a_Right);
unsigned int length = length_left + length_right;
char* result = (char*)malloc(length);
// clear the string
memset(result, 0, length);
// copy the left part to the final string
memcpy(result, a_Left, length_left);
// append the right part the to the final string
memcpy(&result[length_left], a_Right, length_right);
// make sure the string actually ends
result[length] = 0;
return result;
}
C++:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length_left = strlen(a_Left);
unsigned int length_right = strlen(a_Right);
unsigned int length = length_left + length_right;
char* result = new char[length];
// clear the string
memset(result, 0, length);
// copy the left part to the final string
memcpy(result, a_Left, length_left);
// append the right part the to the final string
memcpy(&result[length_left], a_Right, length_right);
// make sure the string actually ends
result[length] = 0;
return result;
}
Now, let's see the sane solution:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length = strlen(a_Left) + strlen(a_Right);
char* result = new char[length];
strcpy(result, a_Left);
strcat(result, a_Right);
return result;
}
So, was this homework? I don't really care.
If it was, ask yourself: what did you learn?