EXERCISE

WJnuHhail發表於2024-11-05

一、選擇題

1.Linux中使用 mkdir命令建立新的目錄時,在其父目錄不存在時先建立父目錄的選項是( )
A -m B -d C -f D -p

tips:D
mkdir [選項] [目錄]
-m —mode=模式,建立目錄的時候同時設定目錄的許可權。
-p —parents 若所建立的上層目錄目前尚未建立,則會一併建立上層目錄。
-v —verbose 每次建立新目錄都顯示資訊。
-h —help 幫助資訊。


2.下面程式碼建立了多少個程序(不包含main程序本身) ( )
int main(int argc,char* argv[])
{
fork();
fork() && fork() || fork();
fork();
}
A 19 B 30 C 24 D 29

tips: A
如果有一個這樣的表示式:cond1 && cond2 || cond3 這句程式碼會怎樣執行呢?
1、cond1為假,那就不判斷cond2了,接著判斷cond3。
2、cond1為真,這又要分為兩種情況:
2.1 cond2為真,這就不需要判斷cond3了。
2.2 cond2為假,那還得判斷cond3。

fork呼叫的一個奇妙之處在於它僅僅被呼叫一次,卻能夠返回兩次,它可能有三種不同的返回值:
1、在父程序中,fork返回新建立子程序的程序ID。
2、在子程序中,fork返回0。
3、如果出現錯誤,fork返回一個負值(題幹中說明了不用考慮這種情況)。
在fork函式執行完畢後,如果建立新程序成功,則出現兩個程序,一個是子程序,一個是父程序。
在子程序中,fork函式返回0,在父程序中,fork返回新建立子程序的程序ID。我們可以透過fork返回的值來判斷當前程序是子程序還是父程序。
很明顯fork() && fork() || fork()建立了4個新程序。
總結:
第一行fork生成1個新程序。
第二行的三個fork生成4+4=8個新程序。
第三行的fork會生成10個新程序(這是因為前面總共有10個程序,呼叫一次fork生成10個新程序。
所以一共會生成1+8+10=19個新程序。


3.如果下列公式成立:3A* 124=446C 。則採用的是( )進位制
A 11 B 12 C 14 D 16

tips:
排除法, 看個位。最後的結果446C個位為C,因此,A,B可以排除。
假設為14進位制,(A * 4 )%14= 12,結果正好為C。因此,答案為14進位制。


4.下面關於字元陣列的初始化,那個是正確的? ( )
A char b[2][3] ={"d","e","f"}
B char b[2][3] ={"d","e"};
C char b[2][3] ={{"d","e","f"},{"a","b","c"}};
D char b[2] ={"d","e"};

tips:B
通常情況下,二維陣列的每一行分別使用一個字串進行初始化。 例如:
char c[3] [8]={{"apple"},{"orange"},{"banana"}};
等價於:
char c[3][8]={"apple","orange","banana"};
A:應改為char b[3][2] ={"d","e","f"};
C:應改為char b[2][3][2] ={{"d","e","f"},{"a","b","c"}};
D:應改為 char b[2][2]={"d","e"};


5.在32位系統中,下列型別佔用8個位元組的為( )
A int
B unsigned long long
C char
D short int

tips:B
32位作業系統中
int:4位元組
unsigned long long:8位元組
char :1位元組
short int:2位元組
注意和64位作業系統的區別:64位系統中,指標變數和long以及unsigned long 都佔8個位元組,其他的和32位系統一樣


二、簡答題

1.程式:
int a[6] = { 1,2,3,4,5,6};
printf("%d\n",((int)(&a+1)- 1));
的輸出結果是什麼?

tips:
首先,定義了一個整型陣列a,包含6個元素。
&a表示陣列a的地址,它是一個指向整型陣列的指標。
(&a+1)表示陣列a的下一個地址,因為&a是指向整型陣列的指標,所以(&a+1)指向陣列a之後的記憶體位置。
((int)(&a+1)-1)將(&a+1)的地址型別轉換為整型指標,並減去1,得到陣列a的最後一個元素的地址。
((int)(&a+1)-1)透過解引用運算子
訪問最後一個元素的值,即6。
最後,printf函式將6作為整數列印出來。
所以,這段程式的輸出結果是6。


2.請寫出常量指標和指標常量的程式碼形式,並簡述他們的區別
答:

  1. 常量指標(Pointer to Constant):指標指向的資料不能被修改,但指標本身可以指向其他資料。
    const int *ptr1;
    在這個例子中,ptr1是一個指向整數常量的指標。你不能透過ptr1來改變它所指向的整數的值,但你可以改變ptr1所指向的地址。
  2. 指標常量(Constant Pointer):指標本身的值(也就是它所指向的地址)不能被修改,但指標指向的資料可以被修改。
    int *const ptr2;
    在這個例子中,ptr2是一個常量指標,指向一個整數。你不能改變ptr2所指向的地址,但你可以改變ptr2所指向的整數的值。
    總的來說,常量指標和指標常量的主要區別在於是否可以改變指標本身的值和指標所指向的資料。常量指標不允許透過指標來改變資料,但可以改變指標所指向的地址。指標常量不允許改變指標所指向的地址,但可以改變指標所指向的資料。

3.如何避免標頭檔案被重複包含

答:

#ifndef HEADER_FILE_NAME_H
#define HEADER_FILE_NAME_H

// 標頭檔案內容

#endif
#pragma once

// 標頭檔案內容
直接放置在標頭檔案的開頭。這個指令告訴編譯器只包含一次該標頭檔案,避免了重複包含的問題。
這樣可以防止標頭檔案被重複包含。


4.如下程式碼,請設計宏定義STR(x) ,將USART_RATE轉換成字串並列印出來

#define USART_RATE 115200
#define STR(x)        ?
printf("usart rate = %s\n",STR(USART_RATE));

tips:
要設計宏定義STR(x),將USART_RATE轉換成字串並列印出來,可以使用宏的字串化運算子#。

#define USART_RATE 115200
#define STR(x) #x
printf("usart rate = %s\n", STR(USART_RATE));

在這個宏定義中,#運算子將宏引數x轉換為一個字串。當我們使用STR(USART_RATE)時,它會被替換為"USART_RATE",然後在printf函式中用%s來列印這個字串


5.請寫出下列程式碼的輸出結果

int main(int argc,char *argv[])
{
	char *buff[] ={"char","int","double"};
	printf("%c\n",*(buff+1)[1]);
	return 0;
}

tips:
首先,我們需要理解(buff+1)[1]的含義。buff+1表示buff陣列的第二個元素的地址,即&buff[1]。然後,(buff+1)表示取出該地址處的值,即buff[1]。由於buff[1]是一個字串,所以可以看作是一個字元陣列。最後,[1]表示取該字元陣列的第二個元素。

在這個例子中,buff[1]是字串"int",然後[1]表示取出字元陣列"int"的第二個字元,即字元'n'。

糾正:如果表示式為(*(buff+1))[1]那麼結果確實為 n
但是在本題中最終的結果為d
上述分析沒問題但是 (buff+1)[1] 系統編譯時等價於((buff+1)[1])
即buff[1]處(buff+1)結果就等價於 buff[2]


6.下面的程式碼輸出什麼?為什麼?

void foo(void)
{
	unsigned int a = 6;
	int b = -20;
	(a+b>6)?puts(">6"):puts("<=6");
}

tips:
下面的程式碼輸出結果為">6"。

這是因為在表示式(a+b>6)中,變數a被宣告為無符號整型(unsigned int),而變數b被宣告為有符號整型(int)。當進行運算時,有符號整型會被自動轉換為無符號整型,這種轉換被稱為整型提升。

在這個例子中,變數b的值為-20,當它與無符號整型a相加時,會發生整型提升。整型提升將b的值轉換為一個大於等於0的無符號整數。

所以,(a+b)的結果為6 + (-20) = -14,但由於整型提升,它會被轉換為一個無符號整數。最終的比較表示式為(unsigned int)(-14) > 6,這個比較結果為假,即(a+b>6)為假。

根據條件運算子(三元運算子)的規則,如果條件為真,則執行冒號前的表示式,否則執行冒號後的表示式。在這個例子中,(a+b>6)為假,所以執行puts("<=6"),輸出結果為"<=6"。


三、程式設計題

1.給定字串,去除重複字母后重新輸出,如輸入s=”abcaadc” ,輸出s=”abcd” ,其中s長度小於等於10000 ;

/*
 * @Author: wvjnuhhail@128.com
 * @Date: 2024-11-05 20:47
 * @LastEditors: None
 * @LastEditTime: None
 * @FilePath: test.c
 * @Description: None
 * 
 * Copyright (c) 2024 by wvjnuhhail@126.com, All Rights Reserved. 
 */
#include <stdio.h>
#include <string.h>

void removeSameCharacter(char* s)
{
    int hash[256] = {0}; // 建立一個大小為256的雜湊表,用於儲存ASCII字元
    char result[10000 + 1]; // 結果字串,多出的一個字元用於儲存字串結束標誌'\0'
    int index = 0; // 結果字串的索引

    for(int i = 0; i < strlen(s); i++)
    {
        if(hash[s[i]] == 0)
        { // 如果字元沒有出現過
            hash[s[i]] = 1; // 標記字元已經出現過
            result[index++] = s[i]; // 將字元新增到結果字串中
        }
    }

    result[index] = '\0'; // 新增字串結束標誌

    strcpy(s, result); // 將結果字串複製回原字串
}

int main() 
{
    char str[10001] = "abbbcacacdc";
    removeSameCharacter(str);
    printf("%s\n", str);  // 輸出結果
    return 0;
}


2.編寫程式,區分當前執行裝置是大端還是小端

/*
 * @Author: wvjnuhhail@128.com
 * @Date: 2024-11-05 20:40
 * @LastEditors: None
 * @LastEditTime: None
 * @FilePath: test.c
 * @Description: None
 * 
 * Copyright (c) 2024 by wvjnuhhail@126.com, All Rights Reserved. 
 */
#include <stdio.h>

int main()
{
    unsigned int x = 0x76543210;
    char *c = (char *)&x;

    /*由於char*指標只能訪問地址中的一個位元組,因此*c將給出x的最低有效位元組。
    如果系統是小端(即最低有效位元組儲存在最小的地址),即*c將等於0x10。
    如果系統是大端(即最低有效位元組儲存在最大的地址),即*c將等於0x76*/

    /* 小端系統中,最低有效位元組位於最小的地址 */
    if (*c == 0x10)
    {
        printf("小端系統\n");
    }
    else
    {
        printf("大端系統\n");
    }

    return 0;
}


3.給定一份資料,長度為N ,資料範圍是0~ 10000 ,求資料的中位數。

/*
 * @Author: wvjnuhhail@128.com
 * @Date: 2024-11-05 20:21
 * @LastEditors: None
 * @LastEditTime: None
 * @FilePath: test.c
 * @Description: None
 * 
 * Copyright (c) 2024 by wvjnuhhail@126.com, All Rights Reserved. 
 */
#include <stdio.h>

/* 氣泡排序演算法 */
void bubbleSort(int *a, int n) 
{
    for (int i = 0; i < n - 1; i++) 
    {
        for (int j = 0; j < n - i - 1; j++) 
        {
            if (a[j] > a[j + 1]) 
            {
                // 交換相鄰的兩個元素
                int temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
}

/* 查詢中位數 */
int find_median(int *a, int n) 
{
    bubbleSort(a, n);  // 使用氣泡排序對陣列進行排序
    if (n % 2 == 0) 
    {
        return (a[n / 2 - 1] + a[n / 2]) / 2;
    } 
    else 
    {
        return a[n / 2];
    }
}

int main() 
{
    int data[] = {5, 3, 1, 4, 2};
    int n = sizeof(data) / sizeof(data[0]); //n為data陣列內資料的個數
    int median = find_median(data, n);      
    printf("中位數為:%d\n", median);
    return 0;
}