顯示具有 C 標籤的文章。 顯示所有文章
顯示具有 C 標籤的文章。 顯示所有文章

2020年3月3日 星期二

11398 - The Base-1 Number System

先說這個解法在uva給我CE.....我的想法是一次讀一行做分析,不過比較好的好像是一個區段一個區段計算就好。

程式碼:(解法一)
#include <stdio.h>

int main()
{
    char s[1000];
    while(gets(s)!=0&&s[0]!='~')
    {
        int i=0,num=0,flag=0,n=0;
        while(s[i]!='#')
        {
            if(s[i+1]==' ')
            {
                i+=2;
                flag=1;
            }
            else if(s[i+2]==' ')
            {
                i+=3;
                flag=0;
            }
            while(s[i]!=' ')
            {
                i++;
                n++;
            }
            i++;
            for(int j=0;j<n-2;j++)
                num=num*2+flag;
            n=0;
        }
        printf("%d\n",num);
    }

    return 0;
}


下面這個丟兩邊都有過,而且想法簡單多了,真不知我為什麼沒想到。
程式碼:(解法二)
#include <stdio.h>
#include <string.h>
int main()
{
    int flag=0,num=0,n;
    char s[31];
    while(scanf("%s",s)&&s[0]!='~')
    {

        if(s[0]=='#')
        {
            printf("%d\n",num);
            num=0;
        }
        else if(strlen(s)==1)
        {
            flag=1;
        }
        else if(strlen(s)==2)
        {
            flag=0;
        }
        else
        {
            n=strlen(s)-2;
            for(int i=0;i<n;i++)
                num=num*2+flag;
        }
    }

    return 0;
}

2020年3月1日 星期日

11462-Age Sort

丟uva好幾次才過,Presentation error害死我......

程式碼:
#include <stdio.h>

int main()
{
    int n,age[101]={0},temp;
    while(scanf("%d",&n))
    {
        for(int i=0;i<101;i++)
            age[i]=0;
        if(n==0)
            break;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&temp);
            age[temp]++;
        }
        int block=0;
        for(int i=0;i<101;i++)
        {
            while(age[i]>0)
            {
                if(block) printf(" ");
                block++;
                printf("%d",i);
                age[i]--;
            }
        }
        printf("\n");
    }
    
    return 0;
}

2020年2月27日 星期四

井字遊戲

簡單的井字遊戲,純C硬刻~

程式碼:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

