C語言博客做業05——指針

1.本章學習總結

1.1思惟導圖

1.2本章學習體會及代碼量

1.2.1學習體會

可能由於以前數組那塊兒的做業拖得過久了,以致於我以爲指針學的好快,還沒反應過來就教完了,而後一開始作題的時候,就是一臉懵逼得狀態。而後前段時間也都在不數組的做業,指針也沒好好看看書,也就上課的時候聽聽老師講課,而後後面作題,一不會就去翻書,一來二去的雖然仍是不很明白指針到底怎麼回事,可是大概的題目也都會作了。而後如今我把指針跟結構體的題目集都刷完了,也該好好補補指針的知識點了。

1.2.2代碼累計

2.PTA總分

2.1截圖PTA中指針題目集的排名得分

2.2個人總分

PTA總分:110

3.PTA實驗做業

3.1PTA題目1

反話-增強版 
給定一句英語,要求你編寫程序,將句中全部單詞的順序顛倒輸出。

3.1.1算法分析

定義整型變量:i、j、k=0、count=0、length、temp
定義字符型指針:ch
ch=(char *)malloc(500001*sizeof(ch));//經過malloc把較大的數組放到堆區,防止爆棧 
輸入字符串ch
經過strlen函數獲得字符串ch的長度
temp=length-1    //解決末尾爲空格的狀況
while length-- do
  while ch[k]爲空格 do    //解決前面有連續空格的狀況
    k++
  end while
  if length=0 且 ch[0]!=' ' then
    for j=0 to count do
      putchar(*(ch+j))    //輸出開頭不爲空格時的單詞
    end for
  end if
  if ch[length] 不爲空格 then
    count++
  else if ch[length]爲空格 且 ch[length+1]不爲空格 且 length不是字符串尾 then 
    for i=1 to count do
      putchar(*(ch+length+i))
    end for
    if length+1!=k then 
      printf(" ")
    end if
    count=0
  else if ch[length]爲空格 且 ch[length+1]爲空格 或者 ch[length]爲空格 then 
    continue
  end if
end while

3.1.2代碼截圖


3.1.3PTA提交列表及說明

  • Q:一開始直接用printf輸出,而後輸出的都是這樣子的
  • A:運行以前,我一直把printf認爲是跟scanf同樣的,遇到空格就停下來,結果是我太天真了…而後當時可能腦子有點抽了,一直想不到除了printf和puts()還有什麼輸出方式,而後又用循環和printf一個一個字符的輸出,結果…不知道爲何輸出了一堆亂七八糟的東西。而後過了很久很久纔想到了putchar()這個傢伙,運行了一下結果對了,就提交了。
  • Q:興致沖沖的提交完以後他告訴我:部分正確…
  • A:而後看了一眼測試點,三個沒過:一個詞,末尾有空格、最小詞,前有空格、只有空格,而後通過一番改動,自認爲能夠過了,結果一提交,仍是部分正確…再看一眼,最小詞,前有空格這個點仍是沒過,我想着我已經把開頭第一個是空格的狀況加進去了,怎麼會還錯,而後一調試,發現當開頭是連續空格的時候,個人輸出是錯的,輸出多了空格。忽然想起來大做業裏消除非法字符串的作法,想一想這裏的狀況也差很少,就用了一個while解決了開頭的連續空格的問題。

4.大做業

題目:實現小學四則運算。

在函數那章,咱們已經實現小學四則運算這份做業,如今要求你們把以前設計函數升級改造,原來的函數你們都是用全局變量實現不一樣函數參數傳遞,此次做業要求改地址傳遞,減小全局變量的使用。算法

題目要求:

題目有3個難度級別,分別爲:數組

  • 第一級是1位數的一步加減乘除計算
  • 第二級是2位數的2步加減運算
  • 第三級是3位數的2步加減運算

4.1改造函數介紹

1.構造字符數組存放算術表達式

**char CreateExp(char *exp,char level);**框架

  • 僞代碼
定義整型變量num、op(獲取隨機數)、i,字符型數組str[10](用於整型轉字符型存放)
srand(time(NULL)) //獲取隨機數種子
if level=='1' then 
  i=3 //一級運算數及運算符的總和
  while --i do
    if i爲偶數 then
      num=rand()%10;
      itoa(num,str,10)//將整型變量num轉化爲字符型變量存入數組str中
      strcat(exp,str);//將str數組中的字符串接在exp數組後
    else
      op=rand()%4;
      switch(op)//隨機獲取運算符,並接在數組exp後
        case 0: strcat(exp,"+");;break;
        case 1: strcat(exp,"-");break
    case 2: strcat(exp,"*");break;
        case 3: strcat(exp,"/");break;
    end if
  end while
else//當level爲2或3時
  i=5 //二(三)級運算數及運算符的總和
  while --i do
    if i爲偶數 then 
      if level=='2' then
        num=rand()%100
      else
        num=rand()%1000
      end if
      itoa(num,str,10)//將整型變量num轉化爲字符型變量存入數組str中
      strcat(exp,str);//將str數組中的字符串接在exp數組後
    else
      op=rand()%4;
      switch(op)//隨機獲取運算符,並接在數組exp後
        case 0: strcat(exp,"+");;break;
        case 1: strcat(exp,"-");break
    end if
  end while
