0

My assignment: -

Write a program that replaces the occurence of a given character (say c) in a primary string (say PS) with another string (say s).

Input: The first line contains the primary string (PS) The next line contains a character (c) The next line contains a string (s)

Output: Print the string PS with every occurence of c replaced by s.

Test case 1: -

Input: -

abcxy

b

mf

Expected output: -

amfcxy

Test case 2: -

Input: -

Al@bal#20owL

l

LL

Expected output: -

ALL@baLL#20owL

My code below: -

#include <stdio.h>
#include <stdlib.h>

int main() {
    char PS[101];
    char c;
    char S[11];
    
    fgets(PS, 101, stdin);          //PS value input.
    
    scanf("%c", &c);
    if (c == '\n' || c == '\0') {
        scanf("%c", &c);              //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
    }

    fgets(S, 11, stdin);            //S value input.
    
    int i = 0;
    while (PS[i] != '\0') {          //Removing the '\n' from PS
        if (PS[i] == '\n') {
            PS[i] = '\0';
            break;
        }
        i++;
    }
    i = i - 1;                      //i now holds the value of the size of the string PS (excluding '\0')
    
    int j = 0;
    while (S[j] != '\0') {
        if (S[j] == '\n') {
            S[j] = '\0';
            break;
        }
        j++;
    }
    j = j - 1;                      //j now holds the value of the size of the string S (excluding '\0')
    
    int k = 0;                      //work as an initializer
    int move = 0;                   //work as an initializer.
    
    while (PS[k] != '\0') {         //This loops checks the whole array for the same character mentioned in char 'c'
        if (PS[k] == c) {
            for (move = i; move > k; move --) {   //This loop advances the all the characters in PS by '(j - 1)' steps to make space for string S characters.
                PS[move + (j - 1)] = PS[move];
            }
            
            for (move = 0; move < j; move++) {    //This loop adds all the characters of string S into string PS at the relevant place.
                PS[k + move] = S[move];
            }
            
            i = i + (j - 1);                    // 'i' now holds the new value of size of string PS after adding all the characters of string S.
        }
        k++;
    }
    
    puts(PS);
    
    return 0;
}

Now the problem is that the code is not taking the input for string S.

After inputting first 2 inputs, it executes and gives a gibberish answer. I cannot figure out the bug, but what I do know is that there is some issue related to the buffer in C. Please help.

Edit: -

Thanks to @WeatherVane I have now edited the code with this: -

    scanf("%c", &c);
    if (c == '\n' || c == '\0') {
        scanf("%c", &c);              //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
    }
    
    char x;
    x = getchar();                    //New addition. It eats the '\n' after scanf().
    
    fgets(S, 11, stdin);            //S value input.

Now my code is working fine but the output is still not correct. It is sometimes failing to copy the last char from string S or giving me gibberish output.

chqrlie
  • 98,886
  • 10
  • 89
  • 149
