All 3 format begin with "%[^\n]".
"%[^\n]" is poor code2 that lacks a width limit and is susceptible to buffer overrun.  Use a width limit like "%99[^\n]"  with char s[100];.
"%[...]" does not consume leading whitespace like many other specifiers.
This specifier directs reading input until a '\n'1 is encountered.  The '\n' is put back into stdin.  All other characters are saved in the matching destination's array s.
If no characters were read (not counting the '\n'), the specifier fails and scanf() returns without changing s - rest of the format is not used.  No null character appended.
If characters were read, they are saved and a null character is appended to s and scanning continues with the next portion of the format.
"\n" acts just like " ",  "\t", "any_white_space_chracter" and reads and tosses 0 or more whitespace characters.  It continues to do so until a non-white-space1 is read.  That non-whitespace character is put back into stdin.
Given line buffered input, this means a line with  non-whitespace following input is needed to see the next non-whitespace and allow scanf() to move on.
With scanf(), a "\n" at the end of a format is bad and caused OP's problem.
"%*c" reads 1 character1 and throws it away - even if it is not a '\n'.  This specifier does not contribute to the return count due to the '*'.
A better alternative is to use fgets().
char s[100];
if (fgets(s, sizeof s, stdin)) {
   s[strcspn(s, "\n")] = '\0';  // To lop off potential trailing \n
A lesser alternative is
char s[100] = { 0 };
scanf("%99[^\n]", s);
// With a separate scanf ....
scanf("%*1[\n]");  // read the next character if it is a \n and toss it.
1 ...  or end-of-file or rare input error.
2 IMO, worse than gets().