string reverse using recursion - c

can someone please tell me what is the problem in my code?
it is showing some strange output.
#include<stdio.h>
#include<string.h>
void reverse(char string[])
{
char b[200];
int t;
t = strlen(string);
if (t==1)
printf("%c",string[0]);
else
{
printf("%c",string[t-1]);
for (int i=0;i<t-1;i++)
b[i]=string[i];
reverse(b);
}
}
int main()
{
char a[200];
scanf("%s",&a);
reverse(a);
return 0;
}

If you had tried to use a debugger, you would see that t is going mad on second iteration. This is because after you have copied string into b you forgot to insert \0 symbol at the end (position with index t-1). This causes t become literally anything on the next iteration because of strlen() needs a null-terminating string and it results in an undefined behaviour as mentioned in docs:
The behavior is undefined if str is not a pointer to a null-terminated
byte string
So a quick fix is as folows:
...
for (int i=0;i<t-1;i++)
{
b[i]=string[i];
}
b[t-1] = '\0';
reverse(b);
...
And as already mentioned in comments by #LPs : change scanf("%s",&a); to scanf("%199s",a); (199 because we need to leave a space for '\0' at the end, thanks to #RoadRunner for noticing that)
Note: take a look at strncpy_s (if you use C11) and use it instead of that for loop:
printf("%c",string[t-1]);
strncpy_s(b, 200, string, t-1); // 200 because char b[200]
reverse(b);
or strncpy:
printf("%c",string[t-1]);
strncpy(b, string, t-1);
b[t-1] = '\0';
reverse(b);
Still another approach is not to copy:
else
{
string[t-1] = '\0'; // you don't need array 'b' at all
reverse(string);
}
And the simpliest way is just to use a loop:
for (int i = strlen(string) - 1; i >= 0; --i)
{
printf("%c", string[i]);
}

You mix up two approaches, i.e. recursive and loop, in one function. Further, for me it remains unclear whether you want to change the input string to a reverse order, or if you just want to print it out in reverse order.
Anyway, see a solution that provides loop bases reverse printing and recursion based reverse printing; hope it helps in understanding the steps the code such goes through:
#include <stdio.h>
#include <string.h>
void reverse_loop(char string[]) {
long i = strlen(string) - 1;
while (i >= 0)
printf("%c",string[i--]);
}
void reverse_recursive (char string[]) {
if (string[0] != '\0') {
reverse_recursive(&string[1]);
printf("%c", string[0]);
}
}
int main()
{
char a[200] = { "some test string" };
reverse_recursive(a);
return 0;
}

The easiest way to reverse a string using recursion is like this:
// C++ program to reverse a string using recursion
# include <stdio.h>
# include<string>
using namespace std;
string in="";
/* Function to print reverse of the passed string */
void reverse(char *str)
{
if (*str)
{
reverse(str+1);
in=in+*str; /* If you want to save the reversed string */
printf("%c", *str); /*If you just want to print the reversed string */
}
}
/* Driver program to test above function */
int main()
{
char a[] = "Reversing a string using recursion";
reverse(a);
printf("\n%s\n",in.c_str());
return 0;
}
/* output : noisrucer gnisu gnirts a gnisreveR */
Explanation:
Recursive function (reverse) takes string pointer (str) as input and calls itself with next location to passed pointer (str+1). Recursion continues this way, when pointer reaches ‘\0’, all functions accumulated in stack print char at passed location (str) and return one by one.
Time Complexity: O(n)

Related

c function convert "fffoootoo" to "foto" (leaves out following repeating characters)

