I am trying to reverse a null terminated string in place in C++. I have written the code below:
//Implement a function to reverse a null terminated string
#include<iostream>
#include<cstdlib>
using namespace std;
void reverseString(char *str)
{
int length=0;
char *end = str;
while(*end != '\0')
{
length++;
end++;
}
cout<<"length : "<<length<<endl;
end--;
while(str < end)
{
char temp = *str;
*str++ = *end;
*end-- = temp;
}
}
int main(void)
{
char *str = "hello world";
reverseString(str);
cout<<"Reversed string : "<<str<<endl;
}
However, when I run this C++ program , I get a a write access violation inside the while loop at the statement : *str = *end ;
Even though this is fairly simple, I can't seem to figure out the exact reason I am getting this error.
Could you please help me identify the error?
char *str = "hello world";
is a pointer to a string literal, and can't be modified. String literals reside in read-only memory and attempting to modify them results in undefined behavior. In your case, a crash.
Since this is clearly an assignment, I won't suggest using std::string instead, since it's good to learn these things. Use:
char str[] = "hello world";
and it should work. In this case, str would be an automatic-storage (stack) variable.
Related
I am getting "Access violation" error but unable to identify the root cause for it . I am new to c++ and preparing for C++ coding contest as a beginner. Please help me to get the root cause for it. Please find the attached screenshot.
Thanks in advance .
Here is my code in a single .cpp file.
#include <iostream>
using namespace std;
void reverse(char *str) {
char * end = str;
char tmp;
if (str) {
while (*end) {
++end;
}
--end;
while (str < end) {
tmp = *str;
*str++ = *end; //Getting exception here
*end-- = tmp;
}
}
}
int main ()
{
char *str="Test";
cout << "Before change"<<str; // prints Hello World!
reverse(str);
cout << "After change"<<str; // prints I'm a C++ program
getchar();
}
You are getting a segmentation fault, because you are trying to edit the read-only memory where the literal string "Test" is stored (since string literals are const char* in c++).
In order to make your code run, you can store the literal string in a char array so the first line in main() will look like this:
char str[] = "Test";
The problem is that the type of string constants by default in C++ is const char *.
In the following line, you assign a non-const char * to a const char *.
char *str="Test";
Thus, when you pass this variable to the reverse function, you are attempting to write to read-only memory. This violates the rules of C++, and leads to unexpected behaviour.
Define your string like this instead to solve the problem:
char str[] = "Test";
This gives you the ability to modify the string, as it isn't a const anymore.
I have built my own functions of strlen and strdup.
When i use my strdup in the first time it's okay, i close the window, run it again, then in the end of the program after the return 0 from the main the program crashes. VS just says that it triggered a breakpoint.
#include "stdafx.h"
#include <iostream>
using namespace std;
int MyStrlen(const char* str);
char* MyStrdup(const char* str);
int main()
{
char *s1 = "Hello World!";
char *s2 = MyStrdup(s1);
cout << s1 << " , " << s2 << endl;
system("pause");
return 0;
}
int MyStrlen(const char* str)
{
register int iLength = 0;
while (str[iLength] != NULL)
{
iLength++;
}
return iLength;
}
char* MyStrdup(const char* str)
{
char* newStr;
int strLength = MyStrlen(str);
newStr = new char(strLength+1);
for (register int i = 0; i < strLength; i++)
{
newStr[i] = str[i];
}
newStr[strLength] = NULL;
return newStr;
}
Can someone note the place that makes it crash? I think it's a memory leak maybe.
Also, can you note things to improve in the code? For my learning purpose
EDIT: Thanks, I don't know why I used () instead of [] to define my new char[]. That was a memory leak or overwrite after all.
The "new" statement for an array should be with square brackets:
newStr = new char[strLength+1];
When you do
new char(c)
It allocates a single character and copies the character c into it.
When you do
new char[n]
it allocates memory for n characters
The expression new char(strLength+1) allocates a single character, and initializes it to strLength + 1. That of course means you will write out of bounds and have undefined behavior when you copy the string.
You should use new char[strLength + 1] instead, to allocate an "array" of characters.
On an unrelated note, while the terminating character in a string is commonly called the null character, it's not actually a null pointer (which is what NULL is for). Not that it really matters since in C++ NULL is a macro that expands to 0, but you should probably be explicit and use '\0' anyway (it gives more context for future readers).
I'm trying to concatenate two dynamic c arrays (containing strings) using pointers. I looked up a bunch of things online that use strcat, but I need to learn how to use pointers to do this. I'm not exactly clear on what a dynamic c array is anyway, I just know I have to use "new" for it. Here's my current code that won't compile:
#include <iostream>
using namespace std;
#define MAX_CHAR 50
void append(char*, char*);
int main()
{
char *str1 = new char[MAX_CHAR];
char *add1 = new char[MAX_CHAR];
str1 = "This string";
add1 = " add this one";
append(str1, add1);
cout << str1;
delete [] add1;
delete [] str1;
return 0;
}
void append(char *str, char *add)
{
while(*str != '\0')
str++;
while(*add != '\0')
{
*str = *add;
add++;
str++;
}
*str = '\0';
}
This part doesn't do what you think it does:
str1 = "This string";
add1 = " add this one";
You're attempting to assign a string literal ("This string") to a string pointer (str1). That won't work because:
you've basically thrown away the pointers that you just allocated with new one line ago and
string literals cannot be modified during run time (literals are of type const char [], so you should expect a compiler error/warning about this).
Hence, you're going to need to manually copy the string literal into your char array. You can use the standard library function strcpy for this (this requires <cstring>):
std::strcpy(str1, "This string");
std::strcpy(add1, " add this one");
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
cout<<str;
return 0;
}
The first program gives output SivaĆ> i.e siva with some garbage values....
But the second program show segmentation fault...Please help me to find out
exact answer...
#include<iostream>
using namespace std;
int main()
{
int i=0;
char *name="Siva",*str;
for(i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
cout<<str;
return 0;
}
char *name="Siva",*str;
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str is a pointer, but it doesn't yet point to anything.
Since you're in C++, you should be using std::string:
#include<iostream>
#include <string>
using namespace std;
int main()
{
char *name="Siva";
std::string str;
for(int i=0;i<strlen(name);i++)
{
str += name[i];
}
cout<<str;
return 0;
}
Even better, get rid of the hand-written loop:
#include <algorithm>
int main()
{
char *name="Siva";
std::string str;
std::copy (name, name + strlen (name), std::back_inserter (str));
cout<<str;
return 0;
}
Better even still, there's no reason in this particular example why you need to do any of that at all:
char* name = "Silva";
std::string str = name;
cout << str;
By the way, string literals in C++ are inherently const:
const char* name = "Silva";
If you really must use a char*, first I would strongly question why, and then I would tell you to do this:
int main()
{
const char *name="Siva";
char* str = new char [strlen (name)+1]; // +1 for the null terminator
strcpy (name, str);
cout << str;
delete [] str;
return 0;
}
I would even more strongly question your need to copy it byte-by-byte:
int main()
{
const char *name="Siva";
char* str = new char [strlen (name)+1]; // +1 for the null terminator
for (size_t i = 0; i < strlen (name); ++i )
str [i] = name [i];
str [strlen (name)] = '\0';
cout << str;
delete [] str;
return 0;
}
You have undefined behaviour here:
str[i]=name[i];
str has not been initialized to anything. You are writing to places you shouldn't.
There are two problems with this.
The pointer str doesn't point to allocated memory, so writing through it is undefined behavior.
Even if it did point to valid memory, you're not writing the correct amount of data. When copying a string, you need to copy the 0 byte at the end which marks the end of the string; so the upper limit of your loop should bt strlen(name) + 1. Or you could use a library method like strdup() instead of your own for loop.
The reason the "working" version prints some garbage characters is that there's no 0 at the end of the copied string to tell iostreams to stop printing. The reason the "working" one doesn't crash, and the other one does, is pure dumb luck: the garbage in str, by chance, points to memory you're allowed to write to, while in the crashing program, it points to memory you're not allowed to write to. Simple as that.
It is because you have no memory allocated for str. (it will cause an undefined behavior)
You can mix that by using a merory allocation function like in this example :
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
// Allocate memory with malloc
str = (char*)malloc( (strlen(name)+1) * sizeof(char) );
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[strlen(name)] = 0;
cout<<str;
// Free the allocated memory
free(str);
return 0;
}
As you are using c++, you can do :
#include<iostream>
using namespace std;
int main()
{
char *name="Siva",*str;
// Allocate memory with new
str = new char[strlen(name) + 1];
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[strlen(name)] = 0;
cout<<str;
// Free the allocated memory
delete []str;
return 0;
}
EDIT :
The reason you have some weird caracters at the end of your ouput is that because you string is not terminated with a '\0', it will continue to print it. (This will occur only if you don't have a segmentation fault )
There are a couple problems with your code.
Firstly, *str is not allocated, so it starts off by pointing to whatever bit of memory the pointer value happens to start off as.
Secondly, strlen() returns the length of the string excluding the terminating null character. So what you are doing is copying all the values of name into some random bit of memory, not terminating it, then telling the system to print that off, which could be any length.
str[i]=name[i]; is illegal, causes Undefined behavior, because you have not allocated memory for str.
Before for loop allocate memory for destination string str:
str = malloc (strlen(name) + 1 );
Also you forgetting string termination, after for-loop add terminate string str[i] = '\0';
Undefined behavior refers to computer code whose behavior is unpredictable.
You code should be:
char *name="Siva", *str;
str = malloc (strlen(name) + 1 ); // mistake
for(int i=0;i<strlen(name);i++)
{
str[i]=name[i];
}
str[i] = '\0'; // forgetting
To understand further you can read this answer: strcat() implementation works but causes a core dump at the end
Your problem is using char arrays and pointers to represent strings in language which has proper string type.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name = "Siva", str;
str = name;
cout << str;
return 0;
}
Problem is with str[i]=name[i] you must know that C++ does not care for memory leaks
as Java or some others. So you must allocate memory to a variable or pointer in order to avoid these problems. Already there are number of answers, you can also try
str=new char[strlen(name)+1];
and do not forget to terminate the char array with null when you done copy. In this case
str[strlen(name)]='\0';
I am writing a very simple program that removes duplicate chars from a string. I ran it visual studio and got the error:
Unhandled exception at 0x00d110d9 in inteviews.exe: 0xC0000005: Access violation writing location 0x00d27830.
I really don't see what the problem is. current cell gets the value of the next cell.
void remove(char *str, char a) {
while (*str != '\0') {
if (*(str+1) == a) {
remove(str + 1, a);
}
*str = *(str +1 );//HERE I GET THE ERROR
++str;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
char *str = "abcad";
while (*str != '\0') {
remove(str,*str);
str++;
}
std::cout << str << std::endl;
return 0;
}
EDIT:
I already tried to change it to char str[] = "abcad" but I still get the same error.
You're attempting to modify a string literal. You can't do that.
char *str = "abcad";
That's a string literal. It's created in read-only memory therefore attempting to write to it is an access violation.
One problem is that you created a read-only string literal and attempted to modify it:
char *str = "abcad"; // String literals are read-only!
You could use a char array instead:
char str[] = "abcad";
There are all sorts of problems with your program. I begun by trying to write them all down but I feel that code is irredeemable. It has indexing errors, parameter passing errors, dubious recursion and so on.
The other answers that point out the error of trying to modify a read-only literal are correct. That is the cause of the error in the code you posted.
The main reason for your troubles, in my view, is that the code is harder to write when you only have a single buffer. You have tied yourself in knots trying to get around this limitation in your design, but with a second buffer to work with, the code is trivial.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
const char *input = "abcad";
char *output = malloc(strlen(input)+1);
char *in = input;
char *out = output;
while (*in)
{
if (*in != input[0])
{
*out = *in;
out++;
}
in++;
}
*out = '\0';
printf("%s\n", output);
free(output);
return 0;
}
If you want to get really clever you can in fact manage happily with just a single buffer, so long as you keep two distinct pointers for iteration.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[] = "abcad";
char compare = str[0];
char *in = str;
char *out = str;
while (*in)
{
if (*in != compare)
{
*out = *in;
out++;
}
in++;
}
*out = '\0';
printf("%s\n", str);
return 0;
}
Note that we had to take a copy of first character in the buffer, the character being removed, since that may be modified by the iteration.
So now you are back where you started, with a single buffer. But now the code works and is easy to understand.
Note that my answer is written in C as per your tag, but note that your code is C++.
Since string literal is created in read-only memory, attempting to write to it is an access violation. What you can do is strcpy(dst, src) to a character array.
#include <stdlib.h>
int _tmain(int argc, _TCHAR* argv[])
{
char *str = "abcad";
char str2[10];
strcpy(str2, str);
while (*str2 != '\0') {
remove(str2, *str2);
str2++;
}
}