2020年1月30日 星期四

羅拉.特萊斯 建議我們說謝謝

影片連結

這位講者的語速好快,字幕都要跟不上了orz...

take in:接受
rehab facility:勒戒中心
facing life and death:面對生死
breadwinner:養家餬口的人
medium rare:(牛排)三分熟
→raw 生
→rare 一分熟
→medium 五分熟
→medium well 七分熟
→well done 全熟
size six shoes:六號鞋
inner circle:死黨、朋友圈
true the wheels:矯正車輪(似乎是指讓車輪受力均衡,以恢復安全性與性能)
wrap:扭曲
show up:出席

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月26日 星期日

How to start a movement

影片連結

dissect:分析、剖析
underestimated:被低估的
take guts:需要勇氣
nut:瘋子、堅果
emulate:模仿、效仿
get momentum:獲得動力
tipping point:引爆點、臨界點
recap:概括
over-glorified:過度崇拜

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月22日 星期三

Weird, or just different?

影片連結

downbeat:重拍、強拍
the beginning of the musical phrase:音樂段落的開端
count off:報數
There's a saying that:有句話說

2020年1月19日 星期日

Keep your goals to yourself

影片連結

for real:認真的、嚴肅的
becoming part of your identity:變成你的一部份
conventional wisdom:普遍的看法
gratification:感足感
mistakes the talking for the doing:把說到誤以為做到

2020年1月17日 星期五

Matt Cutts:用30天嘗試新事物

影片連結

stuck in a rut :一成不變
right amount of time :非常適合的時間(長度)
desk-dwelling computer nerd:常駐書桌的電腦書呆子
So here's my question to you:所以,我想問你
I guarantee you the next 30 days are going to pass whether you like it or not:我保證不論你喜不喜歡,接下來的30天照樣會過去(跟ted中文字幕翻的不一樣欸.....)
give it a shot:試試看

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;
}

struct 練習

題目:
Reads a file (input.txt) which contains several player data, including ID, Name, Age and Score.
Parse these data into struct with the format shown below.

struct
{
  id (integer number)
  name (string)
  age (integer number)
  score (floating number)
}

Reads another file (cmd.txt) which contains several numbers, iterate through each number and show the player data if the ID matched the number; otherwise print “Player data not found.” as the output.

範例輸入:
(Input File: input.txt)
3
12,Samina Hubbard,22,852.4
2,Idris Lindsey,30,1234.5
21,Briony Mullins,37,2123.5

(Command File: cmd.txt)
12
21
0
2
3











範例輸出:



















程式碼:
#include <stdio.h>
#include <string.h>
#include "FileHandler.h"
int main()
{
 int n = 0, i_now = 0;
 char *str = readAllTextFromFile("./input.txt");

 while (str[i_now] != '\n') //read case number
 {

  n = (str[i_now] - '0') + n * 10;
  i_now++;
 }
 i_now++; //skip new line
 struct data
 {
  int id;
  char name[50];
  int age;
  char score[50];
 };
 struct data player[100];
 for (int i = 0; i < n; i++) //read player data
 {
  for (int j = 0; j < 50; j++)
   player[i].name[j] = NULL;
  for (int j = 0; j < 50; j++)
   player[i].score[j] = NULL;
  int id = 0, len1 = 0, age = 0, len2 = 0;
  while (str[i_now] != ',')
  {
   id = id * 10 + str[i_now] - '0';
   i_now++;
  }
  player[i].id = id;
  i_now++;
  while (str[i_now] != ',')
  {
   player[i].name[len1] = str[i_now];
   i_now++;
   len1++;
  }
  i_now++;
  while (str[i_now] != ',')
  {
   age = age * 10 + str[i_now] - '0';
   i_now++;
  }
  player[i].age = age;
  i_now++;
  while (str[i_now] != '\n')
  {
   player[i].score[len2] = str[i_now];
   i_now++;
   len2++;
  }
  i_now++;
  if (str[i_now] == NULL)
   break;
 }

 str = readAllTextFromFile("./cmd.txt");
 i_now = 0;
 while (str[i_now]!=NULL)
 {
  int num = 0, check = 0;
  while (str[i_now] != '\n'&&str[i_now]!=NULL)
  {
   num = num * 10 + str[i_now] - '0';
   i_now++;
  }
  i_now++;
  for (int i = 0; i < n; i++)
  {
   if (player[i].id == num)
   {
    printf("ID: %d\n", player[i].id);
    printf("Name: %s\n", player[i].name);
    printf("Age: %d\n", player[i].age);
    printf("Score: %s\n\n", player[i].score);
    check = 1;
    break;
   }
  }
  if (check == 0)
   printf("Player not found\n\n");
  if (str[i_now]==NULL)
   break;

 }

 system("pause");
 return 0;
}

大數加減

題目:

  • Only add or minus two large number(+ or -).
  • All inputs are positive numbers.
  • The number may contain an decimal point, you need to handle it by your self.
  • The first input is how many testing data.
  • The answer you print should have it’s data number.

範例輸入:(intput.txt)
5
12345678991019231124+1234567890000000
12345678991019231124-1234567890000000
1-123456789123456789
123465789.123456789+987654321.987654321
1000000000-0.1

範例輸出:
#1:12346913558909231124
#2:12344444423129231124
#3:-123456788
#4:1111111111.11111111
#5:999999999.9


備註:
這題....我只寫整數加減而已,而且還寫得很醜.....反正我是放棄了。
根據助教,可以想成好幾個整數來代表,那只要處理接起來時的進位問題就好,但讀檔真的好難處理.......。

