例如,在Python中,如果我们把一个列表当作一个数组,它会直接打印整个数组,只需要一行代码,有没有办法在C语言中实现同样的效果?
uurity8g1#
没有
这取决于你的意思。在内部,Python也可以使用循环。它只是对你隐藏起来了,所有的编程语言都是如此。如果你想处理一个数组,你通常需要在某种程度上使用循环。因此,如果你的问题是是否有一些打印数组的预定义函数,答案是否定的,前提是数组不是字符串,但是为此编写一个自定义打印函数并不难,下面是一个打印得相当漂亮的示例:
void print_int_array(int *arr, size_t size) { if (size == 0) { printf("[]"); } else { putchar('['); for (int i = 0; i < size - 1; i++) printf("%d, ", arr[i]); printf("%d]", arr[size - 1]); } }
也可以使用递归,但递归基本上只是一个伪装的循环。下面是上面的递归版本:
void print_int_array_rec(int *arr, size_t size) { if (size == 0) { putchar(']'); } else { printf("%d", *arr); if (size == 1) printf(", "); print_int_array_rec(arr + 1, size - 1); } } void print_int_array(int *arr, size_t size) { putchar('['); print_int_array_rec(arr, size); }
但正如我所说,它基本上只是一个伪装的循环。至少在这个简单的例子中是这样的。所有的循环在汇编中通常都转换成这样的东西:
loop_start: // Code if(<condition>) goto loop_start
或者使用嵌套循环:
loop_start: <----------------------| // Code | loop2_start: <-----------| | // Code | | if(<condition>) goto loop2_start ---| | // Code | if(<condition>) goto loop_start -------|
使用递归时,这些跳转可能会变得更加复杂。如果使用复杂的递归,跳转可能无法正确嵌套。这可能会导致以下情况:
loop_start: <--------------| // Code | loop2_start: <-----------+--| // Code | | if(<condition>) goto loop_start --| | // Code | if(<condition>) goto loop2_start ----|
注意,我调换了gotos的位置,所以这个“循环”没有正确嵌套。没有内部循环和外部循环。这就是所谓的“意大利面代码”,也是goto不受欢迎的原因,因为它使代码很难理解。但当它是编译器编写的汇编时,这并不重要。那么这个代码片段算不算一个循环,虽然很复杂?TBH,我不确定。但是我知道递归和常规迭代是 * 同样有表达力的 *,这意味着 * 没有什么东西你可以递归计算,你不能迭代计算,反之亦然 *。阅读here了解更多信息。有些东西用递归风格写起来会容易得多,例如阿克曼函数:How to rewrite Ackermann function in non-recursive style?
goto
xghobddn2#
你可以使用递归-没有循环。
void printarray1(int *array, size_t size, size_t pos) { if(pos < size) {printarray1(array, size, pos + 1); printf("%d%s", array[size - pos - 1], pos ? " ": "");} } void printarray(int *array, size_t size) { printf("[");printarray1(array, size, 0);printf("]"); } int main(void) { int array[] = {1,2,3,4,5,6,7,8,9,10}; printarray(array, sizeof(array)/sizeof(array[0])); }
https://godbolt.org/z/Y79xTG
idfiyjo83#
是的,我们可以。如果数组大小是固定的,比如说数组的大小是6。那么你可以打印这些值,比如printf(a[0])到printf(a[5])。如果你给用户给予了“n”的值(这里n是数组的大小),那么你不知道用户会给什么值。所以在这种情况下,你需要循环来打印数组中的值。
mepcadol4#
如果是字符数组,则如下所示:
char a[] = "abcdefghi"; printf("%.3s", a); // prints -> abc
如果你想打印可变数量的字符:
char a[] = "abcdefghi"; char fmt[128]; int n = 3; sprintf(fmt, "%%.%ds", n); printf(fmt, a); // prints -> abc
用于不以\0结尾的字符数组
vbkedwbf5#
是的,它可以打印一个没有循环的数组,你只需要使用后藤statemenet来创建一个循环,并检查if条件
my: if(i<n) { scanf("%d",&arr[i]); i++; goto my; } else{ printf(" "); } j=0; to: if(j<n) { printf("%d ",arr[j]); j++; goto to; } else{ printf(" "); }
5条答案
按热度按时间uurity8g1#
简短回答
没有
表单上几乎所有问题的简短答案 “你能像Python一样简单地在C中执行X吗?"
没有
长答案
这取决于你的意思。在内部,Python也可以使用循环。它只是对你隐藏起来了,所有的编程语言都是如此。如果你想处理一个数组,你通常需要在某种程度上使用循环。
因此,如果你的问题是是否有一些打印数组的预定义函数,答案是否定的,前提是数组不是字符串,但是为此编写一个自定义打印函数并不难,下面是一个打印得相当漂亮的示例:
也可以使用递归,但递归基本上只是一个伪装的循环。下面是上面的递归版本:
但正如我所说,它基本上只是一个伪装的循环。至少在这个简单的例子中是这样的。所有的循环在汇编中通常都转换成这样的东西:
或者使用嵌套循环:
使用递归时,这些跳转可能会变得更加复杂。如果使用复杂的递归,跳转可能无法正确嵌套。这可能会导致以下情况:
注意,我调换了gotos的位置,所以这个“循环”没有正确嵌套。没有内部循环和外部循环。这就是所谓的“意大利面代码”,也是
goto
不受欢迎的原因,因为它使代码很难理解。但当它是编译器编写的汇编时,这并不重要。那么这个代码片段算不算一个循环,虽然很复杂?TBH,我不确定。但是我知道递归和常规迭代是 * 同样有表达力的 *,这意味着 * 没有什么东西你可以递归计算,你不能迭代计算,反之亦然 *。阅读here了解更多信息。
有些东西用递归风格写起来会容易得多,例如阿克曼函数:How to rewrite Ackermann function in non-recursive style?
xghobddn2#
你可以使用递归-没有循环。
https://godbolt.org/z/Y79xTG
idfiyjo83#
是的,我们可以。如果数组大小是固定的,比如说数组的大小是6。那么你可以打印这些值,比如printf(a[0])到printf(a[5])。如果你给用户给予了“n”的值(这里n是数组的大小),那么你不知道用户会给什么值。所以在这种情况下,你需要循环来打印数组中的值。
mepcadol4#
如果是字符数组,则如下所示:
如果你想打印可变数量的字符:
用于不以\0结尾的字符数组
vbkedwbf5#
是的,它可以打印一个没有循环的数组,你只需要使用后藤statemenet来创建一个循环,并检查if条件