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;
}
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");
...
I am still a newbie to c++; I was wondering why the code i wrote for a custom string split fuction does not work? (it splits by char and not string) I think there is something wrong with memcpy in the second instance?
char** strsplit(const char *s, const char splitboi)
{
const int LEN = length(s);
int segs = 0;
char *segstore, **out;
for (int chrs=0; chrs<=LEN; chrs++)
{
if(*(s+chrs) != splitboi)
{char* temp = chrs==0 ? (char*)"" : segstore;
segstore = new char[chrs+1];
memcpy(&segstore, &temp, sizeof(char*));
segstore[chrs] = *(s+chrs);}
else if(*(s+chrs) == splitboi)
{char **temp = out;
out = new char* [segs+1];
memcpy(&out, &temp, sizeof(char**)); //something wrong with this
out[segs] = segstore;
segs++;}
}
delete segstore;
cout << out[0] << '\n';
return out;
}
When I run the program, I get exception "heap has been corrupted" after completion of the function
I have read that this exception may cause if you are using memory that has been freed, or when you are writing to index which is out of array index. But none of the cases applies here. I have read other answers of some problems but it didn't help much.
`char fileNametoExport[26]="d:\\FOlder1\\part1.ipt";
char WorkingFolderName[260] ="d:\\folder";
int start = rFind(fileNametoExport, '\\');
int finish = rFind(fileNametoExport, '.');
if (start == -1)
start = 0;
char partname[260];
strcpy(partname,substr(fileNametoExport, start, finish));
::AfxMessageBox((LPCTSTR)partname);
char xtfile[260];
char xmltxtfile[260];
strcpy(xtfile, strcat(WorkingFolderName, partname));
strcat(xtfile, "__Default.x_t");
strcpy(xmltxtfile, WorkingFolderName);
strcat(xmltxtfile,"_XT_SE_INV_Default_SOLID_0_Solid1_xt.xmt_txt");`
function rfind() to find occurence of char in char array-
int rFind(char* s, char c)
{
int sz = 0;
char *tmp = s;
while (*tmp != '\0')
{
sz++;
tmp++;
}
for (int i = sz - 1; i >= 0; i--)
{
if (*(s + i) == c)
return i;
}
return -1;
}
function substr() to get substring from position x to y (y exclusive)
char* substr(char* s, const int b, const int f)
{
char *str = new char[f - b];
int t = 0;
for (int i = b; i != f; i++)
{
str[t] = s[i];
t++;
}
str[t] = '\0';
return str;
}
P.S- While giving input I ensure that fileNametoExport always contains '.' and '\'.
Your program do not check lengths of input strings. You can receive a string longer than your buffer and program will fail.
If your program get fileNametoExport = "d:\\somefolder\\somefilewithoutdot" , finish will be -1 and program fail at strcpy(partname,substr(fileNametoExport, start, finish)); .
Program writes after buffer in char* substr(char* s, const int b, const int f) at line
str[t] = '\0';
because t at this point equal f-b , size of str buffer.
Function _ASSERTE( _CrtCheckMemory( ) ); from <crtdbg.h> very useful when searching for bugs like this. Put it around suspicious code and it fails after your bug. It works only in debug.
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'
// 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.