【问题标题】:Passing a string through a function. C [duplicate]通过函数传递字符串。 C [重复]
【发布时间】:2016-11-12 09:30:00
【问题描述】:
void printInstructions();
char *getUserWord();


int main()
{
    printInstructions();
    char *baseWord = getUserWord();
    printf("%s", baseWord);
    return 0;
}


void printInstructions()
{
    printf("                      Instructions:                        \n"
   "===================================================================\n"
   "= This program is a hangman game.                                 =\n"
   "= The first user will enter the name to be guessed                =\n"
   "= After that, the second user will guess the letters of the word  =\n"
   "= the second user will loose if they have three strikes           =\n"
   "===================================================================\n");
   return;
}


char *getUserWord()
{
    static char str[20];
    scanf("%s", str);
    return str;
}

我的函数getUserWord 通过传递一个字符串来完成它的任务。从我在线阅读的内容来看,char *baseWord = getUserWord(); 是将字符串分配给主函数中的变量的唯一方法。我不知道为什么这是有效的,我什至不确定这在内存中做了什么。以下是对我有意义的内容。为什么这行不通?

 char baseWord[21];
 baseWord = getUserWord();

【问题讨论】:

    标签: c arrays string function


    【解决方案1】:

    您已经陷入了认为指针和数组是同一事物的陷阱。他们不是。

    按照 C 中的约定,字符串通常表示为 char 的数组,并在末尾附加一个额外的终止符 '\0'(所谓的 nul 字符)。所以字符串文字 "AB" 表示为三个 char 的数组,其值为 'A''B''\0'

    指针与数组完全不同,因为字符串是用char 的数组表示的,所以指针和字符串是完全不同的东西。指针是一个包含内存地址的变量。

    令人困惑的地方是数组的名称在许多上下文中被转换为指针。例如;

     char x[] = "AB";
     char *p = x;
    

    这个赋值有效,但这并不意味着数组是指针,或者指针是数组。相反,名称x 被转换为指向其第一个字符的指针。所以初始化在功能上等价于

     char *p = &x[0];
    

    所以p指向字符串"AB"中值为'A'的字符。

    同样的事情发生在你的代码中,所以

    char *getUserWord()
    {
        static char str[20];
        scanf("%s", str);
        return str;
    }
    

    等价于

    char *getUserWord()
    {
        static char str[20];
        scanf("%s", &str[0]);
        return &str[0];
    }
    

    在这两种情况下,getUserWord() 返回的指针都有一个值,即str[0] 的地址。这是用于在main() 中初始化baseWord 的值

    char *baseWord = getUserWord();
    

    因为baseWord 现在指向数组的第一个字符,所以可以将其视为数组。在 C 中,对于给定值 i,这包括 baseWord[i](在 main())和 str[i](在 getUserWord())之间的等价。使用数组语法这一事实并不意味着指针和数组是一回事。这只是意味着它们可以使用相同的语法进行处理。

    然而,重要的是要意识到一个指针可以从一个函数返回(并且返回的值分配给或用于初始化另一个指针)但数组不能。所以,在main() 这是合法的;

     char *p = getUserWord();
     p[0] = 'X';    /*  will change str[0] in getUserWord() */
    

    但这不会是;

     char array[20] = getUserWord();
    

    【讨论】:

    • 非常感谢您的澄清。所以没有办法真正通过数组传递一个字符串?另外,当我说“char *getUserWord()”时,它是否告诉函数它正在返回一个地址?
    • 您在这里的第一个问题的措辞不清楚-“通过数组传递字符串”是什么意思?至于第二个——声明char *getUserWord()指定了一个返回指针的函数——指针是一种包含地址的变量。
    • 第一个问题我的意思是有可能在函数中实际返回一个字符串。
    • 没有。函数可以返回指针,但不能返回数组。可以返回一个结构,该结构又包含一个数组,但这是不同的。
    【解决方案2】:

    不能在 C 中分配数组。这是 C 标准1 规定的。第二个示例中的左值是baseWord,其类型为char[21],它是一个数组。

    在您的第一个示例中,当您返回类型为 static char[20]str 时,它会转换为类型 char*,并且可以从函数返回并分配给指针 baseWord。由于str 具有静态存储持续时间,因此指针指向一个有效对象。

    如果你想返回一个非静态字符串,你可以分配它(使用函数 malloc),将一个现有的字符串传递给一个函数或者用一个结构体包装字符串。


    1(引自:ISO:IEC 9899:201X 6.3.2.1。左值、数组和函数指示符 1)
    可修改的左值是一个左值 没有数组类型,没有不完整的类型,没有 const- 限定类型,如果是结构或联合,则没有任何成员(包括, 递归地,所有包含的聚合或联合的任何成员或元素)具有 const- 限定类型。

    【讨论】:

      【解决方案3】:

      这将解决您的问题。

      #include <stdio.h>
      
      void getUserWord(char* str);
      
      int main(void)
      {
          char baseWord[21] = ""; /* initialize for avoiding undefined behavior in case no data is read */
           getUserWord(baseWord);
           printf("%s", baseWord);
      
           return 0;
      }
      
      void getUserWord(char* str)
      {
          scanf("%s", str);
      }
      

      【讨论】:

        【解决方案4】:

        这段代码

        char baseWord[21];
        baseWord = getUserWord();
        

        不起作用,因为从数组转换的不是左值 (N1570 6.3.2.1),而赋值运算符的左操作数需要可修改的左值 (N1570 6.5.16)。

        您可以将指针传递给一个数组,该数组将从被调用者读取的字符串存储在该数组中。

        #include <stdio.h>
        
        void getUserWord(char* str);
        
        int main(void)
        {
            char baseWord[21] = ""; /* initialize for avoiding undefined behavior in case no data is read */
            getUserWord(baseWord);
            printf("%s", baseWord);
        
            return 0;
        }
        
        void getUserWord(char* str)
        {
            scanf("%s", str);
        }
        

        本例省略,请检查是否读取成功。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-01-21
          • 2021-10-03
          • 1970-01-01
          • 1970-01-01
          • 2011-07-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多