【问题标题】:Checking contents of char variable - C Programming检查 char 变量的内容 - C 语言编程
【发布时间】:2012-01-12 10:33:18
【问题描述】:

这似乎是一个非常简单的问题,但我正在努力解决它。几个月来,我一直在用 Objective C 编写 iPhone 应用程序,但我决定学习 C 编程来给自己打下更好的基础。

在 Objective-C 中,如果我有一个名为“label1”的 UILabel,其中包含一些文本,并且我想根据该文本运行一些指令,那么它可能类似于;

if (label1.text == @"Hello, World!")
{
NSLog(@"This statement is true");
}
else {
NSLog(@"Uh Oh, an error has occurred");
}

我编写了一个非常简单的 C 程序,它使用 printf() 请求一些输入,然后使用 scanf() 接受用户的一些输入,所以是这样的;

int main()
{
    char[3] decision;

    Printf("Hi, welcome to the introduction program.  Are you ready to answer some questions? (Answer yes or no)");
    scanf("%s", &decision);
}

我想要做的是应用if 语句来说明如果用户输入了“是”然后继续提出更多问题,否则打印出一行文字表示感谢。

使用 scanf() 函数后,我正在捕获用户输入并将其分配给变量“decision”,因此现在应该等于是或否。所以我认为我可以做这样的事情;

if (decision == yes)
{
     printf("Ok, let's continue with the questions");
}
else 
{
     printf("Ok, thank you for your time.  Have a nice day.");
}

这会引发“使用未声明的标识符是”的错误。我也试过了;

if (decision == "yes")

这会导致“未指定与字符串文字的比较结果”

我尝试通过计算输入的字符数来查看它是否有效;

if (decision > 3)

但是得到“指针和整数'Char和int'之间的有序比较”

我也试过这个来检查变量的大小,如果它大于2个字符,它必须是yes;

if (sizeof (decision > 2))

我很感激这可能是我忽略的一些简单或微不足道的事情,但任何帮助都会很棒,谢谢。

【问题讨论】:

  • 你犯的第一个最开始的错误,是在主题中滥用'char variable',在内容中滥用'string variable'或'char * variable'或'char []'。对于每个 C 程序员 char 变量是:char c;

标签: c variables if-statement char


【解决方案1】:

Daniel Haviv 的回答告诉你应该怎么做。我想解释一下为什么您尝试的方法不起作用:

if (decision == yes)

没有标识符“是”,所以这是不合法的。

if (decision == "yes")

这里,“yes”是一个字符串字面量,其计算结果为指向其第一个字符的指针。这将“决定”与等价指针进行比较。如果它是合法的,那么如果它们都指向同一个地方,那就是真的,这不是你想要的。事实上,如果你这样做:

if ("yes" == "yes")

行为未定义。如果实现将相同的字符串文字折叠到相同的内存位置,它们都将指向同一个位置,它可能会或可能不会这样做。所以这绝对不是你想要的。

if (sizeof (decision > 2))

我猜你的意思是:

if( sizeof(decision) > 2 )

'sizeof' 运算符在编译时计算,而不是在运行时计算。它独立于存储的内容。 sizeof 决定为 3,因为您将其定义为容纳三个字符。所以这并没有测试任何有用的东西。

正如另一个答案中提到的,C 具有“strcmp”运算符来比较两个字符串。如果您愿意,您也可以编写自己的代码来逐个字符地比较它们。 C++ 有更好的方法来做到这一点,包括字符串类。

下面是一个示例,说明您可以如何做到这一点:

int StringCompare(const char *s1, const char *s2)
{ // returns 0 if the strings are equivalent, 1 if they're not
  while( (*s1!=0) && (*s2!=0) )
  { // loop until either string runs out
     if(*s1!=*s2) return 1; // check if they match
     s1++; // skip to next character
     s2++;
  }
  if( (*s1==0) && (*s2==0) ) // did both strings run out at the same length?
      return 0;
  return 1; // one is longer than the other
}

