Program to replace a letter with another in C - c

I wrote a program to replace a letter in a string. Although it has no error, the output is not as expected. Please help me with it.
#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
void replace(char s,char d);
char a[100];
int main()
{
char b,r;
printf("enter the string\n:");
gets(a);
printf("enter the the letter to be replaced\n:");
scanf("%c", &b);
printf("enter the letter to be replaced with\n:");
scanf("%c", &r);
replace(b,r);
}
void replace(char s, char d)
{
int i,f=0;
for (i = 0; a[i] != '\0'; i++)
{
if (a[i] == s)
{
a[i] = d;
f = 1;
}
}
if (f == 0)
{
printf("letter not found");
}
}
Output
enter the string
:hello every one
enter the the letter to be replaced
:e
enter the letter to be replaced with
:letter not found
I wanted to replace e with o but I am not able to give the input for word to be replaced
UPDATE
Use this loop to get rid of the input buffer problem when using scanf
but I am not sure how to implement it on my program need help
void
clear(void)
{
while ( getchar() != '\n' )
;
}

The scanf() function skips over initial whitespace characters when you read in strings using the %s specifier, but it does not do this when your read chars with the %c specifier. The gets() function that you use (which you should never ever ever use ever) reads through the newline, and discards it. So your first call to scanf() has a clean input stream. When you call scanf() the first time, a value is read into the variable b, but the trailing newline is left behind in the input stream. Then, when you try to read the next value, scanf() picks up this newline, instead of the value that you want to enter.
One fix for this is to discard any unwanted characters from the input stream like this:
while (getchar() != '\n')
continue; // discard unwanted characters
You can also test for the EOF character in the conditional expression if you really want to be careful. One virtue of this approach is that, no matter how many characters the user enters at your second prompt, only the first is taken, and the remaining characters through the newline are discarded. Since there is nothing left in the input stream, scanf() has to wait for the user to enter something at your third prompt. You should place this code after each call to scanf() to make sure that the input stream is clear.
Now, gets() is a terrible and unsafe function begging for buffer overflows, because it doesn't check to see if there is enough memory allocated for the string it is getting. Instead, use fgets(). This function takes an argument that specifies the maximum number of characters to read, including the null-terminator. fgets() also reads the newline character into the string, so you have to dispose of that yourself if you don't want it. Here are the modifications you need to make:
int i = 0;
...
char b,r;
printf("enter the string\n:");
fgets(a, 100, stdin);
while(a[i] != '\n' && a[i] != '\0') // remove newline
++i;
a[i] = '\0';
printf("enter the the letter to be replaced\n:");
scanf("%c", &b);
while (getchar() != '\n')
continue; // discard unwanted characters
printf("enter the letter to be replaced with\n:");
scanf("%c", &r);
while (getchar() != '\n')
continue; // discard unwanted characters
replace(b,r);
printf("%s\n", a);
...
I added a final printf() to display the changed string.

Related

Undefined behaviour of scanf() in a do-while loop

