不使用数组

时间:2017-08-08 01:38:28

标签: c gcc

我最近发现一个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发出输入结束信号之前,不应显示任何输出。

编辑:程序无法使用文件存储输入以便稍后读回。

5 个答案:

答案 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)打印currentprevious之间的差异。然后需要(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", &current) != 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", &current) != 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;
}