As already pointed out in the comments section, the problem is that the line
scanf("%s",&k[i]);
is wrong. When using scanf
with the %s
format specifier, it will read a whole word of input and write that word into the character array k
(causing a buffer overflow in your case).
If you want to only read a single character, you should use the %c
format specifier instead of %s
.
However, using "%c"
has the problem that it will always read the first character on the input stream, which could be a newline character. If you don't want scanf
to write newline characters into your variable, you can use the format string " %c"
instead. This will cause scanf
to first extract and discard all whitespace characters (spaces, tabs, newlines, etc.) from the input stream before extracting and writing the character to your variable. That way, scanf
will never write a newline character to your variable.
The solution described above describes how to solve your problem with scanf
. However, for line-based input, using scanf
is generally not recommended. See this guide for some alternatives:
A beginners' guide away from scanf()
One reason why using scanf
is bad is for example the following:
Let's say that you want to input two characters from the user. Using scanf
, your code might look like this:
char first, second;
printf( "Please enter the first character: " );
scanf( " %c", &first );
printf( "Please enter the second character: " );
scanf( " %c", &second );
If the user responds to the first prompt by entering several characters before pressing ENTER, then scanf
will accept this input as valid and return the first character the user entered. The second call to scanf
will return the second character the user entered. It will not wait for the user to enter a new line of input. In other words, scanf
will take the user's response to the first prompt as an answer to the second prompt.
This example shows that scanf
is not designed for reliably taking line-based input from the user. Therefore, I recommend that you use the function fgets
instead. That way, you can for example reject user input if the user enters more than one character per response line.
In your case, I would recommend creating a function get_char_from_user
which uses fgets
instead of scanf
, for example like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//this function will continue prompting the user until
//the user enters a valid response of a line consisting
//of exactly one character
char get_char_from_user( const char *prompt )
{
for (;;) //infinite loop
{
char buffer[1024], *p;
//prompt user for input
fputs( prompt, stdout );
//attempt to read exactly one line of input
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
printf( "Error reading input from user!\n" );
exit( EXIT_FAILURE );
}
//find the newline character, if it exists
p = strchr( buffer, '\n' );
//make sure that entire line was read into buffer
if ( p == NULL && !feof(stdin) )
{
int c;
printf( "The line was too long to fit buffer.\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
printf( "Unrecoverable error when reading from input!\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//remove the newline character from string
*p = '\0';
//verify that exactly one character was entered
if ( strlen( buffer ) != 1 )
{
printf( "Error: Please enter exactly one character!\n" );
continue;
}
return buffer[0];
}
}
Using this function, the example above which reads two characters from the user can be changed to the following:
char first, second;
first = get_char_from_user( "Please enter the first character: " );
second = get_char_from_user( "Please enter the second character: " );
Now, the code is both simpler and has much better input validation.
However, in the case of your original code, it would be nice to be able to write code in such as way as that it allows you to write prompts such as
Please enter the first character:
Please enter the second character:
Please enter the third character:
Please enter the fourth character:
Please enter the fifth character:
in a loop. This would require changing the prompt
parameter of the get_char_from_user
to a printf
format string. Afterwards, you would be able to write code like this:
int main()
{
const char * const nth_strings[] =
{ "first", "second", "third", "fourth", "fifth" };
char k[5];
for ( int i = 0; i < 5; i++ )
{
k[i] = get_char_from_user(
"Please enter the %s character: ",
nth_strings[i]
);
}
printf( "You entered the following characters:\n" );
for ( int i = 0; i < 5; i++ )
{
putchar( k[i] );
}
}
This is possible, by making the function get_char_from_user
a variadic function, like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
//this function will continue prompting the user until
//the user enters a valid response of a line consisting
//of exactly one character
char get_char_from_user( const char *prompt, ... )
{
for (;;) //infinite loop
{
char buffer[1024], *p;
va_list vl;
//prompt user for input
va_start( vl, prompt );
vprintf( prompt, vl );
va_end( vl );
//attempt to read exactly one line of input
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
printf( "Error reading input from user!\n" );
exit( EXIT_FAILURE );
}
//find the newline character, if it exists
p = strchr( buffer, '\n' );
//make sure that entire line was read into buffer
if ( p == NULL && !feof(stdin) )
{
int c;
printf( "The line was too long to fit buffer.\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
printf( "Unrecoverable error when reading from input!\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
continue;
}
//remove the newline character from string
*p = '\0';
//verify that exactly one character was entered
if ( strlen( buffer ) != 1 )
{
printf( "Error: Please enter exactly one character!\n" );
continue;
}
return buffer[0];
}
}
If you combine the last two code blocks (the function main
and the function get_char_from_user
) into one program, you will get the following interaction between the program and user:
Please enter the first character: Hello
Error: Please enter exactly one character!
Please enter the first character: H
Please enter the second character: e
Please enter the third character: l
Please enter the fourth character: l
Please enter the fifth character: o
You entered the following characters:
Hello
As you can see, the program rejected the input when entering several characters at once, in the same line, and prompted the user a second time.