i wrote this code in two ways
trying to run in visual studio 2012 - i open the project as simple console application and i get access valuation exception.
code 1
void revReq(char* str)
{
if(*(str+1) != '\0')
revReq(str+1);
putchar(*str);
}
Code 2
void rev(char* str)
{
char* retVal = new char[strlen(str)]+1;
char* ptr = str + strlen(str)-1;
int i = 0;
while(ptr != str)
{
retVal[i++]=*ptr;
*ptr = '\0';
ptr--;
}
}
the inpus is
char* n = "abcdef";
revReq(n);
the exception
Unhandled exception at 0x00B11E7C in Ex003.exe: 0xC0000005: Access violation reading location 0xFFFFFFFF.
In the first function you compare a character in pointer str plus 1 with '\0' The condition can be equal to true only if char is equivalent to signed char and the internal code of *str is equal to 255 (-1).
void revReq(char* str)
{
if((*str+1) != '\0')
revReq(str+1);
putchar(*str);
}
The valid code will look
void revReq( const char *s)
{
if( *str )
{
revReq( str + 1 );
putchar( *str );
}
}
The second function is also wrong. At least you have to write
char* retVal = new char[strlen(str) + 1];
instead of
char* retVal = new char[strlen(str)]+1;
Also there is a memory leak. The function has to return the reversed string.
The valid code will look as
char * rev( const char *s )
{
size_t n = strlen( s );
char *p = new char[ n + 1];
const char *s1 = s + n;
char *q = p;
while ( s1 != s ) *q++ = *--s1;
*q = '\0';
return p;
}
Use strlen(str) + 1
The strlen function returns the size of the string not including the null character '\0'
Related
This question already has answers here:
Why is conversion from string constant to 'char*' valid in C but invalid in C++
(4 answers)
Deprecated conversion from string literal to 'char*' [duplicate]
(3 answers)
Closed 4 months ago.
I'm trying to invert the case manually, and I tried this:
char* invertirCase(char* str){
int size = 0;
char* iterador = str;
char* retorno = str;
while (*iterador != '\0') {
if (retorno[size] < 96) {
retorno[size] = *iterador + 32;
}
else {
retorno[size] = *iterador - 32;
}
iterador++;
size++;
}
return retorno;
}
I'm trying to figure out where's the error, but I don't get it since I'm pretty new at C++ language.
Why do I get "forbids converting a string constant to ‘char*’" in C++?
The error message means that you are trying to pass a string literal to the function.
String literals in C++ have types of constant character arrays that passed by value to functions are implicitly converted to the type const char *. And any attempt to change a string literal results in undefined behavior.
You could pass to the function a character array initialized by a string literal as for example
char s[] = "Hello";
std::cout << invertirCase( s ) << '\n';
In turn the function can be defined the following way
#include <cctype>
char * invertirCase( char *str )
{
for ( char *p = str; *p; ++p )
{
unsigned char c = *p;
if ( std::isalpha( c ) )
{
if ( std::islower( c ) )
{
*p = std::toupper( c );
}
else
{
*p = std::tolower( c );
}
}
}
return str;
}
or
char * invertirCase( char *str )
{
for ( char *p = str; *p; ++p )
{
unsigned char c = *p;
if ( std::islower( c ) )
{
*p = std::toupper( c );
}
else if ( std::isupper( c ) )
{
*p = std::tolower( c );
}
}
return str;
}
There is no "string constant" in the code you have shown, so it would have to be at the call site, ie if you were doing something like invertirCase("string"), which will not work, for 2 reasons:
since C++11 onward, C++ does not allow a string literal to be assigned to a char* pointer. This is because a string literal is a const char[] array, and you can't have a pointer-to-non-const pointing at const data. So you need to use const char* instead.
however, that will still not work, because invertirCase() modifies the data pointed at by its str parameter. You can't modify the data of a string literal.
So, you will have to make a copy of the string literal into writable memory. You can either make that copy at the call site, eg:
char str[] = "string";
invertirCase(str);
Or, you can make the copy inside of invertirCase() (but then the caller will have to free the copy when done using it), eg:
char* invertirCase(const char* str){
int size = 0;
char* retorno = new char[strlen(str)+1];
while (*str != '\0') {
retorno[size] = (*str < 96) ? (*str + 32) : (*str - 32);
str++;
size++;
}
retorno[size] = '\0';
return retorno;
}
char *str = invertirCase("string");
...
delete[] str;
Otherwise, simply don't use char* at all. Use std::string instead, eg:
std::string invertirCase(const std::string &str){
std::string retorno;
retorno.reserve(str.size());
for(char ch : str) {
retorno.push_back((ch < 96) ? (ch + 32) : (ch - 32));
}
return retorno;
}
std::string str = invertirCase("string");
...
//this is my own function, when i call it nothing shows up on the screen
char * strcat1(char * destination, const char * value)
{
while(*destination != '\0')
destination++;
while(*value != '\0')
{
*destination = *value;
destination++;
value++;
}
*destination = '\0';
return destination;
}
The problem is that the function returns pointer to the terminating zero of the string pointed to by pointer destination.
The correct function can look the following way
char * strcat1(char * destination, const char * value)
{
char *p = destination;
while ( *p != '\0' ) ++p;
while( *p++ = *value++ );
return destination;
}
You can use it the following way
char string3[30] = "this is done";
char string4[] = " using pointers";
puts( strcat1( string3, string4 ) );
puts( string3 );
I've tried so may ways on the Internet to append a character to a char* but none of them seems to work. Here is one of my incomplete solution:
char* appendCharToCharArray(char * array, char a)
{
char* ret = "";
if (array!="")
{
char * ret = new char[strlen(array) + 1 + 1]; // + 1 char + 1 for null;
strcpy(ret,array);
}
else
{
ret = new char[2];
strcpy(ret,array);
}
ret[strlen(array)] = a; // (1)
ret[strlen(array)+1] = '\0';
return ret;
}
This only works when the passed array is "" (blank inside). Otherwise it doesn't help (and got an error at (1)). Could you guys please help me with this ? Thanks so much in advanced !
Remove those char * ret declarations inside if blocks which hide outer ret. Therefor you have memory leak and on the other hand un-allocated memory for ret.
To compare a c-style string you should use strcmp(array,"") not array!="". Your final code should looks like below:
char* appendCharToCharArray(char* array, char a)
{
size_t len = strlen(array);
char* ret = new char[len+2];
strcpy(ret, array);
ret[len] = a;
ret[len+1] = '\0';
return ret;
}
Note that, you must handle the allocated memory of returned ret somewhere by delete[] it.
Why you don't use std::string? it has .append method to append a character at the end of a string:
std::string str;
str.append('x');
// or
str += x;
The function name does not reflect the semantic of the function. In fact you do not append a character. You create a new character array that contains the original array plus the given character. So if you indeed need a function that appends a character to a character array I would write it the following way
bool AppendCharToCharArray( char *array, size_t n, char c )
{
size_t sz = std::strlen( array );
if ( sz + 1 < n )
{
array[sz] = c;
array[sz + 1] = '\0';
}
return ( sz + 1 < n );
}
If you need a function that will contain a copy of the original array plus the given character then it could look the following way
char * CharArrayPlusChar( const char *array, char c )
{
size_t sz = std::strlen( array );
char *s = new char[sz + 2];
std::strcpy( s, array );
s[sz] = c;
s[sz + 1] = '\0';
return ( s );
}
The specific problem is that you're declaring a new variable instead of assigning to an existing one:
char * ret = new char[strlen(array) + 1 + 1];
^^^^^^ Remove this
and trying to compare string values by comparing pointers:
if (array!="") // Wrong - compares pointer with address of string literal
if (array[0] == 0) // Better - checks for empty string
although there's no need to make that comparison at all; the first branch will do the right thing whether or not the string is empty.
The more general problem is that you're messing around with nasty, error-prone C-style string manipulation in C++. Use std::string and it will manage all the memory allocation for you:
std::string appendCharToString(std::string const & s, char a) {
return s + a;
}
char ch = 't';
char chArray[2];
sprintf(chArray, "%c", ch);
char chOutput[10]="tes";
strcat(chOutput, chArray);
cout<<chOutput;
OUTPUT:
test
I have a code like following -
Value = "Current &HT"; //this is value
void StringSet(const char * Value)
{
const char *Chk = NULL;
Chk = strpbrk(Value,"&");
if(Chk != NULL)
{
strncpy(const_cast<char *> (Chk),"&",4)
}
}
In above code I would like to replace "&" from Value with "&.It works fine if I have "&" single character but in current case strpbrk() return "&HT"and in below strncpy whole "&HT"is replaced.
Now I would like to know methods by which I can only replace a single character from a string.
You cannot replace one character in a C style string with several because you cannot know in a C style string how much room you have available to add new characters. You can only do this by allocating a new string and copying the old string to the new. Something like this
char* StringSet(const char* value)
{
// calculate how many bytes we need
size_t bytes = strlen(value) + 1;
for (const char* p = value; *p; ++p)
if (*p == '&')
bytes += 3;
// allocate the new string
char* new_value = new char[bytes];
// copy the old to the new and replace any & with &
char* q = new_value;
for (const char* p = value; *p; ++p)
{
*q = *p;
++q;
if (*p == '&')
{
memcpy(q, "amp", 3);
q += 3;
}
}
*q = '\0';
return new_value;
}
But this is terrible code. You really should use std::string.
I think you need some temp array to hold string past & and then replace & in original string and append temp array to original. Here is the above code modified, I believe you can use strstr instead of strchr it accepts char* as second argument.
void StringSet(char * Value)
{
char *Chk = NULL,*ptr = NULL;
Chk = strchr(Value,'&');
if(Chk != NULL)
{
ptr = Chk + 1;
char* p = (char*)malloc(sizeof(char) * strlen(ptr));
strcpy(p,ptr);
Value[Chk-Value] = '\0';
strcat(Value,"&");
strcat(Value,p);
free(p);
}
}
Thanks
Niraj Rathi
You should not modify a constant string, and certainly can't modify a string literal. Although it is much much better to use a std::string instead of dealing with resource management yourself, one way is to allocate a new c-style string and return a pointer to it:
char *StringSet(const char *Value) {
char buffer[256];
for (char *p = (char*)Value, *t = buffer; p[0] != 0; p++, t++) {
t[0] = p[0];
if (p[0] == '&') {
t[1] = 'a'; t[2] = 'm'; t[3] = 'p';
t += 3;
}
t[1] = 0;
}
char *t = new char[strlen(buffer)+1];
strcpy(t, buffer);
return t;
}
string str="Current &HT";
str.replace(str.find('&'),1,"&");
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reversing a string in C
I'm currently switching from C++ to C programming for a project and I haven't done much with Char arrays as strings. I need a function that will read in a pointer to a char array and reverse it. I wrote this in C++, which is pretty easy using the string functions, but I'm a little confused on if there are functions or something else in C that is the best way to do this. Thanks, and I'm not necessarily looking for someone to completely finish the code, but to point me in the right direction. If it's simple one line something feel free, but don't do anything that makes you feel uncomfortable.
#include<stdio.h>
#include<string.h>
void reverseString(char *myString)
{
//reverse string here
}
int main(void)
{
char myString[] = "This is my string!";
reverseString(myString);
return 0;
}
Simplest way: Loop the string char by char and insert each char to another char array in the reverse order.
Or try this:
2)
void reverse_string(char str[])
{
char c;
char *p, *q;
p = str;
if (!p)
return;
q = p + 1;
if (*q == '\0')
return;
c = *p;
reverse_string(q);
while (*q != '\0') {
*p = *q;
p++;
q++;
}
*p = c;
return;
}
3)
if( strlen( str ) > 0 ) {
char* first = &str[ 0 ];
char* last = &str[ strlen( str ) - 1 ];
while( first < last ) {
char tmp = *first;
*first = *last;
*last = tmp;
++first;
--last;
4)
char* strrev( char* s )
{
char c;
char* s0 = s - 1;
char* s1 = s;
/* Find the end of the string */
while (*s1) ++s1;
/* Reverse it */
while (s1-- > ++s0)
{
c = *s0;
*s0 = *s1;
*s1 = c;
}
return s;
}