Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading in a string with spaces in C

Tags:

c

fgets

scanf

I am trying to read in a string that may or may not include spaces ex. "hello world". By doing the following with a number select menu that is inputted by the user. This is just a small replica of what I am trying to do.

#include <stdio.h>
#include <string.h>

int main(void){
  char line[3][80];

  strcpy(line[0],"default line 1\n");
  strcpy(line[1],"default line 2\n");
  strcpy(line[2],"default line 3\n");

  for(int i = 0; i < 3; i++){
    printf("%s", line[i]);
  }

  int option = 0;
  printf("would you like to replace line 1? (1 for yes)\n");
  scanf("%d",&option);
  if(option==1){
   printf("what would you like to replace the line with?\n");
   fgets(line[0],strlen(line[0]),stdin);
  }

  for(int i = 0; i < 3; i++){
    printf("%s", line[i]);
  }
}

Why is it that after I enter 1 to change the line, it prints the statement asking what I want to replace it with and will automatically enter nothing then printing the strings with the first one as empty?

I also have already tried reading the line with sscanf("%[^\n\t]s", line[0]); without any luck. Any ideas?

like image 315
TheBoxOkay Avatar asked Nov 11 '16 16:11

TheBoxOkay


People also ask

How do you check if there is a space in a string in C?

C isspace() The isspace() function checks whether a character is a white-space character or not. If an argument (character) passed to the isspace() function is a white-space character, it returns non-zero integer. If not, it returns 0.

Does scanf read spaces?

Adding a whitespace character in a scanf() function causes it to read elements and ignore all the whitespaces as much as it can and search for a non-whitespace character to proceed.

How do I make scanf ignore spaces?

The secret to getting scanf to perform this way is to put a blank in the format string before the %c format specifier. The blank tells scanf to skip white space and it will actually skip any number of white space characters before reading and storing a character.

How do you give spaces in C?

For just a space, use ' ' .


3 Answers

It's because

scanf("%d",&option);

leaves the \n character in stdin and is consumed by the first call to fgets(). That's why it's best to avoid scanf() in C completely.

You can fix it with:

  scanf("%d",&option);
  getchar(); /* consume the newline */

But I'd suggest using fgets() to read option as well and then you can use strtol() to convert it into an integer.

Note that this statement is not probably what you intended (which limits what you can read into line[0]).

   fgets(line[0],strlen(line[0]),stdin);

You probably meant to use:

   fgets(line[0],sizeof line[0],stdin);

so that you can read upto the actual size of line[0].

Please read the C Faq entry as well: http://c-faq.com/stdio/scanfprobs.html

like image 139
P.P Avatar answered Oct 11 '22 22:10

P.P


Using fgets() generally seems less error-prone than tangling with scanf(), but if the user enters a string that is as long as or longer than the maximum number of characters specified, any extra characters up to and including the newline remain in the input stream. For this reason I usually write my own version of gets() to get input strings from the user, and if I want numeric input I use strtol(). Here is an example of such a function:

char * s_gets(char *st, int n)
{
    char *ret;
    int ch;

    ret = fgets(st, n, stdin);
    if (ret) {
        while (*st != '\n' && *st != '\0')
            ++st;
        if (*st)
            *st = '\0';
        else {
            while ((ch = getchar()) != '\n' && ch != EOF)
                continue;           // discard extra characters
        }
    }
    return ret;
}

Applied to the OPs problem, I might do something like this:

#include <stdlib.h>                // for strtol()

...

char buf[80];
int option = 0;

printf("would you like to replace line 1? (1 for yes)\n");
s_gets(buf, sizeof(buf));
option = strtol(buf, NULL, 10);

if(option==1){
    printf("what would you like to replace the line with?\n");
    s_gets(line[0],sizeof(line[0]));
}
like image 37
ad absurdum Avatar answered Oct 11 '22 20:10

ad absurdum


Your problem is that the '\n' char is left into stdin and consumed by fgets.

I'd suggest you to always use fgets for read inputs, so

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

int main(void)
{
    char line[3][80];
    char temp[3];

    strcpy(line[0],"default line 1\n");
    strcpy(line[1],"default line 2\n");
    strcpy(line[2],"default line 3\n");

    for(int i = 0; i < 3; i++){
        printf("%s", line[i]);
    }

    int option = 0;
    printf("would you like to replace line 1? (1 for yes)\n");
    fgets(temp,sizeof(temp),stdin);
    option = atoi(temp);

    if(option==1){
        printf("what would you like to replace the line with?\n");
        fgets(line[0],sizeof(line[0]),stdin);
    }

    for(int i = 0; i < 3; i++){
    printf("%s", line[i]);
    }
}
like image 2
LPs Avatar answered Oct 11 '22 20:10

LPs