程式碼:
#include<stdio.h>
#include "FileHandler.h"
void add(char *a, char *b, char *c,int length_a,int length_b)
{
 int n;
 if (length_a > length_b)
 {
  n = length_b;
  for (int i = 0; i < n; i++)//clean char to int and add
   c[i] = a[length_a - 1 - i] - '0' + b[length_b - 1 - i] - '0';
  for (int i = n; i < length_a; i++)//add the rest
  {
   c[i] = a[length_a - 1 - i]-'0';
  }
  for (int i = 0; i < length_a-1; i++)
  {
   c[i + 1] += c[i] / 10;
   c[i] %= 10;
  }
  for (int i = 0; i < length_a; i++)//int to  char
   c[i] += '0';
 }
 else
 {
  n = length_a;
  for (int i = 0; i < n; i++)
   c[i] = a[length_a - 1 - i] - '0' + b[length_b - 1 - i] - '0';
  for (int i = n; i < length_b; i++)
   c[i] = b[length_b - 1 - i] - '0';
  for (int i = 0; i < length_b - 1; i++)
  {
   c[i + 1] += c[i] / 10;
   c[i] %= 10;
  }
  for (int i = 0; i < length_b; i++)
   c[i] += '0';
 }
}
void sub(char *a, char *b, char *c, int length_a, int length_b)
{
 int n;
 if (length_a > length_b) //when a>b, find a-b 
 {
  n = length_b;
  for (int i = 0; i < length_b; i++)
  {
   c[i] = (a[length_a - 1 - i] - '0') - (b[length_b - 1 - i] - '0');
  }
  for (int i = n; i < length_a ; i++)
   c[i] = a[length_a - 1 - i] - '0';
  for (int i = length_b - 1; i >= 0; i--)
  {
   if (c[i] < 0)
   {
    c[i + 1] -= 1;
    c[i] += 10;
   }
  }
  for (int i = 0; i < length_a; i++)
   c[i] += '0';
 }
 else //caution: when length_a==length_b but a>b
 {
  n = length_a;
  for (int i = 0; i < length_a; i++)
   c[i] = (b[length_b - 1 - i] - '0')-(a[length_a-1-i]-'0');
  for (int i = n; i < length_b; i++)
   c[i] = b[length_b - 1 - i] - '0';
  for (int i = length_a - 1; i >= 0; i--)
  {
   if (c[i] < 0)
   {
    c[i + 1] -= 1;
    c[i] += 10;
   }
  }
  for (int i = 0; i < length_b; i++)
   c[i] += '0';
  c[length_b] = '-';
 }
}
int main()
{
 char *str = readAllTextFromFile("./input.txt");
 int n = 0, i_now = 0, t = 1;
 while (str[i_now] != '\n')//read case number
  n = str[i_now++] - '0' + n * 10;
 i_now++;//skip new line
 while (n--)
 {
  char num1[200] = { 0 }, num2[200] = { 0 }, result[200] = { 0 };
  int length_1 = 0, length_2 = 0, length = 0, check1 = 0, check2 = 0;
  char command[1];
  while (str[i_now] != '+'&&str[i_now] != '-')//read num1 while '+' or '-' then stop
  {
   if (str[i_now] == '.')
    check1 = 1;
   num1[length_1++] = str[i_now++];
  }
  command[0] = str[i_now++];
  while (str[i_now] != '\n'&&str[i_now]!=NULL)//read num2 while '\n' then stop
  {
   if (str[i_now] == '.')
    check2 = 1;
   num2[length_2++] = str[i_now++];
  }
  i_now++;
  //for (int i = 0; i < length_1; i++)//print num1
  // printf("%c", num1[i]);
  //printf("%c", command[0]);//print '+' or '-'
  //for (int i = 0; i < length_2; i++)
  // printf("%c", num2[i]);//print num2
  //printf("\n");
  printf("#%d:", t++);//print result
  if (check1 == 0 && check2 == 0)
  {
   if (command[0] == '+')//add
    add(num1, num2, result, length_1, length_2);
   else if (command[0] == '-')//substract
    sub(num1, num2, result, length_1, length_2);
   for (int i = 199; i >= 0; i--)
   {
    if (result[i] != NULL)
     printf("%c", result[i]);
   }

  }
  else if(check1==1&&check2==1)
  {
   ;
  }
  
  
  printf("\n");
 }
 system("pause");
 return 0;
}

All you need is love

題目:
UVa-10193
Zerojudge d306
內容一樣,但是讀檔版本。

解題思路:
大致上就是把從二進位轉回十進位,然後判斷最大公因數。

