I am not able to concat two const char*.
I do the following:
const char* p = new char[strlen(metadata.getRoot())+strlen(metadata.getPath())];
strcat(const_cast<char*>(p),metadata.getRoot());
strcat(const_cast<char*>(p),metadata.getPath());
strcpy(const_cast<char*>(args2->fileOrFolderPath),p);
function(args2->fileOrFolderPath);
Now when I print the variable args2->fileOrFolderPath on the console then the correct output appears... But when I call a method with the variable as parameter, and work with the variable then I got a segmentation fault. What is the problem?
I did not declare them like this but i know they have this information
So, I have this:
const char* ruta1 = "C:\\Users\\Deivid\\Desktop\\";
const char* ruta2 = "lenaGris.xls";
Then I used this for concatenation:
char * RutaFinal = new char[strlen(ruta1) + strlen(ruta2) + 1];
strcpy(RutaFinal, ruta1);
strcat(RutaFinal, ruta2);
printf(RutaFinal);
This worked for me.
I would prefer using std::string for this, but if you like char* and the str... functions, at least initialize p before using strcat:
*p = 0;
BTW:
using std::string, this would be:
std::string p = std::string(metadata.getRoot()) + metadata.getPath();
strcpy(const_cast<char*>(args2->fileOrFolderPath), p.c_str());
function(args2->fileOrFolderPath);
And you don't have to deallocate p somewhere.
1.
const char* p=new char[strlen(metadata.getRoot())+strlen(metadata.getPath())+1];
the length plus 1 to store '\0'.
2.
strcpy(const_cast<char*>(args2->fileOrFolderPath),p);
You can not guarantee args2->fileOrFolderPath 's length is longger than strlen(p).
This works well
#include <iostream>
using namespace std;
void foo(const char*s){
cout<<s<<endl;
}
int main(int argc,char*argv[]){
const char* s1 = "hello ";
const char* s2 = "world!";
const char* p = new char [strlen(s1)+strlen(s2)+1];
const char* s = new char [strlen(s1)+strlen(s2)+1];
strcat(const_cast<char*>(p),s1);
strcat(const_cast<char*>(p),s2);
strcpy(const_cast<char*>(s),p);
cout<<s<<endl;
foo(s);
return 0;
}
You have char pointers, pointing to char constants which can't be modified . What you can do is to copy your const char array to some char array and do like this to concate const strings :
char result[MAX];
strcpy(result,some_char_array); // copy to result array
strcat(result,another_char_array); // concat to result array
I believe you need to include space for the null terminator, and the first parameter to strcat shouldn't be const as you're trying to modify the memory being pointed to.
You want to do something like this:
char * str1 = "Hello, ";
char * str2 = "World!\n";
char * buffer = malloc(strlen(str1) + strlen(str2) + 1);
strcpy(buffer, str1);
strcat(buffer, str2);
printf(buffer);
Which prints out "Hello, World!" as expected.
As for the error you're seeing when using a parameter, I've wrote some tests to see why it doesn't break when using a const local variable. While compiling using a const char * for the pointer I'm using as the target I get this warning:
./strings.c:10: warning: passing argument 1 of ‘strcat’ discards qualifiers from pointer target type
As it states, const is discarded and it works as expected. However, if I pass a parameter which is a const char * pointer, then I get a bus error when trying to modify the buffer it writes to. I suspect what is happening is that it ignores the const on the argument, but it can't then modify the buffer because it's defined as const elsewhere in the code.
Related
#include <iostream>
#include <cstring>
using namespace std;
class String {
private :
const char * str; // declaration "char str[30];" is appropriate
public :
String(const char * _str) {
str = new char[30];
strcpy(str, _str);
}
};
int main() {
const char* sz = "Hello!";
String s("Hi!");
s = sz;
return 0;
}
I have a question for the types const char * and char array.
What I know is that "the name of a char array" has the same type as "the const char * variable".
So, as what i wrote in the above code, I thought it would be compiled properly.
But the compiler rejects my code, because the function strcpy() doesn't support conversion from the type const char * to the type char*.
What's wrong with this situation? Am I having wrong C++ grammatical knowledge?
The result of new char[30] is of type char* and you would have no problems copying something to the allocation using strcpy (although it's definitely not something you should be doing, since it's an open invitation to buffer overflow). The problem is that you immediately assign that pointer to str and str has type const char*. const is constant; you can't assign to a const, which is what strcpy will do.
In fact, assigning the pointer to a const char* member doesn't magically change the nature of the memory pointed to. If you were able to call strcpy, for example by const_casting the first argument, then nothing would break. The memory is writable. But the compiler won't let you write to it through a const char* because declaring a pointer to be const char* is a promise that you won't try to write to the memory. And it's a promise which you immediately break.
Anyway, you can do the following, at no extra cost:
class String {
private :
const char * str; // declaration "char str[30];" is appropriate
public :
String(const char * _str) {
char * cpy = new char[strlen(_str) + 1];
str = strcpy(cpy, _str);
}
};
I have a char pointer:
char* s = new char[150];
Now how do i fill it? This:
s="abcdef";
Gives warning about deprecation of conversion between string literal and char*, but generally works.
This:
char* s = new[150]("abcdef");
Does not work, gives an error.
How to do this properly? Note that I want the memory allocation to have 150*sizeof(char) bytes and contain "abcdef". I know about malloc, but is it possible to do with new?
Its for an assignment where i cant use the standard library.
This sequence of statements
char* s = new char[150];
s="abcdef";
results in a memory leak because at first a memory was allocated and its address was assigned to the pointer s and then the pointer was reassigned with the address of the string literal "abcdef". And moreover string literals in C++ (opposite to C) have types of constant character arrays.
If you allocated a memory for a string then you should copy a string in the memory either by using the C standard function strcpy or C standard function strncpy.
For example
char* s = new char[150];
std::strcpy( s, "abcdef" );
Or
const size_t N = 150;
char* s = new char[N];
std::strncpy( s, "abcdef", N );
s[N-1] = '\0';
Or even the following way
#include <iostream>
#include <cstring>
int main()
{
const size_t N = 150;
char *s = new char[N]{ '\0' };
std::strncpy( s, "abcdef", N - 1 );
std::cout << s << '\n';
delete []s;
}
In any case it is better just to use the standard class std::string.
std::string s( "abcdef" );
or for example
std::string s;
s.assign( "abcdef" );
The basic procedure for creating a memory area for a string and then filling it without using the Standard Library in C++ is as follows:
create the appropriate sized memory area with new
use a loop to copy characters from a string into the new area
So the source code would look like:
// function to copy a zero terminated char string to a new char string.
// loop requires a zero terminated char string as the source.
char *strcpyX (char *dest, const char *source)
{
char *destSave = dest; // save copy of the destination address to return
while (*dest++ = *source++); // copy characters up to and including zero terminator.
return destSave; // return destination pointer per standard library strcpy()
}
// somewhere in your code
char *s1 = new char [150];
strcpyX (s1, "abcdef");
Given a character array:
char * s = new char [256];
Here's how to fill the pointer:
std::fill(&s, &s + sizeof(s), 0);
Here's how to fill the array:
std::fill(s, s+256, '\0');
Here's how to assign or copy text into the array:
std::strcpy(s, "Hello");
You could also use std::copy:
static const char text[] = "World";
std::copy(text, text + sizeof(text), s);
Remember that a pointer, array and C-Style string are different concepts and objects.
Edit 1: Prefer std::string
In C++, prefer to use std::string for text rather than character arrays.
std::string s;
s = "abcdef";
std::cout << s << "\n";
Once you've allocated the memory for this string, you could use strcpy to populate it:
strcpy(s, "abcdef");
I'm trying to use the function with the following declaration:
extern int stem(struct stemmer * z, char * b, int k)1
I'm trying to pass a C++ string to it, so I thought I'd use the c_str() function. It returns const char *. When I try to pass it to the stem() function, I get this error: error: invalid conversion from 'const char*' to 'char*' [-fpermissive].
How can I store the result of c_str() such that I can use it with the stem function?
Here is the code I'm running:
struct stemmer * z = create_stemmer();
char * b = s.c_str();
int res = stem(z, b, s.length()); //this doesn't work
free_stemmer(z);
return s.substr(0,res);
The problem you are having is that c_str() returns a buffer that can not be modified (const), while stem() may modify the buffer you pass in (not const). You should make a copy of the result of c_str() to get a modifiable buffer.
The page http://www.cplusplus.com/reference/string/string/c_str/ has more information on the C++ 98 and 11 versions. They suggest replacing char * b = s.c_str(); with the following:
char * b = new char [s.length()+1];
std::strcpy (b, s.c_str());
You shouldn't try to remove constness of a string returned by c_str():
char * b = s.c_str();
but you can pass an address of std::string's internal buffer directly:
int res = stem(z, static_cast<char*>(&s[0]), s.length());
If stem() is going to modify the string, then make a copy of it:
char * scpy= strdup( s.c_str()) ;
int res = stem(z, scpy, strlen( scpy));
free( scpy) ;
Use const_cast:
int res = stem(z, const_cast<char*>(s.c_str()), s.length()+1);
free_stemmer(z);
return s.substr(0,res);
Note the length+1 expression which might (or might not) be needed. C-style strings (char*) have an additional null terminator (zero byte, equivalent "\0") at the end. Your stem function may (or may not) expect a null terminator at the end of the string - try both variants.
Note also that "stem" function should not try to modify the string, otherwise bad things may happen (warning based on #David Heffernan's comment)
.c_str()
Just returns a pointer to the data, I would update the stem function to accept a 'const char*' unless you are wanting to modify the data in the string, in that case you should pass it as a new string object.
If you can't edit the stem function you can cast it:
int res = stem(z, const_cast<char*>(s.c_str()), s.length());
It's not good to do this, but nothing stops you:
#include <iostream>
#include <string>
using namespace std;
void foo(char *ch)
{
ch[0] = 'B';
}
int main()
{
string str = "helo world";
char *ch = const_cast<char *>(str.c_str());
foo(ch);
// Belo world
cout << str << endl;
return 0;
}
char *buffer1 = "abc";
const char *buffer2 = (const char*) buffer;
std :: string str (buffer2);
This works, but I want to declare the std::string object i.e. str, once and use it many times to store different const char*.
What's the way out?
You can just re-assign:
const char *buf1 = "abc";
const char *buf2 = "def";
std::string str(buf1);
str = buf2; // Calls str.operator=(const char *)
Ah well, as I commented above, found the answer soon after posting the question :doh:
const char* g;
g = (const char*)buffer;
std :: string str;
str.append (g);
So, I can call append() function as many times (after using the clear()) as I want on the same object with "const char *".
Though the "push_back" function won't work in place of "append".
str is actually copying the characters from buffer2, so it is not connected in any way.
If you want it to have another value, you just assign a new one
str = "Hello";
Make a Class say MyString which compose String buffer.
Have a constant of that class.
and then u can reassign the value of the composed string buffer, while using the same constant.
When I create something like
char* t = new char[44];
t = strcpy(s,t);
then strlen(t); return some wrong results. how I can change this?
Both strcpy and strlen expect to find the special character NUL or '\0' in the array. An uninitialized array, as the one you've created, may contain anything at all, which means the behavior of your program is undefined when it is passed to strcpy as the source argument.
Assuming the goal was to copy s into t, to make the program behave as expected, try this:
#include <iostream>
#include <cstring>
int main()
{
const char* s = "test string";
char* t = new char[44];
// std::strcpy(t, s); // t is the destination, s is the source!
std::strncpy(t, s, 44); // you know the size of the target, use it
std::cout << "length of the C-string in t is " << std::strlen(t) << '\n';
delete[] t;
}
But keep in mind that in C++, strings are handled as objects of type std::string.
#include <iostream>
#include <string>
int main()
{
const std::string s = "test string";
std::string t = s;
std::cout << "length of the string in t is " << t.size() << '\n';
}
What are you trying to do? Do you want to copy from s to t? If so, the arguments to strcpy are reversed.
char* t = new char[44]; // allocate a buffer
strcpy(t,s); // populate it
Such C-style string processing is a red flag, but that's all I can say given this little information.
This code might be helpful:
char * strcpy (char * destination, const char * source);
t = strcpy(t, s);
You have to initialize the variable t
Do something like this:
char *t = new char[44];
memset(t, 0, 44);
// strlen(t) = 0
The strcpy function is described thus:
#include <string.h>
char *strcpy(char *dest, const char *src);
The strcpy() function copies the string pointed to by src (including the terminating '\0' character) to the array pointed to by dest.
So, if you are trying to fill in your newly allocated array, you should be doing:
strcpy(t, s);
Not the other way around.