-6

I wrote the following code to accept characters from user and enter into an array till he inputs a free space (' ') or a line \n. But code is not functioning. As in, when space bar or return key is pressed in the input, my computer is still accepting values without exiting the loop.

char X[99];
printf ("Type the string without spaces\n");
for (i=0;i<99;i++) {
  scanf ("%c",&m);
  if(m!=' '&&m!='\n')
    X[i]=m;
  else i=99;
  }

Please explain the error.

ThisaruG
  • 3,222
  • 7
  • 38
  • 60
Hari
  • 121
  • 1
  • 18
  • 3
    `if(m!=' '||m!='\n')` evaluates true for all values of `m`. Think about it for a minute. – Yu Hao Oct 06 '14 at 10:45
  • But it doesn't evaluate for ' ' and '\n' right. This is what I want. – Hari Oct 06 '14 at 10:47
  • 3
    Either `m` is not a space, then the condition is true, or it is a space, then it isn't a newline, so the condition is true. – mafso Oct 06 '14 at 10:50
  • Thank you guys.. Got it.. Such a dumbo I am. Think about it for a minute @ Yu Hao. Awesome. – Hari Oct 06 '14 at 10:54
  • But still the code functions in the same way. The changes I made: 1) if(m!=' '&&m!='\n'). 2) Replaced scanf("%c",&m); with m=getchar(); Any more changes I should make?? – Hari Oct 06 '14 at 10:54
  • Perhaps, you will need to terminate the string with NUL. – BLUEPIXY Oct 06 '14 at 10:56

9 Answers9

3

First the issue: the default tty mode is canonical, meaning input is made available line by line (see man termios)

Once you fix that, you can use getchar() or read() to get one character at a time. The tty setting, example straight out of the man page of termios .

#include <stdio.h>
#include <termios.h>




int ttySetNoncanonical(int fd, struct termios *prev)
{
    struct termios t;
    if (tcgetattr(fd, &t) == -1)
        return -1;
    if (prev != NULL)
        *prev = t;
    t.c_lflag &= ~ (ICANON);
    t.c_cc[VMIN] = 1; // 1-char at a go
    t.c_cc[VTIME] = 0; // blocking mode
    if (tcsetattr(fd, TCSAFLUSH, &t) == -1)
        return -1;
    return 0;
}



void main(void) {
    printf ("\nType the string without spaces\n");
    ttySetNoncanonical(0,NULL); // set to non-canonical mode
    char X[1000];
    int m, ec=0;
    int i;
    X[0] = 0;
    for (i=0;i<1000;i++) {
        //ec = read(0,X+i,1); // read one char at a time
        m = getchar();
        if(m == EOF || m==' ' || m=='\n') {
            X[i] = 0;
            break;
        }
        X[i] = m;
    }
    printf("You entered %s. Bye.\n\n", X);
}

HTH. You might want to check the boundary condition, in case your user typed in 1000 characters. It works for me on a GNU Linux.

Dinesh
  • 4,437
  • 5
  • 40
  • 77
1

The scanf function reads and ignores any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters). So, instead of

scanf("%c",&m);

use

m = getchar();

The function int getchar ( void ); gets character from stdin, returns the next character from the standard input (stdin). It is equivalent to calling getc with stdin as argument.

Also, the condition should use logical-AND as in:

if(m!=' '&& m!='\n')

Also, outside the loop, write,

X[i] = '\0';
Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • getchar() also doesn't work. Anyways thanks for enlightening me about scanf. U may edit the answer and remove getchar(). – Hari Oct 06 '14 at 10:44
  • `c` conversions (like `[` conversions) don't skip white-space. – mafso Oct 06 '14 at 10:47
  • But still the code functions in the same way. The changes I made: 1) if(m!=' '&&m!='\n'). 2) Replaced scanf("%c",&m); with m=getchar(); Any more changes I should make?? – Hari Oct 06 '14 at 10:57
  • @Hari, outside the loop, write X[i] = '\0'; – Dr. Debasish Jana Oct 06 '14 at 11:13
1

use getch(), scanf() will not work that way.

it would be something like :