程式碼:
#include<stdio.h>
#include"FileHandler.h"
int gcd(int a, int b)
{
 if (a == 0 || b == 0)
  return a + b;
 while ((a %= b) != 0 && (b %= a) != 0);
 return a + b;
}
int main()
{
 
 char *str = readAllTextFromFile("../love.txt");
 int n=0,i=0;
 while(str[i]!='\n')//read amount
 {
  n = str[i] - '0' + n * 10;//change char to int
  i++;
 }
 i++;
 for (int j = 0; j < n; j++)
 {
  int s1 = 0, s2 = 0,num1=0,num2=0,bi=1,x=0,check=0;
  while (str[i] != '\n'&&str[i]!=NULL)//read number s1
  {
   if (x == 0 && str[i] == '0')//if first digit is 0, it is invalid
    check = 1;
   s1 = str[i] - '0' + s1 * 10;
   i++;
   x++;
  }
  i++;
  x = 0;
  while (str[i] != '\n'&&str[i]!=NULL)//read number s2
  {
   if (x == 0 && str[i] == '0')
    check = 1;
   s2 = str[i] - '0' + s2 * 10;
   i++;
   x++;
  }
  i++;
  printf("%d %d\n", s1, s2);
  while (s1 > 0)//turn binary to decimal
  {
   num1 += (s1 % 10)*bi;
   bi *= 2;
   s1 /= 10;
  }
  bi = 1;
  while (s2 > 0)
  {
   num2 += (s2 % 10)*bi;
   bi *= 2;
   s2 /= 10;
  }
  
  printf("Pair #%d: ", j + 1);
  if (s1 < 0 || s2 < 0||check==1||num1<=1||num2<=1)//if each length smaller than 2 is also invalid
  {
   printf("invalid input.\n");
  }
  else if (gcd(num1, num2) != 1)
   printf("All you need is love!\n");
  else
   printf("Love is not you need!\n");
  if (str[i] == NULL)
   break;
 }
 system("pause");
 return 0;
}

2020年1月12日 星期日

迷宮走訪 Maze Traversal

題目:
一、隨機產生一個12X12的迷宮(入口在左邊、出口在右邊),無須確保能從入口走到出口。


















二、隨機產生三組能走到出口的迷宮,以x代表走過的路徑。每次輸出兩個迷宮,一個是產生的迷宮,一個是迷宮的走法。(無須是最短路徑)















三、讀一個迷宮檔案進來,並輸出走訪結果,如果走不出去,還要再輸出"This maze has  no solution"。

解題思路:
第一題網路上都說要用到甚麼二元樹,但根本沒教過,反正助教只要求「有出入口、裡面有牆有路」就好,所以我寫的很爛~
第二題則是先生成一條能走到底的路徑,然後在剩下的空間隨機改為路。
第三題因為solution實作一直有點問題,最後是拿這篇去改的。
(因為學期末有拿這題進階出題,變成malloc宣告)

程式碼:
第一題
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main()
{
 int in = 0, out = 0;
 srand(time(NULL));
 char maze[12][12] ;
 for (int i = 0; i < 12; i++)
 {
  for (int j = 0; j < 12; j++)
   maze[i][j] = '#';
 }
 in = rand() % 11 + 1;
 out = rand() % 11 + 1;
 maze[in][0] = '.';
 maze[out][11] = '.';
 for (int i = 0; i < 100; i++)
 {
  int x, y;
  x = rand() % 10 + 1;
  y = rand() % 10 + 1;
  maze[x][y] = '.';
 }
 for (int i = 0; i < 12; i++)
 {
  for (int j = 0; j < 12; j++)
   printf("%c", maze[i][j]);
  printf("\n");
 }
 return 0;
}
第二題
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define up 0
#define down 1
#define right 2
#define left 3
char find_solution(char maze[12][12], int x, int y,int direction);
int main()
{
 int randomx, randomy;
 int x=0, y=0,direction=0;
 char maze[12][12];
 for (int i = 0; i < 12; i++)//initialze the maze
 {
  for (int j = 0; j < 12; j++)
   maze[i][j] = '#';
 }
 srand(time(NULL));
 int in, out;//set the entrance and exit
 in = rand() % 10 + 1;
 out = rand() % 10 + 1;
 maze[in][0] = '.';
 maze[out][11] = '.';
 x = in;
 maze[x][++y] = '.';
 while (x!=out||y!=11)//make the maze
 {
  direction = rand() % 3;//0~2
  if (direction == up&&(x-1)>=1)
  {
   maze[--x][y] = '.';
  }
  else if (direction == down && (x + 1) != 11)
  {
   maze[++x][y] = '.';
  }
  else if (direction == right&&(y+1)<=10)
  {
   maze[x][++y] = '.';
  }
  else if (direction == right && (y + 1) == 11)
  {
   if (x == out)
    maze[x][++y] = '.';
  }

 }
 for (int i = 0; i < 20; i++)
 {
  randomx = rand() % 10 + 1;
  randomy = rand() % 10 + 1;
  maze[randomx][randomy] = '.';
 }
 x = in;//at the entrance and face right
 y = 0;
 direction = right;
 for (int i = 0; i < 12; i++)
 {
  for (int j = 0; j < 12; j++)
   printf("%c", maze[i][j]);
  printf("\n");
 }
 printf("\n");
 find_solution(maze, x, y,right);
 for (int i = 0; i < 12; i++)
 {
  for (int j = 0; j < 12; j++)
   printf("%c", maze[i][j]);
  printf("\n");
 }
 return 0;
}
char find_solution(char maze[12][12], int x, int y,int direction)
{
 maze[x][y] = 'x';
 if (y >= 11)
  return 'x';
 if (direction = right)
 {
  if (maze[x][y+1]=='#')
  {
   if (maze[x + 1][y] == '.')
    find_solution(maze, x + 1, y, down);
   else
    find_solution(maze, x - 1, y, up);
  }
  else if (maze[x + 1][y] == '.')
   find_solution(maze, x + 1, y, down);
  else
   find_solution(maze, x, y + 1, right);
   
 }
 else if (direction == up)
 {
  if (maze[x][y+1] == '.' || maze[x][y+1] == 'X')
  {
   if (maze[x][y + 1] == '.')
    find_solution(maze, x, y + 1, right);
   else
    find_solution(maze, x, y - 1, left);
  } 
  else
   find_solution(maze, x - 1, y, up);
 }
 else if (direction == down)
 {
  if (maze[x][y-1] == '.' || maze[x][y-1] == 'X')
  {
   if (maze[x][y - 1] == '.')
    find_solution(maze, x, y - 1, left);
   else
    find_solution(maze, x, y + 1, right);
  }
   
  else
   find_solution(maze, x, y + 1, down);
 }
}
第三題
#include "FileHandler.h"
#include<stdio.h>
#include<stdlib.h>
//#define up 0
//#define down 1
//#define left 2
//#define right 3
enum DIR { left, right, up, down };

