0

The Question is to take three names as input and check whether the 4th input is the first letter of one of those three names. *It needs to be only of alpha type and no other.

Sample Input:

@ON SNOW
ARYA STARK
HODOR
@ 

Output:

NO

My code:

#include <stdio.h>
#include <ctype.h>
int main(){
    char s1[100],s2[100],s3[100];
    char ch[1];
    scanf("%[^\n]s",s1);
    scanf("%[^\n]s",s2);
    scanf("%[^\n]s",s3);
    scanf("%s",ch);
    if(isalpha(ch[0]) && (s1[0]==ch[0] || s2[0]==ch[0] || s3[0]==ch[0]))
        printf("yes");
    else
        printf("no");
}

As I figured out that gets() no longer works, I tried scanf("%s",s1);. But since it does not store the calude after the whitespace " ", I tried this scanf("%[^\n]s",s1);. But the scanning stops at the first name itself.

John Player
NO

What is the way to store multiple strings in a char array without using loops and only using branching??

isekaid_maou
  • 273
  • 1
  • 9
  • 19
  • 2
    Try `"%[^\n]s"` --> `"%99[^\n]%*c"` – BLUEPIXY Jul 04 '17 at 17:59
  • @BLUEPIXY can u explain me what this means?! and yes ..the coding is working now! – isekaid_maou Jul 04 '17 at 18:05
  • 1
    Note that `%[…]` is a scan set, a complete conversion specification. The trailing `s` would only match a literal `s`, but since the next character is a newline, the match will fail, but you'll never know that. The scan sets (and `%c` and `%n` — and only these three conversion specifiers) do not skip leading white space. Add a blank to the start (not the end) of your code. Or use `fgets()` to read lines — that's probably better. – Jonathan Leffler Jul 04 '17 at 18:06
  • 1) `s` is superfluous. 2) It is necessary to consume the remaining newlines. – BLUEPIXY Jul 04 '17 at 18:07
  • @JonathanLeffler `fgets()` is an option. But since this is from the fundamental part of the book and library functions are not mentioned well yet, I wanted to know the other possibilities. _Add a blank to the start (not the end) of your code_ What do u mean by this? – isekaid_maou Jul 04 '17 at 18:25
  • Sorry: 'start (not the end) of your code' is horribly sloppily written. I meant 'format string' rather than 'code'. That is, consider using `" %99[^\n]"` and do not consider using `"%99[\n] "`. See [Trailing blank in `scanf()` format wreaks havoc](http://stackoverflow.com/questions/19499060/what-is-difference-between-scanfd-and-scanfd). – Jonathan Leffler Jul 04 '17 at 18:27
  • Why do you think gets wont work here? As i understand gets(str) will prompt user to enter string and that will be stored in str where str is a char[]. – Kraken Jul 04 '17 at 18:29
  • @Kraken: See [Why `gets()` is so dangerous that it should never, ever be used?](http://stackoverflow.com/questions/1694036/) – Jonathan Leffler Jul 04 '17 at 18:35
  • 1
    @Kraken I believe `gets()` has been removed from the stdio.h as a std library function because of situations causing buffer overflow and are suggested to us `fgets()`. These days you get a message saying : _implicit declaration of function ‘gets’ warning: the `gets' function is dangerous and should not be used_ – isekaid_maou Jul 04 '17 at 18:35
  • 1
    If only the fundamentals have been taught, then using `scanf()` with scan sets is unlikely to have been taught; it isn't part of the basics of `scanf()`. Using `fgets()` is relatively straight-forward. And the results are generally a lot more predictable than using `scanf()` et al. – Jonathan Leffler Jul 04 '17 at 18:37
  • regarding lines like: `scanf("%[^\n]s",s1);`. There are several problems. 1) always check the returned value (not the parameter values) to assure the operation was successful. In this case, if the returned value is not 1 then some error occurred. 2) the 's' requires that the incoming data contains a 's' at the end of the line, BUT the input/format specifier '%[^\n]' has left the newline in the input buffer, so no 's' will be found. Suggest: remove that trailing 's' 3) always include a MAX CHARACTERS modifier that is one less than the length of the input buffer, to avoid a buffer overflow. – user3629249 Jul 05 '17 at 23:16
  • (cont) the code should look similar to: `if( 1!= scanf( "%99[^\n]", s1 ) ) { fprintf( stderr, "scanf failed to input the string for 's1'" ); exit( EXIT_FAILURE ); }` – user3629249 Jul 05 '17 at 23:19
  • regarding: `char ch[1]; ... scanf("%s",ch); the input format specifiers: '%s' and '^[..]' always append a NUL byte to the input. so the array 'ch[]' is not big enough for even a single char. Suggest using: `char ch[1]; ... scanf("%c", &ch[0]);` – user3629249 Jul 05 '17 at 23:24
  • for ease of understanding and readability: 1) follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* 2) separate code blocks (for, if, else, while, do...while, switch, case, default) via a single blank line. – user3629249 Jul 05 '17 at 23:26
  • regarding this kind of statement: `printf("yes");` `stdout` is buffered and will not be displayed on the terminal until one of four things occurs 1) the buffer overflows 2) a newline sequence is output 2) this call is made: `fflush( stdout );` 4) the program exits. In the current scenario, the string: "yes" and the string "no" should both be terminated with a `\n` (newline) character. Also, since no formatting is being performed, an even better statement would be: `puts( "yes" );` as that will automatically add a newline sequence. – user3629249 Jul 05 '17 at 23:33

