#include <stdio.h>
#define MAX 100
char *reverse(char[]);
int main()
{
char str[MAX], *rev;
enter code here //printf("Enter a String: ");
scanf("%s", str);
rev = reverse(str);
printf("The reversed string is : %s\n", rev);
return 0;
}
char* reverse(char str[])
{
static int i= 0;
static char rev[MAX];
if (*str)
{
reverse(str+1);
rev[i++]= *str;
}
return rev;
}
how is the execution taking place in the function reverse......pls explain each step of the execution with example
thank you
The main point of the function reverse is recursion.
Recursive function as you know, are functions that call themselves from within their own code. Generally, each call got a smaller "problem" than the previous one.
Let's look at the function. We have two static variables that are static so as dxiv said in the comment, they will "keep" their value once they are initialized the first time. But in certain cases, "static" variables are also a problem to deal with.
Now we have an if that check whether we have still some character inside the string or not. That means that if we reach the end of the string, the piece of the code inside the if will not be executed.
Let's look at this example:
I added a printf to check the string content each time and as you see, the function goes to the last element of the string (if we think of it as an array) and once it reaches the end, it starts to do the next instruction.
So the function will call itself, increasing str time by time:
reverse(str + 1);
Once we reach the end of str, the program passes with the following instruction:
assign a char to the reverse array that in this case will start from zero since the counter variable i is still at 0.
The returning value is considered just at the end and not during the recursion "phase".
At this point the game is done, recursion function calls that are on the stack are going to be removed one by one, and each of them now can add the letter at the reverse array. Doing this i will increase and we are considering each time the letter before in the string.
In this way, in the end, we will have the reversed string.
Some tips:
Use fgets(..., ..., ...) instead of scanf so that you can take also sentences instead of just a word let's say. But there are still some other advantages, that I let you discover.
Generally, that returning value should be used also in the recursion process
Personally, I prefer to don't have static variables in a recursive function (unless I really need it). I prefer to have (if it is possible) the variables that I need as parameters.
I'm going to attach the code with fgets(...) right here below:
#include <stdio.h>
#include <string.h>
#define MAX 100
char *reverse(char[]);
int main() {
char str[MAX], *rev;
printf("Enter a String: ");
fgets(str, sizeof(str), stdin);
str[strcspn(str, "\n")] = '\0';
rev = reverse(str);
printf("The reversed string is: %s\n", rev);
return 0;
}
char *reverse(char str[]) {
static int i = 0;
static char rev[MAX];
if (*str) {
reverse(str + 1);
rev[i++] = *str;
printf("\n%s", str);
}
return rev;
}
I really hope that this can help you :D
Best regards,
Denny
Related
i'm trying to get a 2 strings from the user and the second one will be the "needle" to copy to the first string
for example:
string 1 (user input): eight height freight
string 2 (user input): eight
output: EIGHT hEIGHT frEIGHT
for example i want to print: toDAY is a good DAY
having trouble copying multiple needles in stack
i have tried using while (*str) {rest of the function with str++}
i would love some explanation
#define _CRT_SECURE_NO_WARNINGS
#define N 101
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
void replaceSubstring(char* str, char* substr);
void main() {
int flag = 1;
char str[N], substr[N];
//char* str_ptr = &str, * substr_ptr = &substr; //creating pointer for the sake of while
while (flag) {
printf("\nEnter main text: ");
gets_s(str,N);
if (!str)
flag = 0;
printf("\nEnter sub-text: ");
gets_s(substr,N);
if (!str)
flag = 0;
replaceSubstring(str, substr);
printf("%s",str);
}
printf("\nExited. (press any key to exit)");
}
void replaceSubstring(char* str, char* substr) {
int lensbstr;
str = strstr(str, substr);
_strupr(substr); //cnvrt to UPPERCASE
lensbstr = strlen(substr); //length of the mutual string
if (str)
strncpy(str, substr, lensbstr);
}
This looks like a programming exercise, so I’m not going to just give you the answer. However, I’ll give you a few hints.
Two big problems:
You don’t have a loop that would replace the second and later instances.
You are upper-casing the substring... not a copy of the substring. A second pass through replaceSubstring would only match the upper-case version of the substring.
A couple of small problems / style comments:
str is an array, so its value is always non-zero, so “if(!str)” is never true.
strncpy is almost never the right answer. It will work here, but you shouldn’t get in the habit of using it. Its behavior is subtle and is rarely what you want. Here it would be faster and more obvious to use memcpy.
You are upper-casing the substring and measuring its length even if you didn’t find it and so won’t need those results.
Although using int for flags works and is the traditional way, newer versions of the language have stdbool.h, the “bool” type, and the “true” and “false” constants. Using those is almost always better.
You appear to intend to stop when the user enters an empty string for the first string. So why do you ask for the second string in that case? It seems like you want an infinite loop and a “break” in the middle.
I am currently learning C, and so I wanted to make a program that asks the user to input a string and to output the number of characters that were entered, the code compiles fine, when I enter just 1 character it does fine, but when I enter 2 or more characters, no matter what number of character I enter, it will always say there is just one character and crashes after that. This is my code and I can't figure out what is wrong.
int main(void)
{
int siz;
char i[] = "";
printf("Enter a string.\n");
scanf("%s", i);
siz = sizeof(i)/sizeof(char);
printf("%d", siz);
getch();
return 0;
}
I am currently learning to program, so if there is a way to do it using the same scanf() function I will appreciate that since I haven't learned how to use any other function and probably won't understand how it works.
Please, FORGET that scanf exists. The problem you are running into, whilst caused mostly by your understandable inexperience, will continue to BITE you even when you have experience - until you stop.
Here is why:
scanf will read the input, and put the result in the char buffer you provided. However, it will make no check to make sure there is enough space. If it needs more space than you provided, it will overwrite other memory locations - often with disastrous consequences.
A safer method uses fgets - this is a function that does broadly the same thing as scanf, but it will only read in as many characters as you created space for (or: as you say you created space for).
Other observation: sizeof can only evaluate the size known at compile time : the number of bytes taken by a primitive type (int, double, etc) or size of a fixed array (like int i[100];). It cannot be used to determine the size during the program (if the "size" is a thing that changes).
Your program would look like this:
#include <stdio.h>
#include <string.h>
#define BUFLEN 100 // your buffer length
int main(void) // <<< for correctness, include 'void'
{
int siz;
char i[BUFLEN]; // <<< now you have space for a 99 character string plus the '\0'
printf("Enter a string.\n");
fgets(i, BUFLEN, stdin); // read the input, copy the first BUFLEN characters to i
siz = sizeof(i)/sizeof(char); // it turns out that this will give you the answer BUFLEN
// probably not what you wanted. 'sizeof' gives size of array in
// this case, not size of string
// also not
siz = strlen(i) - 1; // strlen is a function that is declared in string.h
// it produces the string length
// subtract 1 if you don't want to count \n
printf("The string length is %d\n", siz); // don't just print the number, say what it is
// and end with a newline: \n
printf("hit <return> to exit program\n"); // tell user what to do next!
getc(stdin);
return 0;
}
I hope this helps.
update you asked the reasonable follow-up question: "how do I know the string was too long".
See this code snippet for inspiration:
#include <stdio.h>
#include <string.h>
#define N 50
int main(void) {
char a[N];
char *b;
printf("enter a string:\n");
b = fgets(a, N, stdin);
if(b == NULL) {
printf("an error occurred reading input!\n"); // can't think how this would happen...
return 0;
}
if (strlen(a) == N-1 && a[N-2] != '\n') { // used all space, didn't get to end of line
printf("string is too long!\n");
}
else {
printf("The string is %s which is %d characters long\n", a, strlen(a)-1); // all went according to plan
}
}
Remember that when you have space for N characters, the last character (at location N-1) must be a '\0' and since fgets includes the '\n' the largest string you can input is really N-2 characters long.
This line:
char i[] = "";
is equivalent to:
char i[1] = {'\0'};
The array i has only one element, the program crashes because of buffer overflow.
I suggest you using fgets() to replace scanf() like this:
#include <stdio.h>
#define MAX_LEN 1024
int main(void)
{
char line[MAX_LEN];
if (fgets(line, sizeof(line), stdin) != NULL)
printf("%zu\n", strlen(line) - 1);
return 0;
}
The length is decremented by 1 because fgets() would store the new line character at the end.
The problem is here:
char i[] = "";
You are essentially creating a char array with a size of 1 due to setting it equal to "";
Instead, use a buffer with a larger size:
char i[128]; /* You can also malloc space if you desire. */
scanf("%s", i);
See the link below to a similar question if you want to include spaces in your input string. There is also some good input there regarding scanf alternatives.
How do you allow spaces to be entered using scanf?
That's because char i[] = ""; is actually an one element array.
Strings in C are stored as the text which ends with \0 (char of value 0). You should use bigger buffer as others said, for example:
char i[100];
scanf("%s", i);
Then, when calculating length of this string you need to search for the \0 char.
int length = 0;
while (i[length] != '\0')
{
length++;
}
After running this code length contains length of the specified input.
You need to allocate space where it will put the input data. In your program, you can allocate space like:
char i[] = " ";
Which will be ok. But, using malloc is better. Check out the man pages.
reverser() reverses a cstring (not in place). 99% of the time it works but some input corrupts it for example it appears if aStr2[] is assigned a string made up of the same character it will have an error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* reverser(const char *str);
int main()
{
char aStr[] = "aaa";
char aStr2[] = "cccccc";
printf("%s %s", aStr, aStr2);
char* tmp = reverser(aStr2);//tmp now has garbage
printf("\n%s", tmp);
printf(" %s", aStr2);
return 0;
}
char* reverser(const char *str)
{
char* revStr = (char*)malloc(strlen(str));
int i;
for(i = strlen(str)-1; i >= 0; i--)
{
revStr[strlen(str)-1-i] = str[i];
}
return revStr;
}
Gives
aaa cccccc
cccccc9 cccccc
Process returned 0 (0x0) execution time : 0.068 s
Press any key to continue
Notice the 9 that shouldn't be there.
Change this malloc to strlen(str) + 1 , plus 1 for '\0'
char* revStr = (char*)malloc(strlen(str) + 1);
and after the for loop
revStr[strlen(str)+1] = '\0';
Your problem is that you don't put the string terminator in your reversed string. All strings in C are actually one extra character that isn't reported by strlen, and that is the character '\0' (or plain and simple, a zero). This tells all C functions when the string ends.
Therefore you need to allocate space for this extra terminator character in your malloc call, and add it after the last character in the string.
There are also a couple of other problems with your code, the first is that you should not cast the return of malloc (or any other function returning void *). Another that you have a memory leak in that you do not free the memory you allocate. This last point doesn't matter in a small program like the one you have here, but will be an issue in larger and longer running programs.
You haven't null-terminated your reversed string. You need to set the final index of revStr[] to 0.
I got this code from the internet but I couldnt get the whole code.
for example if(*str) . What does this code mean? and also can a string be returned? I thought that an array in main can be changed
directly in a function but here its been returned..
#include<stdio.h>
#define MAX 100
char* getReverse(char[]);
int main(){
char str[MAX],*rev;
printf("Enter any string: ");
scanf("%s",str);
rev = getReverse(str);
printf("Reversed string is: %s\n\n",rev);
return 0;
}
char* getReverse(char str[]){
static int i=0;
static char rev[MAX];
if(*str){
getReverse(str+1);
rev[i++] = *str;
}
return rev;
}
This is not the clearest example of recursion due to the use of the static variables. Hopefully the code generally seems clear to you, I suspect the part that is confusing to you is the same that was confusing to me at first.
if(*str){
getReverse(str+1);
rev[i++] = *str;
}
So line by line.
if(*str){
If we have not reached the null terminator.
getReverse(str+1);
Call the getReverse function on the next character of the string. It seems pretty straight forward up to here. But it also seems like it may not actually reverse anything because this is the next line
rev[i++] = *str;
We assign index i the character at the beginning of str and increment i but here is the tricky part. i may not be what you think. getReverse gets called before i is incremented. And i is static, so changes will persist between function calls. So, lets say we have a 5 letter word, let say "horse" we will end up with 6 calls on the stack to getReverse. The 6th will not do anything because that is where it finds the null terminator. The trick is that we will then go about resolving the calls in reverse order. First the call where str is pointing to 'e' will resolve and increment i because all the other ones are are still waiting for their calls to getReverse to return. So the last letters are actually the first ones to get added and increment i which is what can be confusing here.
Using just C
I would like to parse a string and:
count the occurrences of a character in a string (for example, count all the 'e's in a passed in string)
Once counted (or even as I am counting) replace the e's with 3's
OK, you're either lazy, or stuck, assuming stuck.
You need a function with a signature something like
int ReplaceCharInString(char* string, char charToFind, char charThatReplaces)
{
}
Inside the function you need
To declare an integer to count the
occurrences
A loop that moves from the start of
the string to it's end
inside the loop, an if statement to
check is the current char the
charToFind,
statements to increment the count of
occurrences and perform the
replacement
After the loop, you need to return
the count of occurrences
This function will take a string, replace every 'e' with '3', and return the number of times it performed the substitution. It's safe, it's clean, it's fast.
int e_to_three(char *s)
{
char *p;
int count = 0;
for (p = s; *p; ++p) {
if (*p == 'e') {
*p = '3';
count++;
}
}
return count;
}
Here's a shell to get you started. Ask here if you need any help.
#include <string.h>
#include <stdio.h>
int main(){
const char* string = "hello world";
char buffer[256];
int e_count = 0;
char* walker;
// Copy the string into a workable buffer
strcpy(buffer,string);
// Do the operations
for(walker=buffer;*walker;++walker){
// Use *walker to read and write the current character
}
// Print it out
printf("String was %s\nNew string is %s\nThere were %d e's\n",string,buffer,e_count);
}
In general, it's better use a standard library function rather than rolling your own. And, as it just so happens, there is a standard library function that searches a string for a character and returns a pointer to it. (It deals with a string, so look among the functions that have the prefix "str") (The library function will almost certainly be optimized to use specialized CPU opcodes for the task, that hand written code would not)
Set a temp pointer (say "ptr") to the start of the string.
In a loop, call the function above using ptr as the parameter, and setting it to the return value.
Increment a counter.
Set the character at the pointer to "3" break when 'e' is not found.
Some of you guys are starting in the middle.
A better start would be
char *string = "hello world";
Assert(ReplaceCharInString(string, 'e', '3') == 1);
Assert(strcmp(string, "h3llo world") == 0);