I have the following simple function:
void reverse(char* str) {
if (str == NULL)
return;
char* end = str;
while(*end != NULL) {
end++;
}
end--;
while(str < end){
char temp = *str;
*str++ = *end;
*end-- = temp;
}
}
int main(int argc, char* argv[]) {
char* second = "SOMETHING\0";
cout << "Before Reverse String: " << second << '\n';
reverse(second);
cout << "Reverse String: " << second << '\n';
}
Simple, right? however I'm getting a Segmentation Fault in lines
*str++ = *end
*end-- = temp
What am I missing?
Thanks!
You are modifying a string literal:
char* second = "SOMETHING\0";
which is undefined behavior, one solution would be to assign the literal to char array:
char second[] = "SOMETHING";
Also,string literals will be NULL terminated, so not need to add the \0. You should also modify your while loop to compare with \0 instead of NULL. Although, it should work since they both will evaluate to 0 since *end is a char it reads better to use \0:
while(*end != '\0')
Change
char* second = "SOMETHING\0";
To
char second[] = "SOMETHING";
Note: string literals are not modifiable, and you don't have to explicitly add \0 in a string literal.
while(*end != NULL) {
should be
while(*end != '\0') {
NULL is used for null pointer only.
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.
I'm doing some basic c++ and decided to implement a revStr method.
But for some reason every time I execute the method, I get a bus error caused by the assignments in the while loop but I can't understand why.
Anybody got any clues? Any help would be much appreciated.
char* reverseStr(char* s){
if(!s){
cout << "Void!"<<endl;
return s;
}
char* end, *start;
end = s;
start = s;
while(*(end) != '\0'){
end++;
}
end--;
while(start < end){
char temp = *start;
cout << temp <<endl;
*start = *end;
*end = temp;
start++;
end--;
}
cout << "The reversed string is: " << s <<endl;
return s;
}
Apologies.. I have added the driver program below:
int main(int argc, char** argv) {
assert(reverseChar("hello") == "olleh");
return 0;
}
If you're passing a string literal it should not compile as your func (correctly) takes non-const.
Unless, of course, you force cast it... so don't remove the const but strdup() it instead.
What could also be happening is that the loop runs forever. You can test it with a debugger.
The reason is that pointers cannot be properly compared for less, or greater then. Only for equality. You have to change your < to !=
Unable to reproduce problem ... code works as expected.
My Test (showing how I created "forwardCharStar[100]);")
int t282(void)
{
std::string forwardStr = "abcdefghijklmnopqrstuvwxyz";
size_t sz = forwardStr.size();
assert(sz < 100); // check fit
// ^^^-----------vvv
char forwardCharStar[100];
for (size_t i = sz-1; i < 100; ++i) forwardCharStar[i] = 0;
for (size_t i = 0; i < sz; ++i) forwardCharStar[i] = forwardStr[i];
std::string rS = reverseStr(forwardCharStar);
std::cout << "The reversed string is: " << rS << std::endl;
return (0);
}
Note: filled tail of forwardCharStar[100] with '\0'
- null terminator is important in c-style strings
Note: then transferred 26 chars from 'forwardStr' to front of forwardCharStar
Output:
The reversed string is: zyxwvutsrqponmlkjihgfedcba
Note: I commented out the char by char output from
2nd line of while loop
// std::cout << temp << std::endl;
Note: forwardCharStar[100] matches the reversed string, the code modifies its input string.
Let's say I have a file. I read all the bytes into an unsigned char buffer. From there I'm trying to read a c string (null terminated) without knowing it's length.
I tried the following:
char* Stream::ReadCString()
{
char str[0x10000];
int len = 0;
char* pos = (char*)(this->buffer[this->position]);
while(*pos != 0)
str[len++] = *pos++;
this->position += len+ 1;
return str;
}
I thought I could fill up each char in the str array as I went through, checking if the char was null terminated or not. This is not working. Any help?
this->buffer = array of bytes
this->position = position in the array
Are there any other methods to do this? I guess I could run it by the address of the actual buffer:
str[len++] = *(char*)(this->buffer[this->position++]) ?
Update:
My new function:
char* Stream::ReadCString()
{
this->AdvPosition(strlen((char*)&(this->buffer[this->position])) + 1);
return (char*)&(this->buffer[this->position]);
}
and calling it with:
printf( "String: %s\n", s.ReadCString()); //tried casting to char* as well just outputs blank string
Example File:
Check this:
#include <cstring>
#include <iostream>
class A
{
unsigned char buffer[4096];
int position;
public:
A() : position(0)
{
memset(buffer, 0, 4096);
char *pos = reinterpret_cast<char*>(&(this->buffer[50]));
strcpy(pos, "String");
pos = reinterpret_cast<char*>(&(this->buffer[100]));
strcpy(pos, "An other string");
}
const char *ReadString()
{
if (this->position != 4096)
{
while (std::isalpha(this->buffer[this->position]) == false && this->position != 4096)
this->position++;
if (this->position == 4096)
return 0;
void *tmp = &(this->buffer[this->position]);
char *str = static_cast<char *>(tmp);
this->position += strlen(str);
return (str);
}
return 0;
}
};
The reintrepret_cast are only for the init, since you are reading from a file
int main()
{
A test;
std::cout << test.ReadString() << std::endl;
std::cout << test.ReadString() << std::endl;
std::cout << test.ReadString() << std::endl;
}
http://ideone.com/LcPdFD
Edit I have changed the end of ReadString()
str is a local c string. Any referencing pointer to str outsider the function is undefined behavior: Undefined, unspecified and implementation-defined behavior, it might or might not cause notable problem.
Null termination is probably the best way to go as long as you're careful, but the reason its not working for you is most likely because you are returning memory that has been allocated on the stack. This memory is going to be freed as soon as you hit the return which will therefore cause undefined behaviour. Instead, allocate your chars on the heap:
char* str = new char[0x10000];
and free the memory when the caller doesn't need it anymore.
It can be fixed with the following method. I was advancing the position, and then returning the address.
char* Stream::ReadCString()
{
u64 str_len = strlen((char*)&(this->buffer[this->position])) + 1;
this->AdvPosition(str_len);
return (char*)&(this->buffer[this->position - str_len]);
}
Hope this helps anyone.
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;
}
`I am trying to write a program that reverses two strings, I though I had it done pretty well but when I run it, the program runs till line 26, then I get a segmentation fault error. The program compiles fine. I am wondering if there is a simple or obvious problem in my functions that I am not seeing, Any help would be appreciated!!
Thanks in advance
#include <iostream>
#include <string>
using namespace std;
// Reversing the characters in strings.
void reverse(string str);
void swap(char * first, char *last);
int main() {
// declarations and initialization
string str1;
string str2;
cout << "Please enter the first string of characters:\n";
cin >> str1;
cout << "Please enter the second string of characters:\n";
cin >> str2;
cout << "The strings before reversing are:" << endl;
cout << str1 << " " << str2 << endl;
// reverse str1
reverse(str1);
// reverse str2
reverse(str2);
// output
cout << "The strings after reversing: " << endl;
cout << str1 << " " << str2 << endl;
return 0;
}
void reverse(string str) {
int length = str.size();
char *first = NULL;
char *last = NULL;
first = &str[0];
last = &str[length - 1];
for (int i = 0; first < last; i++) {
swap(first, last);
first++;
last--;
}
}
void swap(char *first, char *last) {
char * temp;
*temp = *first;
*first = *last;
*last = *temp;
}
I don't know where line 26 is, but
char * temp;
*temp = ...
is not valid. temp should be pointed at a char, or (better yet) rewrite the function to where temp is a char.
Seth Carnegie observes that you'll have to pass the strings by reference if you want to modify the originals.
void reverse(string& str) { //pass by reference, so origional is modified
In your swap function, you are assigning a value to *temp when temp is not pointing to anything (it's uninitialized). Thus, your segmentation fault.
You want this:
void swap(char* first, char* last)
{
char temp = *first;
*first = *last;
*last = temp;
}
The other answers are valid in regards to the segfault cause.
I just think you may be interested in knowing that you can reverse a string easily using std::string's reverse_iterator:
std::string reverse(std::string str) {
std::string out;
for (std::string::reverse_iterator it = str.rbegin(); it != str.rend(); it++) {
out += *it;
}
return out;
}
So, calling:
reverse("foo");
...will return oof.
You're passing the strings by value, which means only a local copy of the string will be reversed in the reverse function. You should pass them by reference.
Also, don't alter the string's memory directly. Use operator[] like this:
for (size_t beg = 0, size_t end = str.size() - 1; beg < end; ++beg, --end)
str[beg] = str[end];
So all together:
void reverse(string& str); // prototype
....
void reverse(string& str) { // note the & which is pass by reference
int length = str.size();
for (size_t beg = 0, size_t end = str.size() - 1; beg < end; ++beg, --end)
str[beg] = str[end];
}
And as stated by Mooing Duck, the place you're probably crashing from is dereferencing a pointer which has a garbage value here:
char * temp;
*temp = ...
You're trying to assign some random memory a value, which is probably segfaulting you.
Again, others have pointed out the what the problem is and would like to show you this:
void reverse(std::string & str) {
for (int i = 0, last = str.size() - 1, lim = str.size() / 2 ; i < lim;) {
std::swap(str[i++], str[last--]);
}
}
I have not tested it thoroughly though.