【问题标题】:Multiple type specifiers in declaration list声明列表中的多个类型说明符
【发布时间】:2017-10-16 10:48:41
【问题描述】:
#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    //ask user for input
    string s = get_string();

    //make sure get_string() returned a string
    if(s != NULL)
    {
        //iterate over the characters one at a time
        for(int i = 0, int n = strlen(s); i < n; i++)
        {
            //print i'th character in s
            printf("%c\n", s[i]);
        }
    }
    else
    {
        //tell the user that their input is not a string
        printf("Sorry, no good\n");
    }

}

编译器抱怨这一行:

for(int i = 0, int n = strlen(s); i < n; i++)

因为我用int声明了整数n来定义类型。

程序编译得很好:

for(int i = 0, n = strlen(s); i < n; i++)

为什么iint 是必需的/良好的形式,但在这个例子中n 不是?

【问题讨论】:

  • comparing int with size_t的可能重复
  • 语句int i,n;(无论是否在for循环中)声明了两个变量(而int i, int n;是不正确的[也在任何地方])。在这里,OP 也恰好在初始化它们。
  • @Eimantas 一点也不。
  • 如果您有兴趣,可以联系cs50 stack exchange
  • @maraguida 啊!谢谢,我不知道!

标签: c for-loop declaration cs50


【解决方案1】:

因为这行:

int i = 0, n = strlen(s)

创建两个名为in 的整数并初始化它们。

当你放:

int i = 0, int n = strlen(s)

您创建一个名为 i 的 int 并对其进行初始化,然后您尝试创建另一个名为 int n 的 int,这没有任何意义。

没有理由将n 初始化到它所在的位置——毕竟它不应该改变。在循环之前初始化它:

int n = strlen(s); 

for(int i = 0; i < n; i++)
{
    ...

【讨论】:

  • 这对我来说看起来也更干净,但教授的方式就是我展示的方式。
  • @phindex 没关系,您可以按照您在问题中提出的方式进行操作。
  • @Steve 我收到了很好的答案,我赞成他们。我需要做些什么来“结束”我的问题或其他任何事情吗?
  • @phindex 您可以将其标记为“已回答”-stackoverflow.com/help/someone-answers。但除此之外,请保持原样,以便其他人在遇到相同问题时可以找到它。
  • @Jean-FrançoisFabre 嗯,它发生了。可能有人认为我是在要求 OP 标记我的答案。
【解决方案2】:

int i = 0, n = strlen(s) 行是一个声明列表。当您在此处键入逗号时,您会说“给我另一个相同类型的变量”。该代码与int x, y; 之类的代码相同。

请注意,在某些情况下,在同一行声明多个变量可能很危险。可能存在初始化误解,并且可能会误解哪个变量是指针,哪个不是指针。 (int* x, y声明了两个指针。)

因此,总是在自己的一行中声明每个变量是一种很好的做法。此外,保持 for 循环尽可能干净和简单也是一个好习惯。因此,编写该循环的最佳方式可能是:

int n = strlen(s);
for(int i = 0; i < n; i++)

【讨论】:

  • 附带说明,在获取数组长度时使用的最正确类型是使用整数类型size_t,这就是我们在这种情况下所做的。 CS50 不会教你这个。
  • 除了 “最正确的类型”之外,还有一个事实,这正是 strlen 返回的内容。所以它应该是size_t,如果没有其他原因,只是为了避免隐式转换。
  • @Lundin 为什么 CS50 教授 size_t?我在不应该去的地方学习吗?
  • @phindex 因为它显然是一个相当糟糕的教程,在 SO 上已经声名狼藉。我还没有阅读完整的课程材料,所以我可能是错的。然而,前几章绝对是废话。
【解决方案3】:

当您第一次使用 int 时,所有逗号分隔的变量现在都是 int。

意思是下面两条语句是一样的:

int a, b; //a = int, b = int
int a; int b; //a = int, b = int

【讨论】:

    【解决方案4】:

    C 允许您在初始类型声明之后声明多个变量:

    int x, y, z =0, whatever;
    

    不允许在列表中添加额外的类型声明,即使它匹配原始类型。

    【讨论】:

      【解决方案5】:

      你正在尝试这个;

      int i = 0, int n =strlen(s);
      

      不正常。 是一样的

      int i = 0 , char s ;
      

      你需要试试这些:

      int i = 0, n=strlen(s);//or
      /*-----------------*/
      int n = strlen(s);
      for(int i = 0;....)//or
      /*-----------------*/
      int i = 0;int n= strlen(s);//unnecessary but not wrong
      

      并且不要在for(...)处定义不相关的veriable,在'for'之前定义。

      【讨论】:

        【解决方案6】:

        for(int i = 0, int n = strlen(s); i &lt; n; i++){ /*...*/ } 不是有效的 C/C++ 语法。 for(int i = 0, n = strlen(s); i &lt; n; i++){ /*...*/ } 是。 不过,您只能做到这一点,in 必须具有相同的类型。如果您希望它们以不同的方式输入,您可以这样做:

        { int i=0; long n=strlen(s); for(; i<n; i++) {  /*...*/ } }
        

        它比 >=C99 for 循环更灵活、更便携。

        【讨论】:

        • 实际上并没有在现有答案上添加任何内容
        【解决方案7】:

        函数strlen(与运算符sizeof一样)的返回类型是size_t,它是通常为unsigned long的无符号整数类型的别名。所以int 类型无法容纳size_t 类型的所有值。

        所以不要使用int 类型,而是使用size_t 类型。

        此外,您显示的 for 循环包含语法错误。

        声明在 C 标准中定义,如

        declaration:
            declaration-specifiers init-declarator-listopt ;
            static_assert-declaration
        

        因此,声明说明符应位于标识符列表中所有已声明标识符的声明符之前。

        所以这个声明在for循环中

        int i = 0, int n = strlen(s); 
        

        不正确,因为在声明符 in 之间遇到了声明说明符 int

        for( size_t i = 0, n = strlen(s); i < n; i++)
        

        而不是

        for(int i = 0, int n = strlen(s); i < n; i++)
        

        其实没有必要调用函数strlen。没有它也可以编写循环。

            for( size_t i = 0; s[i] != '\0'; i++ )
            {
                //print i'th character in s
                printf("%c\n", s[i]);
            }
        

        注意你应该释放指针s 声明为

        string s = get_string();
        

        在程序结束时。例如

        free( s );
        

        【讨论】:

        • 这篇文章到底是怎么被贬低的?
        • @sp2danny 这些制裁是针对俄罗斯的吗?:)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-21
        • 1970-01-01
        相关资源
        最近更新 更多