我正在构建一个程序,接受用户输入,操作它,并输出更改(如果有的话)。指导方针是:
删除所有数字
如果一行超过2行,则只打印2行
换文
为每个空间打印2个空格
正常打印所有其他字符
如果stdin和stdout相同,则从main返回1,否则返回0。
我不能为这个项目使用任何数据结构,所以我使用getchar()逐字符读取stdin char。
有没有办法把stdin和C中的stdout进行比较?我对这门语言还不熟悉,甚至不知道该如何看待它。我的代码和所有符合SAN 6的准则如下:

#include <stdio.h>

int newline(int iochar);
void testChars(int iochar);
void upperCase(int iochar);
void lowerCase(int iochar);
void space(int iochar);
void digit();


int main()
{
    int iochar = 0;
    iochar = getchar();

    testChars(iochar);

    return 0;
}

void testChars(int iochar)
{
    while(iochar != EOF) {
        if (iochar == 10)
            iochar = newline(iochar);

        else if(iochar == 32)
        space(iochar);

        else if (iochar > 64 && iochar < 91)
        upperCase(iochar);

        else if (iochar < 123 && iochar > 96)
        lowerCase(iochar);

        else if (iochar < 58 && iochar > 47)
        digit();

        else putchar(iochar);

        iochar = getchar();
    }
}

void space(int iochar)
{
    putchar(iochar);
    putchar(iochar);
}

int newline(int iochar)
{
    int count = 0;
    while (iochar == 10){
        if(count < 2)
            putchar(iochar);
        count++;
        iochar = getchar();
    }
    return iochar;
}

void digit()
{
    return;
}

void upperCase(int iochar)
{
    iochar += 32;
    putchar(iochar);
}

void lowerCase(int iochar)
{
    iochar -=32;
    putchar(iochar);
}

最佳答案

虽然可以将测试分成多个函数,但由于处理的案例数量有限,只需将测试直接包含在一个“state”循环中,该循环跟踪换行的数量以及是否对输入进行了任何修改,这是一种同样可读的方法。(在XY问题上很好地抓住了iBug)。
有很多方法可以解决字符分类问题,这基本上就是你所拥有的。(意思是你读一个字符,分类是否符合某个预先定义的测试,然后根据它的分类方式采取一些行动)。处理它的一种有效方法是使用一个跟踪事物状态的循环(例如,“顺序读取了多少新行?”,或者我是否在一个单词中,通过设置、重置或递增几个变量来读取空白等,这些变量跟踪您感兴趣的任何条件(或状态),而这些条件(或状态)是基于当前字符以外的某个字符。
您只需找出需要遵循的内容(这里是连续换行的数量,以及是否以任何方式修改了输出)。很简单,只需对读取的顺序换行数进行计数,如nl并保留设置的整数标志(如果您做了任何更改,请将其称为modified或其他逻辑值)。当您读取除'\n'以外的任何内容时,请重置您的换行计数,例如nl = 0;
然后,只需要读取输入的每个字符,直到遇到EOF为止,然后执行一些测试来确定您所读取的字符(使用if, else if, else或使用switch语句)。然后针对每个不同的测试,采取适当的操作。
例如,您可以使用一些简单的方法来满足您的条件,例如:

#include <stdio.h>

int main (void) {

    int c, modified = 0, nl = 0;

    while ((c = getchar()) != EOF) {        /* loop over each char       */
        if (c == '\n') {                    /* am I a '\n'?              */
            if (nl < 2)                     /* have I ouput less than 2? */
                putchar ('\n');             /* output the newline        */
            else
                modified = 1;               /* set modified flag         */
            nl++;                           /* update the number seen    */
            continue;                       /* get next char             */
        }
        else if ('A' <= c && c <= 'Z') {    /* am I uppercase?           */
            putchar (c + 'a' - 'A');        /* convert to lowercase      */
            modified = 1;                   /* set modified flag         */
        }
        else if ('a' <= c && c <= 'z') {    /* am I lowercase?           */
            putchar (c + 'A' - 'a');        /* convert to uppercase      */
            modified = 1;                   /* set modified flag         */
        }
        else if (c < '0' || '9' < c) {      /* am I not a digit?         */
            if (c == ' ') {                 /* am I a space ?            */
                putchar (c);                /* output extra space        */
                modified = 1;               /* set modified flag         */
            }
            putchar (c);                    /* output unmodified char    */
        }
        nl = 0;                 /* reset newlines seen to zero */
    }

    return modified ? 0 : 1;    /* 0 - modified, 1 - stdout == stdin */
}

注意:尽量避免在代码中使用幻数。如果需要'A'的ASCII值,则使用'A',而不是65。阅读散布着神奇数字的思想代码(例如653210并不像'A'' ''\n'那样具有信息性。
另外,还可以使用宏isctype.h(例如isupper()islower()isdigit()等)以非常可读的方式轻松测试当前字符。手工操作也有学习价值,可以理解ctype.h中那些方便的函数实际上在做什么,并正确地练习设置条件测试。
示例输入文件
现在只需创建一个测试用例来练习角色分类,并确保循环的工作方式是正确的。没有什么特别的要求。与其试图构造无数的assert()语句,不如创建一个输入文件,该文件具有适合每种情况的字符:
$ cat dat/stateloop.txt
This Is a Line followed by THREE-newlines


and with SEVEN single-spaced asterisk * * * * * * *
aND a lINE fOLLOWED bY five nEWLINES ('\N')




And A Few Numbers zERO-tO-nINE (123456789)
1
a b c d e f g - A B C D E F G
Done2Day

示例使用/输出
然后仔细检查输出:
$ ./bin/stateloop <dat/stateloop.txt
tHIS  iS  A  lINE  FOLLOWED  BY  three-NEWLINES

AND  WITH  seven  SINGLE-SPACED  ASTERISK  *  *  *  *  *  *  *
And  A  Line  Followed  By  FIVE  Newlines  ('\n')

aND  a  fEW  nUMBERS  Zero-To-Nine  ()

A  B  C  D  E  F  G  -  a  b  c  d  e  f  g
dONEdAY

检查返回值
并验证return是否正确。
$ echo $?
0

尝试(不改变)案例
对未修改的情况执行相同的操作:
$ printf "~@##$@#$%%#*[]{};:^^&&*)\n" | ./bin/stateloop
~@###$%#*[]{};:^^&&*)

检查适当的退货
$ echo $?
1

如前所述,有许多方法可以解决这类问题。找一些逻辑性强、可读性强、易懂的东西。祝你编码顺利。

关于c - 如何在C中检查stdin == stdout,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48838232/

10-09 17:54
查看更多