end if
strcat(exp,"=")//將等號接在表達式後
if 表達式合法 then
  輸出表達式
else
  返回CreateExp(exp,level)函數,從新建立表達式
return *exp//返回指針*exp
  • 函數代碼
char CreateExp(char *exp,char level)//構造字符數組存放算術表達式
{
    int num,i;
    int op;
    char str[10];
    srand(time(NULL));
    if(level=='1')
    {
        i=3;//運算數及運算符的總和 
        do
        {
            if(i%2)
            {
                num=rand()%10;
                itoa(num, str, 10);
                strcat(exp,str);
            }
            else
            {
                op=rand()%4;
                switch(op)
                {
                    case 0: strcat(exp,"+");;break;
                    case 1: strcat(exp,"-");break;
                    case 2: strcat(exp,"*");break;
                    case 3: strcat(exp,"/");break;
                }
            }
        }while(--i);
    }
    else
    {
        i=5;//運算數及運算符的總和 
        do
        {
            if(i%2)
            {
                if(level=='2')
                    num=rand()%100;
                else
                    num=rand()%1000;
                itoa(num, str, 10);
                strcat(exp,str);
            }
            else
            {
                op=rand()%2;
                switch(op)
                {
                    case 0: strcat(exp,"+");break;
                    case 1: strcat(exp,"-");break;
                }
            }
        }while(--i);
    }
    strcat(exp,"=");
    if(IsExp(exp,level))//判斷表達式是否合法
        printf("\n\t\t\t\t%s",exp);
    else
        return CreateExp(exp,level);//表達式不合法時返回CreateExp(exp,level)函數,從新建立表達式
    return *exp;
}

2.表達式是否合法

**int IsExp(char *exp,char level);**函數

  • 僞代碼
if 等級爲2、三級 then //二三等級不含除法,即不存在表達式不合法狀況
  return 1;
定義整型變量m=0,sum=0,i=0、字符型變量c=exp[i],oldc='+'
while c!='=' do
  c=exp[i]
  if c爲數字 then 
    m=10*m+c-'0'//將字符型數字轉化爲整型數字
  else
    if oldc=='+' then 
      sum+=m
    else if oldc=='/' then
      if m==0 或者 sum%m!=0 then //不合法狀況,即除數爲零、不能整除
        return 0
      end if
    end if
    m=0//初始化 ,用於下一輪轉化整型變量
    oldc=c
  end if
  i++
end while
return 1
  • 函數代碼
int IsExp(char *exp,char level)//表達式是否合法
{
    if(level=='2'||level=='3')//二三等級不含除法,即不存在表達式不合法狀況
        return 1;
    int m=0, sum=0,i=0;
        char c, oldc='+';
        do 
    {
        c = exp[i];
        if( c<='9'&&c>='0' ) 
            m = 10*m + c - '0';
        else 
        {
            if( oldc == '+' )
                sum += m;
            else if(oldc == '/')
            {
                if(m==0 || sum%m!=0)//不合法狀況,即除數爲零、不能整除
                return 0;
            }
            m = 0;
            oldc = c;
          }
          i++;
    } while(c!='=');
    return 1;
}

3.表達式運算

**int ComputeExp(char *exp);**學習

  • 僞代碼
定義整型變量m=0,sum=0,i=0、字符型變量c=exp[i],oldc='+'
while c!='=' do
  c=exp[i]
  if c爲數字 then
    m=10*m+c-'0'//將字符型數字轉化爲整型數字
  else
    if oldc是+ then
      sum+=m
    else if oldc是- then 
      sum-=m
    else if oldc是* then 
      sum*=m
    else if oldc是/ then 
      sum/=m
    end if
    m=0//初始化
    oldc=c
  end if
  i++
end while
return sum
  • 函數代碼
int ComputeExp(char *exp)//表達式運算
{
    int m=0, sum=0,i=0;
        char c, oldc='+';
        do 
    {
        c = exp[i];
        if( c<='9'&&c>='0' ) 
            m = 10*m + c - '0';//將字符型數字轉化爲整型數字
        else //計算表達式
        {
            if( oldc == '+' )
                sum += m;
            else if(oldc == '-')
                sum -= m;
            else if(oldc == '*')
                sum*=m;
            else if(oldc == '/')
                sum/=m;
            m = 0;//初始化
            oldc = c;
        }
        i++;
   } while(c!='=');
   return sum;
}

4.3與原有函數代碼比較

  • 函數的功能上
    由於上一回作大做業的時候時間有點趕,代碼功能不夠齊全,函數的設計上自我感受也不夠理想,因而此次的大做業是我在上回大做業的思路的基礎上從新打的,與原來默認每輪只作十道題相比,多了一個題數選擇的功能。
  • 函數分裝上
    將原來void Screen();//提示界面 、void Menu();//顯示菜單這兩個函數整合成一個函數void Screen();//提示界面
  • 建立表達式上
    · 原代碼
