Getting input with fgets and outputing the answer in reverse with recursion - c

This is a sample snippet from a book. I am not understanding how it is printing the string in reverse. The first time reverse is called, the element at 0 is not null assuming of course a valid string was entered. In the else statement, we are calling the function again passing in the address of element at index 1.
So let's say I input "hello". Then I am passing the address of e. The second time reverse is called, however, how is the string being traverse? The index being checked is still 1. Also, it seems to me we are not replacing the values of the array. When we start printing the values with putchar I get so confused that the value at index 0 starts with the last element of the array. I understand that when we use recursion and we hit the base case, and since the items are put on the stack, we start reading them from the top of the stack pointer until the end which is why is in reverse. But here I don't see that happening.
The hard-coded indexes at
reverse( &ptr[1]);
putchar(ptr[0]);
do not make sense to me. I guess I am having difficulty seeing how the string is being traverse when it is the same address being passed each time in the recursion. Please help me understand what is happening.
I have modified the code a bit for simplicity but it does the same thing the one in the book does.
#include <stdio.h>
void reverse(char * ptr);
int main(){
char sentence[10];
printf("enter text \n");
fgets(sentence, 10, stdin);
printf("The line is: \n");
reverse(sentence);
return 0;
}
void reverse( char * ptr){
if(ptr[0] == '\0'){
return;
} else{
reverse( &ptr[1]);
putchar(ptr[0]);
printf("\n");
}
}

The &ptr[1] is equivalent to ptr + 1. Now, if you think of ptr as a number (which it is, really) it should be obvious that it's not the same number being passed every time, but rather one greater for each level of recursion. It's basically passing a substring starting from the second character, only in C the substring is not a separate object but rather a pointer to a different position in the same string.

Related

Using pointers to count _ and ! in a string outside of the main function in C

