5

I want to read all the text entered until a new line character is entered.

This is my code.

int i=0;
char ch[MAX];
printf("Enter the text\n");
while(true)
{
     scanf("%c",&ch[i]);
     if(ch[i]=='\n')
         break;
     i++;
}

But when I try to execute it reads only one word.

I have also tried scanf("%s",ch); but the result is the same.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Aditya Kiran
  • 251
  • 1
  • 4
  • 12
  • 1
    @almasshaikh No, `gets()` should *never* be recommended. It's dangerous. – unwind Dec 28 '14 at 13:59
  • 2
    "it reads only one word"-No. Your code does exacly what you need. Or another way would be to use `scanf("%[^\n]",ch);getchar();` – Spikatrix Dec 28 '14 at 14:00
  • 1
    You haven't null-terminated your string. You also don't check that `scanf()` returned a character; you should always check that it returned what you expected. You should also be checking that the input does not exceed the length of `ch` so you don't have a buffer overflow (in this case, that would be a [stack overflow](http://stackoverflow.com), of course). – Jonathan Leffler Dec 28 '14 at 15:52

5 Answers5

9

Transferring comment to answer.

Your code will work. The code you posted scans everything until a newline character(\n) is found. But as Jonathan Leffler commented, you never NUL-terminate your string. To do it just use

ch[i]='\0';

after the loop. Also, the user could enter more characters than MAX-1(One extra for the \0 at the end) and this could cause a buffer overflow. You should add a check like

if(i==MAX-1)
break;

just before your scanf in order to prevent it from overflowing.

Note that scanf("%s",ch); will scan until it encounters a space or a newline character.


Instead of looping and scanning character by character, just use
scanf("%[^\n]",ch);
getchar();

The above scanf scans everything until a newline character is found and puts them in ch. The getchar() then discards the \n from the stdin. You can also improve safety by limiting the amount of characters that scanf reads into ch.

scanf("%49[^\n]",ch);

The above scanf will scan a maximum of 49 characters and will add a \0 at the end. You can substitute the value of MAX-1 there. I've used 50 as an example.

Community
  • 1
  • 1
Spikatrix
  • 20,225
  • 7
  • 37
  • 83
  • 2
    You've not null terminated the string; you've not checked for the length of the buffer. – Jonathan Leffler Dec 28 '14 at 15:52
  • @JonathanLeffler , Yeah.You are right. I've edited the answer. – Spikatrix Dec 29 '14 at 07:02
  • I'm now a little concerned aboubt your comments about the macro MAX in the format string. If you have `#define MAX 39` (for sake of argument), and macros `#define STRINGIZE(x) EVALUATE(x)` and `#define EVALUATE(x) #x`, and you define `char ch[MAX+1];`, then you could use `scanf("%" STRINGIZE(MAX) "[^\n]", ch)`, but MAX must expand to a simple number, not to a general expression. Otherwise, I don't see how it can be made to work. – Jonathan Leffler Dec 29 '14 at 07:18
  • @JonathanLeffler , I just tried what I described in my answer and GCC threw a warning :/(`unknown conversion type character 'M' in format` and points at the `scanf`) . I thought that the preprocessor replaces all `MAX` in the program with 50(if we had `#define MAX 50`) before compiling the program. And I tried what you said and it worked..... – Spikatrix Dec 29 '14 at 08:15
  • @JonathanLeffler ,Dosen't the preprocessor do its work before the compilation stage? – Spikatrix Dec 29 '14 at 09:02
  • Yes, but the preprocessor in Standard C doesn't expand macros inside strings. In pre-standard C, some pre-processors would look for macro arguments inside strings in the macro expansion, but that was a long time ago! The `#` operator was introduced to handle that; the `##` operator was introduced to handle token pasting which was done with `#define PASTE(x,y) x/**/y` in some pre-standard processors. The standard requires a space in place of the comment, and the use of `#define PASTE(x, y) x ## y` to paste arguments together. – Jonathan Leffler Dec 29 '14 at 09:04
  • @JonathanLeffler , Ah. That explains why my idea didn't work. Thanks! – Spikatrix Dec 29 '14 at 09:10
7

You're not checking that scanf() succeeds before relying on ch[i] to have a valid value, that's not a good idea.

Just use fgets() to read a whole line at once.

unwind
  • 391,730
  • 64
  • 469
  • 606
3

As commented by @Jonathan Leffler, OP 's code does not null terminate the string or prevent buffer overflow.

Since code fetches 1 char at a time, use the much simpler fgetc().

int i=0;
char ch[MAX];
int single;  // Important that this in an int to distinguish EOF from input.

printf("Enter the text\n");

while((single = fgetc(stdin)) != EOF) {
  if (i >= (MAX-1)) {
    ;  // Too many, do not save or maybe indicate error
  } else {
    ch[i++] = single;
  }
  if (single == '\n') {
    break;
  }
}
ch[i] = '\0';  // Add termination
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

your code working fine . I checked, it reads a line not a word.

Bond
  • 41
  • 1
  • 3
0

I hope it will be better for you with respect to your code :

int main()
{
    int i=0;
    char ch[100];
    printf("Enter the text\n");
    gets(ch);  // input text
    puts(ch);  // output text
    return 0;
}

input : asdf ghjkl zxcvb

output: asdf ghjkl zxcvb

Sakib Ahammed
  • 2,452
  • 2
  • 25
  • 29
  • 4
    NO! Absolutely never, _never_, **never**, ***never*** suggest the use of `gets()`. It is poisonously awful. It is no longer standard C, and arguably (easily arguably) never should have been — though, that said, there were reasons for including it in C89. See [Why is the `gets()` function dangerous? Why should it not be used?](http://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used) – Jonathan Leffler Dec 28 '14 at 15:49
  • @JonathanLeffler Never say never. If someone wants elegant code to buffer overflow on purpose, scanf and gets are great candidates :) – Sujay Phadke Jun 17 '18 at 06:14