char map[3][3] = {'\0'};
void initializeboard()
{
 int number = 1;
 for (int i = 0; i < 3; i++)
 {
  for (int j = 0; j < 3; j++)
   map[i][j] = ('0'+number++);
 }
}
void printborad()
{
 printf("-------------\n");
 printf("| %c | %c | %c |\n",map[0][0],map[0][1],map[0][2]);
 printf("----+---+---\n");
 printf("| %c | %c | %c |\n", map[1][0], map[1][1], map[1][2]);
 printf("----+---+----\n");
 printf("| %c | %c | %c |\n", map[2][0], map[2][1], map[2][2]);
 printf("-------------\n");
}
void playerturn()
{
 int cmd,correct_input=0;
 char mark='o';
 while (1)
 {
  printf("請選擇編號: ");
  scanf_s("%d", &cmd);
  if (cmd == 1 && map[0][0] == '1')
   map[0][0] = 'o', correct_input = 1;
  else if (cmd == 2 && map[0][1] == '2')
   map[0][1] = 'o', correct_input = 1;
  else if (cmd == 3 && map[0][2] == '3')
   map[0][2] = 'o', correct_input = 1;
  else if (cmd == 4 && map[1][0] == '4')
   map[1][0] = 'o', correct_input = 1;
  else if (cmd == 5 && map[1][1] == '5')
   map[1][1] = 'o', correct_input = 1;
  else if (cmd == 6 && map[1][2] == '6')
   map[1][2] = 'o', correct_input = 1;
  else if (cmd == 7 && map[2][0] == '7')
   map[2][0] = 'o', correct_input = 1;
  else if (cmd == 8 && map[2][1] == '8')
   map[2][1] = 'o', correct_input = 1;
  else if (cmd == 9 && map[2][2] == '9')
   map[2][2] = 'o', correct_input = 1;
  else
   printf("錯誤輸入,請再輸入一次!\n");

  if (correct_input)
   break;
 }
 
}
void computerturn()
{
 int x = rand() % 3, y = rand() % 3,i=0;
 while (map[x][y] == 'o' || map[x][y] == 'x')
 {
  x = rand() % 3, y = rand() % 3;
  i++;
  if (i >= 9)
   return;
 }
 map[x][y] = 'x';
 
}
int winorlose()
{
 // o win
 if (map[0][0] == 'o'&&map[0][1] == 'o'&&map[0][2] == 'o') return 1; //橫向
 if (map[1][0] == 'o'&&map[1][1] == 'o'&&map[1][2] == 'o') return 1;
 if (map[2][0] == 'o'&&map[2][1] == 'o'&&map[2][2] == 'o') return 1;
 if (map[0][0] == 'o'&&map[1][0] == 'o'&&map[2][0] == 'o') return 1; //縱向
 if (map[0][1] == 'o'&&map[1][1] == 'o'&&map[2][1] == 'o') return 1;
 if (map[0][2] == 'o'&&map[1][2] == 'o'&&map[2][2] == 'o') return 1;
 if (map[0][0] == 'o'&&map[1][1] == 'o'&&map[2][2] == 'o') return 1; //斜向
 if (map[0][2] == 'o'&&map[1][1] == 'o'&&map[2][0] == 'o') return 1;
 // x win
 if (map[0][0] == 'x'&&map[0][1] == 'x'&&map[0][2] == 'x') return 2;
 if (map[1][0] == 'x'&&map[1][1] == 'x'&&map[1][2] == 'x') return 2;
 if (map[2][0] == 'x'&&map[2][1] == 'x'&&map[2][2] == 'x') return 2;
 if (map[0][0] == 'x'&&map[1][0] == 'x'&&map[2][0] == 'x') return 2; //縱向
 if (map[0][1] == 'x'&&map[1][1] == 'x'&&map[2][1] == 'x') return 2;
 if (map[0][2] == 'x'&&map[1][2] == 'x'&&map[2][2] == 'x') return 2;
 if (map[0][0] == 'x'&&map[1][1] == 'x'&&map[2][2] == 'x') return 2; //斜向
 if (map[0][2] == 'x'&&map[1][1] == 'x'&&map[2][0] == 'x') return 2;

 int record = 0;
 for (int i = 0; i < 3; i++)
 {
  for (int j = 0; j < 3; j++)
  {
   if (map[i][j] == 'o' || map[i][j] == 'x')
    record++;
  }
 }
 if (record == 9) return 3;

 return 0;
}
int main()
{
 srand(time(NULL));
 printf("\n\n\n");
 printf("\t\t\t~~歡迎來玩 井字遊戲~~\n\n");
 printf("\t\t\t        <規則>\n");
 printf("\t\t\t1.玩家為先手,與電腦對決\n");
 printf("\t\t\t2.先連成一線者獲勝\n\n\n");
 system("pause");
 system("cls");
 initializeboard();

 int result = 0;
 while (1)
 {
  system("cls");
  printborad();
  playerturn();
  if ((result = winorlose()) != 0)
   break;
  computerturn();
  if ((result = winorlose()) != 0)
   break;
 }
 system("cls");
 printborad();
 if (result == 1)
  printf("你贏了~\n");
 else if (result == 2)
  printf("你輸了~\n");
 else if (result == 3)
  printf("平手~\n");
 system("pause");
 return 0;
}

2020年2月24日 星期一

00147 - Dollars

解題思路:
零錢問題。我直接把0~300.00想成0~30000元去算,唯一要稍微注意的是小數在乘的時候會有誤差。

程式碼:
#include <stdio.h>
#define N 30000
long long int s[N+1]={0};
int C[11]={5,10,20,50,100,200,500,1000,2000,5000,10000};
int main()
{
    double n;
    s[0]=1;
    for(int i=0;i<11;i++)
    {
        for(int j=C[i];j<=N;j++)
            s[j]+=s[j-C[i]];
    }
    while(scanf("%lf",&n)&&n)
    {
        n+=1e-6;
        printf("%6.2lf",n);
        printf("%17lld\n",s[(int)(n*100)]);
    }
        
    return 0;
}

2020年2月21日 星期五

d140: On Sale

覺得自己的解法比較簡單,故紀錄之

解題思路:
大致上就是照著題目直觀去解,只是要注意1.誤差問題2.無條件捨去至第二位
1.誤差:由於小數在儲存時有誤差,運算時為避免錯誤要加上
2.無條件捨去:使用floor()函數(如求無條件進位則用ceil())

程式碼:
#include <stdio.h>
#include <math.h>

