Reverse a string with pointers [duplicate] - c++

This question already has answers here:
C++ Reverse Array
(5 answers)
Closed 7 years ago.
This is an amateur question. I searched for other posts about this topic, found lots of results, but am yet to understand the concepts behind the solution.
This is a practice problem in my C++ book. It is not assigned homework. [Instructions here][1] .
WHAT I WOULD LIKE TO DO:
string input;
getline(cin, input); //Get the user's input.
int front = 0;
int rear;
rear = input.size();
WHAT THE PROBLEM WANTS ME TO DO
string input;
getline(cin, input); //Get the user's input.
int* front = 0;
int* rear;
rear = input.size();
Error: a value of type "size_t" cannot be assigned to an entity of type int*
This makes sense to me, as you cannot assign an 'address' of an int to the value of an int.
So my questions are:
What is the correct way to go about this? Should I just forget about initializing front* or rear* to ints? Just avoid that all together? If so, what would be the syntax of that solution?
Why would this problem want me to use pointers like this? It's clear this is a horrible usage of pointers. Without pointers I could complete this problem in like 30 seconds. It's just really frustrating.
I don't really see an advantage to EVER using pointers aside from doing something like returning an array by using pointers.
Thanks guys. I know you like to help users that help themselves so I did some research about this first. I'm just really irritated with the concept of pointers right now vs. just using the actual variable itself.
Posts about this topic that I've previously read:
[Example 1][2]
[Example 2][3]
[Example 3][4]
[1]: http://i.imgur.com/wlufckg.png "Instructions"
[2]: How does reversing a string with pointers works "Post 1"
[3]: Reverse string with pointers? "Post 2"
[4]: Reverse char string with pointers "Post 3"

string.size() does not return a pointer - it returns size_t.
To revert a string try this instead:
string original = "someText"; // The original string
string reversed = original; // This to make sure that the reversed string has same size as the original string
size_t x = original.size(); // Get the size of the original string
for (size_t i = 0; i < x; i++) // Loop to copy from end of original to start of reversed
{
reversed[i]=original[x-1-i];
}
If you really (for some strange reason) needs pointers try this:
string input;
getline(cin, input); //Get the user's input.
char* front = &input[0];
char* rear = &input[input.size()-1];
but I would not use pointers into a string. No need for it.

I guest you may not quite understand the problem here. This problem want you to COPY a C string then REVERSE it by pointer operation. There is no classes in standard C. So, the C string is quite different from string class in C++. It is actually an array of char-type elements ended with character '\0'.
After understand this, you may start to understand the problem here. If you want to copy a C string, you can not just use str_a = str_b. You need constructor here. However, in pure C style, you should REQUIRE memory space for the string at first (you can use malloc here), then copy each element. For example, you want to create a function to make a copy of input string,
#include <string.h>
char *strcopy(char* str_in) {
int len = strlen(str_in);
char *str_out = (char*)malloc(len+1);
char *in = str_in;
char *out = str_out;
while(*in != '\0') { *out++ = *in++; }
return str_out;
}
As you see, we actually use char* not int* here to operate string element. You should distinguish the pointer (such as in) and the element pointed by the pointer (such as *in) at first.
I'll show you a solution in pure C style for your problem, I hope this would help you to understand it. (You should be able to compile it without modification)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* strreverse(char* in){
// length of input string
int len = strlen(in);
// allocate memory for string operation
char *out = (char*)malloc(len+1);
// initialize <front> and <end>
char *front = out, *end = out + len - 1;
char buffer;
// copy input string
for(int i = 0; i <= len; i++){ out[i] = in[i]; }
// reverse string
for(; front < end; front++, end--) {
buffer = *front;
*front = *end;
*end = buffer;
}
return out;
}
int main() {
printf("REVERSE >> %s\n", strreverse("Hello, World!"));
return 0;
}
This is not you would do by C++ in actual programming, however, I guess the problem here is trying to let you understand mechanism of pointers. In this aspect, original C style would help a lot.

Related

Convert from vector<unsigned char> to char* includes garbage data