Swarnim Khosla
  • 113
  • 1
  • 9
  • 4
    Please see [fgets() doesn't work after scanf](https://stackoverflow.com/questions/5918079/fgets-doesnt-work-after-scanf). The simple answer is not to mix them. Get all your inputs with `fgets()`. BTW I would work with larger strings than you have. You can afford to use twice the buffer size you imagine you will need, certainly to begin with. `char S[11];` looks as though you have something very specific in mind, but don't forget newlines, string terminators, random spaces etc. – Weather Vane Oct 11 '20 at 12:13
  • To "flush" or clear the input buffer of `stdin`, don't use `scanf`. First of all you use it wrongly, secondly it's overly powerful for something that simple. First of all you need a loop, then in the loop use e.g. [`getchar`](https://en.cppreference.com/w/c/io/getchar) until you have read either a newline or `EOF`. But please note that `getchar` returns an ***`int`*** which is important for that `EOF` check. – Some programmer dude Oct 11 '20 at 12:20
  • @Someprogrammerdude I know my code sucks, but can you please post an answer for my "edit" as well as what practices should I use to keep the buffer clean? – Swarnim Khosla Oct 11 '20 at 12:22
  • If you are using `fgets()` for all your input you don't need to "clean out the buffer". You input one string, then you input another one. The newlines are read into the strings, and there aren't any `'\0'` characters that come in. So you don't need `scanf()` at all. Please see [Removing trailing newline character from fgets() input](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input/28462221#28462221) although obviously the search character is simply the first character of that particular string. – Weather Vane Oct 11 '20 at 12:33
  • "code is working fine but the output is still not correct." --> Rather than only describe output, post the exact output. – chux - Reinstate Monica Oct 11 '20 at 12:37
  • I suspect `for(move = i; move > k; move --) //This loop advances the all the characters in PS by '(j - 1)' steps to make space for string S characters.` is incorrect as the _null character_ might not have moved. – chux - Reinstate Monica Oct 11 '20 at 12:39
  • You could make it simpler by building another string. Copy each character to the new string unless it is the one to be replaced, when you copy the replacement string instead. Finally add a string terminator. – Weather Vane Oct 11 '20 at 12:44

1 Answers1

0

The problem with the code was: -

i = i - 1;                     //i now holds the value of the size of the string PS (excluding '\0')
j = j - 1;                     //j now holds the value of the size of the string S (excluding '\0')

The value of i and j are the true values of the size of string PS and string S; not i = i - 1 and j = j - 1.

Lesson learnt from this assignment: -

  1. scanf() does not treat '\n' in any way. It WILL be left in the buffer.
  2. If possible use fgets and then remove '\n' from your respective array/pointer.
  3. Be extra careful of your C buffer when dealing with chars and strings.

The final correct code is: -

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char PS[101];
    char c;
    char S[11];
    
    
    fgets(PS, 101, stdin);          //PS value input.
        

    
    scanf("%c", &c);
        if(c == '\n' || c == '\0')
        {
            scanf("%c", &c);              //Clearing the buffer. I want the real value of 'c' from STDIN not '\n'
        }
        
        
        char x;
        x = getchar();                    //New addition. It eats the '\n' after scanf().
        
        
        fgets(S, 11, stdin);            //S value input.
    
    
    
    int i = 0;
    while(PS[i] != '\0')            //Removing the '\n' from PS
    {
        if(PS[i] == '\n')
        {
            PS[i] = '\0';
            break;
        }
        
        i++;
    }
    i = i;                     //i now holds the value of the size of the string PS (excluding '\0')
    
    
    
    
    int j = 0;
    while(S[j] != '\0')
    {
        if(S[j] == '\n')
        {
            S[j] = '\0';
            break;
        }
        j++;
    }
    j = j;                     //j now holds the value of the size of the string S (excluding '\0')
    
    
    
    int k = 0;                      //work as an initializer
    int move = 0;                   //work as an initializer.
    
    
    
    while(PS[k] != '\0')            //This loops checks the whole array for the same character mentioned in char 'c'
    {
        if(PS[k] == c)
        {
            for(move = i; move > k; move --)    //This loop advances the all the characters in PS by '(j - 1)' steps to make space for string S characters.
            {
                PS[move + (j - 1)] = PS[move];
            }
            
            for(move = 0; move < j; move++)     //This loop adds all the characters of string S into string PS at the relevant place.
            {
                PS[k + move] = S[move];
            }
            
            i = i + (j - 1);                    // 'i' now holds the new value of size of string PS after adding all the characters of string S.
        }
        k++;
    }
    
    puts(PS);
    
    
    return 0;
}

Warning: -

  1. The above code is very unoptimised and unreadable. Do not use it for long term projects. It just "works".
  2. Any suggestions for improvements of the above code are welcomed in the comments.

Further necessary reading material recommended if you face any issue regarding C buffer in the future: -

  1. Read 1
  2. Read 2
Swarnim Khosla
  • 113
  • 1
  • 9