以下代码有效,但我不太明白 * if( s == 0) 的工作原理。 它检查字符串是否为0?
return(isnumber(s + 1)) 背后的逻辑是什么? 我知道s是一个字符串,但我可以将s + 1传递给函数?它怎么知道我在找什么角色?
int isnumber(char *s) {
if (*s == 0) {
return 1; /* Reached end, we've only seen digits so far! */
}
if(!isdigit(*s)) {
printf("The number is invalid\n");
return 0; /* first character is not a digit, so no go */
}
return(isnumber(s+1));
}
int main () {
char inbuf[LENGTH];
int i, j;
printf("Enter a string > ");
fgets(inbuf, LENGTH-1, stdin); // ignore carriage return
inbuf[strlen(inbuf)-1] = 0;
j = isnumber(inbuf);
....
}
答案 0 :(得分:4)
此函数是一个递归函数,用于检查字符串是否包含所有数字。要了解代码的工作原理,您必须了解C如何存储字符串。如果你有字符串" 123",C将这个字符串存储在内存中,如下所示:
|-----------------------------------|
| 0x8707 | 0x8708 | 0x8709 | 0x870A |
|--------|--------|--------|--------|
| | | | |
| '1' | '2' | '3' | '\0' |
|-----------------------------------|
C的作用是将它们分解为字符,将它们存储在内存中的任意位置,并在字符串的末尾添加空字符(\0)
(ASCII 0)。这个空字符是C知道字符串结束的位置。
您的isnumber()
函数将char *s
作为参数。这称为指针。在内部,最新进展的是main()
函数调用isdigit()
,它实际上是传入地址您的字符串,而不是字符串本身。这很重要:
j = isnumber(inbuf);
编译器如何解释这是call isnumber() and pass along the address of inbuf and assign the return value to j
。
现在备份到isnumber()
功能,它接收inbuf
的地址并将其分配给s
。通过在(*)
前放置一个星号s
,您正在执行一项名为取消引用 s
的操作。解除引用意味着您希望包含在s
地址中的值。所以说if (*s == 0)
的行基本上是If the value contained at the address of s is equal to 0
。记得早些时候我在内存中告诉过你,字符串总是有一个终止的空(\0)
字符?这就是你的函数知道结束和返回的方式。
接下来要理解的是指针算术。根据您的系统,char
可能占用1个字节的内存或2个字节。您可以通过打印sizeof(char)
来确定。但是当你引用(s+1)
时,它告诉计算机取s
指向的内存地址,并添加char
的大小。因此,如果char
长度为1个字节且s
指向0x8707
,那么(s+1)
将使s
等于0x8708
和{{1}将指向' 2'在我们的字符串中(参见上面的内存框图)。这就是我们如何遍历字符串中的每个字符。
希望这可以解决困惑!
答案 1 :(得分:1)
语句if (*s == 0)
检查char
s
指向的是否为零。换句话说,它会检查s
是否为零长度字符串,如果是则返回1
。
语句return (isnumber(s+1))
将1
添加到s,使其指向字符串中的第二个char
,并将其传递给isnumber()
。如果isnumber
处的字符串是数字,则s[1]
返回true。
答案 2 :(得分:0)
在C中,字符串以空字符终止。
(*s == 0)
正在检查空终止符。
这段代码有些怪异。
return(isnumber(s+1));
由于当前字符是一个数字,所以继续...从NEXT字符开始再次调用该函数。这是一个递归函数调用,当迭代变得更简单时,确实没有必要。