int main()
{
    
    double m;
    while(scanf("%lf",&m)!=EOF)
    {
        int check=0;
        if(m<100)
            check=1;
        if(m<=100)
            m*=0.9;
        else if(m<=500)
            m*=0.8;
        else
            m*=0.6;
        if(check)
            m+=8;
        m+=1e-6;
        printf("$%.2lf\n",floor(m*100)/100);
    }
    return 0;
}

2020年2月20日 星期四

c672: RGB ⇆ HEX

解題思路:
先了解RGB與HEX兩種分別是十進位與十六進位轉換,接著想辦法把三色分別取出即可。

程式碼:
#include <stdio.h>

int main()
{
    char s[12];
    while(gets(s)!=0)
    {
        if(s[0]=='#')
        {
            int r,g,b;
            sscanf(s,"#%02x%02x%02x",&r,&g,&b);
            printf("%d %d %d\n",r,g,b);
        }
        else
        {
            int r,g,b;
            sscanf(s,"%d %d %d",&r,&g,&b);
            printf("#%02X%02X%02X\n",r,g,b);
        }
    }
    return 0;
}

2020年2月18日 星期二

21點

很簡單的21點小遊戲。
無法不要牌繼續。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int card[13] = { 0 };
int player_point = 0, computer_pount = 0, temp_record;

int get_card()
{
 int point = rand() % 13 + 1;//1~13
 while (card[point] >= 4)
 {
  point = rand() % 13 + 1;
 }
 card[point]++;

 return point;
}
void player_get_card()
{
 temp_record = get_card();
 player_point += temp_record;
 printf("你拿到一張牌: [%d]\n",temp_record);
 printf("你的總點數為: %d\n", player_point);
}
void computer_get_card()
{
 printf("電腦拿了一張牌\n");
 computer_pount += get_card();
}
void lose_or_win()
{
 if (player_point > 21 && computer_pount > 21)
  printf("兩方都輸啦!!");
 else if (player_point > 21)
  printf("你輸啦!!");
 else if (computer_pount > 21)
  printf("你贏啦!!");
 else if (player_point > computer_pount)
  printf("你贏啦!!");
 else if (player_point < computer_pount)
  printf("你輸啦!!");
 else if (player_point == computer_pount)
  printf("平手啦!!");
}
int main()
{
 srand(time(NULL));
 char cmd;

 printf("\n\n");
 printf("~~歡迎來玩 21點 小遊戲~~\n\n");
 system("pause");
 system("cls");

 player_get_card();
 computer_get_card();


 while (1)
 {
  printf("-----------------------");
  printf("\n\n");
  printf("請問要繼續嗎? (y/n)\n");
  printf("y: 繼續 n:結束此局\n");
  scanf_s("%c", &cmd);
  getchar();
  if (cmd == 'n' || cmd == 'N')
   break;
  printf("-----------------------");
  printf("\n");

  player_get_card();
  computer_get_card();

  if (player_point > 21 || computer_pount > 21)
   break;
 }
 printf("-----------------------\n\n");
 printf("你的點數: %d\n", player_point);
 printf("電腦的點數: %d\n", computer_pount);
 printf("\n");
 
 lose_or_win();
 system("pause");
 return 0;
}

早餐生成器

有選擇障礙症,因此產出的簡單小程式
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void breakfast()
{
 int food = rand() % 8;
 printf("\n");
 char  menu[10][10] = { "包子","三明治","香腸炒蛋","香腸","炒蛋","蛋餅","蔥油餅","絕食" };
 printf("就決定是你了 ──  %s !!\n\n", menu[food]);
}
void lunch()
{
 int food = rand() % 7;
 printf("\n");
 char menu[20][20] = { "炒飯","池上便當","燒賣","水餃","鍋貼","便當","媽媽愛心午餐" };
 printf("那就吃  %s  好了~\n\n", menu[food]);
}
void dinner()
{
 int food = rand() % 8;
 printf("\n");
 char menu[20][20] = { "火鍋","壽司","麥當勞","摩斯","吉野家","炒飯","漢堡王","披薩" };
 printf("吃  %s  感覺很不錯!\n\n", menu[food]);
}
int main()
{
 int command;
 system("color f0");
 srand(time(NULL));
 printf("================\n");
 printf("歡迎來到 菜單生成器\n");
 printf("================\n");
 printf("\n\n");
 while (1)
 {
  char c;
  printf("1) 早餐\n");
  printf("2) 午餐\n");
  printf("3) 晚餐\n");
  printf("請輸入選項: ");
  scanf_s("%d", &command);
  getchar();
  if (command == 1)
   breakfast();
  else if (command == 2)
   lunch();
  else if (command == 3)
   dinner();
  else
   printf("請好好輸入好嗎=口=\n");
  printf("\n");
  while (1)
  {
   printf("還要繼續嗎? y=繼續   n=結束\n");
   scanf_s("%c", &c);
   getchar();
   if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
    break;
   else
    printf("請好好輸入好嗎=口=\n\n");
   printf("\n");
  }
  if (c == 'n' || c == 'N')
   break;
  printf("\n");
 }
 printf("~~~~謝謝你的光臨~~~~\n");
 system("pause");
 return 0;
}