void mazeTraverse(char **maze, int s_x, int s_y, int g_x, int g_y,int maze_width)
{
 int x, y,check=0;
 enum DIR dir;

 x = s_x, y = s_y;
 if (y == 0)
  dir = right;
 else if (x == 0)
  dir = down;
 else if (y == maze_width-1)
  dir = left;
 else
  dir = up;

 while (1)
 {
  maze[x][y] = 'x';
  if (dir == right)
  {
   if (maze[x + 1][y] != '#')
   {
    x++;
    dir = down;
   }
   else
   {
    if (maze[x][y + 1] == '#')
     dir = up;
    else
     y++;
   }
  }
  else if (dir == left)
  {
   if (maze[x - 1][y] != '#')
   {
    x--;
    dir = up;
   }
   else
   {
    if (maze[x][y - 1] == '#')
     dir = down;
    else
     y--;
   }
  }
  else if (dir == up)
  {
   if (maze[x][y + 1] != '#')
   {
    y++;
    dir = right;
   }
   else
   {
    if (maze[x - 1][y] == '#')
     dir = left;
    else
     x--;
   }
  }
  else if (dir == down)
  {
   if (maze[x][y - 1] != '#')
   {
    y--;
    dir = left;
   }
   else
   {
    if (maze[x + 1][y] == '#')
     dir = right;
    else
     x++;
   }
  }
  if (y < 0)
   break;
  if (check == 0)
  {
   if (x == s_x && y == s_y)
    break;
  }
  if (x == g_x && y == g_y)
  {
   maze[x][y] = 'x';
   break;
  }
  check = 1;
 }
}

int main()
{
 int maze_height , maze_width;//動態配置的部分
 char **maze = NULL;
 char *str = readAllTextFromFile("../maze.txt");
 for (int i = 0;; i++)
 {
  if (str[i] == '\n')
  {
   maze_height = i;
   maze_width = i;
   break;
  }
 }
 maze = (char**)malloc(sizeof(char*)*maze_height);
 for (int i = 0; i < maze_height; i++)
  maze[i] = (char*)malloc(sizeof(char)*maze_width);

 int k = 0, x = 0, y = 0;
 for (int i = 0; i < maze_height; i++)//讀迷宮進來
 {
  for (int j = 0; j < maze_width + 1; j++)
  {
   if (j != maze_width)
    maze[i][j] = str[k++];
   else
    k++;
  }

 }
 int x_out, y_out=11;
 for (int i = 0; i < maze_height; i++)//找入口
 {
  if (maze[i][0] == '.')
   x = i;
  if (maze[i][maze_width - 1] == '.')
   x_out = i;
 }
 mazeTraverse(maze, x, y,x_out,y_out ,maze_width);
 for (int i = 0; i < maze_height; i++)//結果
 {
  for (int j = 0; j < maze_width; j++)
   printf("%c", maze[i][j]);
  printf("\n");
 }
 for (int i = 0; i < maze_height; i++)
 {
  if (maze[i][maze_width - 1] == '.')
   printf("this maze has no solution.\n");
 }
 return 0;
}


字串切割與串接

題目:
Read a char array from .txt file, then using the following operations, “append, split, copy”to the string and show the results(on cmd window).
Each operation should be implement as a function with predefined input and output.
//copy the value from src to dist.
void copy(char *src, char *dist);

//append the text after target.
void append(char *target, char *text); 

//split src char array to two part by target,  then output the left and right part by segmentA and segmentB.
void split(char *src, char target, char *segmentA, char *segmentB);

Input(filename: input.txt)
First line  : input char array
Second line : append text
Third line: Split Char
Other line: Remove








Output
Append result
Original char array
Split result
(add linebreak after each segments, and change first letter from lowercase to uppercase)
Student ID











解題思路:
此題主要是練習讀檔以及運用字元陣列對字串處理,因此不能使用strnpy等函式。
先把第一行、第二行字串分別存起來後,copy的函式就是再準備一個空的char array,從頭一個字元一個字元開始存,只要不是空字元就放到空的array裡。
append的函式是先找到要串接的字串的尾巴,然後再把待加內容一個個加進去,直到待加內容也指到空字元。
split直接看下面程式碼吧~感覺看code比較好懂。

