C語言學習筆記(3)——指針七題

之前學習語言都只是看視頻,到自己寫的時候什麼都寫不出來,現在要改掉這個壞習慣O(∩_∩)O哈哈~。都是很基礎的東西。
首先第一題(參考了視頻中的答案。嘗試自己寫的):輸入年份、和這一年的第N天,最後算出這一天是這一年的幾月幾日。(區分閏年)

#include <stdio.h>

int main()
{
    int month[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
    int Leap_month[12] = { 31,29,31,30,31,30,31,31,30,31,30,31 };
    int year, day, i;
    int Leap_flag;
    int R_flag = 1;
    while (R_flag == 1)
    {
        printf("Please input year and day\n");
        scanf_s("%d,%d", &year, &day);
        if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
        {
            Leap_flag = 1;//這裏寫的並不好,可以用指針直接修改2829就不用列出兩個數組以及再加一個leap判斷
        }
        else
        {
            Leap_flag = 0;
        }
        if (day>365 && Leap_flag == 0 || day>366 && Leap_flag == 1)
        {
            printf("Please input right day");
        }
        else
        {
            R_flag = 0;
//          break;
        }
    }
    if (Leap_flag == 1)
    {
        for (i = 0; day>*(Leap_month + i); i++)
        {
            day -= *(Leap_month + i);
        }
        printf("Years=%d,Month=%d,Day=%d", year, i + 1, day);
    }
    else
    {
        for (i = 0; day>*(month + i); i++)
        {
            day -= *(month + i);
        }
        printf("Years=%d,Month=%d,Day=%d", year, i + 1, day);
    }

    return 0;

}

第二題
取十個1-100的隨機整數,並倒序打印出來(用指針,不要用數組下標)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 10

void func(int *num)
{
    int i;
    srand((unsigned int)time(NULL));// srand()函數初始化隨機數種子,rand()產生隨機數
    for (i = 0; i < N; ++i)
    printf("num[%d] = %d.\n", i, *(num + i) = rand() % 100 + 1);// 循環產生0~99的隨機數,再加上1, 放入num裏,同時打印出來

}
int main()
{
    int num[N] = {0};
    int *p = num;
    func(num);
    for (p = num + N - 1; p >= num; --p)
        printf("%d ", *p);
    // 把p的下標移動到數組的最後一位,然後從後往前循環遍歷,
    // 如果當前下標的地址大於數組的首地址,那就每次往前移動一個int,同時打印出來

    printf("\n");
    return 0;
}

第三題

通過隨機函數獲取到26個小寫英文字母,存儲到數組裏並小寫字母順序打印出來。
這題對我而言還是比較難的,直接參考原文吧-_-||

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LEN 26

void func(char *s)//用這個函數直接實現按順序把字母放進去,就不用在後面再排序!!!
{
    srand((unsigned int)time(NULL));
    int n = 0;
    while(n < LEN) // 循環條件是,數組存滿了26個字母
    {
        int temp = rand() % LEN;// 設定一個變量用來接收 0~25 的隨機數
        if(*(s + temp) == 0)    // 如果數組裏的某個下標的值是 0,那麼就進入後面的語句,如果數組裏的某個下標的值是字母,說明就賦值過了,就不執行後面的語句,對應一下這個函數的功能就能懂這裏
        {
            *(s + temp) = temp + 'a';   // 把隨機到的數字,加上字符'a',隱式轉換成字母,對應下標存放到字符數組裏
            n++;    // 每次放入一個正確的字母,n就自增1,
        }
    }
}

int main()
{
    char a[LEN] = { 0 };
    func(a);
    for (int i = 0; i < LEN; ++i)
            printf("%c\n", *(a + i));
    printf("\n");
    return 0;
}

第四題

將字符串“We Are Family!”,去除空格後打印出來。(WeAreFamily!)
先按照我自己的思路寫一下試試吧ヾ(◍°∇°◍)ノ゙

#include <stdio.h>

char *func(char *str)
{
    int i = 0;
    int j = 0;
    for (; *(str + i) != '\0'; ++i)
    {
        if (*(str + i) != ' ')
        {
            *(str + j++) = *(str + i);//只要是不爲空格,i 和 j都會自增,並且做替換;如果是空格,那麼i會自增,j不動
        }
    }
    *(str + j) = '\0';
    return str;
}

int main()
{
    char str[] = "we are family";
    func(str);
    printf("After delete spaces = %s\n", func(str));
    return 0;
}

第五題

輸入一個字符串,判斷其是否是迴文。(迴文:即正讀和反讀都一樣,如abcba, abccba)
兩種方法:1。

#include <stdio.h>
#include <string.h>
#define N 50    //50個足夠了

int func(char *p, int len)      // 獲取字符串的首地址,和字符串長度
{
    for(int i = 0; i < len / 2; ++i)    // 循環次數是字符串長度的一半
        if( *(p + i) != *(p + len - i - 1)) // 比較前面的字符和後面的字符是否不等
            return 0;                       // 如果不相等,就返回0,表示字符串不是迴文
    return 1;                           // 如果循環接收一直沒有返回 0, 則表示字符串是迴文,返回1 給調用函數
}

int main(void)
{
    char str[N] = { 0 };            // 創建一個長度爲50的字符串
    scanf("%s", str);               // scanf()接收用戶輸入的字符串

    if(func(str, strlen(str)))      // 這裏做了三步:1.獲取字符串長度,並且和字符串首地址一起傳給被調用函數的形參
                                    // 2. 調用了func()函數,同時接收函數的返回值
                                    // 3. 接收函數的返回值,決定了分支語句的執行
        printf("Yes! %s is huiwen! \n", str);
    else
        printf("Sorry! %s is not huiwen! \n", str);
    return 0;
}

方法2

int func(char *p, int len)      // 獲取字符串的首地址,和字符串長度
{
    for(int i = 0; i < len / 2; ++i)    // 循環次數是字符串長度的一半
        if( *(p + i) != *(p + len - i - 1)) // 比較前面的字符和後面的字符是否不等
            return 0;                       // 如果不相等,就返回0,表示字符串不是迴文
    return 1;                           // 如果循環接收一直沒有返回 0, 則表示字符串是迴文,返回1 給調用函數
}
int main(int argc, char *argv[])
{
    if(func(argv[1], strlen(argv[1])))      // argv[0]是程序名字,argv[1]是緊接着的字符串。這裏做了三步:1.獲取字符串長度,並且和字符串首地址一起傳給被調用函數的形參// 2. 調用了func()函數,同時接收函數的返回值// 3. 接收函數的返回值,決定了分支語句的執行
        printf("Yes! %s is huiwen! \n", argv[1]);
    else
        printf("Sorry! %s is not huiwen! \n", argv[1]);
    return 0;
}

問題6

輸入一段字符串,無論是否有重複字母出現,都只打印出現過的小寫字母,並按照小寫字母順序打印。(如輸入qewqwr322rqw<>211qESFSSEraZz, 打印aeqrwz)感覺和第三題差不多,只是判斷條件有點區別

#include <stdio.h>
#include <stdlib.h>
#define N 500

int main()
{
    char str1[N] = { 0 };   // 存儲用戶輸入的字符串
    char str2[N] = { 0 };   // 存儲要打印的字符串

    scanf("%s", str1);      // 接收用戶輸入

    int index = 0;          
    for (int i = 0; *(str1 + i) != '\0'; ++i)   // 遍歷str1字符串,直到字符串結尾'\0'
    {
        index = *(str1 + i) - 97;               // 取出*(str + i)的字符,減去 小寫字母a的ascii碼 97,當作數組下標,給index
        *(str2 + index + 97)  = '+';            // 在str2裏面,把 index下標的元素置爲 + 號,做爲標記
    }

    for (int i = 97; i < 26 + 97; ++i)      //  下標從97開始,循環遍歷str2
        if( *(str2 + i) == '+')             //  如果遍歷到的下標有 + 號標記,之前判斷這裏是有出現過字母,
            printf("%c ", i);               // 那麼就打印這個下標對應的字母ASCII碼,也就是打印字母了。

    printf("\n");
    return 0;
}

問題7

輸入某個月的第N周和這一週的第M天,通過int *GetDay() 函數獲取參數並返回結果,來得出這一天是這個月的第多少天。
(如輸入:3,4,即這個月的第3周的第4天,即這個月的第18天)

#include <stdio.h>

int *GetDay(int n, int m)
{
    // 在函數返回時,函數內部的局部變量會被銷燬
    // static 定義靜態變量,這個變量的聲明週期是整個源程序,作用域不變
    static int calc[5][7] = 
    {
        {1,2,3,4,5,6,7},
        {8,9,10,11,12,13,14},
        {15,16,17,18,19,20,21},
        {22,23,24,25,26,27,28},
        {29,30,31}
    };
    return &calc[n-1][m-1];
    // 返回數組下標的地址,數組下標是從0開始的,所以要減 1
}

//如果函數返回局部變量的值,程序是不會出錯的
//如果函數返回局部變量的地址,雖然你把地址返回了,但是地址裏的值已經被銷燬了
// 如果其他程序用了這塊內存,那麼程序執行結果將不可預估


// 作用域: 表示某個變量的作用範圍,一般在某個代碼塊了,用 {} 分隔
// 生命週期: 決定這個變量什麼時候被銷燬,靜態變量的生命週期是整個源程序

int main(int wk, int dy, char Y)
{
    int a = 0;
    do
    {
        int b = 0;
        printf("Please input week and day: \n");
        scanf("%d %d", &wk, &dy);
        getchar();
        if(wk > 5 || wk < 1 || dy > 31 || dy < 1)
        {
            printf("Error input! Byebye!\n");
            return 0;
        }

        printf("The days is %d\n", *GetDay(wk, dy));

        printf("If you want again, inpyt 'Y' (other for quit): \n");
        scanf("%c", &Y)


    }while(Y == 'Y')
    printf("\n \n");
}

這個思路好棒,看來還需要加油啊!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章