2020年2月2日 星期日

質數

質數篩法
#define N 100
int isprime[N];
int prime[N],pnum;
void sieve(int n)
{
    pnum=0;
    for(int i=0;i<n;i++)
        isprime[i]=1;
    isprime[0]=isprime[1]=0;
    int sqn=sqrt(n);
    for(int i=2;i<=sqn;i++)
    {
        if(isprime[i])
        {
            prime[pnum++]=i;
            for(int j=i*i;j<n;j+=i)
                isprime[j]=0;
        }
    }
    for(int i=sqn+1;i<=n;i++)
    {
        if(isprime[i])
            prime[pnum++]=i;
    }
}

其他
int isprime[N]={1,1};
    int sqn=sqrt(N);
    for(int i=2;i<=sqn;i++)
    {
        if(!isprime[i])
        {
            for(int j=i*i;j<N;j+=i)
                isprime[j]=1;
        }
    }

int Prime[100], Pt;
void Sieve() {
 Pt = 0;
 int i, j, mark[100] = {0};
 Prime[Pt++] = 2;
 for(i = 3; i < 100; i += 2) 
 {
  if(mark[i] == 0) 
  {
   Prime[Pt++] = i;
   for(j = 3; i*j < 100; j += 2)
    mark[i*j] = 1;
  }
 }
}
質因數
#include <stdio.h>
#include <math.h>
#define M 1000
#define N 10000
int fact[M],count[M],fnum;
int prime[N],isprime[N],pnum;
void sieve()
{
    int sqn=sqrt(N);
    isprime[0]=isprime[1]=1;
    for(int i=2;i<N;i++)
    {
        if(!isprime[i])
        {
            for(int j=i+i;j<=N;j+=i)
                isprime[j]=1;
        }
    }
    pnum=0;
    for(int i=0;i<N;i++)
    {
        if(!isprime[i])
            prime[pnum++]=i;
    }
}
void factorization(int n)
{
    fnum=0;
    for(int i=0;i<pnum&&n>1;i++)
    {
        if(n%prime[i]==0)
        {
            fact[fnum]=i;
            count[fnum]=0;
            fnum++;
            while(n%prime[i]==0)
            {
                count[fnum-1]++;
                n/=prime[i];
            }
        }
    }
}
int main()
{
    sieve();
    factorization(120);
    printf("%d = \n",120);
    for(int i=0;i<fnum;i++)
        printf("%d^%d\n",prime[fact[i]],count[i]);
    return 0;
}

2020年1月30日 星期四

d041: 11219 - How old are you?

題目連結

解題思路:
date=(y1-y2)-(m1<m2)-(m1==m2&&d2>d1);
1.從(y1-y2)可以得知大概的年齡。而可能因為最新的天數未滿一年,需要減1,所以繼續判斷。
2.需要減一有兩種情況:第一是(m2>m1),第二是當同月份時(d2>d1)
3.所以把這兩個情況減掉即可

程式碼:
#include <stdio.h>
int main()
{
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        int d1,m1,y1,d2,m2,y2,date=0;
        scanf("%d/%d/%d",&d1,&m1,&y1);
        scanf("%d/%d/%d",&d2,&m2,&y2);
        date=(y1-y2)-(m1<m2)-(m1==m2&&d2>d1);
        printf("Case #%d: ",i);
        if(date<0)
            printf("Invalid birth date\n");
        else if(date>130)
            printf("Check birth date\n");
        else
            printf("%d\n",date);
    }
    return 0;
}

2020年1月29日 星期三

a263: 日期差幾天

題目連結

(算日期的題目都好麻煩....把我的解法分享,希望能幫到其他同樣抓狂的人)

