我最近发现一个C拼图写一个程序来读取一组整数x 0 ,x 1 ,x 2 ,... ...。直到输入-1
作为输入..
阅读-1
后,程序应打印每个相邻数字之间的差异。
即,x 1 -x 0 ,x 2 -x 1 ,x 3 -x <子> 2 子>,... ..
例如:
输入:
1 2 4 7 11 -1
输出
1 2 3 4
输出是(2-1),(4-2),(7-4),(11-7)的结果
问题是程序不应该使用数组。即使动态分配的数组也不行。
我尝试了很多,这就是我带来的东西
#include<stdio.h>
int a, b;
int fn()
{
int r=b-a;
a=b;
scanf("%d", &b);
if(b!=-1)
{
printf("%d ", fn());
}
return r;
}
int main()
{
scanf("%d%d", &a, &b);
printf("%d ", fn() );
return 0;
}
上面的程序使用递归函数,但在这种方法中,因为它就像一个堆栈,所以最后打印的值是先打印的,而不是先打印的值先打印出来。
即,与上述输入相同的输出是:
4 3 2 1
代替
1 2 3 4
有没有办法保存从这个调用堆栈中获取的值(如果我没有使用正确的术语,请纠正我)并再次将它们推入堆栈,这样在检索第一个计算值时,现在将是第一个弹出?
例如:
我得到了值4,3,2和2; 1使用fn()
,因为在弹出4
之前它就像在堆栈上一样:
4 3 2 1
假设我弹出堆栈中的所有元素,并按弹出顺序将它们推送到另一个堆栈。然后新的堆栈将是
1 2 3 4
(即,4
首先被弹出并推送(因此最终在底部),然后3
被弹出和推动等等。)
如果可以这样做,我们可以从新堆栈中弹出元素并按照它们弹出的顺序显示它们。
注意:我所指的堆栈是调用堆栈&amp;不是显式创建的堆栈(可能需要数组)。
或许有一种更简单的方法?
编辑:我需要将输入和输出阶段分开而不是交错。在使用-1
发出输入结束信号之前,不应显示任何输出。
编辑:程序无法使用文件存储输入以便稍后读回。
答案 0 :(得分:4)
有没有办法保存从这个调用堆栈中获取的值...并再次将它们推送到堆栈,这样在检索第一个计算值时,现在将是第一个被弹出的值?
每次读取数字时递归(除-1)。
创建一个由先前递归中的变量组成的链表。
除了printf()
格式外,没有使用任何数组。
在上次打印int
之后,需要做一些工作来避免空格。
#include<stdio.h>
#include<stdlib.h>
typedef struct list {
const struct list *prev;
int i;
} list;
void print_list(const list *previous) {
if (previous && previous->prev) {
print_list(previous->prev);
printf("%d ", previous->i - previous->prev->i);
}
}
void JSfoo(const list *previous) {
list node = { previous, 0 };
int cnt = scanf("%d", &node.i);
if (cnt == 1 && node.i != -1) {
JSfoo(&node);
} else {
print_list(previous);
puts("");
}
}
int main(void) {
JSfoo(NULL);
return 0;
}
输出(不交错)
1 2 4 7 11 -1
1 2 3 4
另一种方法是维护一个队列,以消除递归打印的需要。相同的输出。
以下使用循环队列。请注意只需要1个next
指针。队列句柄只需指向队列的末尾。不需要指向头部和尾部的指针。插入时间为O(1)
。
#include<stdio.h>
#include<stdlib.h>
typedef struct que {
struct que *next;
int i;
} que;
// Pass in the tail of the queue and return the updated tail
// `tail` points to the head. (Circular queue)
que *que_append(que *tail, que *node) {
if (tail) {
node->next = tail->next;
tail->next = node;
} else {
node->next = node;
}
return node;
}
void JSfoo(que *tail) {
que node;
int cnt = scanf("%d", &node.i);
if (cnt == 1 && node.i != -1) {
tail = que_append(tail, &node);
JSfoo(tail);
} else if (tail) {
que *head = tail->next;
while (head != tail) {
printf("%d ", head->next->i - head->i);
head = head->next;
}
puts("");
}
}
答案 1 :(得分:2)
您是否希望程序在输入“-1”后立即停止从用户那里获取更多输入字符,然后打印出差异序列?
如果没有,那就是如果你允许用户在“-1”之后输入更多的字符,程序会忽略直到输入换行符为止,那时你的程序可以打印出差异序列。然后,您可以使用以下代码段:
unsigned int x, y;
while( scanf("%d",&x)==1 && x != -1 && scanf("%d",&y)==1 && y != -1 )
printf("%d ",y-x);
printf("\n");
编辑: 感谢@JoëlHecht指出上述代码中的错误,我误读了所需的输出规范,以下代码应该修复它:
int x, y = -1;
while( scanf("%d",&x)==1 && x != -1 ) {
if( y != -1 ) printf("%d ",x-y);
y = x;
}
printf("\n");
答案 2 :(得分:1)
这是一个需要递归函数的经典问题。递归函数(1)接受一个值并为退出条件提供测试以打破递归; (2)对数据进行一些操作;然后(3)再次调用自己(进行递归调用),导致进程重复。
在你的情况下,递归函数需要的值是(1)先前读取的整数然后它将从current
读取stdin
值(验证和处理任何错误)和测试退出条件的current
是 -1
。然后,该函数必须(2)打印current
和previous
之间的差异。然后需要(3)将current
值作为参数传递给递归函数,再次调用自身直到满足退出条件。
将这些部分放在一起,您可以执行类似于以下difference()
功能的操作:
#include <stdio.h>
#include <stdlib.h> /* for EXIT_FAILURE */
/* recursive function taking previous read value as input */
void difference (int prev)
{
int current; /* variable to hold current value */
if (scanf ("%d", ¤t) != 1) { /* read / validate input */
fprintf (stderr, "error: invalid input.\n");
exit (EXIT_FAILURE);
}
if (current == -1) /* recusion exit condition */
return;
printf (" %d", current - prev); /* print difference */
difference (current); /* recursive call passing current */
}
int main (void) {
int n; /* variable for first value */
if (scanf ("%d", &n) != 1) { /* read / validate input */
fprintf (stderr, "error: invalid input.\n");
exit (EXIT_FAILURE);
}
if (n == -1) /* verify not -1 */
return 0;
difference (n); /* recursive call passing first value */
putchar ('\n'); /* tidy up */
return 0;
}
示例使用/输出
$ ./bin/diffints
1 2 4 7 11 -1
1 2 3 4
使用辅助函数开始递归
如果你想在main()
中稍微整理一下,可以创建一个辅助函数,它将读取第一个值并开始递归。这样只会在main()
中调用辅助函数。这根本不会改变程序的运行。而不是调用和验证scanf
的返回并在difference
中第一次调用main()
,而是将这些任务简单地移动到名为diffcheck()
的新函数,然后调用{ {1}}开始递归。完全取决于你。
difference()
注意:如何将#include <stdio.h>
#include <stdlib.h> /* for EXIT_FAILURE */
/* recursive function taking previous read value as input */
void difference (int prev)
{
int current; /* variable to hold current value */
if (scanf ("%d", ¤t) != 1) { /* read / validate input */
fprintf (stderr, "error: invalid input.\n");
exit (EXIT_FAILURE);
}
if (current == -1) /* recusion exit condition */
return;
printf (" %d", current - prev); /* print difference */
difference (current); /* recursive call passing current */
}
/* helper function to read 1st value and call difference */
void diffcheck (void)
{
int n; /* variable for first value */
if (scanf ("%d", &n) != 1) { /* read / validate input */
fprintf (stderr, "error: invalid input.\n");
exit (EXIT_FAILURE);
}
if (n == -1) /* verify not -1 */
return;
difference (n); /* recursive call passing first value */
putchar ('\n'); /* tidy up */
}
int main (void) {
diffcheck();
return 0;
}
简化为对main()
的单次调用,这比重复读取/验证更加清晰,并首先检查您要调用的所有地方<{1}}功能贯穿整个代码。
仔细研究,考虑diffcheck()
的递归函数操作,如果您有任何其他问题,请告诉我。
答案 3 :(得分:0)
该计划将
#include <stdio.h>
int main()
{
unsigned int x, y;
if(!(scanf("%d",&x)==1 && x != -1))
return 0;
while(scanf("%d",&y)==1 && y != -1 )
{
printf("%d ",y-x);
x = y;
}
printf("\n");
}
答案 4 :(得分:-1)
以下是我提出的建议:
#include <stdio.h>
int a, b;
void fn()
{
int r=b-a;
a=b;
scanf("%d", &b);
printf("%d ", r);
if(b!=-1)
fn();
}
int main()
{
scanf("%d%d", &a, &b);
fn();
printf("\n");
return 0;
}