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

int main()
{
    char *userInput;
    userInput = (char*)malloc(sizeof(userInput));

    printf("Commands:\n");
    printf("\ta name - adds given name to list\n");
    printf("\tr name - removes given name from list\n");
    printf("\tp      - prints out list\n");
    printf("\te      - exits\n");

    printf("\n\nEnter a command: ");
    scanf("%s\n",userInput);
    printf("\nThe user input was: %s\n", userInput);

    return 0;
}

I compile the code "gcc -std=gnu99 -m32 -Wall -g -o namelist namelist.c" whenever I run the executable all of the first printf are displayed and I get prompt on an input. Whenever I enter an input and press enter, I don't get prompt the next printf until I put another input in.

This is what is looks like when I run the program

Ruslan Osmanov
  • 20,486
  • 7
  • 46
  • 60
Programmer
  • 105
  • 2
  • 11

4 Answers4

1

While a character (char) or set of characters (char*) are coming from stdin with scanf of similar function \n (result of Enter key pushing) remains in the buffer. So before next input the program should clean that \n as well as all other mess that can be in the input buffer (e.g. after incorrect entering numbers, such as 12asw - scanf takes 12 and leaves asw\n in the buffer).

Consider the following example and pay attention, that I recommend to use clnInpBuf():

#include <stdio.h>

void clnInpBuf()
{
    char c;
    while ((c = getchar()) != '\n' && c != EOF);
}

int main(void)
{
    char str[10];
    char ch;
    scanf("%c", &ch);
    fflush(stdin); // in some cases that works for input stream 
                   // (but fflush is better to use only for output streams)
    scanf("%9s", str);
    clnInpBuf(); // this works always
    printf("char was %c.\n", ch);
    printf("string was %s.\n", str);
}

UPDATE:

template for your "command processor" can be:

int main(void)
{
    char name[21];
    char command;
    while (1)
    {
        scanf("%c", &command);
        clnInpBuf();
        switch (command)
        {
        case 'a':
        case 'r': scanf("%20s", name);
                  clnInpBuf();
                  printf("Command was:\n%c %s\n", command, name); // if ('a'==command) addRecord(name); else removeRecord(name);
                  break;
        case 'p': // TODO: add output
                  break;
        case 'e': return 0;
                  break; // this is not realy needed
        default:
                  printf("Wrong command\n");
        }

    }
}
VolAnd
  • 6,367
  • 3
  • 25
  • 43
0

Just take out the "\n" in your

scanf("%s\n",userInput)
jim
  • 1,026
  • 2
  • 15
  • 37
0

Read carefully scanf(3). Notice that with gcc -m32 you have sizeof(userInput) equal to 4 (the size of all pointers is the same; without the -m32 it would be 8). So if the user is typing something like working (or any input of four characters or more, not just one letter like a), you have undefined behavior (because of a buffer overflow) and that is really bad. You probably should consider using getline(3) instead (or perhaps even readline(3)), e.g.

char* userInput=NULL;
size_t sizeInput= 0;
printf("Commands:\n");
/// put your other printfs here, then
ssize_t lengthInput = getline(&userInput, &sizeInput, stdin);
if (lengthInput < 0 || userInput==NULL)
  { perror("input error"); exit(EXIT_NULL); };

Now you have the entire typed line in userInput (including the terminating newline) and you know that its length is lengthInput. You can parse that line, perhaps using sscanf(3) (hint: use its return count, and consider using %n) or just using other techniques (some strcmp, or strtok(3)...). When done, you should free(userInput).

Notice that scanf (or sscanf) do not allocate any memory for parsed data, unless you use %ms (which is probably POSIX specific). With %s it always expecting some fixed length buffer, and for a array buffer declared char buf[64]; you'll better give the size with %63s; BTW, you should always test the result count of scanf. So you might code (after the above)

char nambuf[64];
if (sscanf(userInput, "a %63s", nambuf)==1) {
 // use nambuf to add it
}
else if (sscanf(userInput, "r %63s", nambuf)==1) {
 // use nambuf to remove it
} 

(but the above is a bit silly, we read an arbitrary sized line but process nambuf of at most 63 bytes). You could just use scanf like if (scanf("a %63s", nambuf)==1) without needing any userInput.

Alternatively, you could use the Linux specific %as or better the POSIX specific %ms like:

char* nameptr=NULL;
if (scanf("a %ms", &nameptr)==1) { 

then that successful scanf would have malloc-ed and filled nameptr and you should later free(nameptr). If you want to accept only lowercase letters consider coding something like if (scanf("a %m[a-z]", &nameptr)==1) etc...

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
0

This statement will allocte 4 bytes of data as userinput is pointer. userInput = (char*)malloc(sizeof(userInput));

as pointed by the above answer this will cause a buffer overflow when the string size is more than 3 bytes.

also i would suggest fgets() over scanf when reading a string

sample code -

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


   int main() {
      // your code goes here
     char *userinput = (char *)malloc(100);
     fgets(userinput,100,stdin);
     printf("%s",userinput);
     return 0;
}
hariudkmr
  • 191
  • 1
  • 12