Reversing a C string function crashes? - c

I'm trying to write a C function to reverse a passed in C style string (ie char *) and return the char pointer of the reversed string. But when I run this in VS2012, nothing is printed in terminal and "main.exe has stopped working" msg shows up.
#include <stdio.h>
#include <string.h>
char * rrev_str(char * str )
{
char *revd_str=""; //I tried char revd_str []="" error: stack around "revd_str" is corrupted
int i,r;
int str_len=strlen(str);
for (i = str_len-1, r=0; i >=0; i--,r++)
{
revd_str[r]= str[i];
}
return revd_str;
}
int main(int argc, char* argv[])
{
char str1 [] ="STEETS";
char str2 [] ="smile everyday!";
//reverse "chars" in a C string and return it
char * rev_string=rrev_str(str1);
}

The problem here is three fold. First you aren't allocating enough space for the reversed string, and secondly you are returning a pointer to a local variable in rrev_str(), and thirdly you're modifying a string literal. You need to allocate space for revd_str on the heap:
char * rrev_str(char * str )
{
int i,r;
int str_len=strlen(str);
char *revd_str=malloc(str_len + 1);
memset(revd_str, 0, str_len + 1);
for (i = str_len-1, r=0; i >=0; i--,r++)
{
revd_str[r]= str[i];
}
return revd_str;
}

Problem: You are accessing invalid memory address.
revd_str is pointing to literal constant string of length 1 and you are accessing it beyond the length which is invalid.
Solution:
Create char array of require length (statically or dynamically).
Reverse the given string.
Pass 2nd param as destination string
syntax: char * rrev_str(char * src, char *dest);
Reverse the given string
char * rrev_str(char * str )
{
int start = 0;
int end = strlen(str) - 1;
char temp;
for (; start < end; start++ ,end--)
{
temp = str[start];
str[start] = str[end];
str[end] = temp;
}
return str;
}
int main(int argc, char* argv[])
{
char string [] ="smile";
//reverse "chars" in a C string and return it
char * rev_string = rrev_str(string);
printf("%s",rev_string);
}
Pass 2nd param as destination string
char * rrev_str(char * src, char *dest)
{
int srcLength = strlen(src);
int destLength = strlen(dest);
int i;
// Invalid destination string
if (srcLength > destLength)
{
return NULL;
}
dest[srcLength] = '\0';
srcLength--;
for (i=0; srcLength >= 0;i++, srcLength--)
{
dest[i] = src[srcLength];
}
return dest;
}
int main(int argc, char* argv[])
{
char string [] ="smile";
char revString[20];
//reverse "chars" in a C string and return it
char * rev_string = rrev_str(string, revString);
printf("%s",rev_string);
}

What! you are doing..
char *revd_str=""; // Creating String Literal which can't be modified because they are read only
char *revd_str[]=""; // Creating Char Array of Size Zero.
So Solution are
Either take reference of your string
char *revd_str = strdup(str);
Or create dynamic char array
char *revd_str = (char*) malloc (strlen(str)+1);
your program will run fine. logic is incorrect for reversing so modify it. A sample solution is given below
char * rrev_str(char * str )
{
char *revd_str=strdup(str);
int i; // no need for extra 'int r'
int str_len=strlen(str);
for (i = 0; i < str_len/2; i++)
{
char temp = revd_str[i];
revd_str[i]= revd_str[str_len - 1 -i];
revd_str[str_len - 1 -i] = temp;
}
return revd_str;
}

Related

c-make String in Reverse with helper swap function use only pointers

I need write the following function: char * Rev(char * str, int size);
The function get *pointer to string. It should replace the order of words within str, and return the result in the pointer. Only need reverse order for the words. Must use the helper swap function. In this function, there is no use of [] anywhere, ONLY USE pointers. Printing via main only.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *str1,*str2,*pRev;
char *pstr="YPEFMI ICMKMS JGLYZJ";
swap(&str1, &str2);
getchar();
*pRev =*RevWords (pstr,SIZE)
return 0;
}
methods.c
void swap(char* str1, char* str2);
char * Rev(char * string, int size);
//The function replaces the contents of both strings 1s and 2s.
void swap(char* str1, char* str2)
{
// if both of them are zero characters then stop
if (*str1 == '\0' && *str2 == '\0')
return;
// else swap the contents of the pointers
else
{
char tmp = *str1;
*str1 = *str2;
*str2 = tmp;
// advance both pointer and swap them too if thye are not '\0'
swap(++str1, ++str2);
}
}
char * Rev(char * string, int size)
{ //no idea-->NOT work in reverse.
char string[SIZE * (SIZE + 1)]
char *str = (char *)(malloc (SIZE * SIZE + SIZE-1));
for (int i = 0; i < SIZE; i++) {
memcpy(string + i * SIZE, matrix + i, SIZE);
if (i < SIZE - 1) {
swap(*(string + i * SIZE + SIZE));
} else {
swap(*(string + i * SIZE + SIZE)) = 0;
}
}
return string;
}
The swap method work but REV method NOT work.
For example:
pStr = YPEFMI ICMKMS JGLYZJ
pRev = -->JGLYZJ ICMKMS YPEFMI <--

