【问题标题】:Why does the the function not work when the parameter is a pointer?为什么当参数是指针时函数不起作用?
【发布时间】:2021-10-04 05:01:37
【问题描述】:
#include "stdio.h"
#include "stdlib.h"


typedef enum lightSwitch {
        OFF = 0,
        ON
}lightSwitch;

void setLight(lightSwitch setting){
        if(setting == 1){
                printf("(v)\n =\n");
        }
}
int main(void){

  char *p = malloc(sizeof(lightSwitch));
  printf("'ON' or 'OFF'?\n");
  scanf("%s", p);
  setLight(*p);

}

我不完全确定这段代码有什么问题。当用户输入“OFF”时,灯泡应该保持隐藏状态,但如果用户输入“ON”,则应该显示灯泡。

【问题讨论】:

  • 枚举不是字符串
  • 除此之外,您的意思是if(setting == ON)?您没有使用您定义的 enum 值。
  • *p 是来自用户的字符串的第一个字符,可能是 'O'
  • 枚举只是一个“掩码”或“映射”或任何您想用于整数的词,在这种情况下与#define OFF 0#define ON 1 没有太大区别。您的代码似乎暗示您认为枚举将字符串映射到一个值,就好像字符串“OFF”解析为 0,如果您认为您对枚举的理解是错误的。

标签: c function pointers enums malloc


【解决方案1】:

在使用char *p = malloc(sizeof(lightSwitch));时,需要注意两点:

  1. 当您不再需要它时,请确保free(p)。 (虽然在这种情况下不需要,因为程序会在终止后自动为您释放它,但您仍然应该这样做,因为它被认为是一种好的做法。)
  2. sizeof (lightSwitch) 本质上只是写 sizeof (int) ,它是平台相关的,所以你的字符串的大小可能会在不同的平台上有所不同,并且可能导致未定义的行为,这是不可取的。
/* The below two lines shouldn't be used unless you have put both 'stdio.h'
   and 'stdlib.h' inside your program's source directory, which isn't really a sane idea */
// #include "stdio.h"
// #include "stdlib.h"

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

typedef enum lightSwitch {
    OFF,
    ON
} lightSwitch;

void setLight(lightSwitch setting) {
    if(setting == ON)
        printf("(v)\n =\n");
}

int main(void) {
    // It suffices to simply use an array instead of a dynamically allocated pointer in this context
    char p[4] = {0};

    printf("'ON' or 'OFF'?\n");
    scanf("%3s", p);

    // strcmp(a, b) essentially compares the equality of two strings passed to it and returns 0 if they are equal
    setLight(strcmp(p, "ON") == 0 ? ON : OFF);
}

【讨论】:

    【解决方案2】:

    您正在尝试向 malloc 请求内存并且您将枚举的大小传递给它,您应该将它传递给 sizeof(char) * 您希望字符串成为的字符数(请注意,您需要保留一个字节为terminating the string)。

    其次,您尝试在 char* 和整数之间进行比较。

    你应该做的是这样的:

    if(strcmp(p,"ON") == 0) 
     setLight(ON); //use the enum attribute
    else
     setLight(OFF);
    

    检查输入字符串,然后将所需的相应枚举值传递给 setLight 函数。

    【讨论】:

    • if(*p == "ON") 这样的代码永远不会起作用。 char (*p) 如何等于字符串 ("ON")?
    【解决方案3】:

    枚举不是字符串。 OFF 只是另一种写 0 的方式。而 ON 只是另一种写 1 的方式。它们与字符串“ON”或“OFF”无关。当你的程序被编译时,编译器不会把名字“ON”或“OFF”放到程序中,所以程序不知道它们叫什么。

    因此,考虑到这一点,您的程序正在分配一些内存,将字符串读入该内存(即假设用户键入 ON,然后字节 0 变为“O”,字节 1 变为“N”,字节 3 变为 0) ,然后检查第一个字节是否等于 1,不是,因为 'O' 的 ASCII 码是 79。

    【讨论】:

      【解决方案4】:

      枚举常量ON 与字符串"ON" 是完全不同的动物,它们之间完全没有联系。您不能以字符串的形式输入变量或常量的名称,也不能访问相应的值 - C 不能那样工作。

      您将不得不找到一种方法来手动将字符串 "ON""OFF" 映射到相应的枚举值(或者放弃使用枚举而只使用字符串)。

      要读取字符串,您需要一个足够大的缓冲区来容纳字符串的所有字符以及字符串终止符。在这种情况下完全没有必要使用动态内存1 - 你只需要分配一个固定长度的数组char

      #include <ctype.h>
      #include <string.h>
      #include <stdio.h>
      
      #define MAX_CHARACTERS 3 // length of "OFF"
      
      int main(void){
      
        char buf[MAX_CHARACTERS+1] = {0}; // +1 to allow for the string terminator
      
        printf("'ON' or 'OFF'?\n");
      
        /**
         * We're going to use fgets instead of scanf - it's easier to
         * protect against buffer overflow.  
         */
        if ( fgets( buf, sizeof buf, stdin ) ) 
        {                                      
          /**
           * First, make sure the input string is all upper case - that way 
           * we don't have to worry about comparing against "on", "On", "oN",
           * etc.
           */
          for ( char *p = buf; *p != 0; p++ )
            *p = toupper( *p );
      
          /**
           * Create a variable of type lightSwitch - this is what we'll
           * pass to setLight.  Default value is OFF
           */
          lightSwitch setting = OFF; 
      
          if ( strcmp( buf, "ON" ) == 0 )
            setting = ON;
      
          setLight( setting );        
        }
        else
        {
          // handle input error here
        }
      }
      

      正如所写,这只会在用户输入"ON" 时启用灯;对于任何其他输入,灯将关闭。如果您不想创建单独的变量,我们也可以编写它:

      if ( strcmp( buf, "ON" ) )
        setLight( ON );
      else
        setLight( OFF );
      

      它会做同样的事情。


      1. sizeof (lightSwitch) 返回 lightSwitch 对象的大小(可能只有 2 个字节),而不是保存字符串 "ON""OFF" 所需的字符数;分配空间存储字符串时,需要为 N 个字符加上字符串终止符分配空间。更好的选择是使用strlen( "OFF" ) + 1 作为malloc 的参数,但同样在这种情况下,您不需要使用动态内存。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-22
        • 1970-01-01
        • 2020-01-03
        • 2019-04-18
        • 2014-04-19
        • 1970-01-01
        • 1970-01-01
        • 2020-04-04
        相关资源
        最近更新 更多