i just want to copy array of string to dynamical array(using new operator) without using string.h of c++
how can i copying the array?
enter code here
const int LEN=3;
int n=15;
char*s1 ;
char *s[LEN]={"music","disc","soft"};
char (*str)[LEN]=new char[n][LEN]; //i want to copy s to this array
i try to do something like this
for(int i=0; i<LEN ;i++){
strcpy(str[i],s[i]);
}
for(int i=0; i<LEN ;i++)
cout<<str[i]<<endl;
but it printing all the array in one Sequence, i think a problem with NULL terminator
i don't no how to deal with
You invert the dimension of str, try:
const int LEN = 3;
const int n = 15;
const char *s[LEN] = {"music", "disc", "soft"};
char (*str)[n] = new char[LEN][n];
for(int i = 0; i < LEN ; i++) {
strncpy(str[i], s[i], n);
}
for(int i = 0; i < LEN ; i++)
std::cout << str[i] << std::endl;
delete []str;
Live example
Look at vector.
string sArray[3] = {"aaa", "bbb", "ccc"};
vector<string> sVector;
sVector.assign(sArray, sArray+3);
Source from here
Sane C++ code would use vector or array, and also string. However, without those, pure C would often use a dynamic array of dynamic strings:
char** strs = new char*[LEN]; //a dynamic array of dynamic strings
//Alternatively, char* (*strs)[LEN]
for(int i=0; i<LEN; ++i) {
strs[i] = new char[strlen(s[i])];
strcpy(strs[i], s[i]);
}
//code goes here
for(int i=0; i<LEN; ++i)
delete[] strs[i];
delete[] strs;
strs = NULL;
However, your code is closer to a dynamic array of fixed length strings:
char **strs = new char[n][LEN]; //a dynamic array of dynamic strings
//Alternatively, char(*strs)[LEN][n], or is it char(*strs)[n][LEN]?
for(int i=0; i<LEN; ++i)
strcpy(strs[i], s[i]);
//code goes here
delete[] strs;
strs = NULL;
Related
Recently I want to convert vector to char* array[].
So I had found the solution. But It was not safety way..
Here is my code
char** arr = new char* [4];
vector<string> vv;
// setting strings
for (int i = 0 ;i < 4; i++)
{
vv.emplace_back("hello world");
}
// convert
for (int i = 0; i < 4; i++)
{
arr[i] = new char[vv[i].size()];
memcpy(arr[i], vv[i].c_str(), vv[i].size());
}
// prints
for (int i = 0; i < 4; i++)
{
cout << arr[i] << endl;
}
// output
// hello world羲羲?솎솨
// hello world羲羲拂솽솨
// hello world羲羲
// hello world羲羲?펺솨
// delete memorys
for (unsigned index = 0; index < 4; ++index) {
delete[] arr[index];
}
delete []arr;
Why does it happen string crash??
Is there no safe way anymore?
When you use memcpy, arr[i] is not guaranteed to be a null-terminated string. To treat arr[i] as null terminated string, as in
cout << arr[i] << endl;
causes undefined behavior.
You need couple of minor changes.
Allocate one more byte of memory.
Use strcpy instead of memcpy.
arr[i] = new char[vv[i].size() + 1];
strcpy(arr[i], vv[i].c_str());
There's an easier way of doing this if you can maintain the lifetime of your initial vector.
for (int i = 0; i < 4; i++)
{
arr[i] = vv[i].c_str();
}
This way you won't allocate no additional memory, however, you'd have to keep in mind that once your initial vector gets destroyed, that array will be corrupted as well. But if you need such conversion for some simple synchronous api call within the same thread, that would do the trick.
In such cases I usually use this ugly construct.
arr[i] = new char[vv[i].size() + 1];
arr[i][vv[i].copy(arr[i], vv[i].size())] = 0;
I am trying to implement a binary tree as a 2d array. I want the user to enter the required height of the tree and the program should give an appropriate size array. Then, I want to print the array, which is why I need to pass it as a parameter. However, I get the following error:
arrayTree/main.cpp|19|error: cannot convert ‘std::__cxx11::string** (*)[maxNumberOfNodes] {aka std::__cxx11::basic_string<char>** (*)[maxNumberOfNodes]}’ to ‘std::__cxx11::string** {aka std::__cxx11::basic_string<char>**}’ for argument ‘1’ to ‘void printTree(std::__cxx11::string*)’|
Please, what is causing the error and how can I fix it?
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
void printTree(string** tree);
int main()
{
int treeHeight = 0;
int maxNumberOfNodes = 1;
cout << "enter tree height";
cin >> treeHeight;
cout << treeHeight<< "\n";
//create an array that can hold every combination for a given tree height
maxNumberOfNodes = pow(2,treeHeight) - 1;
string** tree [3][maxNumberOfNodes];
cout << maxNumberOfNodes;
printTree(tree);
}
void printTree(string** tree){
//not fully implemented yet
for(int i=0; i < sizeof(tree); i++){
cout << "*" << " ";
}
}
string** tree [3][maxNumberOfNodes];
is the syntax of a static 2D array of type string** , where both dimensions have to be declared const.
The difference between a static and a dynamic array is shown in here: Multidimensional variable size array in C++
Instead you want to write something like
string** tree = new string*[3];
for(int i = 0; i < 3; i++)
tree[i] = new string[maxNumberOfNodes];
As #Remy Lebeau commented: Every occurrence of new[] needs to be answered by a delete[] call, like this:
for (int i = 0; i < 3; i++)
delete tree[i];
delete[] tree;
to remove the dynamic allocation from the heap.
Like #drescherjm pointed out sizeof(tree) is not valid, as tree is just a pointer and does not include size information about the array.
You could solve this by additionally passing the dimensions of your array with it:
void printTree (string** tree, int dim, int dim2)
and rewriting the loop to
for(int i = 0; i < dim; i++){
for(int j = 0; j < dim2; j++){
cout << tree[i][j]; //...
}
}
string** tree [3][maxNumberOfNodes];
This declares a 2D array of string** pointers. That is not what you want. You want a 2D array of string objects instead, so drop the pointers:
string tree [3][maxNumberOfNodes];
Also, your printTree() is not implemented correctly. It would need to be implemented more like this instead:
void printTree(string** tree, int height) {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < height; j++) {
// use tree[i][j] as needed ...
}
}
}
That being said, since the value of maxNumberOfNodes is not known until runtime, the string tree [3][maxNumberOfNodes] syntax is declaring a Variable Length Array, which is not officially supported by the C++ standard, only as an extension by a few C++ compilers. You need to use new[] instead to allocate the 2nd dimension:
string* tree [3];
for(int i = 0; i < 3; ++i)
tree[i] = new string[maxNumberOfNodes];
printTree(tree, maxNumberOfNodes);
for(int i = 0; i < 3; ++i)
delete[] tree[i];
Or better, use std::vector instead:
std::vector<string> tree [3];
for(int i = 0; i < 3; ++i)
tree[i].resize(maxNumberOfNodes);
Though, in this latter case, you won't be able to pass tree to a string** function parameter, so you will have to adjust the code accordingly.
the method call is given by
printTree(tree [3][maxNumberOfNodes]);
it's working for me
Written code to find and remove the largest word in a string without the using of library functions. Everything works fine. But when I want to free memory, the result is negative (displays an empty line). If you remove the call to the memory release function, everything will work correctly, but there will be a leak of memory.
How do I fix it? Please help me.
#include <iostream>
using namespace std;
int length(char *text) // string length
{
char *begin = text;
while(*text++);
return text - begin - 1;
}
int size(char **text) // size of two-dimensional array
{
int i = 0;
while(text[i]) i++;
return i;
}
void free_memory(char **text)
{
for(int i=0; i<size(text); i++)
delete text[i];
delete [] text;
}
char **split(char *text, char delim)
{
int words = 1;
int len = length(text);
for(int i=0; i<len; i++)
if(text[i] == delim) words++;
char **result = new char*[words + 1];
int j = 0, t = 0;
for(int i=0; i<words; i++)
{
result[i] = new char[len];
while(text[j] != delim && text[j] != '\0') result[i][t++] = text[j++];
j++;
t = 0;
}
result[words + 1] = nullptr;
return result;
}
char *strcat(char *source, char *destination)
{
char *begin = destination;
while(*destination) destination++;
*destination++ = ' ';
while(*source) *destination++ = *source++;
return begin;
}
char *removeWord(char *in_string)
{
char **words = split(in_string, ' ');
int max = length(words[0]);
int j = 0;
for(int i=0; i<size(words); i++)
if(max < length(words[i]))
{
max = length(words[i]);
j = i;
}
int index;
char *result;
if(!j) index = 1;
else index = 0;
result = words[index];
for(int i=0; i<size(words); i++)
if(i != j && i != index)
result = strcat(words[i], result);
free_memory(words); // I want free memory here
return result;
}
int main()
{
char text[] = "audi and volkswagen are the best car";
cout << removeWord(text) << endl;
return 0;
}
In fact, this is C style programming - not C++. I see that your aim is to implement everything from scratch, possibly for practicing. But even then, your code is not designed/structured properly.
Besides that, you also have several bugs in your code:
result[words + 1] = nullptr; must be result[words] = nullptr;
You need result[i][t] = '\0'; after the while loop in split
delete text[i] must be delete [] text[i]
You cannot assign to your result pointer memory from words, then free it and then return it for use by the caller.
There is at least one further bug in the second half of removeWord. It would be tedious to try to understand what you are trying to do there.
You might want to start with a simpler task. You also should proceed step-by-step and check each function for correctness independently first and not implement everything and then test. Also take a look at the tool valgrind for memory checking - if you use Linux.
The way you free memory correctly is to use RAII:
Only use new and new[] in constructors
Pair those with delete and delete[] in the corresponding destructor
Use automatic storage duration objects as much as possible
If you are specifically not using std::string and std::vector etc, for reasons of learning pointers, you will end up writing some small number of classes that resemble string and vector and unique_ptr, and then you go about programming as if you were using the std versions.
You have two issues. First is that result is assigned to a memory location in words. Second, is that you're storing the result of strcat in words[i] which will likely not have enough room (see strcat documentation).
result = new char[len(in_string)+1]; // +1 for space for null char
// the old loop reversed the word order -- if you want to keep doing
// that, make this a descending loop
for(int i=0; i<size(words); i++)
if(i != j && i != index)
strcat(result, words[i]);
free_memory(words);
return result;
So that when you free words, what result points to is also free'd. You would then need to free your result in main().
int main()
{
char text[] = "audi and volkswagen are the best car";
char * result = removeWord(text);
cout << result << endl;
delete[] result;
return 0;
}
Disclosure: I'm trying to solve a challenge with strict time and memory limits. I would normally use vectors and strings, but here I need the fastest and smallest solution (with vectors it actually ran above the time limit), so I turned to dynamic arrays of char*.
The relevant parts of my code:
char** substrings(string s, int* n){
*n = 0;
...
////////////////////////////////
char** strings = new char*[*n];
////////////////////////////////
for (int i = 0; i < s.length(); i++){
for (int j = 1; j < s.length() - i + 1; j++){
...
strings[si] = tmp;
...
}
}
return strings;
}
int main(){
...
for (int ti = 0; ti < t; ti++){
cin >> s;
char** substr = substrings(s, &n);
...
for (int i = 0; i < n; i++){
delete substr[i];
}
}
return 0;
}
Everything runs just fine without deleting the array (of arrays), but that is unacceptable, so how do I go about this? I've tried a lot of variations that seemed logical but I get runtime errors.
It is similar to allocating, but in reverse order, and using delete[] instead of new[]:
for(int i = 0; i < LENGTH; i++)
delete[] strings[i]; // delete each pointer in char** strings
delete[] strings; // finally delete the array of pointers
I assumed here that LENGTH is the length of the array of pointers to char*. So it looks that you only perform the first round of de-allocation
for (int i = 0; i < n; i++){
delete substr[i]; // need delete[] substr[i] here
but with delete instead of delete[], you need delete[] substr[i] instead, as my guess is that substr[i] is a char* pointer pointing the first element of an array of chars allocated by new[]. You finally need the additional
delete[] substr;
I have an array of chars. n is array's length
char tab[n];
cin.get(tab, n);
cout<<tab<<"\0"<<endl;
then I create second array
char* t = new char[n];
for(int i = 0; tab[i] != '\0'; i++){
t[i] = tab[i];
}
I would like to have pointers to corresponding element. I mean t[2] contains addres of tab[2]. Then I would like to sort array t so tab stays as it was and only t shuffles but when I make change in the array t for example
t[2] = 'a';
I loose t[3]t[4]....
EDIT:
do{
for(int i = 0; i < n -1; i++){
if(t[i] > t[i+1]){
char* x = &t[i];
t[i] = t[i+1];
t[i+1] = *x
}
n--;
}
}while(n>1);
I would like to have pointers to corresponding element. I mean t2 contains addres of tab2.
So try this:
char** t = new (char*)[n];
for(int i = 0; tab[i] != '\0'; i++){
t[i] = tab+i; // or `&(tab[i])`
To sort the t array based on tab values, use *t[i] to access character values stored in location i of the t array.
See here and here for good tutorials about C pointers.