程式碼:
#include<stdio.h>
#include<string.h>
#include"FileHandler.h"
void copy(char *src, char *dist);
void append(char *target, char *text);
void split(char *src, char target, char *segmentA, char *segmentB);
int main()
{
 int i_str = 0,line1_length=0,line2_length=0;
 char *str = readAllTextFromFile("../input.txt"), segmentA[200] = { '\0' }, segmentB[200] = { '\0' };
 char line1[200] = { '\0' }, line2[200] = { '\0' }, append_result[200] = { '\0' }, target[1] = { '\0' };
 while (str[i_str] != '\n')//讀第一行資料
  line1[line1_length++] = str[i_str++];
 i_str++;
 printf("Input char array:%s\n\n", line1);
 while (str[i_str] != '\n')//讀第二行資料
  line2[line2_length++] = *(str + i_str++);
 i_str++;
 printf("Append text:%s\n", line2);
 copy(line1, append_result);
 append(line2, append_result);
 printf("Append result:%s\n\n", append_result);
 printf("Original char array:%s\n\n", line1);
 target[0] = str[i_str++];
 printf("Split char:%c\n",target[0]);
 printf("Split result:\n");
 split(append_result, target[0], segmentA, segmentB);
 /*system("pause");*/
 return 0;
}
void copy(char *src, char *dist)
{
 int i = 0;
 while (src[i] != '\0')//把src的資料都複製給dist
 {
  dist[i] = src[i];
  i++;
 }
  
}
void append(char *target, char *text)
{
 int i = 0, j = 0;
 while (text[i] != '\0')//把原本內容尾端先找出來
  i++;
 while (text[j] != '\0')//再加上去
 {
  text[i] = target[j];
  i++;
  j++;
 }
}
void split(char *src, char target, char *segmentA, char *segmentB)
{
 //src是要被分割的句子,依target被分割到A與B裡
 int i = 0,j=0,k=0,m=0;
 while (segmentA[m] != '\0')//把上一次的清空
  segmentA[m++] = '\0';
 m = 0;
 while (segmentB[m] != '\0')//把上一次的清空
  segmentB[m++] = '\0';
 while (src[i] != target && src[i] != '\0')//如果剩下的句子不是目標字元也不是空字元
  segmentA[j++] = src[i++];//就存到A裡面
 i++;//跳過目標字元
 while (src[i] != '\0')//再把剩下的存到B裡面
  segmentB[k++] = src[i++];
 if ('a'<=segmentA[0]&&segmentA[0]<='z')//把行首字母變大寫
  segmentA[0] -= 32;
 printf("%s\n", segmentA);//把分好的印出來
 int l = 0;
 while (segmentB[l] != '\0')//把剩下的句子判斷,如果還需要分或還沒印完
 {
  if (segmentB[l] == target || segmentB[l + 1] == '\0')
  {
   split(segmentB, target, segmentA, src);
   break;
  }
  l++;
 }
}

標頭檔(.h)與實作檔(.c)

學期中助教受不了每次檢查都要等我們手動輸入測資,於是就自己寫了讀檔程式讓我們用。不過話雖如此,他並沒有仔細解釋過這隻函式如何運作,以及為何要分成.c檔與.h檔。

剛剛隨便找的,感覺這篇很容易懂,就是另外去宣告還有實作功能,讓其他人能引入檔案後輕鬆使用吧?不知道理解有沒有錯。

接下來紀錄.c跟.h檔的使用步驟。

假設兩個檔案給你下載了,在下載資料夾找到它們

複製兩個檔案,然後找到該程式的資料夾,應該會長得像這樣
如果程式有成功編譯過,裡面應該會有兩個資料夾,一個與程式檔名相同,一個叫做Debug。把.c檔與.h檔丟進與檔名相同的資料夾。
這時候打開IDE,我是用visual stdio,會看到


把.c檔與.h檔分別放入資源檔與標頭檔之下就好了。

記得要include .h檔進來,就可以開始用啦!

2020年1月11日 星期六

河內塔問題

題目:
輸入一個數代表圓盤的數量,再輸入一個數代表第幾個步驟。
輸出該步驟要如何移動圓盤,若該步驟不存在,輸出"Step out of range!",若圓盤數不合法,輸出"Invalid disk number!"

範例輸出:






解題思路:
這題是河內塔的變化題。
在寫之前可以先寫出原始版本的程式:
#include <stdio.h>
void hanoi(int n,char a,char b,char c)
{
    if(n==1)
        printf("move %d from %c to %c\n",n,a,c);
    else
    {
        hanoi(n-1,a,c,b);
        printf("move %d from %c to %c\n",n,a,c);
        hanoi(n-1,b,a,c);
    }
}
int main()
{
    int n;
    printf("how many disks: ");
    scanf("%d",&n);
    hanoi(n,'A','B','C');
    return 0;
}
hanoi這個函式可以理解成把問題分為n與n-1的圓盤,第n個是當前處理的目標,而剩下的n-1個則是丟到遞迴中繼續處理。

hanoi(n-1,a,c,b);

這行可以用:n-1的圓盤由A經過C最後放到B來想,下面那行也是同樣的邏輯。

然後再處理out of range的狀況,也就是超出(2^n) -1的時候。
接下來只需要再宣告一個變數s來記錄當前是第幾個步驟,當等於所求步驟數時,再將其輸出即可。

程式碼:
#include<stdio.h>
int s = 1;
int step;
void hanoi(int n, char a, char b, char c);
void move(char m, char n, int now_disk);
int main()
{
 int n, range = 1;
 printf("How many disks do you select?");
 scanf_s("%d", &n);
 if (n < 0)
  printf("Invalid disk number!");
 else
 {
  for (int i = 1; i <= n; i++)
  {
   range *= 2;
  }
  range -= 1;
  printf("Which step do you want to print?");
  scanf_s("%d", &step);
  if (step > range)
   printf("Step out of range!");
  else
  {
   hanoi(n, 'A', 'B', 'C');
  }
  return 0;
 }


 return 0;
}

void hanoi(int n, char a, char b, char c)
{
 if (n == 1)
  move(a, c, n);
 else
 {
  hanoi(n - 1, a, c, b);
  move(a, c, n);
  hanoi(n - 1, b, a, c);
 }
}
void move(char m, char n, int now_disk)
{
 if (s == step)
  printf("Disk %d move from %c to %c\n", now_disk, m, n);
 s++;
}