解法:
首先,我是參考這份講義中提供的想法(章節3.3.2),把從西元元年到所求日期的總天數分別加起來後,相減即是答案。

判斷閏年照定義做。

計算天數的詳細流程:
1.先算出從元年到(y-1)年的天數。全當作平年計算是因為相減後會相消,不影響。
(真的不影響嗎?其實我不是很清楚,但反正有對)
2.再來找出有幾個閏年。因為閏年比平年天數多1,所以求出有n個閏年則總天數多n。
3.再計算第y年的天數。先算m個月的天數,如果超過二月且當年是閏年則多加1。然後加上d。

其他就很簡單了。


程式碼:AC (4ms, 64KB)
#include <stdio.h>
int isleap(int year)
{
    if((year%400==0)||((year%100!=0)&&(year%4==0)))
        return 1;
    return 0;
}
int countdaysum(int y,int m,int d)
{
    int dayofmonth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    int sum=(y-1)*365;
    sum+=(y-1)/4;
    sum-=(y-1)/100;
    sum+=(y-1)/400;
    for(int i=1;i<m;i++)
        sum+=dayofmonth[i];
    if(m>2&&isleap(y))
        sum++;
    sum+=d;
    return sum;
}
int main()
{
    int y1,m1,d1,y2,m2,d2;
    while(scanf("%d %d %d %d %d %d",&y1,&m1,&d1,&y2,&m2,&d2)!=EOF)
    {
        int sum1,sum2;
        sum1=countdaysum(y1,m1,d1);
        sum2=countdaysum(y2,m2,d2);
        if(sum1>sum2)
            printf("%d\n",sum1-sum2);
        else
            printf("%d\n",sum2-sum1);
    }
    return 0;
}

2020年1月25日 星期六

scanf相關問題 筆記

