James
James

Reputation: 11

Exit the loop when I press enter (C-programming)

I have a little problem with my program I'm trying to code.. Basically I want to enter a symbol one by one inside my loop and when I'm done I just want to press enter in order to exit the loop and then print out the string to the console. However, this doesn't seem to work and I've been trying for hours without getting the grip of it. This is my code

#include <stdio.h>

int main(int argc, char *argv[]){


    int i = 0;
    char text[i];
    char symbol;

    while(1){
       scanf("%s", &symbol);
       if(symbol == 13){ //13 should be the ascii value for enter
                 break;          
       }
       text[i] = symbol;
       i++;

    }
    printf("%s", text);

    getch();
    return 0;
}

Upvotes: 1

Views: 7401

Answers (6)

ForceBru
ForceBru

Reputation: 44838

On Windows, when you hit Enter, it's read as \r\n, not simply \r. So you may want to try this:

while(1){
    scanf("%c", &symbol); //use %c to read a character
    if(symbol == '\r'){
         scanf("%c", &symbol);
         if(symbol == '\n') break;          
    }
text[i] = symbol;
i++;

}

Moreover, you're creating an array of nothing and then trying to place data in it. This won't work. You'd better allocate some memory first and only then read into it:

char text[1024];
int i =0; // then increase i up to 1023

What's more, if your sole intention is to capture the Enter hit, you won't need text at all, just symbol will suit your needs.

Upvotes: 0

You might use fgetc(3) but it probably wont work (since stdin is buffered in the C standard library -see setvbuf(3), and in the kernel for ttys, read more about ttys). So the entire line is sent to your program only when the user pressed the return key.

In practice, it is heavily operating system specific; I hope you are on Linux or on some other POSIX system. I strongly suggest using ncurses or readline; see also termios(3)

Upvotes: 0

Mr. E
Mr. E

Reputation: 2120

First, arrays don't increase it's size magically just cause you increase the variable you used to set it's size (the i in text[i] in your code), you should allocate memory dynamically (malloc, realloc or calloc), and remember to free it. Your code should be like this:

int main(int argc, char *argv[]){


  int i = 0;
  char* text = malloc(sizeof(char));
  char symbol;
  char* aux;
  while(1){
     symbol = getchar(); //Use getchar to read only one char, scanf would be more problematic
     if(symbol == 13){ //13 should be the ascii value for enter
             break;          
     }
     text[i] = symbol;
     if ((aux = (char*)realloc(text, sizeof(char)*(i+1))) == NULL){
         // Handle error
         return -1;
     }
     text = aux;
     i++;
  }
  text[i] = '\0'; //Remember to set last char in your string to '\0' or printf won't work properly
  printf("%s", text);
  free(text);
  getch();
  return 0;
}

Upvotes: 0

Karoly Horvath
Karoly Horvath

Reputation: 96266

  • %s reads a word. If you want to read a character with scanf, use %c.
  • C strings are NUL terminated, you first have to terminate the string before printing it.
  • char text[i] - i is zero at this point. You won't be able to store your string here. Either know the max size at compilation time (and check at runtime when appending) or dynamically allocate memory as needed.

Note: naked scan from the stream is just asking for a lot of trouble. Prefer to read lines.

Upvotes: 2

Gordon Amable
Gordon Amable

Reputation: 193

You can set your terminal in raw mode with termcaps:

term.c_lflag &= ~(ICANON); 
term.c_lflag &= ~(ECHO);
term.c_cc[VMIN] = 1;
term.c_cc[VTIME] = 0;


if (tcsetattr(0, TCSADRAIN, &term) == -1)
    return (-1);

Then use the function:

int              main(int ac, char **av, char **env)
{
  char           *name_term;
  struct termios term;

  if ((name_term = getenv("TERM")) == NULL)
     return (-1);
  if (tgetent(NULL, &name_term) == ERR)
     return (-1);
  if (tcgetattr(0, term) == -1)
     return (-1);
  grab_key();
return (0);
}

int     grab_key()
{
  char     buffer[3];

  while (1)
  {
    read(0, buffer, 3);
    if (buffer[0] == 13)
      printf("Exit !");
  }
  return (0);
}

And to set your terminal to "normal" mode:

struct termios term;

if (tcgetattr(0, &term) == -1)
   return (-1);
term.c_lflag = (ICANON | ECHO);
if (tcsetattr(0, 0, &term) == -1)
   return (-1);

Upvotes: 1

dbush
dbush

Reputation: 223972

Three issues. The first is how you're reading the characters:

scanf("%s", &symbol);

The %s format specifier is for reading in a string. You're not passing in a string, but the address of a character. This will result in scanf reading in multiple characters starting with the address of symbol and continuing into whatever bytes may follow. This is undefined behavior.

For reading in a single character, use the %c format specifier instead:

scanf("%c", &symbol);

Second issue:

if(symbol == 13){ 

A newline isn't necessarily ASCII 13 on all systems. Use the escape code for a newline instead:

if(symbol == '\n'){ 

Third issue:

int i = 0;
char text[i];

This creates an array of 0 size. To keep things simple, give this array some known fixed size:

char text[100];

Your loop would then need to check that you don't enter too many characters.

Upvotes: 0

Related Questions