I am working on an assignment for school and am having trouble getting the correct output. I am unsure if there is a problem with my loop or a problem with the method of saving values with pointers. When I run the code I end up with something like this:
Output: There are 369224989 underscores and 0 exclamation points in the sentence.
The assignment specifies to use the prototype and the getchar() function to read the input. I feel like since the first value is so high it is an issue with my loop but I have been working on this for two days and haven't seen anything wrong with it (though I could be staring through it at this point).
In addition I get these warnings when I try and compile the program:
characters.c:28: warning: value computed is not used
characters.c:31: warning: value computed is not used
This makes me think that maybe it isn't communicating properly with the main function.
#include<stdio.h>
//this function prototype was required for the assignment
void count(int* num_, int* num_exclamation);
// intended to count the number of _ and ! in a string using pointers
int main()
{
int num_, num_exclamation;
count(&num_, &num_exclamation);
return 0;
}
void count(int* p_num_, int* p_num_exclamation)
{
char ch;
*p_num_ = *p_num_exclamation = 0;
//attempts to scan a string get the first character
printf("Enter a sentence: ");
ch = getchar();
//attempts to loop while incrementing if it is a ! or _
while(ch != '\n')
{
if(ch == '_')
*++p_num_;
if(ch == '!')
*++p_num_exclamation;
ch = getchar();
}
//prints result
printf("Output: There are %d underscores and %d exclamation points
in the sentence.\n", *p_num_, *p_num_exclamation);
}
This is the second time I have really interacted with pointers with the first being the other half of this assignment which is working properly. I am not particularly comfortable with them yet nor aware of all of their nuances. Any advice to get me looking in the right place would be greatly appreciated.
You have Undefined behavior in your code. *++p_num_; increments the pointer first and then it dereferences it. The value of it is not used. And this way, the pointer points to some memory which are not the variables you supposed it to be. Then you dereference it - that location contains indeterminate value and you print it. Accessing some memory which you don't have permisssion to is - UB.
(*p_num_)++
is the one you wanted. This holds for the other variable also - namely p_num_exclamation. Also return value of getchar is int not char - you should use int to hold the value returned by getchar.

I am trying to create a program that takes a name and outputs the initials but keep running into an array error

I am trying to create a program that take the input from the user and prints the first character of each word but every time I try to Here is my code.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
int main(void)
{
char leng[100];
int len;
scanf("%s", &leng[100]);
len = strlen(&leng[100]);
char name[len];
//checking if at end or not
while (name[len] != '\0')
{
if (name[len] == ' ')
printf("%c", name[len + 1]);
len++;
}
}
Every time I give a name it shows an error something like:
index 3 out of bounds for type 'char [len]'
These two lines are incorrect:
scanf("%s", &leng[100]);
len = strlen(&leng[100]);
If you translate these into English, their meanings as written are:
Scan a string to the memory at the address of 101st element of the
leng array.
Get the length of the string that starts at the address
of the 101st element of the leng array.
The array index is out of bounds because leng[100] is past the end of the array. Remember that a 100 element array goes from 0 to 99, not from 1 to 100!
You want to be scanning into the base address of the array, and passing the base address of the array into strlen(). I'll leave the syntax for you to figure out from your textbook.
And by the way, you also have a problem in your code because you're reading your data into an array named leng, but your loop is working with an array named len. There are at least two additional problems in your code, but I'll leave them for you to debug.
There are a few things to consider with your code. As #richardschwartz already mentioned, you are not referencing your char arrays correctly. you have:
scanf("%s", &leng[100]);
len = strlen(&leng[100]);
You may want the following instead:
scanf("%s", leng);
len = strlen(leng);
Also, keep in mind that scanf with the %s flag will stop reading input once white-space is detected. For example, if you input "hello world",
scanf("%s", leng);
will only catch the characters "hello". To get around this, you could loop scanf to read multiple words and return the first character of each word as you desire.
Lastly, scanf is not advised for beginners though. See paxdiablo's excellent reason regarding lack of overflow protection, here: https://stackoverflow.com/a/1248017/6870832

How to check each character in a dynamically allocated string array, in C?

So what I am trying to ultimately do is search an array for a name, and if the name is found return that name. Well, to do that I need to check for each character in every row and column for a match. And before I could do that I need to know exactly how to go about doing that, so I am trying to figure out how to get the dynamic array to print out the first character, then second and so on in order to compare it with the name being searched. But I am having trouble doing this. So my question is how would I go about checking each character in such an array? I've let out most parts of the code but I think I included the main parts that I am troubled in. Thanks for the help in advance.
I'm a beginner in C, so sorry if I did anything gravely wrong, thanks!
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define STRINGSIZE 20
int main(){
char **firstNames, **lastNames;
int classSize,i;
char sample[21] = "Slack";
printf("Please indicate number of records you want to enter (min 5, max 15):\n");
scanf("%d", &classSize);
firstNames=malloc(classSize*sizeof(char*));
for (i=0; i<classSize; i++) {
firstNames[i]=malloc(STRINGSIZE*sizeof(char));
}
printf("Please input records of students (enter a new line after each record), with following format: first name");
*firstNames="Slack";
printf("\n\n");
printf("%c", *(sample)); //Will print out S
printf("%c", **firstNames); //Will print out S
printf("%c", *(sample+1)); //Will print out l
printf("%c", **(firstNames+1)); //Will give error
printf("%c", **(firstNames)+1); //Will print T (Next ascii char after 'S'
printf("%c", **((firstNames)+1)); //Will give error
}
A C string is an array of characters. Even if dynamically allocated, you can treat it as such, so:
sample[0]; // S
sample[1]; // l
sample[2]; // a
// etc
You are storing multiple pointers to C strings in firstNames. You access it as an array:
firstNames[0]; // first name
firstNames[1]; // second name
firstNames[2]; // third name
// etc.
Now you just combine these, as firstName[0] is just a C string, just like sample:
firstName[0][0]; // first letter in first name
firstName[0][1]; // second letter in first name
firstName[1][0]; // first letter in second na,e
// etc.
You have an array of pointers to char firstNames the size of classSize. Every pointer in this array points to valid memory you allocated with malloc.
The error you make is assigning a string literal to the first pointer of the array firstNames, overwriting the pointer with the address of the string literal. This will lose the memory you allocated and also the string literal cannot be modified, which you do later causing the program to crash.
This line will copy a string "Slack" to the memory the first pointer in the array points to:
strcpy( firstNames[0] , "Slack" ) ; //make sure you have enough space
Note that firstNames[0] equals to *firstNames.
i used in the for loop is not defined anywhere.

swapping string in c using pointer

Need help
this is my code
void swapstringfun()
{
int i=0,j=0;
char *str=(char *)malloc(sizeof(char)*15);
char *mystr=(char *)malloc(sizeof(char)*15);
system("cls");
printf("Please enter first string :\t");
scanf("%s",str);
printf("Please enter second string :\t");
scanf("%s",mystr);
while(*(str+i)!='\0' && *(mystr+i)!='\0')
{
*(str+i) ^=*(mystr+i);
*(mystr+i) ^=*(str+i);
*(str+i) ^=*(mystr+i);
i++;
}
printf("%s swapped to %s",str,mystr);
getch();
main();
}
I wrote the above code to swap the string using XOR operator. The problem with this code is. when my input is lets say.. RAJESH and ASHISH. Then, it shows output ASHISH and RAJESH. And, that is expected.
But, when input is let say.. ABHISHEK and CODER .Then, output is CODERHEK and ABHIS. But, the expected output is CODER and ABHISHEK. Anyone help me to solve this problem. I will appreciate.
You iterate and swap until you reach the end of the shorter string
while(*(str+i)!='\0' && *(mystr+i)!='\0')
(or both, if the lengths are equal). To iterate until you reach the end of the longer string, you need an || instead of the && and be sure that 1. both pointers point to large enough memory blocks, and 2. the shorter string ends with enough 0 bytes. So you should calloc the memory, not malloc.
However, you should swap the pointers, really,
char *tmp = str;
str = mystr;
mystr = tmp;
You also need to swap the terminating 0, as its part of what is called a string in C.
The 0 is the stopper element in the character array, describing the string.
You need to XOR the entire length of both strings. Since in your second example, the strings are different lengths, your algorithm won't work.
This is the statement you'll have to reconsider:
while(*(str+i)!='\0' && *(mystr+i)!='\0')

Reverse a string using recursion

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.

Resources