3x3 矩陣乘法

題目:
輸入兩個3X3矩陣後輸出兩矩陣相乘結果。
輸入:兩個3X3矩陣(整數)。
輸出: 一個3X3矩陣,未滿3位數須補0。
  (ex : 1 → 001 , 12→ 012)

範例輸出:













解題思路:
可以先用紙筆模擬矩陣乘法,觀察在每一次相乘相加中哪些變動、哪些不變,照著實作就好了。

程式碼:
#include <stdio.h>

int main()
{
 int matrix_1[3][3], matrix_2[3][3], result[3][3] = { 0 }, temp;
 printf("The first matrix:\n");
 for (int i = 0; i < 3; i++)
 {
  for (int j = 0; j < 3; j++)
   scanf_s("%d", &matrix_1[i][j]);
 }
 printf("The second matrix:\n");
 for (int i = 0; i < 3; i++)
 {
  for (int j = 0; j < 3; j++)
   scanf_s("%d", &matrix_2[i][j]);
 }
 printf("The mutiple result is:\n");
 for (int i = 0; i < 3; i++)
 {
  for (int j = 0; j < 3; j++)
  {
   temp = 0;
   for (int k = 0; k < 3; k++)
   {
    temp += matrix_1[i][k] * matrix_2[k][j];
   }
   result[i][j] = temp;
  }
 }
 for (int i = 0; i < 3; i++)
 {
  for (int j = 0; j < 3; j++)
   printf("%03d ", result[i][j]);
  printf("\n");
 }
 return 0;
}

找重複數字

題目:
輸入十個整數,輸出其中有重複的數字,輸入與輸出請參照下圖範例。
輸入:十個整數,以空格隔開。
輸出:重複的數字(有多個以逗號隔開),若無重複數字則顯示“No repeated number!”。

範例輸出:






解題思路:
每輸入一個數都先跑看看之前有沒有相同的數字。

程式碼:
#include <stdio.h>

int main()
{
 int n[10] = { 0 }, counter[10] = { 0 }, m, length = 0, check = 0;//m接暫時數字,length紀錄陣列長度,check看有無被記錄
 printf("Please enter 10 number:\n");
 for (int i = 0; i < 10; i++)//題目輸入10個數字
 {
  check = 0;
  scanf_s("%d", &m);
  for (int j = 0; j < length; j++)//檢查有沒有出現過,有counter[]++,沒有放到n[]
  {
   if (n[j] == m)
   {
    counter[j]++;
    check = 1;
    break;
   }
  }
  if (check == 0)
  {
   n[length] = m;
   counter[length] += 1;
   length++;
  }
 }
 check = 0;
 printf("The repeat number is:\n");
 for (int i = 0; i < length; i++)
 {
  if (counter[i] > 1)
  {
   if (check == 1)
    printf(",");
   printf("%d", n[i]);

   check = 1;
  }
 }
 if (check == 0)
  printf("No repeat number!\n");
 return 0;
}


進位轉換

題目:
輸入五個浮點數
輸出

  • 由小到大排序的結果(禁止使用內建的函數)
  • 將排序結果依序轉為下列格式輸出:
  •  二進位
     八進位(最前面加0,ex:19(10) -> 023(8))
     十六進位(最前面加0x,ex:22(10) -> 0x16(16))
     右移一位
     左移一位

範例輸出:







解題思路:
排序用泡沫排序法,可參考這裡
二進位、八進位與十六進位概念相同,而後兩者在printf時有更簡單的方法:
printf("%o",n); //8進位格式輸出
printf("%x",n); //16進位格式輸出
左移與右移的實作則可直接由 >> 或 << 實現,概念可參考此篇

程式碼:
#include <stdio.h>

int main()
{
 float n[5];
 int bi[10], oct[10], hex[10], length = 0;
 printf("Input 5 number: ");
 for (int i = 0; i < 5; i++)
  scanf_s("%f", &n[i]);
 printf("Sorted result: ");
 for (int i = 0; i < 4; i++)
 {
  for (int j = i + 1; j < 5; j++)
  {
   if (n[i] > n[j])
   {
    float temp;
    temp = n[i];
    n[i] = n[j];
    n[j] = temp;
   }
  }
 }
 for (int i = 0; i < 5; i++)
  printf("%.2f ", n[i]);
 int temp = n[0];
 printf("\nConvert %d to binary: ", temp);
 while (1)
 {
  if (temp == 1 || temp == 0)
  {
   bi[length] = temp;
   break;
  }
  bi[length] = temp % 2;
  temp /= 2;
  length++;
 }
 for (int i = length; i >= 0; i--)
  printf("%d", bi[i]);
 temp = n[1];
 length = 0;
 printf("\nConvert %d to octal: ", temp);
 while (1)
 {
  if (temp < 8)
  {
   oct[length] = temp;
   break;
  }
  oct[length] = temp % 8;
  temp /= 8;
  length++;
 }
 for (int i = 2; i >= 0; i--)
 {
  if (i > length)
   printf("0");
  else
   printf("%d", oct[i]);
 }
 temp = n[2];
 length = 0;
 printf("\nConvert %d to hexadecimal: 0x", temp);
 while (1)
 {
  if (temp < 16)
  {
   hex[length] = temp;
   break;
  }
  hex[length] = temp % 16;
  temp /= 16;
  length++;
 }
 for (int i = length; i >= 0; i--)
  printf("%d", hex[i]);
 temp = n[3];
 printf("\n%d right shift 1 bit: ", temp);
 temp = temp >> 1;
 printf("%d", temp);
 temp = n[4];
 printf("\n%d left shift 1 bit: ", temp);
 temp = temp << 1;
 printf("%d", temp);
 return 0;


}