I'm trying to base64 decode a string, then convert that value to a char array for later use. The decode works fine, but then I get garbage data when converting.
Here's the code I have so far:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
decodedChar[decodedData.size() + 1] = 0; // terminate the string
for (size_t i = 0; i < decodedData.size(); ++i) {
decodedChar[i] = decodedData[i];
}
vector<BYTE> is a typedef of unsigned char BYTE, as taken from this SO answer. The base64 code is also from this answer (the most upvoted answer, not the accepted answer).
When I run this code, I get the following value in the VisualStudio Text Visualiser:
TestStringÍ
I've also tried other conversion methods, such as:
char* decodedChar = reinterpret_cast< char *>(&decodedData[0]);
Which gives the following:
TestStringÍÍÍýýýýÝÝÝÝÝÝÝ*b4d“
Why am I getting the garbage data at the end of the string? What am i doing wrong?
EDIT: clarified which answer in the linked question I'm using
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
Why would you manually allocate a buffer and then copy to it when you have std::string available that does this for you?
Just do:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
std::string decodedString { decodedData.begin(), decodedData.end() };
std::cout << decodedString << '\n';
If you need a char * out of this, just use .c_str()
const char* cstr = decodedString.c_str();
If you need to pass this on to a function that takes char* as input, for example:
void someFunc(char* data);
//...
//call site
someFunc( &decodedString[0] );
We have a TON of functions and abstractions and containers in C++ that were made to improve upon the C language, and so that programmers wouldn't have to write things by hand and make same mistakes every time they code. It would be best if we use those functionalities wherever we can to avoid raw loops or to do simple modifications like this.
You are writing beyond the last element of your allocated array, which can cause literally anything to happen (according to the C++ standard). You need decodedChar[decodedData.size()] = 0;

Segfaults on appending char* arrays

I'm making a lexical analyzer and this is a function out of the whole thing. This function takes as argument a char, c, and appends this char to the end of an already defined char* array (yytext). It then increments the length of the text (yylen).
I keep getting segfaults on the shown line when it enters this function. What am I doing wrong here? Thanks.
BTW: can't use the strncpy/strcat, etc. (although if you want you can show me that implementation too)
This is my code:
extern char *yytext;
extern int *yylen;
void consume(char c){
int s = *yylen + 1; //gets yylen (length of yytext) and adds 1
//now seg faults here
char* newArray = new char[s];
for (int i = 0;i < s - 1;i++){
newArray[i] = yytext[i]; //copy all chars from existing yytext into newArray
}
newArray[s-1] = c; //append c to the end of newArray
for (int i = 0;i < s;i++){ //copy all chars + c back to yytext
yytext[i] = newArray[i];
}
yylen++;
}
You have
extern int *yylen;
but try to use it like so:
int s = (int)yylen + 1;
If the variable is an int *, use it like an int * and dereference to get the int. If it is supposed to be an int, then declare it as such.
That can t work:
int s = (int)yylen + 1; //gets yylen (length of yytext) and adds 1
char newArray[s];
use malloc or a big enought buffer
char * newarray=(char*)(malloc(s));
Every C-style string should be null-terminated. From your description it seems you need to append the character at c. So, you need 2 extra locations ( one is for appending the character and other for null-terminator ).
Next, yylen is of type int *. You need to dereference it to get the length (assuming it is pointing to valid memory location ). So, try -
int s = *yylen + 2;
I don't see the need of temporary array but there might be a reason why you are doing it. Now,
yytext[i] = newArray[i]; //seg faults here
you have to check if yytext is pointing to a valid write memory location. If yes, then is it long enough to fill the appending character plus null terminator.
But I would recommend using std::string than working with character arrays. Using it would be a one liner to solve the problem.

How to reverse a user input without using array or any library function(any function for reversing)?

Let me clear you first that I'm not a college student and this is not my home assignment. I am just curious to know the solution of this question which was once asked to me. I think this is a nice and tricky question which I feel worth sharing.The question was--
How do you input a string(said in general sense, independent of programming) from a user and print reverse of it in C/C++ without using array or any library function for reversing the user input?
I am unable to break-into this. Help please
Note: Members are marking it as a duplicate for this question. But All answers to this are either using library functions or using a pointer to char array(char *). None of them is allowed in my case. Please review it once again
You can try recursion.
void print_reverse_str() {
int c = getchar();
if (c != EOF) {
print_reverse_str();
putchar(c);
}
}
Technically this is impossible because a string is a char array in c and an object representing a char array in c++.
I hope you meant not using arrays directly.
So try this pointer based solutions :
void strrev(char *str)
{
if( str == NULL )
return;
char *end_ptr = &str[strlen(str) - 1];
char temp;
while( end_ptr > str )
{
temp = *str;
*str++ = *end_ptr;
*end_ptr-- = temp;
}
}