%s:“跳過0或多個 white space,由鍵盤緩衝區裡讀取連續不是 white space 的字元”(white space=空格、 '\t、 '\n' )
%c:只讀取緩衝區的一個字元
%d:跳過所有white space讀取數字

所以像在輸入數字時,多打空格仍然能被正確存進去。

scanf(" %c",&c);
%c前加空格,代表跳過緩衝區所有空格直到遇到字元。

scanf("%[^\n]", str);
代表直到碰到換行字元前的字元都存進去str,等同於gets(str),都是避免遇到空白讀不進去。

sscanf()用法:http://programmermagazine.github.io/201312/htm/article2.html

參考文章:
http://squall.cs.ntou.edu.tw/cprog/practices/scanfCommonTraps.pdf

2020年1月14日 星期二

猜數字遊戲

很簡單的一個小遊戲,單純猜數字~


程式碼:
#include <stdio.h>
#include <time.h>

int main()
{
 srand(time(NULL));
 int n=rand()%1000;//0~999
 printf("Hi.Let's start the game!\n");
 while (1)
 {
  int temp;
  printf("Enter one number(0~999): ");
  scanf_s("%d", &temp);
  if (temp == n)
  {
   printf("Congratulation! You win!\n");
   break;
  }
  else if (temp > n)
   printf("This number is too big!\n");
  else
   printf("This number is too small!\n");
  printf("\n");
 }
 return 0;
}

Linked List--Delete

刪除第N個node
#include <stdio.h>
#include <stdlib.h>
struct Node
{
    int data;
    struct Node *next;
};
struct Node *head;
void Print()
{
    struct Node *temp=head;
    while(temp!=NULL)
    {
        printf("%d ",temp->data);
        temp=temp->next;
    }
    printf("\n");
}
void Delete(int n)
{
    struct Node *temp1=head;
    if(n==1)
    {
        head=temp1->next;
        free(temp1);
        return;
    }
    for(int i=0;i<n-2;i++)
        temp1=temp1->next; //temp1 points to (n-1)th Node
    struct Node *temp2=temp1->next; //nth node
    temp1->next=temp2->next; //(n+1)th Node
    free(temp2); //Delete temp2
}
void Insert(int n)
{
    struct Node *temp1=(struct Node*)malloc(sizeof(struct Node));
    temp1->data=n;
    temp1->next=NULL;
    struct Node *temp2=head;
    if(temp2==NULL)
    {
        head=temp1;
        return;
    }
    while(temp2->next!=NULL) // not while(temp2!=NULL)
    {
        temp2=temp2->next;
    }
    temp2->next=temp1;
}
int main()
{
    head=NULL; //empty list
    int n;
    char c,ch;
    Insert(1);
    Insert(2);
    Insert(3);
    Insert(4); // 1 2 3 4
    Print();
    Delete(2); // 1 3 4
    Print();
    return 0;
}

以值刪除node
#include <stdio.h>
#include <stdlib.h>
struct node
{
    int data;
    struct node *next;
};
struct node *head;
void print()
{
    struct node *temp=head;
    while(temp!=NULL)
    {
        printf("%d ",temp->data);
        temp=temp->next;
    }
    printf("\n");
}
void insert(int data,int n)
{
    struct node *temp1=(struct node*)malloc(sizeof(struct node));
    temp1->data=data;
    temp1->next=NULL;
    if(n==1)
    {
        temp1->next=head;
        head=temp1;
        return ;
    }
    struct node *temp2=head;
    if(temp2==NULL&&n>1)
    {
        printf("error!\n");
        return ;
    }
    for(int i=0;i<n-2;i++)
    {
        temp2=temp2->next;
        if(temp2==NULL)
        {
            printf("error!\n");
            return ;
        }
    }
        
    temp1->next=temp2->next;
    temp2->next=temp1;
}
void delete(int n)
{
    int i=0;
    struct node *temp1=head;
    struct node *temp2=head;
    while(temp1!=NULL)
    {
        if(temp1->data==n) //points to n
        {
            if(i==0)
            {
                head=temp1->next;
                free(temp1);
                return ;
            }
            temp2->next=temp1->next;
            free(temp1);
            return ;
        }
        temp2=temp1;//temp2 is temp1-1
        temp1=temp1->next;
        i++;
    }
    printf("no this number!\n");
}
int main()
{
    head=NULL;
    int n,p;
    while(1)
    {
        printf("enter number to insert in list: ");
        scanf("%d",&n);
        if(n<0)
            break;
        printf("enter insert position: ");
        scanf("%d",&p);
        insert(n,p);
        print();
    }
    printf("delete one number: ");
    scanf("%d",&p);
    delete(p);
    print();
    return 0;
}

用scanf或getchar()讀取 y/n值 所遇問題

之前無聊想寫一個猜數字的遊戲,結果在問到要不要繼續時,每次輸入y,接下來都會印出兩次結果。

譬如說下面的code:
#include <stdio.h>

int main()
{
 char c;
 while (1)
 {
  printf("do you what to continue? ");
  scanf_s("%c", &c);
  if (c == 'n')
   break;
 }
 return 0;
}

就會出現:
輸入一個y,結果印了兩次"do you want to continue?"

後來查了一下網路,好像是因為scanf用%c讀值的時候,一次只接一個字元,但使用者是輸入了y或n被存到c之後,又再輸入了\n。第一個輸入的y/n的確被拿去判斷了沒錯,所以才會有前一個"do you want to continue? ",但後一個換行符號則被存到緩衝區,等下一次再拿出來判斷,造成多輸出了一次。

所以如果在scanf後多加一行,變成:
#include <stdio.h>

int main()
{
 char c;
 while (1)
 {
  printf("do you what to continue? ");
  scanf_s("%c", &c);
  getchar();
  if (c == 'n')
   break;
 }
 return 0;
}

也就是用getchar()把\n吃掉,就沒有問題了。



這個問題我一開始不知道怎麼下關鍵字,只好先跳過,是之後看到課本上有一行:
while(getchar()!='\n');
我才慢慢找對方向。
相關關鍵字大概是:clean input buffer, while loop error, getchar() in while loop 等等?

參考文章:
How to clear input buffer in C?
http://c-faq.com/stdio/scanfc.html

也可以參考http://squall.cs.ntou.edu.tw/cprog/practices/scanfCommonTraps.pdf

2020年1月13日 星期一

Linked List--Insert

我是看這個影片自學的,因為上課老師講的聽不懂。影片雖然是印度腔英文,但有字幕不難看懂,可以自己先畫圖理解過後在實作。

insert at beginning
//Linked List: Inserting a node at beginning
#include <stdio.h>
#include <stdlib.h>
struct Node
{
    int data;
    struct Node *next;
};
struct Node *head;
void Insert(int x)
{
    struct Node *temp=(struct Node *)malloc(sizeof(struct Node));
    temp->data=x;
    temp->next=head;
    head=temp;
}
void Print()
{
    struct Node *temp=head;
    printf("List is: ");
    while(temp!=NULL)
    {
        printf(" %d",temp->data);
        temp=temp->next;
    }
    printf("\n");
}
int main()
{
    
    head=NULL; //empty List
    printf("How many numbers?\n");
    int n,x;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        printf("Enter the number:\n");
        scanf("%d",&x);
        Insert(x);
        Print();
    }
    return 0;
}

