EXC_BAD_ACCESS occurred when assign char with a poitner - c++

EXC_BAD_ACCESS occurred in *str++ = *end;. What's wrong with this?
#include <iostream>
using namespace std;
int main() {
char *hello = "abcdefgh";
char c = 'c';
char *str = hello;
//printf("%s",str);
char * end = str;
char tmp;
if (str) {
while (*end) {
++end;
}
--end;
while (str < end) {
tmp = *str;
printf("hello:%s str:%c, end:%c\n", hello, *str, *end);
*str++ = *end;
*end-- = tmp;
}
}
return 0;
}

It is undefined behavior to attempt to alter a string literal. Change your code to the equivalent below, and you will see the issue:
const char *hello = "abcdefgh";
const char *str = hello;
const char * end = str;
So do you see why the line *str++ = *end; had a problem? You're attempting to write to a const area, and you can't do that.
If you want an even simpler example:
int main()
{
char *str = "abc";
str[0] = 'x';
}
Don't be surprised if this simple program produces a crash or segmentation fault when the
str[0] = 'x';
line is executed.
Unfortunately, string-literals did not have to be declared as const char* in C, and C++ brought this syntax over. So even though it looks like you are not using const, you are.
If you want the code to actually work, declare a writeable buffer, i.e. an array of char:
char hello[] = "abcdefgh";
char str[100];
strcpy(str, hello);
char end[100];
strcpy(end, str);

It seems like you're trying to reverse the string. It also looks like you're overcomplicating things.
C-style strings declared on the stack have to be declared as const char *, which means you can't change the characters as they are constant.
In C++ we use strings, and string iterators:
#include <iostream>
#include <string>
using std::string;
using std::reverse;
using std::swap;
using std::cout;
using std::endl;
int main(int argc, const char * argv[])
{
string hello("abcdefgh");
reverse(hello.begin(), hello.end());
cout << hello << endl;
return 0;
}
Manually:
static void reverse(std::string & str)
{
string::size_type b = 0, e = str.length() - 1, c = e / 2;
while(b <= c)
{
swap(str[b++], str[e--]);
}
}
Recursively:
static void reverse_helper(std::string & str,
string::size_type b,
string::size_type e)
{
if(b >= e)
return;
swap(str[b], str[e]);
reverse_helper(str, ++b, --e);
}
static void reverse(std::string & str)
{
reverse_helper(str, 0, str.length() - 1);
}

Related

Program received signal SIGSEGV, Segmentation fault. C++

I'm getting this error (*s = *end; line) during debugging, while trying to reverse string using pointers.
I'm using Windows 10 OS, codeblocks IDE and GDB debugger.
#include <stdio.h>
#include <string.h>
#include <limits.h>
void myreverse(char* s);
int main()
{
char* s1 = "1234";
myreverse(s1);
printf("%s", s1);
return 0;
}
void myreverse(char* s) {
char tmp;
char* end = s + strlen(s) - 1;
for(; s < end; s++, end--) {
tmp = *s;
*s = *end;
*end = tmp;
}
}
You should change s1 to char s1[] = "1234"; since you are making changes to the string.
Then in your myreverse() function, you never use the tmp variable, which makes your swap block failing.
Fixed:
#include <cstdio> // use the C++ versions of the header files
#include <cstring>
void myreverse(char* s) {
char tmp;
char* end = s + std::strlen(s) - 1;
for(; s < end; s++, end--) {
// swap
tmp = *s;
*s = *end;
*end = tmp; // use tmp
}
}
int main() {
char s1[] = "1234";
myreverse(s1);
printf("%s", s1);
}
Note that the 3 lines in the swap block can be replaced with std::swap(*s, *end); and also that myreverse() can be completely replaced with std::reverse(std::begin(s1), std::end(s1));.

Why does my char* copier return different things?