Assigning chars to a char array with +=

Currently I'm writing a rather extensive homework assignment that - among other things - reads a file, builds a binary search tree and outputs it.
Somewhere inside all that I've written a recursive method to output the values of the binary search tree in order.
void output(node* n)
{
if(n->leftChild != NULL)
output(n->leftChild);
cout << n->keyAndValue << " || ";
outputString += n->keyAndValue << '|';
if(n->rightChild != NULL)
output(n->rightChild);
}
No problem with that, but you'll notice the line outputString += n->keyAndValue << '|';, because I also want to have all the values inside a char array (I am not allowed to use strings or other more current features of C++) that I can use later on in a different method (e.g. Main method).
The Char-Array is declared as follows:
char *outputString;
This being just one of the ways I've tried. I also tried using the const keyword and just regularly building an array char outputString[]. With the version I've shown you I encounter an error when - later on in the program in a different method - calling the following code:
cout << outputString;
I get the following error:
Unhandled exception at 0x008c2c2a in BST.exe: 0xC00000005: Access Violation reading location 0x5000000000.
Any clue as to how I'd be able to build a dynamic char array, assign values to it numerous times using += and outputting it without triggering an access violation? I am sorry for asking a rather basic question but I am entirely new to C++.
Thanks and Regards,
Dennis
I'm guessing that since you can't use std::string, you also can't use new[].
You can concatenate strings with a function like this:
char *concat(const char *s1, const char *s2)
{
size_t len = strlen(s1) + strlen(s2);
char *result = (char*)malloc(len+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
This can be done more efficiently, but that probably doesn't matter for homework. And you need to check for errors, etc. etc.
You also need to decide who is going to call free on s1 and s2.
For what it is worth, the efficient version looks like this:
char *concat(const char *s1, const char *s2)
{
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
char *result = (char*)malloc(len1+len2+1);
memcpy(result, s1, len1);
memcpy(result+len1, s2, len2);
result[len1+len2] = '\0';
return result;
}
It's more efficient because it only walks the input strings once.
+= on pointers does pointer arithmetic, not string concatenation. Eventually you get way beyond your array that outputString was pointing to, and trying to print it leads to a segfault.
Since you can't use std::string, you need to use strcat along with new[] and delete[] and make sure you allocated your original array with new[].

Simple C++ char array encryption function - Segment fault

As always, problems with the pointers. I am trying to create a very simple "encryption/decryption" function for char arrays. Yes, I know I can use strings, but I want to improve my knowledge about pointers and make use of simple bytes to achieve a simple task.
So, I created a simple struct like this:
struct text {
char* value;
int size;
}
And I created this simple function:
text encrypt(text decrypted) {
char key = 'X';
for (int i=0; i<decrypted.size; i++) {
decrypted.value[i] = decrypted.value[i] ^ (key + i) % 255);
}
return decrypted;
}
At this point, an experienced C++ programmer should have spot the problem, I think. Anyway, I call this function like this:
...
text mytext;
mytext.value = new char[5];
mytext.value = "Hello";
mytext.size = 5;
mytext = encrypt(mytext);
...
I get, like always, a 'Segmentation fault(core dumped)' error. This is Linux, and, of course, g++. What have I done, again? Thanks!
mytext.value = new char[5];
mytext.value = "Hello";
on the second line, you throw away the (handle to the) allocated memory, leaking it, and let mytext.value point to a string literal. Modifying a string literal is undefined behaviour, and usually crashes, since string literals are often stored in a read-only memory segment.
If you insist on using a char*, you should strncpy the string into the allocated memory (but be aware that it won't be 0-terminated then, you should better allocate a new char[6] and copy also the 0-terminator).
Or let decrypt create a new text that it returns:
text encrypt(text decrypted) {
char key = 'X';
text encrypted;
encrypted.size = decrypted.size;
encrypted.value = new char[encrypted.size];
for (int i=0; i<decrypted.size; i++) {
encrypted.value[i] = decrypted.value[i] ^ (key + i) % 255;
}
// What about 0-terminators?
return encrypted;
}
But, as you're using C++, std::string would be a better choice here.
You're modifying string literals:
mytext.value = "Hello";
after this, you can no longer legally mutate what mytext.value points to, you can only re-assign the pointer.
The fix: use std::string