I have the following stupid snippet:
#include <iostream>
#include <cstring>
using namespace std;
int main() {
const string classpath = "Hello Dolly!";
const int len = classpath.length()+1;
char str[len];
strncpy(str, classpath.c_str(), len);
cout << str << endl;
return 0;
}
The aim ist to assign a c++ string to a c char array. The string is known at compile time, hence a constant. But the string may vary from one project to an other. I have no intention to count chars for the compiler. Hence the const len should be computed at compile time as shown. This works with cygwin and on linux. But the visualstudio compiler sees a problem and gives me the error C2131!
How to work around?
(Please consider I'm a Java programmer being troubled loosing time on such kind of problems!)
In C++ array sizes must be known at compile time.
You can dynamically allocate contiguous memory during run-time by using operator new:
char * my_array = new char[length];
Remember to use the delete[] to free up the memory after you are finished with it.
Also, C-style arrays need that terminating nul character so you will need to allocate one extra slot in the array.
To copy a std::string to a character array:
const std::string example = "example";
const std::string::size_type length = example.length();
char * p_array = new char [length + 1];
strcpy(p_array, example.c_str());
cout << p_array << endl;
delete[] p_array;
Related
I want to create a char array in a function from a string I have passed in.
bool foo(string s1, string s2) {
char s1_char_array[] = s1;
char s2_char_array[] = s2;
}
But I am met with
"Initialization with '{...}' expected for aggregate object."
For both declarations.
I've tried a lot of work arounds but they all have errors of their own. Learning C++ and every tutorial I find has the value hardcoded. How to make this work?
You can dynamically allocate arrays and copy data from the strings there.
#include <string>
#include <cstring> // for strcpy()
#include <algorithm> // for std::copy()
using std::string;
bool foo(string s1, string s2) {
// allocate arrays (+1 for terminating null-characters)
char* s1_char_array = new char[s1.size() + 1];
char* s2_char_array = new char[s2.size() + 1];
// copy data to arrays
#if 0
// if the strings are guaranteed not to contain '\0'
strcpy(s1_char_array, s1.c_str());
strcpy(s2_char_array, s2.c_str());
#else
// if the strings may contain '\0'
std::copy(s1.begin(), s1.end(), s1_char_array);
std::copy(s2.begin(), s2.end(), s2_char_array);
s1_char_array[s1.size()] = '\0';
s2_char_array[s2.size()] = '\0';
#endif
// do things with the arrays
// deallocate the arrays
delete[] s1_char_array;
delete[] s2_char_array;
// return something
return false;
}
The bad news is that there is no way to create an array variable from a std::string in general because std::string can represent strings of any size (very large practial limits exist but you'll run out of memory first on 64 bit systems) and that size is dynamic i.e. determined at run time. By contrast, the size of an array must be known at compile time at which time the size of the string is still unknown.
Another problem is that your arrays have automatic storage and the memory available for automatic storage is very limited - usually one to few megabytes on desktops / servers; potentially much less on embedded - while the dynamic memory owned by the string doesn't have such restriction and thus attempting to fit a large string into automatic storage could easily cause a "stack overflow".
Another issue is that arrays cannot be copy-constructed nor converted from other types so char s1_char_array[] = some_variable; can never work.
The good news is that you don't ever need to do that either. std::string already contains an array of chars internally, so there is no need to create a new array. Just keep using the array that is in the string.
this is what I come up with.
you have to declare the char array size same as strings by using string.lenght() function and
then use loops to copy the strings elements to char array index by index
bool foo(string s1, string s2) {
char s1_char_array[s1.length()] ;
char s2_char_array[s2.length()] ;
for(int i=0; i<s1.length(); i++){
s1_char_array[i]=s1[i];
}
for(int i=0; i<s2.length(); i++){
s2_char_array[i]=s1[i];
}
}
char* s1;
strcpy(s1,"smilehihi");
s1[6] = 'a';
When I compile, VS do not have any errors. But in the runtime, my code makes mistake. I think I do not really understand about strcpy
The main issue here is not the strcpy() function but the fact that you don't allocate any memory for the string itself.
If I were you, I would do something like
char* s1=(char*)malloc(SIZE); // the SIZE is the predefined maximum size of your string
strcpy(s1,"smilehihi");
s1[6] = 'a';
Edit:
Just as an advice, consider using stpncpy(). It helps to avoid buffer overflow, and, in your case, will help you avoid exceeding the maximum size of char*
char * stpncpy(char * dst, const char * src, size_t len);
The problem is that you have not allocated any space for what you wish to store in s1: "smilehihi". You declare s1 as a pointer variable, but it needs something to point at. You can allocate space by using the new operator.
char* s1 = new char[stringLength + 1]; //stringLength = length of string stored
// + 1 to hold null terminator character
strcpy(s1, "smilehihi");
s1[6] = 'a';
You have to declare #define _CRT_SECURE_NO_WARNINGS at the top of your main file to avoid an error during compilation due to strcpy() being deprecated.
You need to allocate variable first by malloc() or by using the keyword new .
Also deallocate the memory at the end
At first you should allocate char* s1.
char *s1 = new char[9]; // C++ version
or you can you use C version:
char *s1 = (char*)malloc(9);
Then you can use following code:
strcpy(s1, "smilehihi");
s1[6] = 'a';
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");
For some reason, I was trying to covert a C++ string to a char array. Below is what I did:
string aS="hello world";
char aC[aS.size()];
strcpy(aC, aS.c_str());
cout << aC[0] << endl;
string bS="veooci m eode owtwolwwwwtwwj mooawee mdeeme eeeec eme aemmeledmll llllleolclclcmslococecewaccocmelaeaccoaaooojutmjooooocoemoooealm omjcdmcmkemmdemmmiwecmcmteeeote eoeeeem ecc e yolc e w dtoooojttttmtwtt ttjcttoowl otdooco ko mooooo aowmemm o et jmc cmlctmmcccjcccecomatocooccoeoclooomoecwooo mcdoo dcdco dddooedoemod eddeedoedje emadleweemeeedeeeec or o m wejeetoj o ojjjlwdjjjj mjmceaeoaai laaadoaa aetmotaemmj mmmmmmlmm cmol c mwoaoe omav";
char bC[bS.size()];
strcpy(bC, bS.c_str());
cout << aC[0] << endl;
When aC[0] was first called, it gave 'h' as expected. However, when aC[0] is called at the second time, it gave ''. Could someone explain me what happened here?
For some reason, I was trying to covert a C++ string to a char array
Why don't you just use .c_str(), it does this for you
string aS="hello world";
cout << aS.c_str();
char aC[aS.size()];
would need to be:
char aC[aS.size() + 1];
in order to allow for the terminating '\0' required for a C string.
If you don't want to use the std::string::c_str() member function, you should then allocate the char array dynamically, as you cannot declare variable length arrays in C++, such as:
char* bC = new char[aS.size() + 1]; // don't forget to delete[]
strcpy(bC, bS.c_str());
I can see some utility of changing to an array if you're calling a function that will change the string buffer (pre C++11). Otherwise, use the other solutions such as c_str() if the buffer is not going to be changed.
However, if you really wanted a char array due to the buffer possibly being changed, use std::vector<char>. This will bypass the issue of using non-standard syntax (aC[aS.size()]), and removes the need to dynamically allocate memory. A std::vector<char> effectively is a changeable string buffer, only wrapped.
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
string aS="hello world";
std::vector<char> aC(aS.begin(), aS.end()); // copy
aC.push_back(0); // null-terminate
cout << &aC[0] << endl;
}
Output:
hello world
Now, where you need to specify a character array pointer, you just pass the address of the first element in the vector (provided that the vector is not empty).
Live Example: http://ideone.com/tF32Zt
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.