首页 > 代码库 > UVa 11111 一般Matrioshka 及 scanf 处理一行

UVa 11111 一般Matrioshka 及 scanf 处理一行

题目:nest,嵌套

思路:思路想通了其实很简单:将负数压栈,遇到输入正数时,检查栈顶元素,如果栈顶是正数,则出栈,一直检查栈顶元素直到栈顶是负数,判断该数和栈顶负数是否为相反数,并判断出栈的那些正数之和是否小于该输入的正数(这个是满足题目中的相加小于m的条件)。如果满足,则栈顶负数出栈,输入的正数入栈。这样循环到最后,如果一直匹配则最后栈中只剩一个元素。    思路很清晰,但实现起来比较麻烦,主要是EOF和\n的判断。我一直以为scanf是不能用来辨别一行的,因为它会跳过空白符。看了别人的一篇,才发觉scanf和getchar搭配还是可以处理一行的,因为scanf每次读过之后是停留在不匹配字符或空白字符处的,所以scanf后用getchar就可以判断是读到了一行行尾还是EOF还是正常地方。这里我是把每行划分为一个char+int组(int是在char判断不为换行时才进行读入),这样当char为换行时循环条件失败不再读入数字,而该行最后一个数字在上一次循环中已处理。但是这样会导致第一个int前没有char,这里是单独处理,情形也比较简单;如果是用int+char组来划分(即在while循环尾部先读int再读char),这样会导致换行的时候,最后一个int没有处理,需要在while循环外用相同的语句进行处理,比较麻烦。(这里的思想就是先判断再处理,即尽量不在循环最后处进行输入)这里根据AC的程序来看,应该是每行都有换行,不会最后一行只有EOF没有换行。

吐槽的是,开始的时候以为整数是一位数,就写了一个函数用getchar()然后返回int,发现不能处理多位数之后就按这个进行改,越改越麻烦。。到最后还RE。。。发现这样又是判断EOF里面又判断\n的用getchar就很麻烦需要很细心。。也许像这个程序一样,把每行先保存下来再处理比较好。。。

小结:scanf后跟getchar是可以辨别一行的。

Code:

//AC    
#include<stdio.h>
#include<string.h>
int stack[10000];

int main()
{
 int num;
 while(scanf("%d",&num)!=EOF)
 {
  char c=getchar();
  int flag=1;
  memset(stack,0,sizeof(stack));
  int top=0;
  if(num<0) stack[++top]=num;
  else {flag=0;};
  while(c!=‘\n‘)
  {
   scanf("%d",&num);
   if(num<0) stack[++top]=num;
   else
   {
    int sum=0;
    while(top>0 && stack[top]>0) { sum+=stack[top--]; }
    if(num+stack[top]==0&&sum<num) stack[top]=num;
    else flag=0;   
   }       
   if(flag==0) while((c=getchar())!=‘\n‘);
   else c=getchar();      
  }//whilec  
  if(flag&&top==1) printf(":-) Matrioshka!\n");
  else printf(":-( Try again.\n");                         
 }
 return 0;   
}

//RE
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>

int stack[10000];
int getin(int* flag);

int main()
{
 int a;
 int* fg;
 int next1=1;
 while((a=getin(fg))&& next1)
 {//*fg==2是EOF 
  int next2=1;
  if(*fg==2) next1=0;
  else if(*fg==1) next2=0;
  memset(stack,0,sizeof(stack));
  int top=0;
  int flag=1;
  while(next2)
  {//*fg==1是换行 
   if(*fg==1) next2=0;
   else if(*fg==2) {next1=0; break;}
   if(a<0) stack[++top]=a;
   else
   {//a>0
    int sum=0;
    while(top>0 && stack[top]>0) sum+=stack[top--];
    if(top>0 &&stack[top]+a==0 && sum<a) { stack[top]=a; }    
    else { flag=0;}//这里不需要break 
   }      
   if(flag==0 && next2) { while((a=getin(fg))&& *fg==0); break;}
   else if(next2!=0) a=getin(fg);    
  }//while
  if(flag==0||top!=1) printf(":-( Try again.\n");
  else printf(":-) Matrioshka!\n");                          
 }//while
 return 0;   
}

int getin(int* flag)
{//读入一个正数或负数,标记flag为1表示读到一行,为2表示读到EOF 
 char str[9];
 int k=0;
 char c=getchar();
 while(isdigit(c)||c==‘-‘)
 {
  str[k++]=c;
  c=getchar();                 
 }
 str[k]=‘\0‘;
 *flag=0;
 if(c==‘\n‘) *flag=1;
 else if(c==EOF) *flag=2;
 return atoi(str);
}