What does the asterisk mean in const char *src?

I have a small program in C that repeats a given string. But I cannot figure out why the function parameter needs to have an asterisk for const char *src.
Here is my code...
char *repeat_str(size_t count, const char *src) {
int length = strlen(src);
char* dest = malloc(count * length * sizeof(char));
for (int i = 0; i < count; i++) {
strcpy(dest + i * length, src);
}
return dest;
}
When I delete the asterisk as a test, I receive errors saying the asterisk is expected, but I don't understand the explanation as to why.
Take a look at the formal explanations of the pointer declarators: 6.7.6.1 declarators.
char *src is a C convention which says that src is a char pointer.
In program below it points to the string literal holding 4 characters 123_ and string terminator \0.
The length of the string is 4.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// `repeat_str` accepts variable count of type size_t and const char * pointer
char *repeat_str(size_t count, const char *src) {
size_t length = strlen(src); // get the length
char* dest = malloc(count * length * sizeof(char) + 1); // you need 1 more character for the `null` termination of the dest string
for (size_t i = 0; i < count; i++) {
strcpy(dest + i * length, src);
}
return dest; // return pointer
}
int main() {
const char *src = "123_"; // pointer declaration
char *p; // pointer declaration
p = repeat_str(3,src);
printf(" %s", p);
return 0;
}
Output:
123_123_123_

C: Take parts from a string without a delimiter (using strstr)

I have a string, for example: "Error_*_code_break_*_505_*_7.8"
I need to split the string with a loop by the delimiter "_*_" using the strstr function and input all parts into a new array, let's call it -
char *elements[4] = {"Error", "code_break", "505", "7.8"}
but strstr only gives me a pointer to a char, any help?
Note: the second string "code_break" should still contain "_", or in any other case.
This will get you half-way there. This program prints the split pieces of the string to the standard output; it does not make an array, but maybe you can add that yourself.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
void split(const char * str, const char * delimiter)
{
char * writable_str = strdup(str);
if (writable_str == NULL) { return; }
char * remaining = writable_str;
while (1)
{
char * ending = strstr(remaining, delimiter);
if (ending != NULL) { *ending = 0; }
printf("%s\n", remaining);
if (ending == NULL) { break; }
remaining = ending + strlen(delimiter);
}
free(writable_str);
}
int main(void) {
const char * str = "Error_*_code_break_*_505_*_7.8";
const char * delimiter = "_*_";
split(str, delimiter);
return 0;
}
Here is a function that splits a string into an array. You have to pass the size of the array so that the function won't overfill it. It returns the number of things it put into the array. What it puts into the array is a pointer into the string that was passed. It modifies the string by inserting null characters to end the pieces - just like strtok does.
#include<string.h>
#include<stdio.h>
int split(char *string, char *delimiter, char* array[], int size)
{
int count=0;
char *current=string;
char *next;
while(current && *current!='\0')
{
next=strstr(current,delimiter);
if(!next)break;
*next='\0';
if(count<size) array[count++]=current;
current=next+strlen(delimiter);
}
if(count<size) array[count++]=current;
return count;
}
int main()
{
char string[100]="Error_*_code_break_*_505_*_7.8";
char *array[10];
int size=split(string,"_*_",array,10);
for(int i=0;i<size;i++) puts(array[i]);
return size;
}

Null terminating char pointer