3 Answers3

1

Now before getting to the specified problem lets see what the actual problem is:

  • Problem with scanf()

    The problem with scanf() is that it is really bad at managing overflows. And in case of chars or char sequences the newline character is read on the press of enter key in the subsequent scanning. There are numerous instances on SO that concern this problem. scanf() leaves the new line char in buffer? and Problems with scanf

  • Problem with gets()

    The biggest drawback is that here you need to know the size of input before-hand. If you know your input extremely well, you may use it (Still I won't recommend). Why is the gets function so dangerous that it should not be used?

  • Problem with fgets()

    There are two really common problems with fgets()

    The syntax of fgets() is:

          char *fgets(char *restrict s, int n, FILE *restrict stream);`
    

    and generally used like

          fgets(char_array,100,stdin)
    
    1. First problem arises when the input is bigger than the integer n provided in the fgets() second parameter. When the input in the buffer is bigger than n it will strip off 1st n chars and allocate it the char pointer which might be a char array. But what about remaining chars? They still are there in the input buffer and will be allocated to next fgets(). Messing things up.

    2. Second problem is that every time a new line feed is allocated to the end of char sequence when the input is smaller than the int n-1.

But if we think for a while the problems with fgets() can be tackled with a simple trick.

  • Just check for the last character in the char sequence which has been recently allocated. If it is new line, replace it by NULL. Else we know that the input was more than that int provided inside fgets(). So all we have to do is eat up the remaining chars in the input buffer.

Here is an example:

   char str1[5];
   char str2[5];
   fgets(str1,5,stdin);

   if(strlen(str1)>0){//to avoid Undefined Behavior in case of null byte input

       if(str1[strlen(str1)-1]=='\n'){

           str1[strlen(str1)-1]='\0';
       }
       else{

           while((getchar())!='\n');//eating the remaing chars in the buffer
       } 
   }

   fgets(str2,5,stdin);


   if(strlen(str2)>0){

      if(str2[strlen(str2)-1]=='\n'){

         str2[strlen(str2)-1]='\0';

      }
      else{

         while((getchar())!='\n');
      }

   }
   printf("\n1.%s\n2.%s",str1,str2);

You could even convert strings you got using fgets to float and integers using things like strol or sscanf, but beware they may not show independent behavior.

Now coming back to the solution to your problem:

#include <stdio.h>
#include <string.h>

int main(){
    char s1[100],s2[100],s3[100];
    char ch[2];//make ch atleast 2 char wide

    fgets(s1,100,stdin);
     if(strlen(s1)>0){

          if(s1[strlen(s1)-1]=='\n'){

             s1[strlen(s1)-1]='\0';

          }
          else{

             while((getchar())!='\n');
          }

    }

   fgets(s2,100,stdin);
     if(strlen(s2)>0){

          if(s2[strlen(s2)-1]=='\n'){

             s2[strlen(s2)-1]='\0';

          }
          else{

             while((getchar())!='\n');
          }

    }

   fgets(s3,100,stdin);
     if(strlen(s3)>0){

          if(s3[strlen(s3)-1]=='\n'){

             s3[strlen(s3)-1]='\0';

          }
          else{

             while((getchar())!='\n');
          }

    }    

    fgets(ch,2,stdin);
      if(strlen(ch)>0){

          if(ch[strlen(ch)-1]=='\n'){

              ch[strlen(ch)-1]='\0';

          }
          else{

              while((getchar())!='\n');
          }

     }

    if(isalpha(ch[0]) && (s1[0]==ch[0] || s2[0]==ch[0] || s3[0]==ch[0]))
        printf("yes");
    else
        printf("no");

        return 0;
}
Pushan Gupta
  • 3,697
  • 5
  • 23
  • 39
0

Try fgets.

fgets(s1,100,stdin);
fgets(s2,100,stdin);
fgets(s3,100,stdin);
Claysmile
  • 21
  • 3
0
#include <stdio.h>
int main(){
char s1[100],s2[100],s3[100];
char ch[1];

fgets(s1,100,stdin);// like gets but limited by length
fgets(s2,100,stdin);
fgets(s3,100,stdin);

scanf("%s",ch);

if( (s1[0]>='a' && s1[0]<='z') || (s1[0]>='A' && s1[0]<='Z') ){//ch-alpha?
    if(s1[0] == ch[0]){  printf("yes"); }//s1[0] == ch[0] ??
    else{ printf("no"); }
    }
else
    printf("no"); return 0; }
Win Key
  • 49
  • 1
  • 7