0

I have this program that I finally finished however I am trying to get it after finishing once to prompt the user "Do you wish to run again? Yes(Y), No(N)". But I also want it to ask for s2 again, and the ch again as well. Keeping s1 to be the same random string if that makes sense.

This is my code:

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

void s1(char *random);
void s2(char *s2_input, int index);
void strfilter(char *random, char *s2_input, char replacement);

int main()
{
    char run = 'Y';
    while(run != 'N')
    {

    int s1_index = 41;
    char s1_random[s1_index];
    s1(s1_random);
    printf("\ns1 = ");
    puts(s1_random);
    printf("s2 = ");
    int s2_index = 21;
    char s2_input[s2_index];
    s2(s2_input, s2_index);
    if(s2_input[1] == '\0')
    {
        printf("size too small");
        exit(0);
    }

    printf("ch = ");
    char replacement = getchar();
    printf("\n");
    int filter_index = 41;
    strfilter(s1_random, s2_input, replacement);
   printf("\ns1 filtered = ");
   puts(s1_random);

    printf("Do you wish to run again? Yes(Y), No(N) ");
    scanf("%c", &run);
}
}




void s1(char *random)
{
    int limit = 0;
    char characters;
    while((characters = (('A' + (rand() % 26))))) /* random generatro */
    {
        if(limit == 41)
        {
            *(random + 41 - 1) = '\0';
            break;
        }
        *(random + limit) = characters;
        limit++;
    }
}



void s2(char *s2_input, int index)
{
    char array[21] = "123456789012345678901"; /* populated array to make sure no random memory is made */
    char input;
    int count = 0;
    int check = 0;

    while((input = getchar() ))
    {
        if(input == '\n')
        {
            *(s2_input + count) = '\0';
            break;
        }

        else if(input < 65 || input > 90)
        {
            printf("invalid input");
            exit(0);
        }

        *(s2_input + count) = input;
        count++;
    }

    index = count;
}

void strfilter(char *random, char *s2_input, char replacement) /* replacement function */
{
    while(*s2_input)
    {
        char *temp = random;

        while(*temp)
        {
            if(*temp == *s2_input)
                *temp = replacement;
            temp++;
        }
        s2_input++;
    }
}

At first I tried a do-while loop within the main function. But it doesn't seem to work. It just messes up the output of my program and still doesn't prompt the user. Should I create a new function with the sole purpose of prompting the User? If so how would I? Thanks in advance.

  • The `while` loop should work. Show what you tried. – Barmar Nov 19 '22 at 05:24
  • 1
    I suspect the problem is with how you're reading the y/n answer, not the loop. See https://stackoverflow.com/questions/1391548/why-doesnt-getchar-wait-for-me-to-press-enter-after-scanf – Barmar Nov 19 '22 at 05:25
  • @Barmar I tried char run = 'Y'; while(run != 'N') {all my code in int main printf("Do you wish to run again? Yes(Y), No(N) "); scanf("%s", &run); } –  Nov 19 '22 at 05:28
  • You have an issue with using `getchar`: `char replacement = getchar();`. This is wrong. `getchar` returns an `int`, not a `char`. It might work for normal characters. It might also work in your loop if you only want to check for `Y/N`. But it can fail as soon as you want to compare with `EOF` as you might not be able to distinguis `255` from `EOF` if your system uses `unsigned char`. – Gerhardh Nov 19 '22 at 05:29
  • You can't use `%s` with a `char` variable, it requires a string. – Barmar Nov 19 '22 at 05:30
  • `char run = 'Y'`Your attempt should result in lots of compiler warnings. You want `char run = 'Y'`, i.e. a single character instead of a string. (You also cannot compare strings with `==` but you need `strcmp`) And you cannot read a string into a single character as it does not provide any memory for storing the terminating 0 byte – Gerhardh Nov 19 '22 at 05:31
  • @Gerhardh, so then what exactly should I do. I understand what your saying, however I am confused on implementing it. –  Nov 19 '22 at 05:32
  • Which part is unclear. Making `replacement` and `int` and changing `"Y"` into `'Y'` are rather straight forward. Which part keeps confusing you? – Gerhardh Nov 19 '22 at 05:35
  • @Gerhardh so then I should still use char run = 'Y'; while(run != 'N') and then printf("Do you wish to run again? Yes(Y), No(N) "); scanf("%c", &run);? Because I used '' when I first tried it. –  Nov 19 '22 at 05:38
  • Then maybe you should show it in the code you provide?! We cannot read your mind. How did you use it? What problems did you get? You might stumple over some pending `\n` that were left in input buffer or anything else we cannot know unless we see what you do. Note: `while(run != 'N')` that can be OK but it will also continue the loop if you enter a lower case `'n`or any other character'. Maybe `while(toupper(run) == 'Y')` – Gerhardh Nov 19 '22 at 05:39
  • @Gerhardh I edited the question and showed what I tried. –  Nov 19 '22 at 05:42
  • OT: What is the purpose of passing `s2_index` to `s2` ? And do you expect `index = count;` to change `s2_index` ? – Support Ukraine Nov 19 '22 at 06:15
  • @SupportUkraine, my issue isn't my actual code. The output runs exactly how I wish. I just need to add the loop somehow. I edited the question with a do while loop, which is what I tried but it doesn't work exactly. –  Nov 19 '22 at 06:20
  • @KevinAlvarez My guess is that you are not treating newlines correct... Remember that `scanf("%c", &run);` will leave a newline in the input stream – Support Ukraine Nov 19 '22 at 06:21
  • @SupportUkraine, that could be true. However it doesn't prompt the user if the person wishes to run. It simply just runs it again, and prints out the promt wihout taking an input. –  Nov 19 '22 at 06:22
  • @KevinAlvarez yes... there is a newline left in the stream from previous inputs and that breaks the logic – Support Ukraine Nov 19 '22 at 06:23
  • OT: `s2` allows the user to overflow the input buffer – Support Ukraine Nov 19 '22 at 06:26