I am completely newbie in C.
I am trying to do simple C function that will split string (char array).
The following code doesn't work properly because I don't know how to terminate char array in the array. There are to char pointers passed in function. One containing original constant char array to be split and other pointer is multidimensional array that will store each split part in separate char array.
Doing the function I encountered obviously lots of hustle, mainly due to my lack of C experience.
I think what I cannot achieve in this function is terminating individual array with '\0'.
Here is the code:
void splitNameCode(char *code, char *output);
void splitNameCode(char *code, char *output){
int OS = 0; //output string number
int loop;
size_t s = 1;
for (loop = 0; code[loop]; loop++){
if (code[loop] == ':'){
output[OS] = '\0'; // I want to terminate each array in the array
OS ++;
}else {
if (!output[OS]) {
strncpy(&output[OS], &code[loop], s);
}else {
strncat(&output[OS], &code[loop], s);
}
}
}
}
int main (int argc, const char * argv[]) {
char output[3][15];
char str[] = "andy:james:john:amy";
splitNameCode(str, *output);
for (int loop = 0; loop<4; loop++) {
printf("%s\n", output[loop]);
}
return 0;
}
Here is a working program for you. Let me know if you need any explanation.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void splitNameCode(char *code, char **output) {
int i = 0;
char* token = strtok(code, ":");
while (token != NULL) {
output[i++] = token;
token = strtok(NULL, ":");
}
}
int main (int argc, const char *argv[]) {
char* output[4];
char input[] = "andy:james:john:amy";
splitNameCode(input, output);
for (int i = 0; i < 4; i++) {
printf("%s\n", output[i]);
}
return 0;
}
If I understand your intent correctly, you are trying to take a string like andy:james:john:amy and arrive at andy\0james\0john\0amy. If this is the case, then your code can be simplified significantly:
void splitNameCode(char *code, char *output){
int loop;
strncpy(code, output, strlen(code));
for (loop = 0; output[loop]; loop++){
if (output[loop] == ':'){
output[loop] = '\0'; // I want to terminate each array in the array
}
}
}

Trouble filling a dynamic c array

I am having issues with filling an array of strings that was created dynamically. The array basically contains two strings and I would like to print them both with their lengths. I am getting a very weird result whereby the memory locations are getting mixed up. Please see the code below.
Any suggestions would greatly be appreciated. Thanks.
void printWords(char **words, int numberOfWords)
{
int index;
for (index = 0; index < numberOfWords; index++)
{
printf("%s, %d\n", &(*words)[index], (int)strlen(&(*words)[index]));
}
}
void fillWords(char **words)
{
*words = malloc(2 * sizeof(char *));
char hello[] = {"Hello"};
(*words)[0] = (char)malloc(strlen(hello) * sizeof(char));
strcpy(&(*words)[0], hello); //Copy word into array
char world[] = {"Worldz"};
(*words)[1] = (char)malloc(strlen(world) * sizeof(char));
strcpy(&(*words)[1], world); //Copy word into array
}
int main (int argc, const char * argv[])
{
char *words;
fillWords(&words);
printWords(&words, 2);
return 0;
}
The expected output should be
Hello, 5
Worldz, 6
however I am getting
HWorldz, 7
Worldz, 6
I think you are getting confused between char * and char **.
Also, be sure to allocate enough memory for the null-termination character at the end of the string.
Here is my solution:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
void printWords(char **words, int numberOfWords)
{
int index;
for (index = 0; index < numberOfWords; index++)
{
printf("%s, %d\n", words[index], (int)strlen(words[index]));
}
}
char ** createWords()
{
char ** words;
// Allocate memory for an array of pointers, length 2.
words = malloc(2 * sizeof(char *));
char hello[] = {"Hello"};
words[0] = malloc((strlen(hello)+1) * sizeof(char));
strcpy(words[0], hello); //Copy word into array
char world[] = {"Worldz"};
words[1] = malloc((strlen(world)+1) * sizeof(char));
strcpy(words[1], world); //Copy word into array
return words;
}
int main (int argc, const char * argv[])
{
char **words;
words = createWords();
printWords(words, 2);
return 0;
}
I renamed fillWords to createWords and made it return a pointer instead of taking a pointer as an argument. If you really want fillWords to take a pointer as an argument, you can do it, but the argument will have to be of type char ***.
First problem: you can't put 2 words in a char * (well ... you can, but not the way you're doing; and the way to do it is nothing like your code).
You need an "array of strings", or, more C-like, an array of char *:
char *words[2]; /* words[0] and words[1] are pointers to char */
char *wrong; /* wrong[0] is a char; wrong[1] is a char */
So, change the definition of words in your main and check/edit all the other functions for correctness.
int main (int argc, const char * argv[])
{
char *words[2];
fillWords(words);
printWords(words, 2);
return 0;
}
Here is the solution. I was getting confused between char* and char. What I want was an array of chars.
void printWords(char **words, int numberOfWords)
{
int index;
for (index = 0; index < numberOfWords; index++)
{
printf("%s, %d\n", words[index], (int)strlen(words[index]));
}
}
void fillWords(char **words)
{
*words = malloc(2 * sizeof(char *));
char hello[] = {"Hello"};
words[0] = malloc(strlen(hello) * sizeof(char));
strcpy(words[0], hello); //Copy word into array
char world[] = {"Worldz"};
words[1] = malloc(strlen(world) * sizeof(char));
strcpy(words[1], world); //Copy word into array
}
int main (int argc, const char * argv[])
{
char *words;
fillWords(&words);
printWords(&words, 2);
return 0;
}

Resources