I am learning how to code in c right now, as such, the next step in my agenda was learning how to code recursively. For this, I tried to write code that takes a users input, then reverses it recursively and tell you if its a palindrome or not.
The current issues number 3, The first is whether or not I have even been writing recursively, the second pertains to which string comparison I have to do in this part of the code to determine if its a palindrome or not:
int main(){
//char stringran[256];
//char done;
char str1[1024];
int size;
printf("Enter a string to reverse, or done to exit program: ");
scanf("%s", str1);
size = strlen(str1);
printf("The string you enterred is: %s\n", str1);
reverse(str1, 0, size - 1);
printf("The string after reversing is: %s\n", str1);
//the if-else statement below is the issue, currently i have a placeholder//
if(str1 == str1){
printf("The string is a palindrome");
}
else{
printf("The string is not a palindrome");
}
Lastly, if I wish to loop the code so that it keeps asking the initial question after a string is input (Enter a string to reverse, or done to exit program), how would I go about doing it? Would it be a for-loop or a while-loop?.
Full code with output:
https://onlinegdb.com/Sk_vTLJp7
"The current issues number 3"
"The first is whether or not I have even been writing recursively."
Yes, your reverse() function is recursive. Any function that calls itself is recursive. However, it is very easy to write a recursive function that operates incorrectly, does not handle appropriate cases very well, mucks up memory management, or runs on infinitely. Programming in C demands great care; writing recursive functions demands even greater care.
As noted in the comments, detecting a palindrome does not require a recursive function. As an exercise, I suppose it's alright, but (1) if you were faced with this problem for real, you'd be much better off approaching it quite differently, and (2) there are much better problems for learning recursion, because of being both simpler and more suited to a recursive approach. Google is your friend here.
"which string comparison I have to do in this part of the code to determine if its a palindrome or not"
The main thing you need to do is compare two things that might be different. As the comments point out str1 == str1 is always true. You point out that this is placeholder code (so that it compiles). Better placeholder code would be:
if (1) { // placeholder code so that it compiles
That would have eliminated quite a bit of confusion.
As for the comparison you need to do, just make a copy of str1 before modifying it. Then, compare the pre-modified copy with the modified value. But be sure you know what you are doing when you make a copy of str1. Since it wasn't already obvious to you that you need to do this, it might not be obvious to you how to do this. It's one of the pitfalls of C that it's easy to get this wrong. Again, Google will help you here.
"if I wish to loop the code so that it keeps asking the initial question after a string is input, how would I go about doing it? Would it be a for-loop or a while-loop?"
Either would work, since it's trivial to write a for loop that acts like a while loop. The real question is, under what circumstances would you break out of the loop? The answer to that question will point you to both the best type of loop, and the loop condition to give it.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 months ago.
Improve this question
I am new to C, I have written a very simple program to get the first name and surname, here is my code...
#include <stdio.h>
#include <conio.h>
int main(){
int num,bankpin;
char fn[20],sn[20];
printf("Welcome to authorization. We ill now begin the process");
printf("\nFirst, please enter your first name: ");
scanf(" %s",fn);
printf("\nEnter your surname: ");
scanf(" %s",sn);
printf("\nWelcome to the system %c %c",&fn,&sn);
return 0;
}
Welcome to authorization. We ill now begin the process
First, please enter your first name: A
Enter your surname: A
Welcome to the system α
Why is this strange "a" appearing on my screen instead of "A A"?
In fact it appears on my screen even if I try a different combination of letters
I have even tried recompiling the code
I'm guessing this is because you are trying to print &fn, which is a pointer, as char. You're basically telling the program to interpret the address o as a symbol code.
Try changing the
printf("\nWelcome to the system %c %c",&fn,&sn) to
printf("\nWelcome to the system %s %s",fn,sn)
Short answer
You are sending the array pointer's address as an argument, and telling printf to interpret it as a single char, resulting in undefined behavior. The fix is to replace the line
printf("\nWelcome to the system %c %c",&fn,&sn);
with
printf("\nWelcome to the system %s %s",fn,sn);
Long answer
The weird character is due to your code reading an unintended value, and trying to interpret it. If you run your code a few times, you will find that you don't always get this symbol, but many other ones, including nothing at all (seemingly). What is going here ?
The short answer is that you are misinforming the printf function by giving her a false symbol and a false value. Let's look at a similar example :
char myString[20] = "Hello!";
printf("%c", &myString);
In this snippet we create an array of characters, which actually means creating a pointer of char* type, and allocating its size (here to 20). Pointers are often confusing when starting with C, but they are in principle pretty simple : they are simply variables that, instead of containing a value, contain an address. Since arrays in C store their value sequentially, that is one after the other, it makes quite a lot of sense to have them be pointers : if you know where the array starts, and that its members are spaced evenly, it makes it quite easy to go over the array.
So since your array is a pointer, reading it directly will print something along the lines of "0x7ffc5a6dbb70". Putting '&' before it gives a very similar result : this operator consists in asking for the address of a variable, which is then in your code transmitted to the printf as an argument.
This doesn't make any sense there : a char is, in C, behind the scene, actually an integer variable with very small capacity, from 0 to 255 to be precise. For example the two lines in the following snippet produce the same result :
printf("%c", 'a');
printf("%c", 97);
Now you see what is happening in the original printf : the function is expecting to receive a very small integer to convert to one character, and instead receives an address, which is the reason why the output is so weird. Since addresses change basically at every run of the code, that is also the reason why the output changes very often.
You thus need to adapt the information in the printf function. First, inform that you wish to print a char array with the symbol "%s". This will make the function expect to receive a pointer to the first element of a char array, which it will then iterate over. Thus, as argument, you need to send this pointer, that you directly have in the form of the myString variable.
Thus running
char myString[20] = "Hello!";
printf("%s", myString);
prints 'Hello!', as expected :)
The funcion scanf is a little tricky, please delete the leading space, inside quotes only include what are you expecting to receive, ever.
scanf("%s",fn);
The printf function needs %s, same as scanf, to deal with string, later you don't need the & operator in this case.
printf("\nWelcome to the system %s %s",fn,sn);
This is a practice question from my school, it's not a homework question:
Given the following declaration, write a snippet of C code that might
lead to strlen(arr) returning no less than 8.
char arr[4];
My attempt to this question is: impossible, there is no way to achieve this. Since strlen will return the number of chars in an char array until it meets the first \0, I don't see there is anyway we can let strlen return 8 in this case. I think if we force to assign a 8-length-long string to this array, the behavior is not predictable.
However, the solution that our instructor gives is the:
strcpy(arr, Any 8-char-long string);
For example:
strcpy(arr, "Overflow");
I don't understand why this is valid, in my understanding, I don't see this array has enough space to hold this 8-length string, is there something I miss for understanding the string in C?
"Given the following declaration, write a snippet of C code that might lead to strlen(arr) returning no less than 8."
That is not possible, since arr can only hold 3 characters and 1 null terminator.
My attempt to this question is: impossible, there is no way to achieve this
Correct.
However, the solution that our instructor gives is the: strcpy(arr, Any 8-char-long string);
Your instructor is incompetent and shouldn't be teaching C. This will write out of bounds of the array and anything can happen, including program crashes or the program seeming to work as intended this time of execution.
I don't understand why this is valid
It is not, it invokes undefined behavior.
I just wanted to start this off by admitting I'm a complete beginner to coding, and that it's not something that comes intuitively to me.
What I'm trying to do is write a simple program that has the user input their full name, and outputs their initials. The logic I'm trying to follow is that since strings in C are just characters in an array, the characters that should be an initial will come after the '\0' value.
I'm not sure if my problem is a problem of logic or translating that logic into working syntax, so any help would be appreciated.
Here is the code in full:
# include <stdio.h>
#include <cs50.h>
#include <string.h>
int main (void)
{
printf ("Please insert your name. \n");
string name = get_string();
//printf ("Your name is %s\n", name);
int x = 0;
char c = name [x];
while (c != '\0')
{
x++;
}
printf ("%c/n", c);
}
I understand it's a complete mess, but again I'm trying to figure out if it's best to just quit, so any help would be appreciated.
Thanks in advance.
The logic I'm trying to follow is that since strings in C are just characters in an array, the characters that should be an initial will come after the '\0' value.
In C, \0 denotes the end of a string, so you definitely don't want to be looking for that value.
Let's think about the logic. Someone's initials are probably:
the first character in the string
the first character after a space
– i.e. "Albus Percival Wulfric Brian Dumbledore" -> "APWBD" –
so you'll want to loop over the string, looking for either:
a space, in which case you'll want to grab the next letter, or
the end of the string ('\0') in which case you'll want to stop.
Edge cases to watch out for:
what happens if the string is empty?
what happens if the string ends with a space? (this might not happen if you're guaranteed to get properly formatted input)
Please don't get discouraged – we were all beginners once. This kind of thinking isn't always straightforward, but the answer will come eventually. Good luck!
Eg-
maabcma is valid because it contains ma as a proper prefix as well as a proper suffix.
panaba is not.
How do I find out if a word is valid or not as above in C language?
I'm not very good at string operations. So, please help me out with a pseudocode.
Thanks in advance.
I'm completely lost. T=number of test cases.
EDIT: New code. My best code so far-
#include<stdio.h>
#include<string.h>
void main()
{
int i,T,flag=0;
int j,k,len=0;
char W[10],X[10];
scanf("%d",&T);
for(i=0;i<T;i++)
{
scanf("%s",W);
for(len=0;W[len]!='\0';len++)
X[len]=W[len];
X[len]='\0';
for(j=len-1;j>=0;j--)
for(k=0;k<len;k++)
{
if(X[k]!=W[j])
flag=0;
else if((j-k)==(len-1))
flag==1;
}
if (flag == 1)
printf("NICE\n");
else
printf("NOT\n");
}
}
Still not getting the proper results. Where am I going wrong?
The thing is you are only setting the value of flag if a match exists, otherwise you must set it to 0. because see, if I have:
pammbap
my prefix is pam and suffix is bap.
According to the final for loop,
p and a match so flag is set to 1.
but when it comes to b and m it does not become zero. Hence, it returns true.
First, void is not a valid return type for main, unless you are developing for Plan 9.
Second, you should get into the habit of checking the return value of scanf() and all input functions in general. You can't rely on the value of T if the user does not input a number, because T is uninitialised. On that same note, you shouldn't use scanf with an unbounded %s scan operation. If the user enters 20 characters, this isn't going to fit into the ten character buffer that you have. An alternative approach is to use fgets to get a whole line of text at once, or, to use a bounded scan operation. If your array fits 10 characters (including the null terminator) then you can use scanf("%9s", W).
Third, single-character variable names are often very hard to understand. Instead of W, use word, instead of T, use testCount or something similar. This means that someone looking at your code for the first time can more easily work out what each variable is used for.
Most importantly, think about the process in your head, and maybe jot it down on paper. How would you solve this problem yourself? As an example, starting with n = 1,
Take the first n characters from the string.
Compare it to the last n characters from the string
Do they match?
If yes, print out the first n characters as the suffix and stop processing.
If no, increment n and try again. Try until n is in the middle of the string.
There are a few other things to think about as well, do you want the biggest match? For example, in the input string ababcdabab, the prefix ab is also the suffix, but the same can be said about abab. In this case, you don't want to stop processing, you want to keep going even if you find a prefix, so, you should just store the length of the largest prefix that is also the suffix.
Second-most-importantly, running into hurdles like this is incredibly common when learning C, so don't let this put a dampener on your enthusiasm, just keep trying!
I've written the code below to calculate the length of a word at the beginning of a string with recursion. I've thought of a case in which my code would not work " ##*hello " what do I need to modify the code to resolve this problem (the correct answer is 5)? Thanks
int startWordLenRec(char s[]) {
int length;
if (isLetter(s[0]) == false){
return 0;
}
else{
length = 1 + startWordLenRec(s+1);
}
return length;
}
It's a little unclear why you're using recursion outside a functional language to solve this problem. It's also, frankly, a little unclear what the actual parameters of the problem are.
If your actual intention is to measure the length of the first word in the string (defined as a sequence of characters that return a True result if passed to isLetter) even if that word does not start at the beginning of the string, then the simplest, clearest solution seems to be: make the function take a flag as an argument, called letterSeenYet. On the initial call to the function, the flag should be set to False.
If the function reads a non-letter character, and the letterSeenYet flag is False, set length equal to 0 + the results of the recursive function call, and make sure the flag on that call is set to False.
If the function reads a letter character, set length equal to 1 + the results of the recursive function call, and make sure the flag on that call is set to True.
If the function reads a non-letter character, and the letterSeenYet flag is True, return 0.
I hope you see the logic: you want a non-letter character to mean "stop counting letters", but only after you've seen some letters to begin with.
Again, I really don't understand why you're using recursion for this problem. There are some problems that are easier to comprehend in their recursive form, but this one seems far, far easier (and more efficient) to handle iteratively. (Also, as Charles Salvia points out, you should be prepared not just for the end of the first word, but for the possible end of the string.)
Thinking in terms of recursion can be a little tricky. Without going into the details as to why or why not to use recursion, let's assume it has to be recursion (homework, discovery, whatever the reason).
So the main thing to consider for recursion is what the terminating condition is. If you have trouble doing so, maybe writing the algorithm in an iterative fashion can help you.
In this instance, what you need to determine is when the character array ends. This will be the case if the current character is '\0'.
A simple recursive algorithm might be:
Check current character. Is it '\0' ?
Yes: Return 0
No. Is the current character a letter?
Yes: return 1 + call this function with incremented character pointer
No: return 0 + call this function with incremented character pointer
Note that this algorithm will not terminate after seeing a non-letter character, so " test a" will return 5, not 4. If you have to terminate before, you would need some type of flag, that gets passed to the function.
Anyway, my main point was to think of what the terminating condition should be.