The task would be to remove following characters that are repeating from a char array, like "deeeciddeee" -> "decide" or "phhhonne" -> "phone".
I have a function that crashes the console, and I can't spot the bug:
char* my_unique(char *first, char *last) {
char* ret=first;
for(int i=0; first+i!=last; i++){
if(first[i]==first[i+1]){
for(int j=i; first+j!=last; j++)
first[j]=first[j+1];
last--;
}
}
return ret;
}
it is called this way:
char* a="oooat";
a=my_unique(a, a+strlen(a));
cout<<a;
please help me!
Besides a small bug (you should add the line i--; after last--;, because you're deleting the character at possition i, so what has been the character at i+1 became the new character at possition i. If you don't decrease i, it will be increased and you jump over a character) the code runs perfectly fine IF it is called with
const char* b = "oooat";
char* a = new char[strlen(b) + 1];
for (size_t c = 0; c < strlen(a) + 1; c++) { a[c] = b[c]; }
a = my_unique(a, a + strlen(a));
cout << a;
delete[] a;
Notice that I've used a edit-able copy of the string, as the literal itself is of type const char* and therefor can't be changed at all. And as I said, this works perfectly fine and prints "oat", just as expected, without any crash. So your problem might be that you try to edit a const string literal? In that case you might consider to copy it, as I did, or use std::string (if you code in C++).
There are many beginner mistakes in the code.
Let me point you one by one.
char* a="oooat";
a=my_unique(a, a+strlen(a));
cout<<a;
When you declare a string like this : char* a="oooat", a is a string literal. The memory for the string is allocated into text section of the program. Which basically means you cannot modify the values inside the strings. You can only read from them. Hence when you are passing pointer a to the function and modifying it, it will result in segmentation fault(Illegal access to memory).
Why do you need a ret pointer here? char* ret=first;
You are passing a pointer and modifying the value inside it. Hence the new data will be reflected in the calling function and we need not return it explicitly. So, it is redundant.
Overall logic can be simplified as well
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MYSTR "ooooat"
void my_unique(char *first, char *last) {
int size = last - first;
int i = 0, j = 0, k = 0;
for (; i < size; i++, j++) {
first[j] = first[i];
// Continue to check how many repetitions are there
while (i + 1 < size && (first[i] == first[i+1])) i++;
}
// In the end terminate the string with a NULL.
first[j] = '\0';
return;
}
int main()
{
char a[] = MYSTR;
my_unique(a, a+strlen(a));
printf("%s", a);
return 0;
}
This is in C. There are simpler ways of doing this in C++, and the code can definitely be condensed but has been left simpler for readability.
#include <stdlib.h>
char* fix(char *input) {
char *lookahead = input;
char *newchar, *ret;
// Determine Max Return String Length
int len = 0;
while (*lookahead != '\0') {
len++;
lookahead++;
};
// allocate max possible memory needed and set the pointers
ret = malloc(len);
newchar = ret;
lookahead = input;
*newchar = *lookahead; // copy the first character
while (*lookahead != 0) {
lookahead++; // incrementing this ptr first starts lookahead at 2nd character and
// ensures the null terminator gets copied before the while loop ends
if (*newchar != *lookahead) { // only copy new characters to new return string
newchar++;
*newchar = *lookahead;
};
};
return ret;
};
I'll try to give my answer so that it makes the as little changes as possible to your original code, while using the simplest methods.
The main problem has already been identified by the previous comments - you cannot alter a string literal.
Also, the line of code
i--;
has to be placed as well, with the reason well clarified above.
While making an editable version of the string may be a good way of fixing the problem, a more straightforward way would be to make it a local string, as such :
char b[] = "oooat";
but doing this will make it incompatible with the return type of your my_unique function (char*). But why would you need a return type in the first place, if you are fixing the string itself?
My final code would look like this :
void my_unique(char *first, char *last) {
char* ret=first;
for(int i=0; first+i!=last; i++){
if(first[i]==first[i+1]){
for(int j=i; first+j!=last; j++)
first[j]=first[j+1];
last--;
i--;
}
}
}
making the function return void.
Hope this helps.

What's wrong with my code function to make strcat function in C?

#include <stdio.h>
#include <stdlib.h>
char wordsum(char FW[256],char SW[256]){
int i;
int j=strlen(FW);
for (i=0;i<=strlen(SW);i++)
FW[i+j+1]=SW[i];
printf("%c",FW);
return FW;
}
int main()
{
char F[256];
char S[256];
printf("Enter the first word\n");
gets(F);
printf("Enter the Second word\n");
gets(S);
wordsum(F,S);
return 0;
}
I don't know what is wrong with my code to make strcat function. I hope to find the answer.
I assume that the code is written to learn more about the C language. If so, may I present an alternative implementation which does not use strlen(). The intention is to present some of the really nice features in the language. It may be a bit complicated to wrap ones head around the first time, but IIRC the code can be found in K&R's book The C Programming Language.
Here we go:
char* mystrcat(char *dest, const char *src)
{
char *ret = dest;
while (*dest)
dest++;
while ((*dest++ = *src++))
;
return ret;
}
The first while-loop finds the end of the destination string. The second while-loop appends the source string to the destination string. Finally, we return a pointer to the original dest buffer.
The function could've been even nicer if it didn't return a pointer.
void mystrcat(char *dest, const char *src)
{
while (*dest)
dest++;
while ((*dest++ = *src++))
;
}
HTH
There are several mistakes in your code. They are:
1) A function can't return an array in C and you don't need to do so. Change the return type from char to void of wordsum and erase the line return FW;
2) You want to print a string, right? Format specifier for string is %s. So write printf("%s",FW); instead of printf("%c",FW);.
3) Do this: FW[i+j]=SW[i];. Why did you add an extra 1 to i+j? Just think logically.
4) Add header file for strlen(), it's <string.h>.
5) Erase those asterisk marks before and after FW[i+j]=SW[i];.
There are a few problems in your function, I've changed and commented them below:
char *wordsum(char FW[256],char SW[256]){ // correct function type
int i;
int j=strlen(FW);
for (i = 0; i <= strlen(SW); i++)
FW[i+j] = SW[i]; //change 'i + j + 1' to 'i + j'
printf("%s",FW); //change format specifier as you are printing string not character
return FW;
}
Then dot forget to capture the returned pointer using a char* variable in the calling function (here main())
char *result;
result = wordsum(F,S);
printf("\n%s\n", result);
Working example: https://ideone.com/ERlFPE