insert at the end
//insert a node at the end
#include <stdio.h>
#include <stdlib.h>
struct Node
{
    int data;
    struct Node *next;
};
struct Node *head;
void Print()
{
    struct Node *temp=head;
    while(temp!=NULL)
    {
        printf("%d ",temp->data);
        temp=temp->next;
    }
    printf("\n");
}
void Insert(int n)
{
    struct Node *temp1=(struct Node*)malloc(sizeof(struct Node));
    temp1->data=n;
    temp1->next=NULL;
    struct Node *temp2=head;
    if(temp2==NULL)
    {
        head=temp1;
        return;
    }
    while(temp2->next!=NULL) // not while(temp2!=NULL)
    {
        temp2=temp2->next;
    }
    temp2->next=temp1;
}
int main()
{
    head=NULL; //empty list
    int n;
    while(1)
    {
        printf("enter the number:(0 to quit) ");
        scanf("%d",&n);
        if(n==0)
            break;
        Insert(n);
        Print();
    }
    return 0;
}

insert node at nth position
#include <stdio.h>
#include <stdlib.h>
struct Node
{
    int data;
    struct Node *next;
};
struct Node *head;
void Print()
{
    struct Node *temp=head;
    while(temp!=NULL)
    {
        printf("%d ",temp->data);
        temp=temp->next;
    }
    printf("\n");
}
void Insert(int data,int n)
{
    struct Node *temp1=(struct Node*)malloc(sizeof(struct Node));
    temp1->data=data;
    temp1->next=NULL;
    if(n==1)
    {
        temp1->next=head;
        head=temp1;
        return;
    }
    struct Node *temp2=head;
    for(int i=0;i<n-2;i++)
    {
        temp2=temp2->next;
    }
    temp1->next=temp2->next;
    temp2->next=temp1;
}
int main()
{
    head=NULL; //empty list
    Insert(2,1);//List: 2
    Insert(3,2);//List: 2,3
    Insert(4,1);//List:4,2,3
    Insert(5,2);//List:4,5,2,3
    Print();
    return 0;
}

Largest Square

題目:
UVa-10908
(讀檔)

程式碼:
#include <stdio.h>
#include <stdlib.h>
#include "FileHandler.h"
int main()
{
 char *str = readAllTextFromFile("./input.txt");
 int testcase = 0, i_now = 0;
 while (str[i_now] != '\n')
 {
  testcase = str[i_now] - '0' + testcase * 10;
  i_now++;
 }
 i_now++;
 while (testcase--)
 {
  int m = 0, n = 0, q = 0;
  while (str[i_now] != ' ')
  {
   m = str[i_now] - '0' + m * 10;
   i_now++;
  }
  i_now++;
  while (str[i_now] != ' ')
  {
   n = str[i_now] - '0' + n * 10;
   i_now++;
  }
  i_now++;
  while (str[i_now] != '\n')
  {
   q = str[i_now] - '0' + q * 10;
   i_now++;
  }
  i_now++;
  printf("%d %d %d\n", m, n, q);
  char map[105][105];
  for (int i = 0; i < m; i++)
  {
   for (int j = 0; j <= n; j++)
   {
    if (str[i_now] != '\n')
     map[i][j] = str[i_now];
    i_now++;
   }
  }
  while (q--)
  {
   int r = 0, c = 0, ans = 1;
   while (str[i_now] != ' ')
   {
    r = str[i_now] - '0' + r * 10;
    i_now++;
   }
   i_now++;
   while (str[i_now] != '\n'&&str[i_now] != NULL)
   {
    if (c > 100)
     break;
    c = str[i_now] - '0' + c * 10;
    i_now++;
   }
   i_now++;
   //printf("%d %d\n", r, c);
   for (int i = 0; i <= m || i <= n; i++)
   {
    int flag = 1;
    for (int j = r - i; j <= r + i; j++)
    {
     for (int k = c - i; k <= c + i; k++)
     {
      if (j < 0 || k < 0 || j >= m || k >= n)
      {
       flag = 0;
       break;
      }
      if (map[j][k] != map[r][c])
      {
       flag = 0;
      }
     }
    }
    if (flag)
     ans = 2 * i + 1;
    else
     break;
   }
   printf("%d\n", ans);
  }
 }
 system("pause");
 return 0;
}