I'm currently learning C by a book "C Programming a modern approach" and encountered this code. When I tried to run it, after typing consecutive characters like 'abc' and hitting Enter (new line), nothing was printed. Please explain what is going on here.
char ch;
do {
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
You're asking the user to input a character using scanf. This is happening in a loop until the user inputs a '\n' or newline character (the same as pressing the enter key), which is when the loop will break.
Your print statement will then print the character in the variable ch, which at that point will be '\n' (since this variable just stores one character, the last one you typed).
This newline character will probably be invisible when you run your program so you may not be seeing it. You can add another print statement after the loop and if that print statement starts at a newline, you know that the '\n' was printed on the previous line.
Something like:
#include <stdio.h>
int main()
{
char ch;
do
{
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
printf("I should show up on a newline");
return 0;
}
The code you provided reads characters from the input using the scanf() function and stores them in the variable ch until a newline character (\n) is encountered. After that, the program prints the last character that was read, which is the newline character.
The reason you are not seeing any output when you enter characters followed by a newline character is because the printf() statement is only executed after the loop has finished running. So, the program is waiting for you to enter a newline character to terminate the loop and print the last character that was read.
If you want to see the characters you enter, you can add a printf() statement inside the loop, like this:
char ch;
do {
scanf("%c" , &ch);
printf("%c", ch);
} while (ch != '\n');
This will print out each character as it is read from the input, so you can see what you're typing. Happy coding :)
When I tried to run it, after typing consecutive characters like abc and hitting Enter (new line), nothing was printed.
Well with the posted code, if the loop even finishes, the last byte read by scanf("%c", &ch) and stored into ch is the newline character. Hence printf("%c", ch) outputs this newline and it seems nothing is printed but something is, the newline which is invisible on the terminal but does move the cursor to the next line.
You can make this more explicit by changing the printf call to this:
printf("last value: '%c'\n", ch);
Note however that the posted code is not a recommended way to read the contents of the input stream:
scanf("%c", &ch) may fail to read a byte if the stream is at end of file. Failure to test this condition leads to undefined behavior (ch is unmodified, hence stays uninitialized if the input stream is an empty file) or to an infinite loop as ch may never receive a newline.
this code is a typical example of a do / while with a classic bug. It would be much better to write the code using getchar() and a while loop.
Here is a modified version:
#include <stdio.h>
int main(void) {
int c; // must use int to distinguish EOF from all valid byte values
int count = 0; // to tell whether a byte was read at all
char ch = 0; // the last byte read
// read all bytes from the input stream until end of file or a newline
while ((c = getchar()) != EOF && c != '\n') {
ch = (char)c;
count++;
}
if (count == 0) {
printf("no characters entered: ");
if (c == EOF) {
printf("end of file or read error\n");
} else {
printf("empty line\n");
}
} else {
printf("last character on line is '%c'\n", ch);
if (c == EOF) {
printf("end of file or input error encountered\n");
}
}
return 0;
}

Program seems to be ignoring one instance of 'gets()' and show an error message when the user hasn't interacted with the program [duplicate]

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
int n=1,i,cont;
char string[50];
scanf("%d",&n);
while(n!=0){
gets(string);
cont=0;
for(i=0;i<strlen(string);i++){
if(string[i]=='.'){
cont++;
}
}
if(cont%2==0){
printf("S\n");
}else{
printf("N\n");
}
scanf("%d",&n);
}
return 0;
}
My problem is quite simple but troublesome, I want to read an integer value n, and then read a string, after that read n again, but whenever I run the program, it only reads the string value... but if I digit 0 the program ends... it's like my scanf is within the gets function.
Mixing scanf with gets or fgets is troublesome because they each handle newlines differently.
Get rid of the gets call (which is unsafe anyway) and replace it with the following scanf call:
scanf("%49s", string);
This will read at most 49 characters into string (i.e. one less that its size).
From OP's comments, it sounds like the goal is to be able to read strings containing spaces. While there are ways to accomplish this using scanf(), it would be better to use fgets(), which is at the least less error-prone.
The fgets() function can be used to read input for the number into a buffer, and this buffer can then be processed by sscanf() to extract the number. Since fgets() keeps the newline character, it is not left behind to interfere with the next I/O operation.
But, when fgets() is used to get the string, since the newline is retained, it may be desirable to remove it. This can be accomplished in a number of ways, but here strcspn() is used to provide the index of the first \r or \n character encountered; a \0 character is then written to this location, removing the terminating newline from the string.
The code below illustrates these suggestions. Note that both buffer[] and string[] are generously allocated to accommodate reasonably large inputs. If a user enters a large number of characters (more than 999 in this case), the extra characters are left behind in the input stream for the next I/O function call. Also note that the main loop has been streamlined a bit; now there is a for(;;) loop that never terminates, broken out of when the user enters 0 for the number. And, there is a nested loop within the main loop that prompts the user to enter a number until a valid number is entered. Since the #include <stdlib.h> was unnecessary, it was removed. Better code would check the values returned from the calls to fgets() for possible errors.
#include<stdio.h>
#include<string.h>
int main(void)
{
int n = 1, cont;
char buffer[1000];
char string[1000];
for (;;) {
/* Loop until user enters a number */
do {
printf("Please enter a number: ");
fgets(buffer, sizeof buffer, stdin);
} while (sscanf(buffer, "%d", &n) != 1);
/* Break on 0 */
if (n == 0) break;
/* Get a string, and remove trailing newline */
printf("Please enter a string\n");
fgets(string, sizeof string, stdin);
string[strcspn(string, "\r\n")] = '\0';
cont = 0;
for (size_t i = 0; i < strlen(string); i++) {
if (string[i] == '.') {
cont++;
}
}
if (cont % 2 == 0){
printf("S\n");
} else {
printf("N\n");
}
}
return 0;
}
When you enter 5 for an example, you hit a new line character afterwards.
So you are entering 2 characters: 5 and a new line character.
That new line character is causing your headache.
The new line character is also considered an input.
In order to ignore this new line char, simply add a new line that acts as a garbage collection:
char garbage[50];
scanf( "%d", &n);
fgets(garbage, sizeof(garbage), stdin);

scanf not reading properly because of gets function

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
int n=1,i,cont;
char string[50];
scanf("%d",&n);
while(n!=0){
gets(string);
cont=0;
for(i=0;i<strlen(string);i++){
if(string[i]=='.'){
cont++;
}
}
if(cont%2==0){
printf("S\n");
}else{
printf("N\n");
}
scanf("%d",&n);
}
return 0;
}
My problem is quite simple but troublesome, I want to read an integer value n, and then read a string, after that read n again, but whenever I run the program, it only reads the string value... but if I digit 0 the program ends... it's like my scanf is within the gets function.
Mixing scanf with gets or fgets is troublesome because they each handle newlines differently.
Get rid of the gets call (which is unsafe anyway) and replace it with the following scanf call:
scanf("%49s", string);
This will read at most 49 characters into string (i.e. one less that its size).
From OP's comments, it sounds like the goal is to be able to read strings containing spaces. While there are ways to accomplish this using scanf(), it would be better to use fgets(), which is at the least less error-prone.
The fgets() function can be used to read input for the number into a buffer, and this buffer can then be processed by sscanf() to extract the number. Since fgets() keeps the newline character, it is not left behind to interfere with the next I/O operation.
But, when fgets() is used to get the string, since the newline is retained, it may be desirable to remove it. This can be accomplished in a number of ways, but here strcspn() is used to provide the index of the first \r or \n character encountered; a \0 character is then written to this location, removing the terminating newline from the string.
The code below illustrates these suggestions. Note that both buffer[] and string[] are generously allocated to accommodate reasonably large inputs. If a user enters a large number of characters (more than 999 in this case), the extra characters are left behind in the input stream for the next I/O function call. Also note that the main loop has been streamlined a bit; now there is a for(;;) loop that never terminates, broken out of when the user enters 0 for the number. And, there is a nested loop within the main loop that prompts the user to enter a number until a valid number is entered. Since the #include <stdlib.h> was unnecessary, it was removed. Better code would check the values returned from the calls to fgets() for possible errors.
#include<stdio.h>
#include<string.h>
int main(void)
{
int n = 1, cont;
char buffer[1000];
char string[1000];
for (;;) {
/* Loop until user enters a number */
do {
printf("Please enter a number: ");
fgets(buffer, sizeof buffer, stdin);
} while (sscanf(buffer, "%d", &n) != 1);
/* Break on 0 */
if (n == 0) break;
/* Get a string, and remove trailing newline */
printf("Please enter a string\n");
fgets(string, sizeof string, stdin);
string[strcspn(string, "\r\n")] = '\0';
cont = 0;
for (size_t i = 0; i < strlen(string); i++) {
if (string[i] == '.') {
cont++;
}
}
if (cont % 2 == 0){
printf("S\n");
} else {
printf("N\n");
}
}
return 0;
}
When you enter 5 for an example, you hit a new line character afterwards.
So you are entering 2 characters: 5 and a new line character.
That new line character is causing your headache.
The new line character is also considered an input.
In order to ignore this new line char, simply add a new line that acts as a garbage collection:
char garbage[50];
scanf( "%d", &n);
fgets(garbage, sizeof(garbage), stdin);

