【问题标题】:C: How to discern between a string and integer? Output is printing ints fine, but not for stringsC:如何区分字符串和整数?输出打印整数很好,但不是字符串
【发布时间】:2018-03-04 15:44:35
【问题描述】:

我的程序对来自用户的输入字符串进行标记,并从这些标记中辨别它们是字符串还是整数(如果任何字母字符附加到数字,意味着它与任何数字相邻 - 它是然后将其视为字符串)。

因此,以下输入:this is 1string 123 1”应输出STR STR STR INT INT。我所做的:获取输入字符串,继续对其进行标记/拆分(使用空格分隔符),然后遍历拆分标记(使用 for 循环)以查看拆分标记是否具有字母表中的任何字符(大写或小写)。

现在,最后一句话是问题所在。我有一个名为 foundChar 的布尔值。如果找到任何字母字符,那么我会将 foundChar 设置为 true。从那里,我会做一个简单的 if 检查,看看 foundChar == true。但是,现在当我输入一个字符串时,它会打印空白?我不确定我在 C 中使用布尔值的方式是否正确,或者在哪里准确指出这里出了什么问题。

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

// main
int main (void)
{
    // declare our stuff for stuffs
    char string[255];
    char *tokenizedString;
    const char delimiter[2] = " ";
    char *pch;
    bool found = false;
    int truth = 0;

    // prompt our user
    do {
        do {
            printf (">");
            fgets (string, 65, stdin);

        } while (strlen (string) <= 0);

        // remove it "\n" so it can terminate from newline input
        pch = strstr (string, "\n");
        strncpy (pch, "\0", 1);

        // tokenize the input string
        tokenizedString = strtok (string, delimiter);

        while (tokenizedString != NULL) {

            // check for any character in the token
            // if found = true, then it's a string by our premade definition 
            for (int i = 0; i < strlen (tokenizedString); i++) {
                if ((i >= 'a' && i <= 'z')
                    || (i >= 'A' && i <= 'Z')) {
                    found = true;
                }
            }

            // if we find a char in the string
            if (found == true) {
                printf ("STR ");
            }

            // if the token is a number
            else if (isdigit (*tokenizedString))
                printf ("INT ");

            tokenizedString = strtok (NULL, delimiter);

            // reset charFound to zero for our next token
            found = false;

        }

        printf ("\n");

    } while (!(strlen (string) == 0));
} // end of program

输出

./prog why are

_________(这里实际上没有打印,空白!STR STR 应该打印,下面的下一个字符串也一样!)

./prog  you not printing output for string

_________(这里也没有打印,应该打印 STR STR STR STR STR STR)

./prog 123
INT 

./prog 1st
INT 

./prog nor printing the right stuff

期望的输出

./prog why are
STR STR

./prog you not printing output for string
STR STR STR STR STR STR

./prog 123
INT 

./prog 1st
STR

./prog nor printing the right stuff
STR STR STR STR STR

【问题讨论】:

  • (i &gt;= 'a' &amp;&amp; i &lt;= 'z') --> (tokenizedString[i] &gt;= 'a' &amp;&amp; tokenizedString[i] &lt;= 'z')
  • 为什么要检查字母?我会做相反的事情。使用isdigit() 检查数字,并将未通过的任何内容视为字符串字符。
  • 啊,谢谢,对不起。我没看到,看了好几个小时。
  • 好吧,虽然它的复杂性很荒谬,但我当时认为这是一个绝妙的主意。

标签: c string if-statement input boolean


【解决方案1】:

既然 BLUEPIXY 已经正确指出(像往常一样)需要检查 tokenizedString 中的字符是数字还是字符,让我们退后一步,从大局看一下您在做什么。虽然对读取的每个字符串进行标记然后迭代每个标记中的每个字符并没有错——也没有必要这样做。

