【问题标题】:' ', '\n' , scanf() and output screen' ', '\n' , scanf() 和输出屏幕
【发布时间】:2014-10-06 10:34:06
【问题描述】:

我编写了以下代码来接受用户的字符并输入一个数组,直到他输入一个空闲空间('')或一行\n。但是代码不起作用。如在输入中按下空格键或返回键时,我的计算机仍在接受值而不退出循环。

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;
  }

请解释错误。

【问题讨论】:

  • if(m!=' '||m!='\n')m 的所有值求值为真。想一想。
  • 但它不能正确评估 ' ' 和 '\n' 。这就是我想要的。
  • 要么m不是空格,则条件为真,要么是空格,则不是换行符,则条件为真。
  • 谢谢你们..明白了..我真是个笨蛋。想一想@于浩。太棒了。
  • 但代码的功能仍然相同。我所做的更改:1) if(m!=' '&&m!='\n'). 2) 替换了scanf("%c",&m);用 m=getchar();我还应该做出什么改变吗??

标签: c string scanf stdio


【解决方案1】:

首先是问题:默认的 tty 模式是规范的,这意味着输入是逐行提供的(请参阅man termios

一旦你解决了这个问题,你就可以使用 getchar() 或 read() 一次获取一个字符。 tty 设置,示例直接来自 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。如果您的用户输入了 1000 个字符,您可能需要检查边界条件。它适用于我在 GNU Linux 上。

【讨论】:

  • 非常感谢!
【解决方案2】:

使用 getch(),scanf() 不会那样工作。

应该是这样的:

for(i=0;i<99;i++)
{
    char ch=getch();
    if(m!=' ' && m!='\n' && m!='\r')
        X[i]=m;
    else i=99;
    printf("%c",ch);
}

【讨论】:

  • getch() 是特定于 Windows 的。使用getchar()
  • 1) getchar() 也不起作用。代码对你们有用吗?我的意思是你跑过去检查了吗? 2) 另外,if 参数中的 && 不应该被 || 替换。
  • 不,||不管用。考虑到这个场景让我们说:m 的值是 ' ' 所以 m!=' ' 将为假,但同时 m!='\n' 将为真,并且你使用的逻辑运算符是 OR,即使一个条件为真,您的结果条件将为真。不是吗?
  • 但代码的功能仍然相同。我所做的更改:1) if(m!=' '&&m!='\n'). 2) 替换了scanf("%c",&m);用 m=getchar();我还应该做出什么改变吗??
  • 你试过 getch() 了吗?什么是米?你还没有给出它的数据类型。为什么不使用 break 而不是 make i=99;?
【解决方案3】:

scanf 函数读取并忽略在下一个非空白字符之前遇到的任何空白字符(空白字符包括空格、换行符和制表符)。所以,而不是

scanf("%c",&m);

使用

m = getchar();

函数 int getchar ( void );从标准输入获取字符,从标准输入(stdin)返回下一个字符。相当于以stdin为参数调用getc。

此外,条件应使用逻辑与,如下所示:

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

另外,在循环之外,写,

X[i] = '\0';

【讨论】:

  • getchar() 也不起作用。无论如何,感谢您对 scanf 的启发。你可以编辑答案并删除 getchar()。
  • c 转换(如[ 转换)不会跳过空格。
  • 但代码的功能仍然相同。我所做的更改:1) if(m!=' '&&m!='\n'). 2) 替换了scanf("%c",&m);用 m=getchar();我还应该做出什么改变吗??
  • @Hari,在循环外,写 X[i] = '\0';
【解决方案4】:

让我们看看 if 条件

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

1。当 m 为空格时 m=' '(即 ASCII 值 32)

 m=' '

根据您的 if 条件 (Cond1 || Cond2),Cond1 将失败并且 o/p 将为 0 但 Cond2 将为 TRUE,因为它不是 ' '。

  if(FALSE || TRUE)              

将是 if(TRUE)。

  1. 当您的输入是换行符时(即 ASCII 值 10)。

    m='\n'

这里的 Cond1 将为 TRUE,因为它不是 SPACE,因此它不会按照 C. 检查第二个条件,并将执行 if(TRUE) 语句。

请尝试自己编写代码....它将帮助您消除一些C疑虑,您将了解如何||和 && 条件有效。

【讨论】:

    【解决方案5】:

    当您逐个字符地阅读时,最好在此处使用 getchar() 而不是 scanf。通常我们使用scanf来获取字符串作为输入。

    使用逻辑运算符:&amp;&amp; (AND) 运算符检查一个条件是否为假,而 || (OR) 运算符检查一个条件是否为真。所以如果你使用&amp;&amp;运算符,它会检查它是否是一个空格,如果不是,它会返回false,甚至不检查第二个条件(EOF)。但是,如果您使用|| 运算符,如下所示,它会检查这两种情况。查看运营商here的更多详细信息

    您还必须在将项目添加到数组(在 if 内)之后增加计数器(i),就像您不这样做一样,它会不断地将项目添加到数组的同一位置,这意味着您将失去宝贵的投入。 所以,这是我的代码:

    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;
    }
    

    【讨论】:

      【解决方案6】:

      使用函数 getch();如果您按下空格或输入,它就会结束!

      #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);
      
          }
      
      }
      

      【讨论】:

        【解决方案7】:

        试试这个

        #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;
        }
        

        【讨论】:

        • 不,即使这段代码也不起作用。即使在空格或 \n 之后,comp 仍然接受值。顺便说一句,我正在使用 Dev C++ IDE。即使它有效为什么还要 i=99;策略不起作用? @BLUEPIXY
        • else i=99; 1) 使用break 比使用幻数更好。 2) i=99 设置终止符是多余的。
        • 是的,最好使用break。谢谢你。但另一种情况(否则 i=99;),我只是好奇 Y 是不是错了?它不属于任何未定义的行为。到底发生了什么?它是如此直截了当。 @BLUEPIXY
        • @Hari 我认为可能会增加额外的代码。顺便说一句,没有,甚至这段代码也不起作用。你重建了吗?
        • 它在你共享的环境中工作。它在 Dev C++ 中不起作用。环境之间的一个区别是,在我们的环境中,我们事先给出了输入。但在 DEv C++ 中,它在运行期间..
        【解决方案8】:

        这是一个有效的代码:

        #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;
        }
        

        这里我使用了一个额外的 getchar() 来消耗用于输入字符 m 的换行符。因此(请注意)您还需要在空格 (' ') 和换行符 ('\n') 之后输入换行符,以便将它们输入并存储在 m 中并在下一行中进行比较。

        【讨论】:

          【解决方案9】:

          第一个错误,正如大家所指出的,是if() 语句中的逻辑运算符。应该是

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

          由于您要检查输入的字符是否既不是(空格)也不是\n,所以您必须使用&amp;&amp; 运算符。

          接下来,您遇到的错误是由于名为 trailing character 的东西引起的。当您输入一个字母并按enter(在您的scanf("%c",&amp;m) 要求输入的位置)。该字母存储在变量m 中,但由按下enter 引起的换行符\n 仍在stdin 中。该字符由for 循环的下一次迭代的scanf("%c",&amp;m) 读取,因此循环退出。

          您需要做的是在执行下一个scanf() 之前消耗trailing character。为此,您需要一个 getchar() 来完成这项工作。所以现在你的代码变成了这样..

          #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);
          }
          

          现在,程序完全按照您的意愿运行。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-03-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多