2 Answers2

1

To avoid running afoul of trailing data, call readchar() till you get a newline or EOF after each prompt:

    for(;;)
    {
        int s1_index = 41;
        char s1_random[s1_index];
        s1(s1_random);
        printf("\ns1 = ");
        puts(s1_random);
        printf("s2 = ");
        int s2_index = 21;
        char s2_input[s2_index];
        s2(s2_input, s2_index);
        if(s2_input[1] == '\0')
        {
            printf("size too small");
            exit(0);
        }

        printf("ch = ");
        int replacement = getchar();
        if(replacement == EOF)
            break;
        while(getchar() != '\n');
        printf("\n");
        strfilter(s1_random, s2_input, replacement);
        printf("\ns1 filtered = ");
        puts(s1_random);

        printf("Do you wish to run again? Yes(Y), No(N) ");
        int run = getchar();
        // or include ctype.h and do:
        // run == EOF || toupper(run) == 'N'
        if(run == EOF || run == 'N' || run == 'n')
            break;
        while(getchar() != '\n');
    }

and example run:

s1 = NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJY
s2 = NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJY
ch = B


s1 filtered = BBBBBBBB
Do you wish to run again? Yes(Y), No(N) y

s1 = DBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPK
s2 = NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJY
ch = B  


s1 filtered = BBBBBBBB
Do you wish to run again? Yes(Y), No(N) N
Allan Wind
  • 23,068
  • 5
  • 28
  • 38
0

A very common mistake in C programs taking user input from stdin using getchar and scanf is to forget that these functions may leave newlines (or other characters) in the input stream.

In this case the line

scanf("%c", &run);

will leave (at least) a newline in the stream. That newline will be read by the next getchar and thereby make the program have unexpected behavior.

So your code should remove that newline just after the scanf. Actually it should remove all characters until it sees a newline.

Further, I would also remove any white space present in the stream before scanning for the user input. That can be done simply by putting a space before %c

Finally, your prompt suggests that you expect the user to input either Y or N but your program continues on any input not being an N

Something like this should fix the above mentioned problems:

char run = 'Y';
while(run != 'N')
{
    // ... do your stuff

    while(1)
    {
        // notice the space before %c to remove initial white spaces
        if (scanf(" %c", &run) != 1) exit(1);  // Input error

        // Empty the input stream until a newline is found
        while (1)
        {
            int temp = getchar();
            if (temp == '\n') break;   // Found end-of-line so break this while-loop
            if (temp == EOF) exit(1);  // Input error
        }

        if (run == 'Y' || run == 'N') break;  // Valid input so break this while-loop
    }
}
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63