【问题标题】:Regarding the scope of functions(parameters) in a loop in C关于C循环中函数(参数)的范围
【发布时间】:2017-08-16 07:55:29
【问题描述】:

我有一个关于 C 中参数范围的问题。我是 C 新手,我一直在解决一个问题,在我苦苦挣扎后,一位 TA 给了我一个函数 getline()

int main(void) {

  printf("Type a string, then hit enter\n");
  printf("You may type strings after an enter, but you must hit enter again to     record the new string\n");
  fflush( stdout );
  int len;
  char line[Limit];


  while((len=getline(line,Limit))>0) 
  {
    reverse(line);
    printf("%s",line);
  }
}

其中调用函数getline()定义为:

int getline(char s[], int lim){
  int i,c;
  for(i=0;i<lim-1 &&((c=getchar())!=EOF) && (c !='\n');++i)
    s[i]=c;

  if(c== '\n')//if c is a newline
  {
    s[i]=c; 
    ++i;
  }
  s[i]= '\0';
  return i;
}

因为 char line[limit] 在 while 条件下被传递给 getline()getline() 确实适用于 line[] 并更改它的值。

我的问题是,一旦循环迭代完成,当 getline() 在 while 循环中再次被调用时,它是否仍然保留第一次迭代的值还是被重置?

我知道line[] 在退出 while 循环后为空,但我想知道它在循环本身中的细微差别。

例如,如果我输入标准输入:

"Hello\n
"How are you\n"

line[]="Hello\n\0"getline() 完成 while 循环的第一次迭代时。当 getline() get 再次调用迭代 2 时,是 line[]="Hello\n\0" 吗? (假装反向不存在)并被覆盖或者是line[]="\0"

如果 reverse 不存在(与打印的一个字符串是否更长无关)并且我输入了

"How are you\n
Hello\n"

line[]="Hello\n\0you\n\0" 会不会?在 while 结束之前的第二次迭代之后?

【问题讨论】:

  • 什么是“当 getline() 在 while 循环中再次调用时,它仍然保留第一次迭代的值还是重置?”中的“它”是什么?
  • 没有理由让数组内容在其仍在范围内时“重置”,除非有明确的修改它们。所以是的,它保留了上次放入其中的任何内容。同样在退出循环后line 没有被清空,它只是在开始时有一个空字符,因为getline() 在最后一次评估循环条件时放了一个......这对应于一个零字符串,但是数组的其余部分仍然有之前读取的内容。
  • "它'是char数组行的值
  • 好吧,我想我明白了@Dmitri 的意思。由于 getline() 无论是否 >0 都会执行,因此 line[] 的值正在发生变化。所以第三次 i=0 但 s[i] 的返回值仍将设置为 '\0'。因此,如果我没有手动放置一个手动空终止字符串 if i is=0 那么 line[] 将具有第二次迭代的值
  • 好吧,所以在 while 的第二次迭代之后 line 并不是真的空(在你的例子中),但是当你尝试 printf("%s", line) 时,因为前导元素是 ' \0',打印是空的,所以它看起来是空的。

标签: c function parameters while-loop scope


【解决方案1】:

因为 char line[limit] 在 while 条件下被传递给 getline()。 getline() 确实在 line[] 上工作并改变了它的值。我的问题是一旦循环迭代完成,当 getline() 在 while 循环中再次调用时,它是否仍然保留第一次迭代的值还是被重置?

数组line 在循环外声明。它最里面的封闭块是作为整个函数体main()的块;它的生命周期是从声明到该块的末尾。在该生命周期内,声明的标识符line 始终指定相同的对象,并且该对象保留其值,除非您的程序可以显式修改该值。特别是,如果数组是用初始化器声明的,那么该初始化器将只应用一次,当数组第一次出现时。

因此,line 数组确实从循环的一次迭代到下一次迭代保留了它的值。然而,在循环的每次迭代中所做的第一件事是测试循环条件,这需要调用getline(),它会修改该数组的部分或全部元素。因此,循环体中的语句将在每次迭代时看到新的数组内容。

【讨论】:

    【解决方案2】:

    是的,在 C 中,数组是按引用传递的,这意味着您的程序不是将整个数组传递给函数,而是传递一个指向存储数组的内存地址的指针。这意味着当您在函数中修改它时,它也会在外部代码中修改它。当您向getline 中的 s 添加更多字符时,您也在向line 中的line 添加字符。

    【讨论】:

    • 详细信息:当数组作为扩充传递给函数时,它会在调用函数之前转换为其第一个元素的地址。该函数接收该地址的副本。所以有点像“按引用传递”,来自数组 POV,但在细节上,仍然按值传递。在这种情况下,指针被传递,并按值传递。
    • 好的,所以 line[] 不断被覆盖,即使在 while 循环完成后它仍然保留它的值。 Dmitri 澄清了一点,为什么在我的代码 line[] 中循环结束时也会 = "\0"。如果它不是这样设置的(我明白它为什么与问题有关),那么 lines[] 将包含与传入的最大字符串的字符连接的最新字符串,该字符串大于最最近的字符串。
    猜你喜欢
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    相关资源
    最近更新 更多