C: reverse string function not affecting pointer

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int reverse(char *, int);
main()
{
char *word = "Thanks for your help";
reverse(word, strlen(word));
printf("%s", word);
getchar();
}
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline;
}
Hey folks. I've got a simple C question that I can't seem to solve.
The program above is meant to take in a string and print it out backwards. Reverse is the function by which this is done.
The issue, specifically, is that when I print word in main(), the string appears unchanged. I've attempted to make the address of line the address of newline, but it doesn't have any effect.
int reverse(char *line, int len)
{
int i, j;
char *newline = malloc(strlen(line));
for (i = len - 1, j = 0 ; i >= 0; i--, j++)
{
newline[j] = line[i];
}
newline[j] = '\0';
line = &newline; // Your problem is here
}
You're merely assigning to the local line pointer. This has no effect on the calling function whatsoever.
Consider instead:
char *reverse(char *line, int len)
{
// ...
return newline;
}
Additional advice:
Turn on compiler warnings, and heed them. You've got lots of little things wrong (e.g. reverse isn't currently returning anything, but is declared as returning int).
Given that the first argument of reverse is a pointer to a C string (NUL-terminated), there's no need to take a length argument as well.
A reverse function doesn't necessarily need to be defined as returning a copy of the string, reversed. It could instead reverse a string in-place. Note that you cannot pass a string literal to a function like this, as they are read-only.
Here's how I would write this:
#include <stdio.h>
#include <string.h>
void reverse(char *str)
{
size_t i, j;
for (i = strlen(str) - 1, j = 0 ; i > j; i--, j++)
{
// Swap characters
char c = str[i];
str[i] = str[j];
str[j] = c;
}
}
int main(void)
{
// Mutable string allocated on the stack;
// we cannot just pass a string literal to reverse().
char str[] = "Here is a test string";
reverse(str);
printf("Result: \"%s\"\n", str);
return 0;
}
Note that the for loop condition is i > j, because we want each to only traverse half the array, and not swap each character twice.
Result:
$ ./a.exe
Result: "gnirts tset a si ereH"
Take a look at the code below:
void addOne(int a) {
int newA = a + 1;
a = newA;
}
int main() {
int num = 5;
addOne(num);
printf("%d\n", num);
}
Do you see why that will print 5, and not 6? It's because when you pass num to addOne, you actually make a copy of num. When addOne changes a to newA, it is changing the copy (called a), not the original variable, num. C has pass-by-value semantics.
Your code suffers from the same problem (and a couple other things). When you call reverse, a copy of word is made (not a copy of the string, but a copy of the character pointer, which points to the string). When you change line to point to your new string, newLine, you are not actually changing the passed-in pointer; you are changing the copy of the pointer.
So, how should you implement reverse? It depends: there are a couple options.
reverse could return a newly allocated string containing the original string, reversed. In this case, your function signature would be char *reverse, instead of int reverse.
reverse could modify the original string in place. That is, you never allocate a new string, and simply move the characters of the original string around. This works, in general, but not in your case because char pointers initialized with string literals do not necessarily point to writable memory.
reverse could actually change the passed-in pointer to point at a new string (what you are trying to do in your current code). To do this, you'd have to write a function void reverse(char **pointerToString). Then you could assign *pointerToString = newLine;. But this is not great practice. The original passed-in argument is now inaccessible, and if it was malloc'd, it can't be freed.

Adding String with Recursive function in C

I need to write a probram in C, which adds a string to a string etc. (for example '5' strings - It needs to read "vbvbvbvbvb" 5 times.) But it doesn't work? Help please!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char s[80];
int len;
int counter = 0;
char* repeat(char* s, int n) {
if (n > 0) {
if (s[len] == n) {
counter++;
}
len--;
repeat(s, (n++));
}
return s;
}
int main(void) {
printf("%s", repeat("vb", 5));
fflush(stdout);
return EXIT_SUCCESS;
}
You're trying to write into the end of "vb" which is a string in the constant pool. Don't do that. Allocate a string that is strlen(s) * n + 1 long and write into that.
Your base case is probably wrong. The base case should probably be when n == 0 which is when the empty string (nothing appended except terminating NUL as below) is appropriate.
Your recursive step (n++) should probably be (n - 1) to count down to that base case. As written, the post-increment does a useless assign and recurses with the same value of n.
I don't know what counter and len are supposed to do, but they looks redundant to me. len is uninitialized, so s[len] has undefined behavior.
After writing the n copies, you need to add a terminating NUL ('\0') at the end so that printf and similar functions can identify the end.
You are using s both as a global and a local variable, the function is working on the local.
Try not to use global variables where not necessary. Also, recursion is not necessary for this.
#include <stdio.h>
void concatenate_string(char *dest, const char *src, int n) {
char *s;
while(n--) {
s = (char*)src;
while(*(s))
*(dest++)=*(s++);
}
*(dest++) = 0;
}
int main(void) {
char out[80];
concatenate_string(out, "ab", 5);
printf("%s", out);
return 0;
}

