char ask2;
and
scanf("%s", &ask2);
are a problem.
The %s
specifier tells scanf
to expect a string. In C, strings are zero terminated and scanf
will append a zero to the input. ask2
is a single character so when the zero is appended, it corrupts memory adjacent to ask2
.
scanf ( " %c", &ask2);
will correct the problem. The %c
specifier tells scanf
to expect a single character. The space before %c
tells scanf
to scan and discard whitespace.
Another issue with %s
is it will scan a series of non-whitespace characters, stopping at the next whitespace character. If the input could contain whitespace, then something else is needed.
scanf ( " %99[^\n]", clip);
could be used. Note the 99 to limit the number characters allowed. The scanset [^\n]
tells scanf
to accept any characters that are not a newline. The scan will stop at a newline or 99 characters.
fgets
is another option. It takes a pointer to an array, the size of the array and the stream to read from.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
int parseint ( char *line, int *value) {
char *end = NULL;
long int number = 0;
errno = 0;
*value = 0;
number = strtol ( line, &end, 10);
if ( end == line) { // nothing was parsed. no digits
fprintf ( stderr, "problem parsing an integer\n");
return 0; // return failure
}
if ( 0 != end[strspn ( end, " \f\n\t\v")]) { // if trailing non-whitespace (6y) is ok, remove this block
fprintf ( stderr, "problem trailing non-digit characters\n");
return 0;
} // if trailing non-whitespace (6y) is ok, remove this block
if ( errno != 0 || number > INT_MAX || number < INT_MIN) { // parsing error from strtol
fprintf ( stderr, "problem error from strtol\n");
return 0;
}
*value = number; // assign number to pointer
return 1;//success
}
int main ( void) {
int ask = 0;
char ask2[40] = "";
char clip[100] = "";
int retry = 0;
do {
if ( retry) {
printf ( "\t\tenter 1 or 2. try again\n");
}
printf("1.start\n2.exit\n");
if ( ! fgets ( ask2, sizeof ask2, stdin)) {
fprintf ( stderr, "problem getting input\n");
return 1;
}
if ( 0 == ( parseint ( ask2, &ask))) {
return 1;
}
retry = 1;
} while ( 1 != ask && 2 != ask);
while (ask == 1) {
retry = 0;
do {
if ( retry) {
printf ( "\t\tenter one character. try again\n");
}
//options
printf("what you want to do :\nA.Enter on Clipboard\nB.Check or Edit Clipboard\nC.Exit\n");
printf("enter A/a,B/b,C/c to select option : ");
if ( ! fgets ( ask2, sizeof ask2, stdin)) {
fprintf ( stderr, "problem getting input\n");
return 1;
}
retry = 1;
} while ( '\n' != ask2[1]);
printf("\n");
switch ( ask2[0]) {
case 'A':
case 'a':
printf(":");
if ( ! fgets ( clip, sizeof clip, stdin)) {
fprintf ( stderr, "problem getting input\n");
return 1;
}
break;
case 'B':
case 'b':
printf("Clipboard:->%s\n", clip);
break;
case 'C':
case 'c':
ask = 2;
break;
default:
printf ( "wrong input\n");
}
}
return 0;
}
This uses fgets
with two arrays to obtain input. A function uses strtol
to parse an integer. strtol
has better error checking than scanf
using %d
.
This also uses a switch
to process each option.
scanf("%s", &clip);
also, it should bescanf("%99s", clip);
but it will only read a single word. Note the removed&
as well as the length restriction.scanf(" %99[^\n]", clip);
, instead ofscanf("%99s", clip);
, to be able to read entire sentences (not only single words).scanf
automatically filter leading whitespace, but%c
and%[]
and%n
do not. Adding a space in front of the%
instructsscanf
to filter leading whitespace here too. The reason is those three specifiers allow you to read every character including whitespace, but a way is provided so they behave like%d
and%f
and%s
(etc) where needed. Also see scanf() leaves the newline char in the buffer.'1'
and'\n'
(new line character), so the scanf which expects to read an int will consume the character'1'
and convert it into an int, but the character'\n'
will be left in stdin, so without the space before%c
to discard it, this character would be read by the second scanf which expects to read a character.scanf("%d", &ask);
returns 0, what doesask
contain when you first hitwhile (ask == 1)
?