Writing a simple string copier and testing it in the main() fucntion. What's odd is that sometimes the program returns
"HelloHello"
like it should, but maybe every third time I run it, the program prints out:
"Hello!Hello!▌▌▌▌▌▌▌▌▌▌▒"UòB╚"
Why is the tail of garbage data only sometimes being added to the end of my second string?
#include <iostream>
using namespace std;
int strlength(const char* c)
{
int size = 0;
while (*c) {
++c;
++size;
}
return size;
}
char* mystrdup(const char* c)
{
int size = strlength(c);
char* result = new char;
copy(c, c + size, result);
return result;
}
void print_array(const char* c)
{
int size = strlength(c);
while (*c) {
cout << *c;
++c;
}
}
int main()
{
char test[] = "Hello!";
char* res = mystrdup(test);
print_array(test);
print_array(res);
}
The program has undefined behavior because you are allocating not enough memory for the result string.
char* mystrdup(const char* c)
{
int size = strlength(c);
char* result = new char;
^^^^^^^^^^^^^^^^^^^^^^^
copy(c, c + size, result);
return result;
}
Moreover you are not copying the terminating zero to the result string.
At least the two functions strlength and mystrdup can look the following way
size_t strlength( const char *s )
{
size_t size = 0;
while ( s[size] ) ++size;
return size;
}
char * mystrdup( const char *s )
{
size_t size = strlength( s ) + 1;
char *result = new char[size];
copy( s, s + size, result );
return result;
}
Of course instead of the standard algorithm std::copy you could use the standard C function strcpy declared in the header <cstring>.
strcpy( result, s );
And do not forget to delete the allocated array.
char* res = mystrdup(test);
//…
delete [] res;
Pay attention to that the function print_array does not use the variable size. There is no need to output a C-string character by character.
The function could be defined like
std::ostream & print_array( const char *s, std::ostream &os = std::cout )
{
return os << s;
}
And at last the identifier c is usually used with single objects of the type char. If you deal with a string then it is better to use the identifier s.
You have multiple bugs in your code. You allocate wrong memory (char instead of char array). You don't delete the memory. Stop using C-string and use std::string
#include <iostream>
#include <string>
using std::cout;
void print_array(const char* c)
{
while (*c) {
cout << *c;
++c;
}
}
int main()
{
std::string = "Hello!";
std::string res = test;
print_array(test.c_str());
print_array(res.c_str());
}
In strcpy you need to create a char size.
char* mystrdup(const char* c)
{
int size = strlength(c);
char* result = new char[size];
copy(c, c + size, result);
return result;
}

reverse a string using pointers

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]);
}

using strstr() function is breaking

I am using strstr() function but I am getting the crash.
This part of code is crashing with error "Access violation reading location 0x0000006c."
strstr(p_czCharactersToDelete, (const char*)p_czInputString[index]))
Here is the complete code...
#include "stdafx.h"
#include <iostream>
#include <string>
void delchar(char* p_czInputString, const char* p_czCharactersToDelete)
{
for (size_t index = 0; index < strlen(p_czInputString); ++index)
{
if(NULL != strstr(p_czCharactersToDelete, (const char*)p_czInputString[index]))
{
printf_s("%c",p_czInputString[index]);
}
}
}
int main(int argc, char* argv[])
{
char c[32];
strncpy_s(c, "life of pie", 32);
delchar(c, "def");
// will output 'li o pi'
std::cout << c << std::endl;
}
The prototype of strstr() is as follows,
char * strstr ( char * str1, const char * str2 );
The function is used to locate substring from a main string. It returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
In your case you are passing the wrong parameters to the strstr(). You are calling,
strstr(p_czCharactersToDelete, (const char*)p_czInputString[index]));, which is wrong. Because the pointer p_czCharactersToDelete points to the sub string constant and p_czInputString points to the main string. Call strstr() as strstr(p_czInputString, p_czCharactersToDelete); and make corresponding changes in the function delchar().
you are using the wrong strstr.
probably you need strchr or strpbrk.
#include <cstring>
#include <algorithm>
class Include {
public:
Include(const char *list){ m_list = list; }
bool operator()(char ch) const
{
return ( strchr(m_list, ch) != NULL );
}
private:
const char *m_list;
};
void delchar(char* p_czInputString, const char* p_czCharactersToDelete){
Include inc(p_czCharactersToDelete);
char *last = std::remove_if(p_czInputString, p_czInputString + strlen(p_czInputString), inc);
*last = '\0';
}

String reverse program throws exception

// ExampleCodes.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<stdio.h>
#include<iostream>
using namespace std;
char* stringReverse(char* s)
{
char temp, *p,*q;
q = s;
while( *(++q));
for( p = s; p < --q; p++)
{
temp = *p;
*p = *q;
*q = temp;
}
return s;
}
int _tmain(int argc, _TCHAR* argv[])
{
stringReverse("StringReverse");
return 0;
}
You can't modify constant string literals.
stringReverse("StringReverse");
You could use a character array instead:
char str[] = "StringReverse";
String literals, like "StringReverse", are not allowed to be modified in C. Use an array:
char str[] = "StringReverse";
stringReverse(str);
Note that your stringReverse() function has undefined behaviour if you feed it a zero-length string.
You never allocated any memory for p. You can try p = new char[sizeof(s)];
Perhaps you should write something like this:
// in - string to reverse
// out - buffer for reversed string
// l - size of in
StringReverse(char* in, char* out, int l) {
for (int i=0;i<l;i++) {
out[l-(i+1)] = in[i];
}
}
*There is very very little to no speed difference between [] and *(p++) / *(p--)
Well I was going to clean up the awful source in the OP but instead I'll just post a cleaner version:
#include <stdio.h>
#include <string.h>
void reverse_string(char *s)
{
char *q = s + strlen(s);
for (char *p = s; p < --q; p++)
{
char temp = *p;
*p = *q;
*q = temp;
}
}
int main()
{
char s[] = "StringReverse";
reverse_string(s);
puts(s);
return 0;
}
I hope for your sake Amit that you're still a student.
Update0
This is actually pure C, so learn from and awe at its performance but don't start writing C++ like this.