Related
I'm trying to write a function that will print out a substring of string however when printing it, only the first character in the array is printed.
As you can see in the code I've put a printf statement in the function after the substring is created and it displays properly. However when the function is passed into a printf function in the main function it only prints the first character.
Thanks for any help people are able to provide.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
char *ft_substr (const char *s, unsigned int start, size_t len)
{
char *str;
unsigned int i;
unsigned int j;
str = malloc(len * sizeof(char) + 1);
i = start;
j = 0;
while (i < len + start)
{
str[j] = s[i];
j++;
i++;
}
str[j + 1] = '\0';
printf("%s\n", str);
free(str);
return (str);
}
int main (void)
{
char hello[] = "Hello World";
char sub = *ft_substr(hello, 1, 4);
printf("%s\n", &sub);
return (0);
}
Before returning the pointer str from the function you freed all the allocated memory
free(str);
return (str);
So the returned pointer is invalid.
Remove the statement
free(str);
Another problem in the function is using an incorrect index in this statement
str[j + 1] = '\0';
Just write
str[j] = '\0';
Also this declaration is incorrect
char sub = *ft_substr(hello, 1, 4);
It declares a single character while you need to declare a pointer that will point to the dynamically allocated string in the function. So write
char *sub = ft_substr(hello, 1, 4);
and then write
printf("%s\n", sub);
free( sub );
And if you are using the type size_t for the length of a string then use indices also of the type size_t.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
char * ft_substr( const char *s, size_t start, size_t len )
{
char *str = malloc( len + 1 );
if ( str != NULL )
{
size_t i = 0;
for ( ; i < len; i++ )
{
str[i] = s[start + i];
}
str[i] = '\0';
}
return str;
}
int main(void)
{
const char *hello= "Hello World";
char *sub = ft_substr( hello, 1, 4 );
if ( sub != NULL ) puts( sub );
free( sub );
return 0;
}
Its output is
ello
The function will be more safer if it will check whether the starting index and the length are specified correctly. For example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * ft_substr( const char *s, size_t start, size_t len )
{
char *str = NULL;
size_t n = strlen( s );
if ( start < n )
{
if ( n - start < len ) len = n - start;
str = malloc( len + 1 );
if ( str )
{
memcpy( str, s + start, len );
str[len] = '\0';
}
}
return str;
}
int main(void)
{
const char *hello= "Hello World";
char *sub = ft_substr( hello, 1, 4 );
if ( sub != NULL ) puts( sub );
free( sub );
return 0;
}
You have UB in your main. Yout try to print as string a single character (passed as reference).
int main (void)
{
char hello[] = "Hello World";
char *sub = ft_substr(hello, 1, 4);
printf("%s\n", sub?sub:"");
free(sub);
return (0);
}
So, I'm trying to build a string_split function to split a c-style string based on a delimiter.
Here is the code for the function:
char** string_split(char* input, char delim)
{
char** split_strings = malloc(sizeof(char*));
char* charPtr;
size_t split_idx = 0;
int extend = 0;
for(charPtr = input; *charPtr != '\0'; ++charPtr)
{
if(*charPtr == delim || *(charPtr+1) == '\0')
{
if(*(charPtr+1) == '\0') extend = 1; //extend the range by one for the null byte at the end
char* string_element = calloc(1, sizeof(char));
for(size_t i = 0; input != charPtr+extend; ++input, ++i)
{
if(string_element[i] == '\0')
{
//allocate another char and add a null byte to the end
string_element = realloc(string_element, sizeof(char) * (sizeof(string_element)/sizeof(char) + 1));
string_element[i+1] = '\0';
}
string_element[i] = *input;
}
printf("string elem: %s\n", string_element);
split_strings[split_idx++] = string_element;
//allocate another c-string if we're not at the end of the input
split_strings = realloc(split_strings, sizeof(char*) *(sizeof(split_strings)/sizeof(char*) + 1));
//skip over the delimiter
input++;
extend = 0;
}
}
free(charPtr);
free(input);
return split_strings;
}
Essentially, the way it works is that there are two char*, input and charPtr. charPtr counts up from the start of the input string the the next instance of the delimiter, then input counts from the previous instance of the delimiter (or the start of the input string), and copies each char into a new char*. once the string is built it is added to a char** array.
There are also some twiddly bits for skipping over delimiters and dealing with the end points of the input string. the function is used as so:
int main()
{
char* str = "mon,tue,wed,thur,fri";
char delim = ',';
char** split = string_split(str, delim);
return 1;
}
Anyway, it works for the most part, except the first char* in the returned char** array is corrupted, and is just occupied by random junk.
For example printing the elements of split from main yields:
split: α↨▓
split: tue
split: wed
split: thur
split: fri
Whats odd is that the contents of split_strings[0], the array of char* which returns the desired tokens is mon, as it should be for this example, right up until the final loop of the main for-loop in the string_split function, specifically its the line:
split_strings[split_idx++] = string_element;
which turns its contents from mon to Junk. Any help is appreciated, thanks.
Your function is incorrect at least because it tries to free the passed string
char** string_split(char* input, char delim)
{
//...
free(charPtr);
free(input);
return split_strings;
}
that in the case of your program is a string literal
char* str = "mon,tue,wed,thur,fri";
char delim = ',';
char** split = string_split(str, delim);
You may not free a string literal.
And the first parameter shall have the qualifier const.
There are numerous other errors in your function.
For example the expression sizeof(string_element)/sizeof(char) used in this statement
string_element = realloc(string_element, sizeof(char) * (sizeof(string_element)/sizeof(char) + 1));
does not yield the number of characters early allocated to the array pointed to by the pointer string_element. And there is no great sense to reallocate the array for each new character.
The function can look for example the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char ** string_split( const char *s, char delim )
{
size_t n = 1;
char **a = calloc( n, sizeof( char * ) );
while ( *s )
{
const char *p = strchr( s, delim );
if ( p == NULL ) p = s + strlen( s );
if ( p != s )
{
char *t = malloc( p - s + 1 );
if ( t != NULL )
{
memcpy( t, s, p - s );
t[p-s] = '\0';
}
char **tmp = realloc( a, ( n + 1 ) * sizeof( char * ) );
if ( tmp == NULL )
{
free( t );
break;
}
a = tmp;
a[n-1] = t;
a[n] = NULL;
++n;
}
s = p + ( *p != '\0' );
}
return a;
}
int main(void)
{
char* str = "mon,tue,wed,thur,fri";
char delim = ',';
char **split = string_split( str, delim );
for ( char **p = split; *p != NULL; ++p )
{
puts( *p );
}
for ( char **p = split; *p != NULL; ++p ) free( *p );
free( split );
return 0;
}
The program output is
mon
tue
wed
thur
fri
The final function for anyone wonder, should be pretty fool proof.
char** string_split(char* input, char delim, bool skip_delim)
{
assert(*input != '\0');
char** split_strings = malloc(sizeof(char*));
char* charPtr;
size_t split_idx = 0;
size_t num_allocated_strings = 1;
size_t extend = 0;
for(charPtr = input; *charPtr != '\0'; ++charPtr)
{
if(*charPtr == delim || *(charPtr+1) == '\0')
{
if(*(charPtr+1) == '\0') extend = 1; //extend the range by one for the null byte at the end
char* string_element = calloc(1, sizeof(char));
for(size_t i = 0; input != charPtr+extend; ++input, ++i)
{
if(string_element[i] == '\0')
{
//allocate another char and add a null byte to the end
char* temp = realloc(string_element, sizeof(char) * (strlen(string_element) + 1));
if(temp == NULL)
{
free(string_element);
free(split_strings);
break;
}
string_element = temp;
string_element[i+1] = '\0';
}
string_element[i] = *input;
}
split_strings[split_idx++] = string_element;
num_allocated_strings++;
//allocate another c-string
char** temp = realloc(split_strings, sizeof(char*) * num_allocated_strings);
if(temp == NULL)
{
free(string_element);
free(split_strings);
break;
}
split_strings = temp;
//skip over the delimiter if required
if(skip_delim) input++;
extend = 0;
}
}
split_strings[num_allocated_strings-1] = NULL;
return split_strings;
}
I am new to pointers and want to learn them well. So this is my own attempt to write my strcat function. If I return just a it prints some binary things (I think it should print the solution), If I return *a it says seg fault core dumped I couldn't find the error. Any help is accepted thanks.
#include <stdio.h>
#include <string.h>
int main() {
char *strcaT();
char *a = "first";
char *b = "second";
printf("%s", strcaT(a, b));
return 0;
}
char *strcaT(char *t, char *s) {
char buffer[strlen(t) + strlen(s) - 1];
char *a = &buffer[0];
for (int i = 0; i < strlen(s) + strlen(t); i++, t++) {
if (*t == '\n') {
for (int i = 0; i < strlen(s);i++) {
buffer[strlen(t) + i] = *(s + i);
}
}
buffer[i] = *(t + i);
}
return a;
}
The code has multiple cases of undefined behavior:
you return the address of a local array in strcaT with automatic storage, which means this array can no longer be used once it goes out of scope, ie: when you return from the function.
the buffer size is too small, it should be the sum of the lengths plus 1 for the null terminator. You write beyond the end of this local array, potentially overwriting some important information such as the caller's framce pointer or the return address. This undefined behavior has a high chance of causing a segmentation fault.
you copy strlen(t)+strlen(s) bytes from the first string, accessing beyond the end of t.
It is unclear why you test for '\n' and copy the second string at the position of the newline in the first string. Strings do not end with a newline, they may contain a newline but and at a null terminator (byte value '\0' or simply 0). Strings read by fgets() may have a trailing newline just before the null terminator, but not all strings do. In your loop, the effect of copying the second string is immediately cancelled as you continue copying the bytes from the first string, even beyond its null terminator. You should perform these loops separately, first copying from t, then from s, regardless of whether either string contains newlines.
Also note that it is very bad style to declare strcaT() locally in main(), without even a proper prototype. Declare this function before the main function with its argument list.
Here is a modified version that allocates the concatenated string:
#include <stdio.h>
#include <stdlib.h>
char *strcaT(const char *s1, const char *s2);
int main() {
const char *a = "first";
const char *b = "second";
char *s = strcaT(a, b);
if (s) {
printf("%s\n", s);
free(s);
}
return 0;
}
char *strcaT(const char *t, const char *s) {
char *dest = malloc(strlen(t) + strlen(s) + 1);
if (dest) {
char *p = dest;
/* copy the first string */
while (*t) {
*p++ = *t++;
}
/* copy the second string at the end */
while (*s) {
*p++ = *s++;
}
*p = '\0'; /* set the null terminator */
}
return dest;
}
Note however that this is not what the strcat function does: it copies the second string at the end of the first string, so there must be enough space after the end of the first string in its array for the second string to fit including the null terminator. The definitions for a and b in main() would be inappropriate for these semantics, you must make a an array, large enough to accommodate both strings.
Here is a modified version with this approach:
#include <stdio.h>
char *strcaT(char *s1, const char *s2);
int main() {
char a[12] = "first";
const char *b = "second";
printf("%s\n", strcaT(a, b));
return 0;
}
char *strcaT(char *t, const char *s) {
char *p = t;
/* find the end of the first string */
while (*p) {
*p++;
}
/* copy the second string at the end */
while (*s) {
*p++ = *s++;
}
*p = '\0'; /* set the null terminator */
return t;
}
It is a very bad idea to return some local variable, it will be cleared after the function finishes its operation. The following function should work.
char* strcaT(char *t, char *s)
{
char *res = (char*) malloc(sizeof(char) * (strlen(t) + strlen(s) + 1));
int count = 0;
for (int i = 0; t[i] != '\0'; i++, count++)
res[count] = t[i];
for (int i = 0; s[i] != '\0'; i++, count++)
res[count] = s[i];
res[count] = '\0';
return res;
}
In the main function
char *strcaT();
It should be declared before main function:
char *strcaT(char *t, char *s);
int main() {...}
You returns the local array buffer[], it's is undefined behavior, because out of strcaT function, it maybe does not exist. You should use the pointer then allocate for it.
The size of your buffer should be +1 not -1 as you did in your code.
char *strcaT(char *t, char *s) {
char *a = malloc(strlen(t) + strlen(s) + 1);
if (!a) {
return NULL;
}
int i;
for(i = 0; t[i] != '\0'; i++) {
a[i] = t[i];
}
for(int j = 0; s[j] != '\0'; j++,i++) {
a[i] = s[j];
}
a[i] = '\0';
return a;
}
The complete code for test:
#include <stdio.h>
#include <stdlib.h>
char *strcaT(char *t, char *s);
int main() {
char *a = "first";
char *b = "second";
char *str = strcaT(a, b);
if (str != NULL) {
printf("%s\n", str);
free(str); // Never forget freeing the pointer to avoid the memory leak
}
return 0;
}
char *strcaT(char *t, char *s) {
char *a = malloc(strlen(t) + strlen(s) + 1);
if (!a) {
return NULL;
}
int i;
for(i = 0; t[i] != '\0'; i++) {
a[i] = t[i];
}
for(int j = 0; s[j] != '\0'; j++,i++) {
a[i] = s[j];
}
a[i] = '\0';
return a;
}
For starters the function strcaT should append the string specified by the second parameter to the end of the string specified by the first parameter. So the first parameter should point to a character array large enough to store the appended string.
Your function is incorrect because at least it returns a (invalid) pointer to a local variable length character array that will not be alive after exiting the function and moreover the array has a less size than it is required to store two strings that is instead of
char buffer[strlen(t) + strlen(s) - 1];
^^^
it should be declared at least like
char buffer[strlen(t) + strlen(s) + 1];
^^^
and could be declared as static
static char buffer[strlen(t) + strlen(s) + 1];
Also the nested loops do not make sense.
Pay attention that you should provide the function prototype before calling the function. In this case the compiler will be able to check passed arguments to the function. And the name of the function strcaT is confusing. At least the function can be named like strCat.
The function can be defined the following way
#include <stdio.h>
#include <string.h>
char * strCat( char *s1, const char *s2 )
{
char *p = s1 + strlen( s1 );
while ( ( *p++ = *s2++ ) );
return s1;
}
int main(void)
{
enum { N = 14 };
char s1[N] = "first";
char *s2 = "second";
puts( strCat( s1, s2 ) );
return 0;
}
The program output is
firstsecond
On the other hand if you are already using the standard C function strlen then why not to use another standard C function strcpy?
With this function your function could be defined more simpler like
char * strCat( char *s1, const char *s2 )
{
strcpy( s1 + strlen( s1 ), s2 );
return s1;
}
If you want to build a new character array that contains two strings one appended to another then the function can look for example the following way.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * strCat( const char *s1, const char *s2 )
{
size_t n1 = strlen( s1 );
char *result = malloc( n1 + strlen( s2 ) + 1 );
if ( result != NULL )
{
strcpy( result, s1 );
strcpy( result + n1, s2 );
}
return result;
}
int main(void)
{
char *s1 = "first";
char *s2 = "second";
char *result = strCat( s1, s2 );
if ( result ) puts( result );
free( result );
return 0;
}
Again the program output is
firstsecond
Of course calls of the standard C function strcpy you can substitute for your own loops but this does not make great sense.
If you are not allowed to use standard C string functions then the function above can be implemented the following way.
#include <stdio.h>
#include <stdlib.h>
char * strCat( const char *s1, const char *s2 )
{
size_t n = 0;
while ( s1[n] != '\0' ) ++n;
for ( size_t i = 0; s2[i] != '\0'; )
{
n += ++i;
}
char *result = malloc( n + 1 );
if ( result != NULL )
{
char *p = result;
while ( ( *p = *s1++ ) != '\0' ) ++p;
while ( ( *p = *s2++ ) != '\0' ) ++p;
}
return result;
}
int main(void)
{
char *s1 = "first";
char *s2 = "second";
char *result = strCat( s1, s2 );
if ( result ) puts( result );
free( result );
return 0;
}
I have changed your program to look like below:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char* strcaT();
char* a = "first";
char* b = "second";
printf("%s",strcaT(a,b));
return 0;
}
char* strcaT(char *t, char *s)
{
char* a = (char*)malloc(sizeof(char)*(strlen(t) + strlen(s) + 1));
for(int i=0; i<strlen(t); i++) {
a[i] = t[i];
}
for(int i=0; i<strlen(s); i++) {
a[strlen(t) + i] = s[i];
}
a[strlen(t)+strlen(s)] = '\0';
return a;
}
You are getting segfault because you are returning address of a local array which is on stack and will be inaccessible after you return. Second is that your logic is complicated to concatenate the strings.
Hello and sorry if this questions is already answered (in the way I want to :-) ) but I think I have a memory problem.
Assuming the following C function (yes, this one is very dirty and not optimized):
char *strreplace(char **str, char *dst, char *replace) {
int replacestart = stringcompare(*str, dst), replaceend = strlen(dst), replacelen = strlen(replace);
char *tmp1 = (char *)malloc(sizeof(char) * (replacestart + 1)), *tmp2 = (char *)malloc(sizeof(char) * ((strlen(*str) - replaceend) + 1));
memset(tmp1, 0, sizeof(char) * (replacestart + 1));
memset(tmp2, 0, sizeof(char) * ((strlen(*str) - replaceend) + 1));
strncpy(tmp1, *str, replacestart);
strncpy(tmp2, *str + replacestart + replaceend, (strlen(*str) - (replaceend + replacestart)));
*str = realloc(*str, strlen(tmp1) + replacelen + strlen(tmp2));
memset(*str, 0, strlen(tmp1) + replacelen + strlen(tmp2));
strncpy(*str, tmp1, strlen(tmp1));
strncpy(*str + strlen(tmp1), replace, replacelen);
strncpy(*str + strlen(tmp1) + replacelen, tmp2, strlen(tmp2));
return *str;
}
As seen, it should replace *dst with *replace whithin **str.
This works basically as expected. Here's the problem:
The output (*str) is not cleard out with zeros after memsetting it and has still the wrong length, even after reallocating.
Means, if the string is longer after replacing, the last chars are cutted of *str.
In turn, if the string is shorter, old chars are at the end of the char string are found.
What did I wrong. Mentioned that I don't want to use sprintf and no C++-STL, just want to do this with pointers in C.
Other words, what would be the right way to replace a string in an c char string with pointers.
Thanks alot.
EDIT after reqeuest for more information
I use this function as following:
...open a textfile via FILE type, determining file lengts (fseek)...
char *filecontent = (char *)malloc(sizeof(char) * filesize);
if(filesize != fread(filecontent, sizeof(char), filesize, fd)) {
free(filecontent);
return -1;
}
streplace(&filecontent, "[#TOBEREPLACED#]", "replaced");
...doing other stuff with filecontent...
EDIT 2, adding stringcompare()
int stringcompare(const char *string, const char *substr) {
int i, j, firstOcc;
i = 0, j = 0;
while(string[i] != '\0') {
while(string[i] != substr[0] && string[i] != '\0') {
i++;
}
if(string[i] == '\0') {
return -1;
}
firstOcc = i;
while(string[i] == substr[j] && string[i] != '\0' && substr[j] != '\0') {
i++;
j++;
}
if(substr[j] == '\0') {
return firstOcc;
}
if(string[i] == '\0') {
return -1;
}
i = firstOcc + 1;
j = 0;
}
}
The logic of the function is not simple as it seems at the first glance.
You should decide what action to execute 1) if the source string is empty and 2) if the destination string is empty.
For example if the destination string is empty then the standard function strstr will return the address of the first character of the source string. However logically if dst is an empty string then the source string should not be changed except the case when it is in turn an empty string. In this case the function should just create a new string equal to the string replace.
Take into account that as the strings dst and replace are not changed within the function they should be declared with the qualifier const.
char * strreplace( char **str, const char *dst, const char *replace );
Also the function should report whether a new memory allocation was successful within the function by returning a null pointer in case when the allocation failed.
Taking all this into account the function can look the following way as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * strreplace( char **str, const char *dst, const char *replace )
{
char *result = *str;
if ( *str[0] == '\0' )
{
if ( dst[0] == '\0' && replace[0] != '\0' )
{
char *result = malloc( strlen( replace ) + 1 );
if ( result )
{
strcpy( result, replace );
free( *str );
*str = result;
}
}
}
else if ( dst[0] != '\0' )
{
char *pos = strstr( *str, dst );
if ( pos != NULL )
{
size_t dst_n = strlen( dst );
size_t replace_n = strlen( replace );
result = ( char * )malloc( strlen( *str ) - dst_n + replace_n + 1 );
if ( result )
{
size_t n = pos - *str;
strncpy( result, *str, n );
strcpy( result + n, replace );
strcpy( result + n + replace_n, *str + n + dst_n );
}
free( *str );
*str = result;
}
}
return result;
}
int main(void)
{
const char *hello = "Hello everybody here";
char *str = malloc( sizeof( char ) );
str[0] = '\0';
if ( strreplace( &str, "", hello ) )
{
puts( str );
}
if ( strreplace( &str, "everybody", "Eurobertics" ) )
{
puts( str );
}
if ( strreplace( &str, "Hello", "Bye" ) )
{
puts( str );
}
if ( strreplace( &str, " here", "" ) )
{
puts( str );
}
if ( strreplace( &str, "Bye ", "" ) )
{
puts( str );
}
free( str );
return 0;
}
The program output is
Hello everybody here
Hello Eurobertics here
Bye Eurobertics here
Bye Eurobertics
Eurobertics
Your function looks overly complex. Here is a simple, working version:
char *strreplace(char **str, char *dst, char *replace) char *strreplace(char **str, char *dst, char *replace)
{
char *start, *tmp;
int n;
if ((start=strstr(*str,dst))==0) return(0);
n= (start-*str) + strlen(start+strlen(dst)) + strlen(replace) + 1;
tmp=malloc(n);
strncpy(tmp,*str,start-*str);
strcpy(tmp+(start-*str),replace);
strcat(tmp,start+strlen(dst));
free(*str);
*str= tmp;
return(tmp);
}
With test function:
void reptest(void)
{
char *src;
char rep[]= "brave new world";
src=malloc(strlen("Hello world of wonders")+1);
strcpy(src,"Hello world of wonders");
strreplace(&src,"world",rep);
printf("%s\n", src);
free(src);
}
Edit: my previous version forgot to copy the remainder. Fixed.
This is my task:
Realize function that reverses null terminated string. The prototype of the function is void Reverse(char *ptr);. Do not use standard library functions.
This is my code for now:
void Reverse(char *ptr) {
char *newString;
char ch = *ptr;
unsigned int size = 0;
for (int i = 1; ch != '\0'; i++) {
ch = *(ptr + i);
size++;
}
newString = (char*)malloc(size);
for (int left = 0, right = size - 1; left < size; left++, right--) {
*(newString + left) = *(ptr + right);
}
printf("%s", newString);
printf("\n");
}
It reverses the string and saves it in the newString
My first problem is that when I print the newString to see if the functions works the string is reversed, but after it there are some symbols.
For example:
If I have char *str = "hello"; and Reverse(str); in the main method
the result of printf("%s", newString) will be olleh****.
But if change the
newString = (char*)malloc(size); to
newString = (char*)malloc(1); it works fine.
My second problem is that I don't know how to save the newString into the given one. I am using a new String because the given one can't be changed.
For starters it is better to declare the function like
char * Reverse( char *ptr );
^^^^^^
because standard C string functions usually return pointers to destination strings.
The function should reverse the original string. It may not create a dynamic string because the caller of the function will be unable to free it provided that the function has return type void.
The function can look as it is shown in the following demonstrative program.
#include <stdio.h>
char * Reverse( char *ptr )
{
char *first = ptr, *last = ptr;
while ( *last ) ++last;
if ( first < last )
{
for ( ; first < --last; ++first )
{
char c = *first;
*first = *last;
*last = c;
}
}
return ptr;
}
int main( void )
{
char s[] = "Hello World!";
puts( s );
puts( Reverse( s ) );
return 0;
}
Its output is
Hello World!
!dlroW olleH
Take into account that you may not call the function like
puts( Reverse( "Hello World!" ) );
because string literals are immutable in C.
If you are going to declare the function like
void Reverse( char *ptr );
then just remove the return statement in the shown function. For example
#include <stdio.h>
void Reverse( char *ptr )
{
char *first = ptr, *last = ptr;
while ( *last ) ++last;
if ( first < last )
{
for ( ; first < --last; ++first )
{
char c = *first;
*first = *last;
*last = c;
}
}
}
int main( void )
{
char s[] = "Hello World!";
puts( s );
Reverse( s )
puts( s );
return 0;
}
If to use your approach with indices then the function can look like
#include <stdio.h>
void Reverse( char *ptr )
{
size_t size = 0;
while ( *( ptr + size ) ) ++size;
if ( size != 0 )
{
for ( size_t left = 0, right = size - 1; left < right; left++, right-- )
{
char c = ptr[left]; // or char c = *( ptr + left ); and so on
ptr[left] = ptr[right];
ptr[right] = c;
}
}
}
int main( void )
{
char s[] = "Hello World!";
puts( s );
Reverse( s );
puts( s );
return 0;
}
In your loop to get the size, you're not counting the null terminator. So your newString is missing the null terminator as well. make sure to do newString = malloc(size + 1);, and to place the null terminator onto the end of newString.
You have several problems in your code:
you do not allocate enough space for the resulting string, you must allocate size+1 bytes and set the \0 terminator at the end of the string.
you only copy half the characters from ptr to newString.
you are not even supposed to allocate memory, since you cannot call any library functions. You should instead reverse the string in place.
Your test fails because modifying a string literal invokes undefined behavior. You should pass an initialized array as shown below.
Here is an improved version:
#include <stdio.h>
void Reverse(char *ptr) {
unsigned int left, right;
for (right = 0; *(ptr + right) != '\0'; right++) {
continue;
}
for (left = 0; left < right; left++, right--) {
char ch = ptr[left];
ptr[left] = ptr[right - 1];
ptr[right - 1] = ch;
}
}
int main(void) {
char buf[] = "Hello world";
Reverse(buf);
printf("%s\n", buf);
return 0;
}
It should print dlrow olleH.
Simple string reverse function without string.h library functions :
#include <stdio.h>
void reverse(char *str, int n);
int main()
{
char str[100];
int n;
printf("Enter a string\n");
scanf("%s",&str);
for( n = 0; str[n] != '\0'; n++)
{
}
reverse(str,n);
puts(str);
return 0;
}
void reverse(char *str,int n)
{
printf("Length = %d\n",n);
printf("Reversed :\n");
int i;
char ch;
for(i = 0; i<n/2; i++)
{
ch = str[i];
str[i] = str[n-i-1];
str[n-i-1] = ch;
}
}