for(i=0;i<99;i++)
{
    char ch=getch();
    if(m!=' ' && m!='\n' && m!='\r')
        X[i]=m;
    else i=99;
    printf("%c",ch);
}
Codeek
  • 1,624
  • 1
  • 11
  • 20
  • `getch()` is windows specific. Use `getchar()` – Ashwani Oct 06 '14 at 10:46
  • 1) getchar() also doesn't work. Is the code working for you guys? I mean did u run and check it? 2) Also, shouldn't the && in the if argument be replaced by ||. – Hari Oct 06 '14 at 10:48
  • No, || will not work. Take this into scenario lets say : m's value is ' ' so m!=' ' will be false, but at the same time m!='\n' will be true, and as the logical operator u use is OR, even if one condition is true, your resultant condition will be true. isn't it? – Codeek Oct 06 '14 at 10:56
  • But still the code functions in the same way. The changes I made: 1) if(m!=' '&&m!='\n'). 2) Replaced scanf("%c",&m); with m=getchar(); Any more changes I should make?? – Hari Oct 06 '14 at 10:56
  • did u try getch()? and what is m? u haven't given it's data type. and why not use break instead of making i=99;? – Codeek Oct 06 '14 at 10:59
  • getch() doesnt work at all. Now my comp doesnt accept inputs even. – Hari Oct 06 '14 at 11:01
  • it does, u just have to include the print statement as well as i've given. – Codeek Oct 06 '14 at 11:02
  • I can not extend this conversation in comment's section plus i don't have enough rep points to start a chat:( and i=99 will work, i was just suggesting a better way, nothing else. – Codeek Oct 06 '14 at 11:17
  • Even I can not extend this conversation in comment's section . Anyways thanks a lot !! :( – Hari Oct 06 '14 at 11:34
1

Lets look into the if condition

if(m!=' '||m!='\n')      

1. When m is space m=' ' (i.e. ASCII value 32)

 m=' '

As per your if condition (Cond1 || Cond2), Cond1 will fail and o/p will be 0 but Cond2 will be TRUE, because it is not ' '.

  if(FALSE || TRUE)              

will be if(TRUE).

  1. When your input is newline (i.e ASCII value 10).

    m='\n'

Here Cond1 will be TRUE because it is not SPACE, due to this it will not check the second condition as per C. and will execute the if(TRUE) statement.

Please try to code it by yourself.... It will help you to clear few C doubts and u will get to know how || and && condition works.

Vid
  • 137
  • 1
  • 2
  • 13
1

Better to use getchar() instead of scanf in here as you read character by character. Usually we use scanf for get strings as input.

Using the logical operators: && (AND) operator checks for one condition to be false, while or || (OR) operator checks for one condition to be true. So if you use && operator, it checks whether it is a space, and if not, it returns false, without even checking the second condition(EOF). But if you use || operator, as used below, it checks for both cases. Check for more details in operators here

You also have to increment the counter (i) after adding an item to the array (Inside the if) as if you don't, it will continuously add items to the same place of the array, which means you will lost the precious inputs. So, here's my code:

char X[99];
char m;

printf ("Type the string without spaces\n");
for (i=0;i<99;i++) {
  m = getchar();

  if(m == ' ' || m=='\n') {
    X[i]=m;
    i++;
  }
  else i=99;
}
ThisaruG
  • 3,222
  • 7
  • 38
  • 60
0

try this

#include <stdio.h>

int main(){
    int i;
    char m, X[99];
    printf("Type the string without spaces\n");
    for (i=0;i<98;i++){//98 --> sizeof(X) -1
        scanf("%c",&m);
        if(m!=' ' && m!='\n')
            X[i] = m;
        else 
            break;
    }
    X[i] = '\0';

    puts(X);
    return 0;
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70
  • No even this code doesn't work. The comp is still accepting values even after space or \n. I'm using Dev C++ IDE by the way. Even if it works Why else i=99; strategy doesn't work? @BLUEPIXY – Hari Oct 06 '14 at 11:06
  • `else i=99;` 1) It is better simply to use `break` than to use magic number. 2) `i=99` is superfluous to set a terminator. – BLUEPIXY Oct 06 '14 at 11:12
  • Yes its better to use break. Thank you. But the other case (else i=99;), im just curious Y is it wrong? it doesnt come under any undefined behavior. What exactly is happening? Its so straight forward. @BLUEPIXY – Hari Oct 06 '14 at 11:20
  • @Hari I think may be used is would increase the extra code. BTW _No even this code doesn't work._ Did you make rebuild? – BLUEPIXY Oct 06 '14 at 11:26
  • It works in the environment u shared. It doesnt work in Dev C++. One difference between the environments is that in ur environment, we give the input beforehand. But in DEv C++, its during running.. – Hari Oct 06 '14 at 11:33
  • Hari I think may be used is would increase the extra code. @BLUEPIXY I dont get this – Hari Oct 06 '14 at 11:35
0

With the function getch(); it ends if your pressing space or enter!

#include <stdio.h>
int main(void) {

    char m, X[99];
    int i;

    printf("Type the string without spaces\n");

    for (i = 0; i < 99; i++) {
        m = getch();

        if (m == ' ' || m == '\n' || m == '\r')
            i=100;
        else 
            X[i] = m;
            printf("%c", m);

    }

}
Rizier123
  • 58,877
  • 16
  • 101
  • 156
-1

First error, as everyone has pointed out is the logical operator in the if() statement. It should be

if(m!=' ' && m!='\n')

As you want to check if the entered character is neither a (space) nor a \n, so you have to use the && operator.

Next, the error you are getting is because of something called the trailing character. When you enter a letter and press enter (at the point where your scanf("%c",&m) is asking for input). That letter gets stored in the variable m, but the newline character \n caused by the enter pressed is still in the stdin. That character is read by the scanf("%c",&m) of the next iteration of the for loop, thus the loop exits.

What you need to do is consume that trailing character before the next scanf() is executed. for that you need a getchar() which does this job. So now your code becomes something like this..

#include<stdio.h>
int main()
{
    char X[99];
    char m;
    int i;
    printf("Type the string without spaces\n");
    for (i=0;i<99;i++)
    {
            scanf("%c",&m);
            if(m!=' ' && m!='\n')
            {
                    X[i]=m;
                    getchar(); // this statement is consuming the left out trailing character
             }
            else
                    i=99;
    }
    printf("%s",X);
}

Now, the program works exactly as you want.

Haris
  • 12,120
  • 6
  • 43
  • 70
-1

Here's a working code:

#include <stdio.h>

int main ()
{
        char x[100] = {0};
        char m;
        int i, j;

        printf ("Type:\n");
        for (i=0; i<99; i++) {
                m = getchar();
                getchar();
                if ((m != ' ') && (m != '\n')) {
                        x[i] = m;
                } else {
                        printf ("Breaking.");
                        break;
                }
        }

        printf ("\n");
        for (j=0; j<i; j++)
                printf ("%c\n", x[j]);

        return 0;
}

Here I have used an extra getchar() to consume the newline used to enter the character m. And so (please note) you will also need to enter a newline after a space (' ') and a newline ('\n') to enter and store these in m and compare them in the next lines.

vvvv
  • 135
  • 10