C function to capitalize first letter of words in an array

I'm pretty new to C and am hitting a wall when creating the below function. I want to use this function to make the first letter of a word upper case for a static character array (char string[]. It looks ok to my eye, but I'm getting some syntax errors which are probably pretty basic.
compiler errors:
error: invalid conversion from const char' toconst char*'
initializing argument 1 of `size_t strlen(const char*)'
assignment of read-only location
void Cap(char string[]){
int i;
int x = strlen(string);
for (i=1;i<x;i++){
if (isalpha(string[i]) && string[i-1] == ' '){
// only first letters of a word.
string[i]= toupper(string[i]);
}if (isalpha(string[0]))
{
string[0]=toupper(string[0]);
}
}
}
you might want to run strlen(string) - as strlen(string[i]) is trying to get the length of a single char.
I will also point out your braces don't match ...
if (isalpha(string[i])){
string[i]= toupper(string[i]);
Remove brace on the if line or put a close brace after your assigning statement.
I took your code and tried to compile it. Well, it would be nice to see compilable code the next time. Here is one with comments.
#include <stdio.h> // Now I am able to use printf.
#include <string.h> // I was not able to use strlen without this...
void Cap(char string[]){
int i;
int x = strlen(string); // You want to get the length of the whole string.
for (i=1;i<x;i++){
if (isalpha(string[i]) && string[i-1] == ' '){
// only first letters of a word.
string[i]= toupper(string[i]);
}
}
}
main(){
char string[] = "text with lowercase words.";
Cap(string);
printf("%s",string);
};
Still the first word of the text is lowercase. This is a task for you.
You're missing the closing curly brace for your if statement. This might just be a typo in the question, but mentioning it just in case.
Your function is declared void. This means it returns nothing. Any return statement should have nothing after the word since the function returns nothing, and in many cases you won't have a return statement at all.
However, the biggest issue is that this isn't an array of strings. It's an array of chars, which is just one string. char* string and char string[] both (potentially) refer to an array of characters, which makes up a single string. You would need to use another level of indirection to refer to an array of array of characters: char** strings, char* strings[], or char strings[][]. The last form would require you specify how long all the strings could be, so you'd usually only use the first two.
The problem here is that you are passing in a single string, not an array of strings.
Basically in C, a string is an array of chars, hence an array of strings is a two dimensional array like so:
const char* strings[];
There are a few other issues with the code. You haven't initialized i before using it.
A alternate approach: (write a function)
1) (optional) Allocate memory for new buffer of same length for results in calling function.
2) In function - Set first char of new string to upper case version of original string
3) Walk through the string searching for spaces.
4) For each space, Set next char of new string to upper case of char in original string
5) Loop on 4) until NULL detected
6) Free any allocated memory in calling program.
Code example:
void capitalize(char *str, char *new)
{
int i=0;
new[i] = toupper(str[0]);//first char to upper case
i++;//increment after every look
while(str[i] != '\0')
{
if(isspace(str[i]))
{
new[i] = str[i];
new[i+1] = toupper(str[i+1]);//set char after space to upper case
i+=2;//look twice, increment twice
}
else
{
new[i] = str[i];//for no-space-found, just copy char to new string
i++;//increment after every look
}
}
}
This should work just fine.
#include <stdio.h>
#include <string.h>
capital(char s[])
{
int i;
for(i=0; i<strlen(s); i++)
{
if (i==0||s[i-1]==' '&&s[i]>='a'&&s[i]<='z')
s[i]=toupper(s[i]);
}
puts(s);
}
main()
{
char s[100];
printf("Enter a line: ");
gets(s);
capital(s);
}
I made an update based on Stefan Bollmann answer:
#include <string.h>
#include <stdio.h>
char* uc_words(char string[])
{
int i;
int x = strlen(string);
int counter = 0;
for (i = 0; i < x; i++)
{
// If found a white-space reset counter
if (isspace(string[i]))
counter = 0;
// Check if first character in word
if (isalpha(string[i]) && !isspace(string[i]) && counter == 0)
{
string[i]= toupper(string[i]);
counter = 1;
}
}
return string;
}
int main()
{
char string[] = "hello world";
printf("%s\n", uc_words(string));
return 0;
}

Resources