K&用于保存输入最长行的R节1.9代码具有以下功能:
int getline(char s[], int lim)
{
int c, i;
for(i = 0; i < lim -1 && (c =getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = c;
return i;
}
然而,对于最佳实践,我已经了解到一个函数只做一件事。我相信这个函数将其输入中的行复制到s的char数组上并返回长度。这不算是两件事吗?我认为这是一种不好的做法,我是否正确?
详细说明,我们确实使用getLine函数的输入,但方式非常不直观。
main()
{
int len; /*current line length*/
int max; /*Current max line length seen so far*/
char line[MAXLINE]; /*Current input line */
char longest[MAXLINE]; /*Longest line saved here*/
max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/*FUNCTION GETLINE TAKEN OUT */
/*copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
答案 0 :(得分:2)
不,有两个原因。
首先可以说getline
(顾名思义)的目的是从输入中读取一行。它也返回读取的字符数这一事实可以通过C-strings的工作方式来解释,否则该函数不能用于读取包含空字节的数据。
其次,该函数不包含任何额外的代码来计算长度。它是读取字符串的副产品。否则该函数的类型为void
,因此返回字符串的长度确实没有任何缺点。
编码指南也不是自己的结束,但应该有助于产生良好的代码。我没有看到如何通过省略return语句并编写单独的 O(n)函数来检索长度来改进此代码。
答案 1 :(得分:2)
getline()
函数没有做两件事。它做了两件非常密切相关的事情,让它恢复字符串的长度绝对不错。
不要试图盲目地将函数,算法和其他类似的东西放入模式中。 getline()
在概念上是正确的,因为字符串是一个对象。它有一个内容缓冲区和一个长度。两个&#34;属性&#34;属于字符串对象,事实上,我认为将它们分开是不好的做法。
此外,还有另一个计算字符串长度的函数会变得不必要地复杂(并且效率低下)。在C中,字符串以0结尾,因此这样的函数必须遍历整个字符串才能找到它的长度。
(更不用说C标准库中已经存在这样的功能,它被称为strlen()
。)
答案 2 :(得分:1)
通常对于字符串和一般数组,这不是一个例外,但实际上是非常有用的行为。从某种意义上说,数组具有隐式长度属性。有时这在编译时是已知的,有时它在运行时已知并存储在变量中,有时它只能通过以空终止的数组来确定。
在任何情况下,由于无法按值返回数组,因此返回数组的长度(通常非常方便)是将数组写入缓冲区的函数的一个非常有用的属性。当调用者无法知道写入数组的长度时,我甚至认为它在C中是惯用的。
此外:
上面的答案是关于不分配内存但只写入提供的缓冲区的函数。如果知道分配的数组大小对调用者总是有用并且您不希望稍后迭代数组,那么返回一个简单的结构struct { size_t size; valtype* vals; }
有时很有用。与你的问题相似,你可以看出为什么在某种程度上它并没有真正做两件事;它只是给你一个更完整的结果。