您真正关心的是该行中的每个单词是否仅由数字组成(用于您的INT 输出),否则您将其归类为STR。为此,您需要做的就是遍历输入中的每个字符并计算行中包含的空格之间的字符数和数字数。您可以在没有任何标记化的情况下这样做。只需计算您找到的每个空格之间遇到的字符数和位数(或最后一个空格和fgets 输入中包含的'\n' 之间的字符数)。

例如,您可以执行以下操作:

#include <stdio.h>

#define MAXS 256

int main (void) {

    char str[MAXS] = "";

    while (fgets (str, MAXS, stdin)) {      /* read each line */
        char *p = str;
        int ch = 0, dig = 0;
        while (*p) {                        /* for each char  */
            if (*p == ' ' || *p == '\n') {  /* if space or \n */
                if (ch)                     /* if char found  */
                    printf (" STR");
                else if (dig)               /* if digit found */
                    printf (" INT");
            }
            /* are we a char? */
            if (('a' <= *p && *p <= 'z') || ('A' <= *p && *p <= 'Z'))
                ch++;   /* incriment ch  */
            else if ('0' <= *p && *p <= '9')    /* are we a digit? */
                dig++;  /* incriment dig */
            p++;
        }
        putchar ('\n');
    }

    return 0;
}

使用/输出示例

$ ./bin/str_or_int
why are
 STR STR
you not printing output for string
 STR STR STR STR STR STR
123
 INT
1st
 STR
nor printing the right stuff
 STR STR STR STR STR

同样,标记化然后扫描每个标记并没有什么问题,但它可能比需要的复杂一些。仔细查看,将 BLUEPIXY 建议的修复程序合并到您的代码中,然后比较版本。一般来说,如果有一种简单的方法来做某事,那么你遇到细微错误的机会就会比你在:):)

如果您对任一版本还有任何疑问,请告诉我。

【讨论】:

  • 嗨,大卫,感谢您的详尽回答。对 if(ch) 和 else if (dig) 有点困惑。似乎没有说明它们的类型,它们只是 int 类型。你正在做的是在字符串的开头指向一个字符类型 p,我明白这一点,然后你已经初始化了 ch 和 dig。我不太明白您将 ch 和 dig 与什么进行比较,在条件内部?几乎就像您将 int 类型用作布尔值一样?另外,你为什么要增加值,这几乎就像你在使用 ch++ 和 dig++ 之类的计数器......
  • 嗨,大卫。我能够看看BLUEPIXY的例子,并解决了问题!但是,我收到一个新错误,指出文件末尾没有换行符。这让我相信我的测试人员不希望我有连续的输入流,只运行一次。预期输出 ------------- > one 1 4word other5 STR INT STR STR -------------- ------------ 程序输出... ------------- >one 1 4word other5 STR INT STR STR > ------------------------- 错误:文件末尾没有换行符
  • 抱歉,刚回来。 chdigwhile 循环中声明。它们只需要在循环的范围内。在适当的范围内声明变量是一种很好的做法。如果在循环退出后我需要它们的值,那么我会在顶部声明它们。 POSIX 需要一个换行符作为每个文件(或程序输出)的最后一行,只需在末尾添加一个 putchar ('\n'); 即可。为什么这是一个很好的要求有很多原因(其中最重要的是在程序完成时在提示之前不要留下部分文本)
  • 我只是在检查它们是否不为零。 if (ch) 只是 if (ch != 0) 的简写——少打字,我不擅长打字,所以我倾向于在可用时使用简写。在循环中,如果找到一个字符,我将 1 添加到 ch (与带有数字的 dig 相同)。 if (ch) 只是检查“我是否在最后一个空格之后和这个空格之前找到任何字符?”(注意:在上面的评论中,它应该是“POSIX 要求文件(或程序输出)中最后一行末尾的换行符“)并非所有程序(或文件)都符合。很高兴你的教授正在检查:)
  • 不用担心,感谢您抽出时间回复!没想到这是速记符号。
猜你喜欢
  • 1970-01-01
  • 2013-05-24
  • 2018-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
相关资源
最近更新 更多