so I'm working on a project that I have to read contents from a file and then analyze them. But I'm having a problem with getting the string out of a pointer that contains the address to what I need.
string lePapel(vector<char> vec){
string *str, s;
int i, j = 0;
vector<char> aux;
aux.resize(6);
for (i = 57; i <= 62; i++){
aux[j] = vec[i];
j++;
}
str = new string[aux.size()];
for (i = 0; i < 6; i++){ str[i] = aux[i]; }
return s;
}
So, the file contains in the array positions from 57 to 62 the word: ABCB4, but when returning the string s my output is A only as expected because of the pointer.
The thing is that I have been trying to find a solution and storing the whole content from vec[57] to vec[64] into the string s and returning it, and the closest that I got to returning anything plausible was using a pointer.
So, now to my question, how can I iterate the *str pointer and copy the whole content to s and return it?
Thanks in advance
I'd suggest you to not use pointers on string in your case. The following code is probably what you want :
#include <iostream>
#include <string>
#include <vector>
using namespace std;
string lePapel(vector<char> vec){
int j = 0;
vector<char> aux;
aux.resize(6);
for (int i = 57; i <= 62; i++){
aux[j] = vec[j];
j++;
}
string str;
str.reserve(6);
for (int i = 0; i < 6; i++){ str.push_back(aux[i]); }
return str;
}
int main() {
char x[5] = {'A', 'B', 'C', 'B', '4'};
vector<char> vec(x, x + 5);
string s = lePapel(vec);
cout << s;
return 0;
}
Tested here : Tested code
About reserving space to your vector : c++ vector::reserve
Same for strings : reserve for strings
The dynamic array of string objects and the whole aux vector seem completely needless here (unless there's some other purpose for them in your code). Additionally, str is currently causing a memory leak because you never delete it when you're finished.
A much simpler approach is just to append the characters one-at-a-time to the s string object (assuming it's a std::string):
string lePapel(vector<char> vec) {
string s;
for (int i = 57; i <= 62; i++) {
s += vec[i];
}
return s;
}
There are various ways to make the code even shorter (and more efficient) than that though, if you really want to.
EDIT: If you still need/want to iterate your dynamic array and concatenate the contents into s, here's how you could do it:
for (i = 0; i < 6; i++) s += str[i];
delete [] str; //<-- very important!
Short answer, you don't want a string * you want a char *. What you created is a string array. String objects contain a pointer to the char * data you are trying to capture. Also, the sizeof(std::string) (8 bytes in size) is a lot bigger than sizeof(char) (1 byte in size) the second character you store is 8 bytes away from the first character instead of being adjacent.
There are a lot of other C++ style and safety concerns, but I'll stick with the question. ;)
Related
I am writing code that finds the number of palindrome strings in a given array of strings. I think I have the right idea, but I am getting weird errors when I run it. What exactly am I doing wrong?
int countPalindromes(string s) {
int size = s.size();
int counter = 0;
string forwardSum = "";
string backwardSum = "";
for(int i = 0; i < size; i++){
for(int j = i; j < size; i++){
forwardSum.push_back(s[j]);
backwardSum.push_back(s[(n - 1)-j]);
if(forwardSum == backwardSum){
counter++;
}
}
}
return counter;
}
string forwardSum[] = {};
This is an array of zero size (which I don't believe is legal but we'll let that pass)
forwardSum[i] = forwardSum[i] + s[j];
This is an attempt to access the ith element of an array which has zero size.
That's bad.
I'm not really following your code (it's late at night), but I think you probably want forwardSum and backwardSum to be strings not arrays of strings. And you probably want to use push_back to add characters from s to those strings. I.e.
string forwardSum;
...
forwardSum.push_back(s[j]); // add s[j] to forwardSum
But if you really do want forwardSum to be an array, then the sensible thing to do would be to use a vector instead.
vector<string> forwardSum(size); // a vector of strings with the given size
Now that should at least not crash with the rest of your code.
I was writing a program where I need to copy a string (length unknown initially) to another string character by character.
I write this code that runs perfectly.
string a = "Hello";
string b( a.length(), 'a');
for (int i = 0; i < a.length(); i++)
b[i] = a[i];
But as the size of the string in C++ is calculated dynamically as
string k = "Hello";
string l = "Hello World";
string m = k;
m = l;
won't give any error. So it is clear that size of a string variable is changing dynamically according to the requirement.
So I tried the same without defining the size of the variable b.
string a = "Hello";
string b;
for (int i = 0; i < a.length(); i++)
b[i] = a[i];
But in this case, my program is crashing and saying String subscript out of range.
Why not in this case the size of variable b is increasing?
What is the cause of the error and how can I achieve this without mentioning the size of any variable?
If you must, you can use push_back:
string a = "Hello";
string b;
for (int i = 0; i < a.length(); i++)
b.push_back(a[i]);
or even1
string a = "Hello";
string b;
for (auto c : a)
b.push_back(c);
But why?
Reference: http://en.cppreference.com/w/cpp/string/basic_string/push_back
1 But don't do this if a is changed in any way: the underlying iterators will be invalidated.
You can simply use the += operator:
for (auto el : a){
b += el;
}
The std::string::operator+= has an overload that accepts character.
Size of the string is dynamic, but it not changed automaticaly as you expect. operator[] only return i-th element, if current size of a string is less than i, it fill fail. It's up to you to make sure size of a string is big enough.
If you couldn't resize string in advance you can query size, increase it by one, ask string to resize, and set last char.
This is how push_back method works
I have a string vector which contains some number of strings greater than 500. I am using openssl functions that require buffers for encryption/decryption. Given that I am using string vectors and buffers in this manner, what is the best algorithm in terms of space and time to make this conversion. Each string can be assumed to be less than 200 chars.
Currently, I am extracting each entry in paths, concatenating the strings, calling the .c_str() method and using strcpy to extract from a function.
void copy(vector<string>& paths, unsigned char** plainTextBuffer, size_t& p_len){
int size = paths.size();
int i = 0;
string temp = "";
for(i=0; i<size; i++){
temp+= paths[i];
temp+= "\n";
}
p_len = temp.length();
(*plainTextBuffer) = malloc(p_len + 1);
strcpy((*plainTextBuffer), temp.c_str());
return;
}
Are there any built in tools to do this better and faster? (I have excluded error checking and casting from this snippet)
Edit:
I added the +1 to the malloc. I asked for a minimum complexity manner of getting from the initial conditions to the expected output. I am using malloc because I am using a simple buffer and it is faster than new.
Edit 2:
Thanks to some of the comments I am cutting out the middleman with some of the copying and have the following
void copy(vector<string>& paths, unsigned char** plainTextBuffer, size_t& p_len){
int size = paths.size(), total = 0, i = 0;
for(i=0; i<size; i++){
total+= paths[i].size() + 1;
}
p_len = total;
(*plainTextBuffer) = malloc(p_len + 1);
(*plainTextBuffer)[0] = '\0';
for(i=0; i<size; i++){
strcat((*plainTextBuffer), paths[i].c_str());
strcat((*plainTextBuffer, "\n");
}
return;
}
Again I left out some casting. Is there a more efficient manner of getting the buffer data into the plainTextBuffer?
The fastest way to convert a string to a C-style string is to not do any conversions. So first, let's convert our std::vector<std::string> into one std::string:
std::vector<std::string> v = ...;
std::string output;
for (auto& s : v) {
output += s;
output += '\n';
}
And then you can pass that in:
void some_c_api(char*, size_t );
void some_const_c_api(const char*, size_t);
some_c_api(&output[0], output.size());
some_const_c_api(output.c_str(), output.size());
Appending repeatedly into a string will result in the string repeatedly reallocating memory and shuffling its content into the new bigger space. A stringstream has a bigger creation cost, but it appends much faster than std::string, so instead of appending to a string in a loop, append to a stringstream:
stringstream temp;
for(size_t i=0; i<paths.size(); i++){
temp << paths[i] << endl;
}
const std::string& tmp = temp.str();
Then just use tmp like you would have used your previous temp string. It is better to get a constant reference to temp.str() because it will not copy the content of the temporary created by str().
Basically, here, I'm trying to reverse an array, and convert the reversed int array into a string (I'm trying to write the equivalent of Java's BigInteger class in C++ - basically turning the input into big endian ordering, breaking down the operations, reversing the result back to little endian format, and returning the string).
And as you can see below, it outputs some strange characters (I think it's an out of range reference?) - but I'm not entirely sure what caused this output?
I would really appreciate if you could take a look at it:
Sample input
int a[] = {1, 2, 3};
int rA[3];
reverseIntArray(a, rA, 3);
string aString = intArrayToString(a, 3);
cout << aString << endl;
Console output
123\216\377
As you can see - it calculates the answer correctly, with the exception of the \277_\377.
I'll post the rest of the relevant functions:
reverseIntArray
void reverseIntArray(int array[], int reversedArray[], int arrayLength) {
for (int i = 0; i < arrayLength; i++) {
reversedArray[i] = array[arrayLength - 1 - i];
}
}
intArrayToString
string intArrayToString(int digits[], int length) {
// convert int array to char array
char digitsChar[length];
for (int i = 0; i < length; i++) {
digitsChar[i] = '0' + digits[i];
}
// convert char array to string
string intString(digitsChar);
return intString;
}
I'm quite sure this is a subtle issue to do with pointers, but I'm still relatively new to C++ (migrating from Java) and I've stared at this for hours but haven't come up with any ideas.
The std::string constructor you are using is assuming that the string you pass is properly terminated, which it isn't and that leads to undefined behavior as the std::string constructor goes beyond the end of the digitsChar array.
Three possible solutions:
Make room for another character in the digitsChar array and terminate it:
char digitsChar[size + 1];
for (...) { ... }
digitsChar[3] = '\0';
string intString(digitsChar);
Use another constructor where you pass the length of the character array:
string intString(digitsChar, length);
Append the characters directly to the string:
string intString;
for (int i = 0; i < length; i++) {
intString += '0' + digits[i];
}
There are of course other solutions as well, like for example using std::ostringstream.
I wrote some code in order to turn a string (read in with getline()) into an array of c_strings. The problem I'm having is that the items I'm reading is not being stored in the array properly. I originally parsed the input based on the number of spaces in between them, and then going on from there, but that also got me the same problem. So I changed my parsing into what's below me, and I'm getting the same exact problem, suggesting to me that my parsing works, but somewhere in the process of reading what's parsed into the char* array, something is going wrong.
My code:
int i = 0;
unsigned inputSize = input.size();
unsigned int prev = 0; //prev as in previous space position
while((prev = input.find(' ', prev)) < inputSize) {
++i; ++prev;
}
char* charArray[i + 2];
memset(charArray, '\0', i + 2);
stringstream ss(input);
string buffer;
for(int a = 0; ss >> buffer; ++a) {
charArray[a] = const_cast<char*>(buffer.c_str());
}
What I'm doing is that I'm counting the number of spaces of my input, and making a char* array of that number + 2 (+2 because I need to end it with NULL). After that, I parse my input and read it into the array. I am using ss >> buffer as my termination clause because I will not end up allocating memory outside the allocated memory for charArray. buffer.c_str gets me a const char*, so I const_cast it in order for me to store it into the (non-const) array of char*. I use memset to set all elements to NULL because I know it'll be written over, except the last element, which I want to remain NULL.
Test:
Input: Why hello world
Output: Junk
What's going wrong inside my program?
The pointer returned by buffer.c_str() is valid only as long as the string stored in buffer is not modified. If you need to modify buffer, you have to copy its contents beforehand, if you need the old content later on.
See Right way to split an std::string into a vector [duplicate].
Live Example
#include <iostream>
#include <sstream>
#include <iterator>
#include <vector>
using namespace std;
int main(int argc, char *argv[]) {
std::string input = "Why hello world";
std::stringstream ss(input);
std::vector<std::string> vstrings(std::istream_iterator<std::string>(ss),
std::istream_iterator<std::string>{}); // C++11 brace syntax
char** charArray = new char*[vstrings.size()];
for (unsigned int i = 0; i < vstrings.size(); i++)
charArray[i] = (char*)vstrings[i].c_str();
for (unsigned int i = 0; i < vstrings.size(); i++)
std::cout << charArray[i] << "\n";
delete[] charArray;
}