After padding a string with zeroes - it prints unspecified characters? (C++) - c++

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.

Related

reverse string in c++ using char array

I tried to reverse a string using char array but in the output it prints some garbage value, I am unaware of that what is the cause plus it is only happening in large strings.
my code
string reverseWord(string str){
int j = 0, n=0;
n = str.length();
char t[n]={0};
for(int i=n-1;i>=0;i--)
{
t[j]=str[i];
j+=1;
}
return t;
}
input = APFGMRZXIFPSXKOQDRRQJBBZ
output = ZBBJQRRDQOKXSPFIXZRMGFPAB#
I want to know the reason behind # these two garbage values
Using online IDE of gfg.
C-style strings must be terminated by a null-character '\0'.
Instead of using Variable-Length Array, which is not in the standard C++, you should directly allocate string because you are returning that. (assuming that string here means std::string)
string reverseWord(string str){
int j = 0, n=0;
n = str.length();
string t(n); // allocate string instead of VLA
for(int i=n-1;i>=0;i--)
{
t[j]=str[i];
j+=1;
}
return t;
}

Find Number of Palindrome Strings in Array Program Errors

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.

Get string content from string pointer C++

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. ;)

using a string array in a function C++

this question should be easy and straight forward, but after searching online, I couldn't find an answer. might because the question is just too simple.
following code is from cplusplus.com. it's a function of making a string lowercase. I was intended to do something similar.
/* tolower example */
#include <stdio.h>
#include <ctype.h>
int main ()
{
int i=0;
char str[]="Test String.\n";
char c;
while (str[i])
{
c=str[i];
putchar (tolower(c));
i++;
}
return 0;
}
and what I made is this:
void search(string A[], string B[], int k)
{
int temp;
for(int j = 0; j <= 4; j++)
{
for(int i = 0; i <= k; i++)
{
string str (A[i]);
int h = 0;
char lstr[] = B[j];
char c;
while (lstr[h])
{
c = lstr[h];
putchar (tolower(c));
h++;
}
string key (B[j]);
.....
this part of the code is in a for loop. B[j] is a string array.
Visual Studio informed me that char lstr[] = B[j]; part is not right, the error message is:
Error: initialization with '{...}' expected for aggregate object.
I think the problem is that I didn't use the correct syntax of using a string array in a function. something should be done for B[j], in order to make it a char array. I couldn't figure it out.
is that something about pointer? sorry I haven't learn pointer yet.
does my question make sense for you? any help is greatly appreciated!!
If you're looking to make the letters in the string lowercase it's more readable to just work with strings all the way and use std::transform. For example,
// make sure to #include <algorithm>
// at the top
string lstr = B[j];
std::transform(lstr.begin(), lstr.end(), lstr.begin(), ::tolower);
This is much more natural and c++ idiomatic than working with char * directly and less error-prone.
You're trying to assign a char to char[]. You can get the effect you want with the following code:
....
int h = 0;
char* lstr = &B[j]; // point lstr to the address of j'th element of B.
char c;
while (lstr[h])
{
c = lstr[h];
putchar (tolower(c));
h++;
}
.....
What this does is that lstr is now a pointer that points to the j'th character in B. Arrays are essentially pointers. When you do B[j], it's equivalent to writing char ch = *(B + j);, where B points to the address of the first character in the array of characters (otherwise known as string).
EDIT
After your edit, it now seems that you're trying to assign a std::string to a char. Here is the corrected solution.
....
int h = 0;
string& lstr = B[j]; // grab a reference to the j'th string in B.
char c;
while (lstr[h])
{
c = lstr[h];
putchar (tolower(c));
h++;
}
.....
Here, lstr is essentially a reference to the j'th string in B and you can use it as a regular string just like how you're using string str(A[i]);, which makes a copy of the i'th string in A.
You're confusing character arrays and string objects here. A character array is an array of bytes of set size which is null terminated, while a string is an object which expands/contracts as is necessary and doesn't require the null terminator. You're attempting to assign a string object to a character array, which is unsupported. If you're working with string objects, and want to retrieve their equivalent character array, utilize the c_str() function:
const char* lstr = B[j].c_str()
Also, utilizing an array name of B and an index of j is hilarious.

Concatenate ints in an array?

As part of a homework assignment I need to concatenate certain values in an array in C++. So, for example if I have:
int v[] = {0,1,2,3,4}
I may need at some point to concatenate v[1] -> v[4] so that I get an int with the value 1234.
I got it working using stringstream, by appending the values onto the stringstream and then converting back to an integer. However, throughout the program there will eventually be about 3 million different permutations of v[] passed to my toInt() function, and the stringstream seems rather expensive (at least when dealing with that many values). it's working, but very slow and I'm trying to do whatever I can to optimize it.
Is there a more optimal way to concatenate ints in an array in C++? I've done some searching and nearly everywhere seems to just suggest using stringstream (which works, but seems to be slowing my program down a lot).
EDIT: Just clarifying, I do need the result to be an int.
Pseudo code for a simple solution:
int result = 0;
for (int i=0; i < len(v); i++)
{
result = result*10 + v[i];
}
Large arrays will bomb out due to int size overflow.
How about:
int result = (((v[1])*10+v[2])*10+v[3])*10+v[4];
If the number of elements is variable rather than a fixed number, I'm sure you can spot a pattern here that can be applied in a loop.
Remember ASCII codes?
char concat[vSize+1];
concat[vSize] = 0;
for(int i = 0; i < vSize; i++) {
concat[i] = (v[i] % 10) & 0x30;
}
All are integers. Shouldn't you do the following.
//if you want to concatenate v[1] and v[4]
int concatenated;
concatenated = v[1]*10+v[4];
//If you want to concatenate all
concatenated = 0;
for(int i=1;i<=4;i++)
concatenated = concatenated*10+v[i];
the output would be an integer ( not a string)
Things you can do:
Make sure that you compile with -O3 (Or equivalent compiler optimization).
Do you generate the values in the vector yourself? If so, try changing toInt() function to accept a simple pointer type.
Write the conversion yourself (Browser code : may not even compile - u get the idea though):
char* toInt(int* values, size_t length)
{
int *end = values + sizeof(int)*length;
int *cur = values;
char* buf = new char[length + 1]
for(char* out = buf;cur < end;++cur, ++buf)
{
*out = (char)*cur + '0';
}
*buf = '\0';
return buf;
}