void NumberGet()
{
    if(levelChoice=='1')
    {
        srand(time(NULL));
        number1=rand()%10;
        number2=rand()%10;
    }
    else if(levelChoice=='2')
    {
        srand(time(NULL));
        number1=rand()%100;
        number2=rand()%100;
        number3=rand()%100;
    }
    else
    {
        srand(time(NULL));
        number1=rand()%1000;
        number2=rand()%1000;
        number3=rand()%1000; 
    }
}
void OperatorGet()
{
    if(levelChoice=='1')
    {
        srand(time(NULL));
        operator_ch1=rand()%4;
        switch(operator_ch1)
        {
            case 0:ch1='+';break;
            case 1:ch1='-';break;
            case 2:ch1='*';break;
            case 3:ch1='/';break;
        }
    }
    else
    {
        srand(time(NULL));
        operator_ch1=rand()%2;
        operator_ch2=rand()%2;
        switch(operator_ch1)
        {
            case 0:ch1='+';break;
            case 1:ch1='-';break;
        }
        switch(operator_ch2)
        {
            case 0:ch2='+';break;
            case 1:ch2='-';break;
        }
    }
}
//函數void GameBegin()中的一部分
if(levelChoice=='1')
{
    NumberGet(); //獲取隨機數 
    OperatorGet(); //隨機獲取運算符 
    printf("%.0f %c %.0f = ",number1,ch1,number2);
    scanf("%lf",&yourAnswer);
    rightAnswer=Calculate();
    if(yourAnswer==rightAnswer)
    {
     printf("\n\t\t\t\tGood job!^_^\n");
     i++;
    }
    else
    {
        printf("\n\t\t\t\t回答錯誤!>_<\n");
        printf("\n\t                                  正確答案是:%.0f %c %.0f = %.2lf\n",number1,ch1,number2,rightAnswer);
        j++;
    }
}
else
{
    NumberGet(); //獲取隨機數 
    OperatorGet(); //隨機獲取運算符 
    printf("%.0f %c %.0f %c %.0f = ",number1,ch1,number2,ch2,number3);
    scanf("%lf",&yourAnswer);
    rightAnswer=Calculate();
    if(yourAnswer==rightAnswer)
    {
            printf("\n\t\t\t\tGood job!\n");
            i++;
    }
    else
    {
        printf("\n\t\t\t\t回答錯誤!>_<\n");
        printf("\n\t\t\t\t正確答案是:%.0f %c %.0f %c %.0f = %.0lf\n",number1,ch1,number2,ch2,number3,rightAnswer);
        j++;
    }
}

· 改造後的代碼(如上char CreateExp(char *exp,char level);函數)測試

1.原函數中,隨機數與隨機運算符的獲取分裝爲兩個函數,表達式的輸出也只是由一個簡單的printf()輸出
而改進後的代碼,將隨機數與隨機運算符的獲取再加上表達式的整合放在同一個函數中,使代碼更加簡潔
2.原代碼中,屢次調用隨機數和隨機運算符的獲取函數,在效率上拖慢了程序的運行,而改進後的代碼則不存在屢次重複調用的狀況出現
  • 在判斷表達式是否合法上
    在原來的程序中,我並無設置判斷表達式是否合理的函數,而是針對除法不能整除時,令結果保留兩位小數(代碼以下)

    而爲了解決除數爲0的狀況,我直接將除數的取值範圍定在1到9之間,就不存在除數爲0的狀況了

    指針版的大做業中老師明確要求了,將除法不能整除和除數爲0的狀況設爲不合法表達式,受老師博客中計算字符串表達式代碼的影響,個人判斷表達式是否合法的函數以下

而後其他的函數基本都大同小異設計

4.4改進大做業總結

  • 其實兩次大做業作下來,都有一個讓我很鬧心的地方,就是我在函數調用上出了點小問題,個人主函數中只有void GameBegin();這一個子函數。在作指針版的大做業時,我在主函數中已經打好框架了,(就是void GameBegin();函數中的內容)可是在個人全部函數都補充完了以後,我想要作一個每輪結束以後再次進入程序的函數,可是不能用 return main 因此我只好將主函數中的全部內容都放到一個函數中,再將這個函數放入主函數中,這樣就致使了個人主函數中只有一行代碼(讓我本身看的很難受,可是又不知道怎麼解決)
  • 老師在課上提到了整型數字轉化爲字符型數字有專門的函數時,我就回去百度了一下,而後按照先獲取整形隨機數,再將其轉化爲字符型數字的思路作了。
  • 而後順着老師提供的如何計算字符串表達式的方法,我在想反正不合法表達式只存在與一級題目的除法運算中,那這種方法也能夠用來判斷表達式是否合法。
  • 其實從整體上看,我此次大做業更多的是依賴於老師博客上提供的思路與作法進行改進的,自我感受並無太多的本身思考的地方。
  • 老師博客上提供的算法實際上是以前課堂派上的一道題目,讓我知道其實咱們能夠多多學習日常課堂派中題目的思路。
相關文章
相關標籤/搜索