Can't find space in string and specified char , even by simple method

I am using this method to find a space or specified word in string.
but this method doesn't works. I've checked the flow many times.
#include <stdio.h>
int main()
{
char text[50], find;
int i = 0, sp = 0;
printf("Enter text: \n");
scanf("%s", text);
printf("Enter a char to find:\n");
scanf("%c", &find);
while ( text[i] != '\0') // to receive a value untill enter is pressed.
{
if (text[i] == find) // count if text[i] is the specified value.
{ sp++; }
i++;
}
printf("%d", sp); // prints 0 always. how to fix this.
}
The find in your code is always assigned with \n or the new line character that you enter at the end of scanning your string text .Try giving a space in scanf statement of find :
scanf(" %c",&find)
Why to give a space?
By giving a space,the compiler omits the '\n' character from the previous scanf
Note: scanf("%s",string) ends scanning when it encounters white space i.e, '\n' or '\0' or '\t' but to account for spaces, try
using this scanf("%[^\n]s",string")
You cannot use scanf() to read a string of characters with space. As soon as the space is encountered, scanf() exits.
Use fgets() instead.
And as for finding a word in the string, to compare strings use strcmp().
SIDE NOTE:
1) Check the return values of scanf()
2) Use the standard definition of main()
int main(void) //if no command line arguments.
I found a solution for that:
scanf("%[^\n]", fullName);
works fine. and receives whole line