二的補數 問題

題目:
If numeric values are represented in two's complement notation, does the following program represent an infinite process? Explain your answer.

x←2
while(x > 0) do
    (x← x + 1)

也就是問說如果以2的補數一直加1,是否恆為正數?




在這個表格裡,表示三個位元的二的補數,由此可知當數字一路加上去到011,也就是+3時,再+1的時候並不會變成+4,而是繞到表格最底端-4,也就是111。

雖然題目並沒有告訴我們有幾個位元來表示二的補數,但不論大小為何,最終必定來到可表達數字的上限,然後繞回到可表達數字的下限。

依此邏輯,我們也可以寫一個間單的程式來檢驗這個想法。

#include <stdio.h>

int main(void)
{
 int a = 2000000000;
 while (a > 0)
 {
  printf("%d\n", a);
  a += 5000000;
 }
 return 0;
}

這個程式將會無止盡的執行嗎?還是會在特定的數字後跳脫while呢?

實際執行後會發現程式在輸出2145000000這個數字後終止,原因是因為int可表達的範圍是-2147483648 to 2147483647,如果跳脫while後把a再印一次,會發現這時候的a正是在負極值端。

其實這個小實驗用a=1,且每次+1也可以,只是為了減少輸出的數目與執行時間。

1/3*3 問題

題目:
int main(void)
{
    float a, b;
    a = 1.0f / 3.0f;
    b = a * 3.0f;
    return 0;
}
For the above sample code, would the value of 'b' equal to one? Please justify your answer and explain.

先看執行結果:
再回過頭思考程式碼的部分。
a=1.0f/3.0f
所以a=0.333333,那麼乘三倍後應該會是0.999999,怎麼又變為1了呢?
有一個重要的點就是:電腦不是以10進位的方式去儲存、運算數字,而是以二進位的方式。在計算機概論裡也有簡單提過概念流程。基本上用二進位去存十進位的數,數字是沒有辦法被精確的紀錄的,必定會產生誤差。
再來看看下圖:

以固定位數到小數點第二十位,會發現除了預設的小數後六位數以後的數值就不是原本所想像的0.3333333333333........了。
而由於預設是小數點後六位才被四捨五入印出來,一開始才會認為跟想像的一樣,也因此這個a*3倍確實也就回到1了!
參考文章:

Traditional bingo

題目:
也是cpe的題目。

不過我寫的也是讀檔版。

解題思路:
其實就照著題目的意思去寫,每次讀數字都確認每行每列每斜排有沒有一條線。

程式碼:
#include <stdio.h>
#include "FileHandler.h"

int main()
{
 int bingo[5][5] = { 0 }, input[75], i_now = 0, row[5] = { 0 }, column[5] = { 0 }, tilt[2] = {1,1},check=0;
 row[2] = 1, column[2] = 1;
 char *str = readAllTextFromFile("./bingo.txt");
 for (int i = 0; i < 5; i++)
 {
  for (int j = 0; j < 5; j++)
  {
   if (i == 2 && j == 2) continue;
   int n = 0;
   while (str[i_now] != ' '&&str[i_now] != '\n')
   {
    n = str[i_now] - '0' + n * 10;
    i_now++;
   }
   i_now++;
   bingo[i][j] = n;
  }
 }
 for (int i = 0; i < 75; i++)
 {
  int n = 0;
  while (str[i_now] != ' '&&str[i_now] != '\n'&&str[i_now]!=NULL)
  {
   n = str[i_now] - '0' + n * 10;
   i_now++;
  }
  i_now++;
  input[i] = n;
 }
 for (int i = 0; i < 75; i++)
 {
  for (int j = 0; j < 5; j++)
  {
   for (int k = 0; k < 5; k++)
   {
    if (input[i] == bingo[j][k])
    {
     row[j]++;
     column[k]++;
     if (j == k)
      tilt[0]++;
     else if (j + k == 4)
      tilt[1]++;
    }
   }
  }
  if (tilt[0] == 5 || tilt[1] == 5)
  {
   printf("BINGO after %d numbers announced\n", i + 1);
   check = 1;
   break;
  }
  else
  {
   for (int j = 0; j < 5; j++)
   {
    if (row[j] == 5 || column[j] == 5)
    {
     printf("BINGO after %d numbers announced\n", i + 1);
     check = 1;
     break;
    }
   }
  }
  if (check == 1)
   break;
 }
 system("pause");
 return 0;
}