【讨论】:

    【解决方案2】:

    你应该使用strcmp:

    if(strcmp(decision, "yes") == 0)
    {
        /* ... */
    }
    

    【讨论】:

    • 你的 char 数组的大小应该是 4 以适应空终止值 - 请原谅我没有解释足够的即时通讯通过 iphone 写入
    • 没关系丹尼尔,我实际上只是将我的代码更改为 if (strcmp(decision, "yes") == 0) 并且它有效,然后我阅读了您的答案,非常感谢。所以我根据你的回答假设所有 C 字符串都以二进制 0 结尾?
    【解决方案3】:

    在 C 编程中,您应该特别注意以空字符结尾的字符串。它不是对象。它是一个指向内存地址的指针。因此,您不能直接将决策的 content 与位于另一个地址的常量字符串“yes”进行比较。请改用 strcmp()。

    请注意,“yes”实际上是“yes\0”,它将占用 4 个字节,并且“\0”对于 strcmp() 非常重要,它将在比较循环期间被识别为终止。

    【讨论】:

      【解决方案4】:

      好几件事:

      • decision 需要是一个由 4 个 chars 组成的数组,以便将字符串“yes”放入其中。这是因为在 C 中,string 的结尾由 NUL char ('\0') 指示。因此,您的 char 数组将如下所示:{ 'y', 'e', 's', '\0' }
      • 字符串使用诸如strcmp之类的函数进行比较,它比较字符串(char数组)的内容,而不是位置 /指针。返回值 0 表示两个字符串匹配。
      • 使用:scanf("%s", &decision);,不需要使用address-of操作符,数组的标签就是数组的起始地址
      • 您使用strlen 来获取字符串的长度,这只会增加一个计数器,直到达到NUL char'\0'不要使用sizeof 来检查字符串的长度,这是一个编译时操作,它将为char[3] 返回值3 * sizeof(char)
      • scanf 与字符串一起使用是不安全,您应该交替使用fgets(stdin...),或在格式字符串中包含宽度说明符(例如"3%s")以防止缓冲区溢出。 注意,如果您使用 fgets,请注意如果读取整行文本,它会存储换行符 char '\n'

      【讨论】:

      • 感谢您的详细解释
      【解决方案5】:

      为了比较,您可以像这样使用strcmp

      if(strcmp(decision, "yes") == 0) {
          // decision is equal to 'yes'
      }     
      

      您还应该将char decision[3] 更改为char decision[4] 以便缓冲区具有 终止空字符的空间。

      char decision[4] = {0}; // initialize to 0
      

      【讨论】:

      • 对 OP 的说明,您可以通过 char decision[4] = {0} 将数组中的所有元素初始化为 0(即使在使用大多数 C 函数时不需要这样做,例如 scanf 或 @ 987654328@.
      【解决方案6】:

      这里有几个问题:

      • 您没有为答案分配足够的存储空间:

        char[3] decision;
        

        C 字符串是字符串中的字节,后跟 ASCII NUL 字节:0x00,\0。此时您只为ye\0 分配了足够的空间。 (好吧,scanf(3) 会给你yes\0 并将NUL 放在无关的内存中。C 可能很残忍。)修改它以包括终止\0 的空间修改你的@ 987654329@调用防止缓冲区溢出:

        char[4] 决定; /* ... */ scanf("%3s", 决定);

        (我已经省略了&,因为简单地给出数组的名称与给出它的第一个元素的地址是一样的。没关系,但我相信这更惯用。)

      • C 字符串不能与== 进行比较。使用strcmp(3)strncmp(3)strcasecmp(3)strncasecmp(3) 比较您的字符串:

        if(strcasecmp(decision, "yes") == 0) {
            /* yes */
        }
        

      【讨论】:

        【解决方案7】:

        C 有很多 lib 函数来处理这个问题,但知道你在声明什么是值得的。

        声明

         char[3] decision;
        

        实际上是在声明一个长度为 3 的 char 数组。因此尝试比较

         if(decision == "yes")
        

        将文字与数组进行比较,因此将不起作用。由于 C 中没有定义的字符串类型,因此如果您不想使用,则必须使用指针,但不能直接使用。在 C 中,字符串实际上是 char 数组,因此您可以两种方式声明它们,例如:

        char[3] decision ;
        * char decision ;
        

        实际上两者都可以工作,但首先编译器会为你分配内存,但它只会分配 3 个字节。现在,由于 C 中的字符串是空终止的,因此您需要实际分配 4 个字节,因为您需要为“是”和空值留出空间。以第二种方式声明它只是在内存中声明一个指向 someplace 的指针,但您不知道真正的位置。然后,您必须分配内存以包含您要放在那里的任何内容,因为否则将更可能导致 SEGFAULT。

        要比较您从输入中获得的内容,您有两个选择,要么使用 strcomp() 函数,要么自己通过迭代 decision 并将每个单独的字节与“Y”和“E”进行比较和“S”,直到你点击 null aka \0。

        strcomp() 有处理大写和小写的变体,它们是标准 string.h 库的一部分。

        【讨论】:

        • 您好,感谢您的回答。我最终使用了 if (strcmp("yes") == 0) 效果很好。
        猜你喜欢
        • 2021-03-26
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 2022-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-29
        相关资源
        最近更新 更多