2020年1月10日 星期五

九九乘法表

題目:
撰寫1隻程式,輸入1~9後,輸出對應的九九乘法表(using loop),若輸入不在範圍內需印錯誤。

輸出範例:











程式碼:
#include <stdio.h>

int main()
{
 int n;
 printf("Please input a number: ");
 scanf_s("%d", &n);
 if (1 <= n && n <= 9)
 {
  for (int i = 1; i <= 9; i++)
  {
   printf("%d * %d = %d\n", n, i, n*i);
  }
 }
 else
  printf("input error\n");
 return 0;
}

算式比較

題目:
撰寫1隻程式,首先輸入「題號」選擇題目後輸出題目,並依序填入參數後,輸出參數是否符合算式。
題號:
1. a + b = c
2. a + b / c = d
3. a * b >= c

使用者可能輸入整數或浮點數,輸出結果取到小數第二位。

範例輸出:









解題思路:
注意輸出表達式時,「"」前面要加上「/」。


程式碼:

#include <stdio.h>

int main()
{
 int n;
 float a, b, c, d;
 printf("Please choose the expression: ");
 scanf_s("%d", &n);
 if (n == 1)
 {
  printf("The expression is \"a+b=c\"\n");
  printf("a= ");
  scanf_s("%f", &a);
  printf("b= ");
  scanf_s("%f", &b);
  printf("c= ");
  scanf_s("%f",&c);
  if (a + b == c)
   printf("\"%.2f + %.2f = %.2f\" is correct\n", a, b, c);
  else
   printf("\"%.2f + %.2f = %.2f\" is incorrect\n", a, b, c);
 }
 else if (n == 2)
 {
  printf("The expression is \"a+b/c=d\"\n");
  printf("a= ");
  scanf_s("%f", &a);
  printf("b= ");
  scanf_s("%f", &b);
  printf("c= ");
  scanf_s("%f", &c);
  printf("d= ");
  scanf_s("%f", &d);
  if ((a + b / c) == d)
   printf("\"%.2f + %.2f/%.2f = %.2f\" is correct\n", a, b, c, d);
  else
   printf("\"%.2f + %.2f/%.2f = %.2f\" is incorrect\n",a, b, c, d);
 }
 else if (n == 3)
 {
  printf("The expression is \"a*b>=c\"\n");
  printf("a= ");
  scanf_s("%f", &a);
  printf("b= ");
  scanf_s("%f", &b);
  printf("c= ");
  scanf_s("%f", &c);
  if (a *b >= c)
   printf("\"%.2f * %.2f >= %.2f\" is correct\n", a, b, c);
  else
   printf("\"%.2f * %.2f >= %.2f\" is incorrect\n", a, b, c);
 }
 return 0;
}

凱薩加密

題目:
凱薩加密是最廣為人知的古老加密法之一,由尤利烏斯·凱撒發明。此方法透過把訊息的每一個字母由固定順位後的另一個字母取代加密。(如果代替的字母超出Z,則加密會回到字母表的開頭。例如如果每一個字母由後兩位的字母取代,那Y會被A取代,Z會被B取代。)寫一個程式用凱薩加密法加密。使用者會輸入待加密訊息與移動順位(字母要被移動的數目)。

輸入:
輸入包含兩行,第一行是待加密的訊息,已知不會超過80個字元。
第二行則是順移數目。

輸出:
輸出加密後的訊息。非字母的字元無須轉換。小寫字母需維持小寫,大寫字母依然大寫。

範例輸出:





解題思路:
這題不能用scanf("%s",sentence),因為%s遇到空白就會停止。可以用getchar()或gets()。

加密部分把大小寫分開討論,然後消除字母的部分單純看成1~26的數字在裡面移動(也就是先減去一個a/A),使用%來限制數字只能在1~26之內,最後再把字母加回去。

程式碼:
#include<stdio.h>
int main()
{
 int i = 0, n = 0;
 char sentence[100] = { '\0' }, ch;
 printf("Enter meaasge to be encrypted:");
 while ((ch = getchar()) != '\n')
 {
  sentence[i++] = ch;
 }
 printf("Enter shift amount: ");
 scanf_s("%d", &n);
 printf("Encrypted message: ");
 for (int j = 0; j < i; j++)
 {
  if (sentence[j] >= 'a'&&sentence[j] <= 'z')
   sentence[j] = (sentence[j] - 'a' + n) % 26 + 'a';
  else if (sentence[j] >= 'A'&&sentence[j] <= 'Z')
   sentence[j] = (sentence[j] - 'A' + n) % 26 + 'A';
 }
 printf("%s\n", sentence);
 return 0;
}

電話號碼轉換

題目:
寫一個程式把字母格式的電話號碼轉乘數字格式。

(如果你手邊沒有手機,這裡有數字鍵與字母的對照:2=ABC,3=DEF,4=GHI,5=JKL,6,MNO,7=PRS,8=TUV,9=WXYZ.)如果電話號碼包含非字母字元(例如數字或標點符號),不需要轉換他們。

你可以假設使用者輸入的所有字母都是大寫。

輸入:
輸入包含一行字串,代表電話號碼。

輸出:
把字母電話號碼轉換為數字型態。

範例輸出:





程式碼:
#include<stdio.h>

int main()
{
 int i = 0,check=0;
 char number[15] = {'\0'}, ch;
 printf("Enter phone number: ");
 while ((ch = getchar()) != '\n')
 {
  if (ch >= 'A'&&ch <= 'Y')
  {
   if (ch <= 'C')
    number[i++] = '2';
   else if (ch <= 'F')
    number[i++] = '3';
   else if (ch <= 'I')
    number[i++] = '4';
   else if (ch <= 'L')
    number[i++] = '5';
   else if (ch <= 'O')
    number[i++] = '6';
   else if (ch <= 'S')
    number[i++] = '7';
   else if (ch <= 'V')
    number[i++] = '8';
   else
    number[i++] = '9';
  }
  else if (ch == '@'||ch=='Z')
  {
   check = 1;
   break;
  }
  else
   number[i++] = ch;
 }
 if (check == 0)
  printf("%s\n", number);
 else
  printf("invalid phone number.\n");
 return 0;
}

2020年1月9日 星期四

排序問題

題目:
有N個在二維座標系上的點,以Pi=(xi,yi)表示第i個點。寫一個程式將這些點從左下到右上進行排序(以遞增、x值優先的方式排序)。

輸入:
輸入第一行為一整數N,代表接下來有幾個點座標。假設0<N<=0,接下來N行每一行包含兩個數字,以空白隔開,分別代表點座標的x與y值。

輸出:
輸出排序後的點座標。
如果N超過範圍,輸出錯誤訊息"invalid number of points"。

範例輸出:















解題思路:
以泡沫排序法排序,記得x值跟y值都要交換,然後再跑一次確定若x值相同時y的大小。


程式碼:
#include <stdio.h>

int main()
{
 int n;
 float a[10][2] = { 0 };
 printf("Enter number of points: ");
 scanf_s("%d", &n);
 if (n >= 0 || n < 10)
  printf("invalid number of points.\n");
 else
 {
  for (int i = 0; i < n; i++)
   scanf_s("%f %f", &a[i][0], &a[i][1]);
  for (int i = 0; i < n; i++)
  {
   for (int j = 0; j < n; j++)
   {
    if (a[i][0] < a[j][0])
    {
     float temp = a[i][0];
     a[i][0] = a[j][0];
     a[j][0] = temp;
     temp = a[i][1];
     a[i][1] = a[j][1];
     a[j][1] = temp;
    }
   }
  }
  for (int i = 0; i < n - 1; i++)
  {
   if (a[i][0] == a[i + 1][0] && a[i][1] > a[i + 1][1])
   {
    float temp = a[i][1];
    a[i][1] = a[i + 1][1];
    a[i + 1][1] = temp;
   }
  }
  printf("\n");
  printf("Sorted result:\n");
  for (int i = 0; i < n; i++)
   printf("%.2f %.2f\n", a[i][0], a[i][1]);
 }
 
 return 0;
}

2020年1月8日 星期三

費式數列

題目:
費式數列的定義:
F(0)=0
F(1)=1
F(n)=F(n-1)+F(n-2)
由定義我們可以得知以下的數列:
0,1,1,2,3,5,8,13,21,34,55,89,144,......

給一個整數N,請輸出第N個費波納西數。

輸入:
輸入包含一個整數N。

輸出:
如果N>=0,輸出第N個費波納西數。
如果N<0,輸出錯誤訊息"invalid input."

範例輸出:




程式碼:
#include<stdio.h>

int main()
{
 int n;
 long long int ans[100] = {0};
 printf("enter number: ");
 scanf_s("%d", &n);
 if (n < 0)
  printf("invalid input");
 else
 {
  if (n == 1)
   printf("%dst ", n);
  else if (n == 2)
   printf("%dnd ", n);
  else if (n == 3)
   printf("%drd ", n);
  else
   printf("%dth", n);
  printf("fibonacci number is: ");
  for (int i = 0; i <= n; i++)
  {
   if (i <= 1)
    ans[i] = i;
   else
    ans[i] = ans[i - 1] + ans[i - 2];

  }
  printf("%lld", ans[n]);
 }
}

筆記:
因為輸出結果可能會很大,所以要用long long int 來儲存。
費式數列的值可以參考這篇

另外,這題是在電腦上demo,所以可以直接加起來,不用考慮效率問題。

印出倒金字塔

題目:
給一整數N代表層數,請以星星(*)印出N層的倒立金字塔。

輸入:
輸入只有一行,包含一個整數N。

輸出:
如果N>0,印出倒立的金字塔。
如果N<=0,印出錯誤訊息"invalid input."

輸出範例:








程式碼:
#include <stdio.h>

int main()
{
 int n;
 printf("Enter layer: ");
 scanf_s("%d", &n);
 if (n <= 0)
  printf("invalid input.\n");
 else
 {
  for (int i = 0; i < n; i++)
  {
   for (int j = 0; j <= i; j++)
    printf(" ");
   for (int j = 0; j < 2 * n - 1 - 2 * i; j++)
    printf("*");
   printf("\n");
  }
 }
 return 0;
}

2020年1月7日 星期二

測試嵌入程式碼

一個簡單的測試!

#include <stdio.h>

int main()
{
    printf("Hello World");

    return 0;
}

參考文章:
應用Google Code Prettify在blogger中顯示程式
https://rreadmorebooks.blogspot.com/2018/08/google-code-prettifyblogger.html

字符串轉換
在線HTML編碼器
https://www.convertstring.com/zh_TW/EncodeDecode/HtmlEncode