scanf not working correclty in this c program

I have wrote a small code to get value from Fahrenheit to Celsius. I wanted to keep inputting data until I press any other key than 'y'. But this loop doesn't work that way and stops after one iteration.
#include <stdio.h>
int main()
{
char ch='y';
int far, cen;
do {
printf("again\n");
scanf("%d",&far);
//cen = (5.0/9.0)*(far-32);//integer division will truncate to zero so we can make 5/9 to 5.0 / 9.0
cen = (5*(far-32))/9;//or this way we can use this formula
printf("\n%d\t%d",far, cen);
printf("ch=%c",ch);
scanf("%c",&ch);
}while(ch == 'y');
return 0;
}
What is the problem here?
P.S
I added a line and made a new code like this
#include <stdio.h>
int main()
{
char ch='y';
int far, cen;
do {
printf("again\n");
scanf("%d",&far);//here we press carriage return. this value is in stdin
//cen = (5.0/9.0)*(far-32);//integer division will truncate to zero so we can make 5/9 to 5.0 / 9.0
cen = (5*(far-32))/9;//or this way we can use this formula
printf("\n%d\t%d",far, cen);
scanf("%c",&ch);//putting a space before %c makes the newline to be consumed and now it will work well
if((ch == '\r')|| (ch == '\n'))
printf("1\n");
printf("ch=%c",ch);//this takes the carriage return in stdin buffer
}while(ch == 'y');
return 0;
}
I need to know carriage return here is \r or \n?
When the value for scanf("%d",&far); is entered and press enter, the scanf stores the carriage return in the buffer. When it encounters the second scanf in the code scanf("%c",&ch); it takes the carriage return present in the buffer as the input to 'ch'. So it doesn't wait for the user input.
Please have a look at the post here
As indicated in one of the reply the solution is to put a space in scanf
scanf(" %c",&ch);
You should always check the return value of scanf. Your first use of scanf may fail if the user does not enter a valid integer, in which case, you are using far without initialising it (which is undefined behaviour). scanf returns the number of items that were successfully scanned. If you are requesting scanf to scan one integer, then it should return 1 if it successfully managed to scan an integer.
int scanresult = scanf("%d", &far);
if (scanresult != 1)
{
puts("Invalid input or unexpected end of input");
return 1;
}
In addition, the %c conversion specifier is unique in that it does not cause scanf to gobble up any preceding whitespace unlike the other conversion specifiers. To force scanf to gobble up the whitespace (such as linefeeds, carriage returns, spaces, tabs etc), simply put a space character before the %c, e.g.
scanresult = scanf(" %c", &ch);
For scanf, the space character is actually a directive to parse and skip all whitespace.
This is because of the previous newline character remaining in the buffer. You can simply replace scanf by this line:
while((ch = getchar()) == '\n');
You'll be needing the same technique in combination with ungetc() in many occasions.
Add fflush() function, just above scanf("%c", &ch). Because buffer of CONSOLE INPUT stores characters that not returned to program. Which is ENTER pressed in previous scanf:
#include <stdio.h>
int main() {
char ch='y';
int far, cen;
do {
printf("again\n");
scanf("%d",&far);
//cen = (5.0/9.0)*(far-32);//integer division will truncate to zero so we can make 5/9 to 5.0 / 9.0
cen = (5*(far-32))/9;//or this way we can use this formula
printf("\n%d\t%d",far, cen);
printf("ch=%c",ch);
scanf("%c",&ch); // This scanf will be ignored, because loads last
// character from buffer that can be recognized
// by scanf which is pressed "ENTER" from previous scanf
printf("%d", ch) // Shows 10, which is ASCII code of newline
fflush(stdin); // Clear buffer
scanf("%c",&ch); // Now it will prompt you to type your character.
// printf("%c"ch); //Without fflush, it must show 10, which is \n code
}while(ch == 'y');
return 0;
}
if after Y you press "space" or "return" this is the character you will find in %C

Resources