-2

EDIT@ I'll just use a string as I can't seem to find a way to solve this with a character

I have the following:

char character;
int valid = 1;

do {

    if( valid == 0 ) {
        printf("ERROR");
    }

    valid = 1; // Validates it again if the do while loop activates

    character = inputCharacter("Insert the character: ");
    system("clear");

    if( certainCondition ) {
        valid = 0;
    }

} while( valid != 1 ); 

inputCharacter being:

char inputCharacter(char* message) { // Inputs a character

    char character;

    printf("%s", message);
    scanf(" %c", &character);

    return character;

}

This function will accept a character and if it is equal to an another character I've typed before it will ask for a new character.

What I wanted to know is:

Is it possible to check if the character input has more than one character, and if so, ask for a new character input while giving an "ERROR: One character only"?

Example:

First character: e

Insert the character: e | ERROR

Insert the character: easd | ERROR: Please insert one character only

Insert the character: wflek | ERROR: Please insert one character only

Insert the character: a | accepts

Is this possible without the use of a string?

(It is fine if I can't give out the error while not allowing more than one character but it would be cool if I was able to)

Ran
  • 153
  • 4
  • 16
  • `scanf` is making your life extremely difficult here... Why not either read each *line* of user input into a buffer (e.g. with `fgets`) and check the first char and the length of the string or use `getchar` in a loop until you find `'\n'` or `EOF`? – David C. Rankin Jun 14 '17 at 19:47
  • My bad about that one, I thought valid alone would run well. – Ran Jun 14 '17 at 19:52

4 Answers4

3

It less error-prone to use fgets() to get a line of text, and sscanf() to parse the line. This is also a more flexible approach that allows multiple scans of the input line when necessary. Note that fgets() keeps the newline character, if there is room in the buffer. Thus one approach would be to read a line of text, and get the first character and the second character. If both characters are successfully read, and the second character is a \n, then input is as expected.

You should always check the return values from functions which do return a value. This can be used to help validate input. In the code below, if sscanf() does not return 2, then a character (other than the newline) was not entered. If two characters were scanned, the second should be a \n; if it is not, more than one character (not including the newline) was entered by the user. Also note that the return value from fgets() itself is checked for errors; an error here causes the program to terminate with an error message.

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

#define BUF_SIZE  1000

int main(void)
{
    char c, rest;
    char buffer[BUF_SIZE];

    do {
        printf("Please enter exactly one character: ");
        if (fgets(buffer, BUF_SIZE, stdin) == NULL) {
            perror("Error in fgets()");
            exit(EXIT_FAILURE);
        }
    } while ((sscanf(buffer, "%c%c", &c, &rest) != 2) ||
             (rest != '\n'));

    printf("You entered: %c\n", c);

    return 0;
}
Sample program interaction:

Please enter exactly one character: 
Please enter exactly one character: fgh
Please enter exactly one character: h
You entered: h
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
3

possible without the use of a string (for input) (?)

Use fgetc()/fgetchar() to read in a character at a time.

int read1char(const char *prompt, const char *reprompt) {
  int ch;
  do {
    // print prompt
    fputs(prompt, stdout);
    fflush(stdout);
    prompt = reprompt;

    // Read first character
    ch = fgetc(stdin);
    if (ch == '\n') continue;
    if (ch == EOF) break;

    // Look for a \n or EOF
    int cheol = fgetc(stdin);
    if (cheol == '\n' || cheol == EOF) break;

    // consume rest of the line
    do {
      ch = fgetc(stdin);
    } while (ch != '\n' && ch != EOF);
  } while (ch != EOF);
  return ch;
}

int main(void) {
  int ch;
  while ((ch = read1char("Insert the character: ",
      "\nERROR: One character only\n" "Insert the character: ")) != EOF) {
    printf("<%c>\n", ch);
  }
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • I sort of ignored OP's request to do without strings, sticking to what seems to be less error-prone and simpler to implement. But have an upvote for more closely following OP's wishes :) – ad absurdum Jun 14 '17 at 23:27
1

Is it possible to check if the character input has more than one character, and if so, ask for a new character input while giving an "ERROR: One character only"?

Let's start by unravelling the double-barreled question into two questions. In the future, please avoid combining questions like this.


First part:

Is it possible to check if the character input has more than one character...?

No. It's not possible for a character to store more than one character. If you want to store more than one character, you need more storage than just one char.


Second part:

... if so, ask for a new character input while giving an "ERROR: One character only"?

... Is this possible without the use of a string?

It doesn't make sense to assume stdin will only contain one character (from the first part) and then ask for another character, does it?

I think what you mean is to ask for a line of input that contains only one character. You need to consider the definition of line of input.

On a related note, you need to realise that the space in " %c" doesn't just cause spaces to be discarded; it also discards newlines. If you want to eliminate spaces only, use scanf("%*[ ]"); first, then use "%c". These two calls should be separate (not combined) as the first will fail when there are no spaces, causing an early return.

A line of input ends with the '\n' or newline character; that paired with the one character only that you want implies that you need to read at least two characters in order to check that the one character only exists on a line all by itself. i.e. something like this might be appropriate:

int c;
do {
    printf("%s", message);
    scanf("%*[ ]"); // discard leading spaces
    c = getchar();
} while (/* check for empty line      */    c == '\n'
         /* check for multiple chars  */ || getchar() != '\n'
         /* discard multiple chars    */ && scanf("%*[^\n]") == 0
         /* discard the trailing '\n' */ && getchar() == '\n'
         /* print error message       */ && puts("ERROR: One character only") != EOF);
Community
  • 1
  • 1
autistic
  • 1
  • 3
  • 35
  • 80
0

I would say, the easiest way here is to use a string, something like this

    char character[255] = "";  
    scanf("%255s", character); // or use gets(character);

    if(character[1] == 0)
    {
       // 1 char entered
    } else {
       // more than one
    }
  • 1
    Why `character[1]` should not be zero before the `scanf()` ? This answer is wrong, who upvote this ? – Stargateur Jun 14 '17 at 19:53
  • 1
    And don't suggest `gets()`! [The usafe `gets()`](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) should never be used for any reason. It was deprecated in C99, and completely removed from the language in C11. – ad absurdum Jun 14 '17 at 19:54
  • @Stargateur. Just run the code bro. If it's working - it is not stupid. – KillerIsDead Jun 14 '17 at 19:56
  • I was trying to avoid a string but I'll go the string way, thank you. – Ran Jun 14 '17 at 20:15
  • you never known if `character[1] == 0` , your pointer on character get by assignation of an empty string NEVER set each bit to 0, in your case, you have to iterate over the array and set each char to 0, by the way, you can use a memset to do such a thing : `memset(character, 0, 254);` – Xephi Jun 14 '17 at 21:16
  • 1
    Off by 1. `char character[255] = ""; scanf("%254s", character);` 254, not 255. – chux - Reinstate Monica Jun 14 '17 at 21:39