I know return end is not correct, I am thinking about to use one of my pointer to go to the end, and then go back by the size of the string to return the reversed string. Is there a more efficient way of doing that? Also, more importantly, am I getting a run time error here? http://ideone.com/IzvhmW
#include <iostream>
#include <string>
using namespace std;
string Reverse(char * word)
{
char *end = word;
while(*end)
++end;
--end;
char tem;
while(word < end) {
tem = *word;
*word = *end;
*end = tem; //debug indicated the error at this line
++word;
--end;
}
return end;
}
int main(int argc, char * argv[]) {
string s = Reverse("piegh");
cout << s << endl;
return 0;
}
You're passing "piegh" to Reverse, which gets converted to a pointer to char. That pointer to char points into a read only string literal. Perhaps you meant to copy the string literal "piegh" before attempting to assign to it:
char fubar[] = "piegh";
string s = Reverse(fubar);
After all, how could you justify "piegh"[0] = "peigh"[4];?
What does this part of your code do?
while(*end)
++end; //Assuming you are moving your pointer to hold the last character but not sure y
--end; //y this one
while(word < end)// also i am not sure how this works
This code works and serves the same purpose
char* StrReverse(char* str)
{
int i, j, len;
char temp;
char *ptr=NULL;
i=j=len=temp=0;
len=strlen(str);
ptr=malloc(sizeof(char)*(len+1));
ptr=strcpy(ptr,str);
for (i=0, j=len-1; i<=j; i++, j--)
{
temp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=temp;
}
return ptr;
}
Related
In the following part of the string swap code
end = &str[len - 1];
I am not understanding the addressing part. When I do it without the addressing part it still runs but gives me a warning that "a values of type char cannot be assigned to identity of type char". Here is the full code:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char str[] = "This is a test";
char *start, *end;
int len;
int t;
cout << "Original " << str << "\n";
len = strlen(str);
start = str;
end = str[len - 1];
//this reverses the string
while (start < end) {
t = *start;
*start = *end;
*end = t;
start++;
end--;
}
cout << "Reversed" << str << "\n";
system("PAUSE");
return 0;
}
I am not understanding the addressing part.
Given
char str[] = "This is a test";
char *start, *end;
len = strlen(str);
then end is pointer to char, and
end = &str[len - 1]; // `end` points to the last character (before the `\0`)
You must use the & (address of) operator because end is pointer and so it must be assigned to the address of something (here the address of the last character of the string).
When I do it without the addressing part it still runs
I don't think it will - you should have got a compile error
end = str[len - 1]; // invalid conversion from ‘char’ to ‘char*’
You should konw the type of end is char*, but the type of str[len-1] is char, so you need change type str[n-1] to char*, so you need &str[len-1].
But if you use string, there will be an easy method:
Use the std::reverse method from STL:
std::reverse(str.begin(), str.end()); //str shoud be string type
You will have to include the "algorithm" library, #include.
Maybe this can help
void reverse (char word[])
{
int left = 0;
int right = strlen(word) - 1;
while (left < right)
{
char temp = word[left];
word[left] = word[right];
word[right] = temp;
left++;
right--;
}
cout << word;
}
I hope this gives you the idea.
So I'm making a function that is similar to SubStr. This is an assignment so I cannot use the actual function to do this. So far I have created a function to take a string and then get the desired substring. My problem is returning the substring. In the function when I do Substring[b] = AString[b]; the substring is empty, but if I cout from inside the function I get the desired substring. So what is wrong with my code?
Here is a working demo: http://ideone.com/4f5IpA
#include <iostream>
using namespace std;
void subsec(char AString[], char Substring[], int start, int length);
int main() {
char someString[] = "abcdefg";
char someSubString[] = "";
subsec(someString, someSubString, 1, 3);
cout << someSubString << endl;
return 0;
}
void subsec(char AString[], char Substring[], int start, int length) {
for (int b = start; b <= length; b++) {
Substring[b] = AString[b];
}
}
Maybe this does what you're looking for? It's hard to say as your initial implementation used the length parameter as more of an end position.
#include <iostream>
using namespace std;
void subsec(char AString[], char Substring[], int start, int length)
{
const int end = start + length;
int pos = 0;
for(int b = start; b < end; ++b)
{
Substring[pos++] = AString[b];
}
Substring[pos] = 0;
}
int main()
{
char someString[50] = "abcdefghijklmnopqrstuvwxyz";
char someSubString[50];
subsec(someString, someSubString, 13, 10);
cout << someSubString << endl;
return 0;
}
There are several problems with the code:
1) The char arraysomeSubString has size 1 which cannot hold the substring.
2) The subsec is not correctly implemented, you should copy to the Substring from index 0.
Also remember to add \0 at the end of the substring.
void subsec(char AString[], char *Substring, int start, int length) {
int ii = 0;
for (int jj = start; jj <= length; jj++, ii++) {
Substring[ii] = AString[jj];
}
Substring[ii] = '\0';
}
You need to allocate more than 1 byte for someSubString i.e.
char someSubString[] = "xxxxxxxxxxxxxxxxxx";
or just
char someSubString[100];
if you know the max size you'll ever need.
Either would allocate enough space for the string you're copying to it. Then, you're not doing anything about the terminating 0 either. At the end of a C-style string there needs to be a terminating null to signify end of string. Otherwise cout will print something like;
abcdefgxxxxxxx
if you initialized with x's as I indicated.
There are a few problems with your code as it stands. Firstly, as your compiler is no doubt warning you, in C++ a string literal has type const char[], not just char[].
Secondly, you need to have enough space to store your substring. A good way to do this is for your function to allocate the space it needs, and then pass back a pointer to this memory. This is the way things are typically done in C code. The only thing is that you have to remember to delete the allocated array when you're done with it. (There are other, better ways to do this in C++, with things like smart pointers and wrapper objects, but those come later :-) ).
Thirdly, you'll have a problem if you request a length which is actually longer than the passed-in string -- you'll run off the end and start copying random memory (or just crash), which is definitely not what you want. C strings are terminated with a "nul byte" -- so you need to check whether you've come across this.
Speaking of the nul, you need to make sure that your substring ends with one.
Lastly, it's not really a problem but there's no need for the start parameter, you can just pass a pointer to the middle of the array if you want to.
char* substring(const char* str, int length)
{
// Allocate memory for substring;
char* subs = new char[length+1];
// Copy characters from given string
int i = 0;
while (i < length && str[i] != '\0') {
subs[i] = str[i];
i++;
}
// Append the nul byte
subs[i] = '\0';
return subs;
}
int main()
{
const char someString[] = "foobarbaz"; // Note -- must be const in C++
char* subs = substring(someString + 3, 3);
assert(strcmp(subs, "bar") == 0);
delete subs;
}
I have to admit, i have no idea how to use pointers, but I tried non the less. the problem with my program is that it shows the string in reverse, except for what was the first letter being missing and the entire string is moved one space forward with the first element being blank.
for example it show " olle" when typing "hello".
#include <iostream>
#include <string>
using namespace std;
string reverse(string word);
int main()
{
char Cstring[50];
cout<<"enter a word: ";
cin>>Cstring;
string results = reverse(Cstring);
cout <<results;
}
string reverse(string word)
{
char *front;
char *rear;
for (int i=0;i< (word.length()/2);i++)
{
front[0]=word[i];
rear[0]=word[word.length()-i];
word[i]=*rear;
word[word.length()-i]=*front;
}
return word;
}
The new code works perfectly. changed the strings to cstrings. the question technicaly asked for cstrings but i find strings easier so i work with strings then make the necesary changes to make it c string. figured out ho to initialize the rear and front as well.
#include <iostream>
#include <cstring>
using namespace std;
string reverse(char word[20]);
int main()
{
char Cstring[20];
cout<<"enter a word: ";
cin>>Cstring;
string results = reverse(Cstring);
cout <<results;
}
string reverse(char word[20])
{
char a='a';
char b='b';
char *front=&a;
char *rear=&b;
for (int i=0;i< (strlen(word)/2);i++)
{
front[0]=word[i];
rear[0]=word[strlen(word)-1-i];
word[i]=*rear;
word[strlen(word)-1-i]=*front;
}
return word;
}
char *front;
char *rear;
then later
front[0]=word[i];
rear[0]=word[strlen(word)-1-i];
Not good. Dereferencing uninitialized pointers invokes undefined behavior.
Apart from that, your code is overly complicated, it calls strlen() during each iteration (and even multiple times), which is superfluous, and the swap logic is also unnecessarily complex. Try using two pointers instead and your code will be much cleaner:
void rev_string(char *str)
{
char *p = str, *s = str + strlen(str) - 1;
while (p < s) {
char tmp = *p;
*p++ = *s;
*s-- = tmp;
}
}
The thing is, however, that in C++ there's rarely a good reason for using raw pointers. How about using std::reverse() instead?
string s = "foobar";
std::reverse(s.begin(), s.end());
inline void swap(char* a, char* b)
{
char tmp = *a;
*a = *b;
*b = tmp;
}
inline void reverse_string(char* pstart, char* pend)
{
while(pstart < pend)
{
swap(pstart++, pend--);
}
}
int main()
{
char pstring[] = "asfasd Lucy Beverman";
auto pstart = std::begin(pstring);
auto pend = std::end(pstring);
pend -= 2; // end points 1 past the null character, so have to go back 2
std::cout << pstring << std::endl;
reverse_string(pstart, pend);
std::cout << pstring << std::endl;
return 0;
}
you can also do it like this:
#include <iostream>
#include <cstring>
using namespace std;
string reverse(char word[20]);
int main()
{
char Cstring[20];
cout<<"enter a word: ";
cin>>Cstring;
string results = reverse(Cstring);
cout <<results;
}
string reverse(char word[20])
{
char a='a';
char b='b';
char *front=&a;
char *rear=&b;
for (int i=0;i< (strlen(word)/2);i++)
{
*front=word[i];
*rear=word[strlen(word)-1-i];
word[i]=*rear;
word[strlen(word)-1-i]=*front;
}
return word;
}
it successfully works on my system ,i.e. on emacs+gcc on windows 7
Taken from C How To Program Deitel & Deitel 8th edition:
void reverse(const char * const sPtr)
{
if (sPtr[0] == '\0')
return;
else
reverse(&sPtr[1]);
putchar(sPtr[0]);
}
I wrote this code to reverse strings. It works well, but when I enter short strings like "american beauty," it actually prints "ytuaeb nacirema2." This is my code. I would like to know what is wrong with my code that prints a random 2 at the end of the string. Thanks
// This program prompts the user to enter a string and displays it backwards.
#include <iostream>
#include <cstdlib>
using namespace std;
void printBackwards(char *strPtr); // Function prototype
int main() {
const int SIZE = 50;
char userString[SIZE];
char *strPtr;
cout << "Please enter a string (up to 49 characters)";
cin.getline(userString, SIZE);
printBackwards(userString);
}
//**************************************************************
// Definition of printBackwards. This function receives a *
// pointer to character and inverts the order of the characters*
// within it. *
//**************************************************************
void printBackwards(char *strPtr) {
const int SIZE = 50;
int length = 0;
char stringInverted[SIZE];
int count = 0;
char *strPtr1 = 0;
int stringSize;
int i = 0;
int sum = 0;
while (*strPtr != '\0') {
strPtr++; // Set the pointer at the end of the string.
sum++; // Add to sum.
}
strPtr--;
// Save the contents of strPtr on stringInverted on inverted order
while (count < sum) {
stringInverted[count] = *strPtr;
strPtr--;
count++;
}
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
cout << stringInverted << endl;
}
Thanks.
Your null termination is wrong. You're using == instead of =. You need to change:
stringInverted[count] == '\0';
into
stringInverted[count] = '\0';
// Add '\0' at the end of stringSize
stringInverted[count] == '\0';
Should use = here.
What is wrong with your code is that you do not even use strlen for counting the length of the string and you use fixed size strings (no malloc, or, gasp new[]), or the std::string (this is C++)! Even in plain C, not using strlen is always wrong because it is hand-optimized for the processor. What is worst, you have allocated the string to be returned (stringInverted) from the stack frame, which means when the function exits, the pointer is invalid and any time the code "works" is purely accidental.
To reverse a string on c++ you do this:
#include <iostream>
#include <string>
int main() {
std::string s = "asdfasdf";
std::string reversed (s.rbegin(), s.rend());
std::cout << reversed << std::endl;
}
To reverse a string in C99 you do this:
char *reverse(const char *string) {
int length = strlen(string);
char *rv = (char*)malloc(length + 1);
char *end = rv + length;
*end-- = 0;
for ( ; end >= rv; end --, string ++) {
*end = *string;
}
return rv;
}
and remember to free the returned pointer after use. All other answers so far are blatantly wrong :)
Okay, so I'm trying to reverse a C style string in C++ , and I'm coming upon some weird output. Perhaps someone can shed some light?
Here is my code:
int main(){
char str[] = "string";
int strSize = sizeof(str)/sizeof(char);
char str2[strSize];
int n = strSize-1;
int i =0;
while (&str+n >= &str){
str2[i] = *(str+n);
n--;
i++;
}
int str2size = sizeof(str)/sizeof(char);
int x;
for(x=0;x<str2size;x++){
cout << str2[x];
}
}
The basic idea here is just making a pointer point to the end of the string, and then reading it in backwards into a new array using pointer arithmetic.
In this particular case, I get an output of: " gnirts"
There is an annoying space at the beginning of any output which I'm assuming is the null character? But when I try to get rid of it by decrementing the strSize variable to exclude it, I end up with some other character on the opposite end of the string probably from another memory block.
Any ideas on how to avoid this? PS: (would you guys consider this a good idea of reversing a string?)
A valid string should be terminated by a null character. So you need to keep the null character in its original position (at the end of the string) and only reverse the non-null characters. So you would have something like this:
str2[strSize - 1] = str[strSize - 1]; // Copy the null at the end of the string
int n = strSize - 2; // Start from the penultimate character
There is an algorithm in the Standard Library to reverse a sequence. Why reinvent the wheel?
#include <algorithm>
#include <cstring>
#include <iostream>
int main()
{
char str[] = "string";
std::reverse(str, str + strlen(str)); // use the Standard Library
std::cout << str << '\n';
}
#ildjarn and #Blastfurnace have already given good ideas, but I think I'd take it a step further and use the iterators to construct the reversed string:
std::string input("string");
std::string reversed(input.rbegin(), input.rend());
std::cout << reversed;
I would let the C++ standard library do more of the work...
#include <cstddef>
#include <algorithm>
#include <iterator>
#include <iostream>
int main()
{
typedef std::reverse_iterator<char const*> riter_t;
char const str[] = "string";
std::size_t const strSize = sizeof(str);
char str2[strSize] = { };
std::copy(riter_t(str + strSize - 1), riter_t(str), str2);
std::cout << str2 << '\n';
}
while (&str+n >= &str){
This is nonsense, you want simply
while (n >= 0) {
and
str2[i] = *(str+n);
should be the much more readable
str2[i] = str[n];
Your while loop condition (&str+n >= &str) is equivalent to (n >= 0).
Your *(str+n) is equivalent to str[n] and I prefer the latter.
As HappyPixel said, your should start n at strSize-2, so the first character copied will be the last actual character of str, not the null termination character of str.
Then after you have copied all the regular characters in the loop, you need to add a null termination character at the end of the str2 using str2[strSize-1] = 0;.
Here is fixed, working code that outputs "gnirts":
#include <iostream>
using namespace std;
int main(int argc, char **argv){
char str[] = "string";
int strSize = sizeof(str)/sizeof(char);
char str2[strSize];
int n = strSize-2; // Start at last non-null character
int i = 0;
while (n >= 0){
str2[i] = str[n];
n--;
i++;
}
str2[strSize-1] = 0; // Add the null terminator.
int str2size = sizeof(str)/sizeof(char);
int x;
cout << str2;
}