C語言上

雖然考研初試27號就結(jié)束了,現(xiàn)在已經(jīng)過去了三十多天,但是看了看我只看了七八十頁的計算機網(wǎng)絡(luò),感覺再浪下去要把自己腿皮斷了,開始復(fù)試的積極準(zhǔn)備階段吧。

1.31:

下載安裝codeblocks并實現(xiàn)調(diào)試使用(有一說一這個下載速度是真的sloooooooooooooooooow)
基本等于沒干什么事情吧,順手把巨人第一季下載了,這個倒是費了蠻大功夫的。

2.1:

今日重學(xué)了C語言(黃迪明 1`59 直到三目運算符)
下面是廢話筆記時間
編程四大階段:需求分析,設(shè)計開發(fā),編寫文檔,以及最后的維護(hù)。
算法:有輸入,有輸出,有窮性,確定性,高效性。
程序結(jié)構(gòu):順序,循環(huán),選擇,調(diào)用。
標(biāo)識符:只能由字母,下劃線和數(shù)字構(gòu)成,并且第一個字符只能是字母或者下劃線。
關(guān)鍵字統(tǒng)稱為保留字。

編輯(.c 類型文件)
編譯,編譯完成后生成.obj 類型文件
連接,連接完成后生成 exe 可執(zhí)行文件

沒有標(biāo)注的統(tǒng)一認(rèn)為是有符號數(shù) signed
float 四字節(jié) double 8字節(jié) long double 16字節(jié)(真稀奇啊)
char 一個字節(jié)

如果一個常量后面加上一個字母u或者U 表示無符號數(shù)常量,同樣如果加上的是一個l或者L,就表示是一個long型,都加同理。

.56以及96. 都是合理的浮點數(shù)表示方式
浮點數(shù)通常還可以使用指數(shù)的方式來表示,例如1E8,2.5E-6 但是要求E前后必須有數(shù)字的同時,指數(shù)部分只能為整數(shù)。

浮點常量默認(rèn)為double,如果加上f或者l 則具體變換即可。
至于浮點數(shù)在計算機內(nèi)的具體表示,由于涉及到二進(jìn)制整數(shù)位1的舍棄,所以比較復(fù)雜,教材這里并沒有詳細(xì)說明。

C語言編譯程序通常會在字符串的末尾自動加上 ‘\0’ 作為字符串的結(jié)束標(biāo)志。

連等賦值不被允許,形如int i=j=k=50;
自增運算符只能用于變量,不可運用于常量和表達(dá)式

int main()
{
    int  a=3;
    printf("%d\n",-a++);
    printf("%d\n", a);
}

自增運算符號存在著陷阱,如上代碼。首先由于++不可對表達(dá)式使用,那么只能是a++再取反,這時候由于++后綴的特性,輸出的值最終是-3 第二個輸出的a則是4
PS:此特性對C++同理

然后又是垃圾運算符優(yōu)先級時間,此處直接把隔壁C++的貼過來吧
后置++ --要比前置++ --優(yōu)先級要高一點,不過應(yīng)該不會考這種shit東西吧 (好在++i++是違法的)

  1. :: 和()
  2. [] . -> 后置++ 后置-- 類型轉(zhuǎn)換
  3. 前置++ ,前置--,大量一元邏輯運算符號(~)
  4. .* ->*
  5. 乘除取余
  6. 加減
  7. 左移右移
  8. 大于 小于 大于等于 小于等于
  9. 等于和不等于
  10. & ^ |(三者優(yōu)先級不等嗷 從高到底)
  11. && ||(同上不等
  12. 三元運算符號?: 它后面是一大堆賦值等號懶得寫了

值得一提的是 int a=b=c=50: 的確不合法,但是int a,b,c; a=b=c=50是合法的,前者的主要錯誤只是在于變量的定義和使用現(xiàn)后順序存在問題。

邏輯運算只在乎最后的結(jié)果是不是0 如果是0就是假 否則統(tǒng)一認(rèn)為是真并將結(jié)果作為1

運算順序總是十分復(fù)雜且難以記憶的,總結(jié)就是 優(yōu)先后++ -- 然后是前++ 前--
再然后是 乘除取余 然后加減 然后大小比較 然后等于不等于比較 再然后邏輯運算(其中位邏輯運算大于普通的邏輯運算 且最高的是~ 依次是& ^ | ),最后是賦值運算和其他的高級賦值運算。

補碼等于反碼+1
按位與 &
按位或 |
按位取反 ~
按位異或 ^

如果i與j進(jìn)行按位與,但是兩個數(shù)字的位數(shù)不同,i為long j為int,那么會在右端對齊的同時依據(jù)j的符號在左側(cè)補上合適的0或者1

異或 指的是 如果兩個位相同則為0 如果不同則為1
按位與將特定位置置為0 或則是置為1 異或則可以將特定位取反
因為與1異或 則一定會與原來的只相反 而與0異或則保持原數(shù)值不變

位邏輯運算符號針對二進(jìn)制位,其只可以運用在整型上,
此處指出位邏輯運算符號和邏輯運算符號的區(qū)別:

  1. 前者針對二進(jìn)制位,后者針對表達(dá)式,前者只可以運用在整形上,且需要計算具體數(shù)值,后者只需要判斷真假。
  2. 前者的兩個運算對象可以交換,后者由于運算的不完全性,一旦運算出確定結(jié)果就不會再向下運算,因此后者運算對象交換會可能會導(dǎo)致程序后續(xù)結(jié)果輸出不同。

2.2&&2.3:

兩天早上摸魚,統(tǒng)一睡到大天亮。
重修C語言之從60~86頁第二章測試題
這兩天摸魚比較嚴(yán)重 昨天抽空上了個黃金 今天看了半天大江大河 希望后面幾天能加把勁吧 我也是加把勁騎士了。

三目運算符號的運算順序為從右到左
P60的 例題2-2 是一個很好的例子 首先三目運算符號先算表達(dá)式1 然后才會考慮計算表達(dá)式2或表達(dá)式3 這將導(dǎo)致最后i的值不同,同時注意 i>=j>=k的運算結(jié)果。

神奇的逗號表達(dá)式 i=35,i2; 該語句i=15 但是整個表達(dá)式的值為30 即
j=(i=3 * 5,i * 2)的結(jié)果j=30,i=15;

float類型數(shù)據(jù),即使是兩個float類型數(shù)據(jù)相加,仍然都將其轉(zhuǎn)化為double類型進(jìn)行運算。
數(shù)據(jù)的自動類型轉(zhuǎn)換,其中是針對兩個操作數(shù)逐步逐步轉(zhuǎn)換的,而不是一次性統(tǒng)一轉(zhuǎn)換,也就是6.0/4+5.5 不等于 6/4+5.5 的原因。

三目運算符號 單目運算符以及賦值運算符都是從右到左,其中務(wù)必需要注意的就是三目運算符的運算方向。
可以確定運算方向是從左到右的三個運算符分別是|| && 和,
其可以舉一個非常的例子如下:

int main()
{
    int a,b,c;
    a=0;
    b=1;
    c=0;
    if(a++||b++&&c++)
    {
        printf("這個式子成立");
    }
    printf("%d,%d,%d",a,b,c);
}

以及

int main()
{
    int a,b,c;
    a=0;
    b=0;
    c=0;
    if(a++||b++&&c++)
    {
        printf("這個式子成立");
    }
    printf("%d,%d,%d",a,b,c);
}

我們可以明確的看到,如果三者全為0時,只會判斷a++和b++,但是b不為0時則會計算c++,我們可以知道c++是最后運算的,如果設(shè)置a=1,那么只有a的數(shù)值發(fā)生了變化,這是由于盡管||運算的優(yōu)先級沒有&&高,但是由于強制從左往右算,其式子等同于i++||(b++&&c++) ,這就是關(guān)鍵,程序依然會先判斷i++再考慮運算右側(cè)的內(nèi)容。

轉(zhuǎn)義字符中 \101 中這個101指的是八進(jìn)制
putchar() 函數(shù)輸出int 變量時會自動轉(zhuǎn)化為ascil碼

printf函數(shù)輸出樣式 %d %o(八進(jìn)制) %x(16進(jìn)制) %u(無符號十進(jìn)制)
%f (浮點數(shù) 自帶六位小數(shù)) %e (指數(shù)形式) %g (數(shù)值最小寬度)

修飾符號
l指的是長整型
m指定數(shù)據(jù)輸出的寬度(指的是域?qū)挘?br> .n 對實數(shù)型數(shù)據(jù)指定輸出n位小數(shù)或者輸出字符串的前n個字符
+表示輸出帶符號數(shù)
- 左對齊
意思也就是如果使用m 指定數(shù)據(jù)輸出的寬度,如果輸出寬度不足m 左邊補上空格,可以做到右側(cè)對齊的效果,左對齊用- 實現(xiàn)即可,其和C++ left right差不多,都需要注意如果一旦輸出實際數(shù)字大于指定長度,則無視指定長度。

%g的優(yōu)勢就在于合理的選擇%f還是%e,將輸出數(shù)值的長度做到最小,其中比較愚蠢的東西就是C++的float的精度并做不到完全的精確,正如234.896存儲的結(jié)果輸出是234.895996一樣,只是一個近似值而不是完全相等的確切值。

輸出格式之 %m.ns 如果n>m那么以n為準(zhǔn)確保n位正確輸出,同時m>n時同樣保證右對齊,并且左側(cè)用空格補齊。

%后面只有XSG可以不區(qū)分大小寫,我想這么細(xì)節(jié)的內(nèi)容應(yīng)該不會考吧。
如果時prinf內(nèi)有算式計算,通常是從右往左開始計算。
如果想要輸出% 需要連續(xù)使用兩個%
但是單雙引號則是 \' 和 \" 的方式來輸出

getchar() 我又想起來當(dāng)初被這個東西支配的恐懼 這個東西會將空格和回車作為標(biāo)準(zhǔn)輸入接受,反正非常讓人發(fā)指這個東西。

下面這個又是神經(jīng)病的東西,這本書講的實在是太細(xì)了,給大佬磕頭了。這個東西對空格的要求非常奇怪,就是scanf你填充空格的地方?jīng)]有空格不會出現(xiàn)異常,但是如果沒有填充空格的地方你輸入空格,就會炸。


注意

其次如果是浮點型數(shù)據(jù)輸入,是不可以使用m.nf的方式來控制輸入的,也就是你不可以指定小數(shù)點后位數(shù),但是可以通過僅使用m的方式確定小數(shù)的輸入整個長度,而不能控制其輸入的小數(shù)點長度。

%*4d 這個 * 用來忽視接下來的輸入,也就是這個輸入請求被屏蔽。

2.4:

今日完成C語言第二章課后習(xí)題
以及第三章部分內(nèi)容 總的來說看到了103頁
規(guī)范的指數(shù)形式要求 小數(shù)部分小數(shù)點前有且只有一位非零數(shù)字。
且指數(shù)形式中,指數(shù)部分只能是整數(shù),否則認(rèn)為不合法。

負(fù)數(shù)取余運算,這里涉及到一個沒講到的知識點,負(fù)數(shù)取余C語言的余數(shù)和被除數(shù)同號,這樣同樣也可以判斷負(fù)數(shù)除法的機制,其都是向0方向收縮。

三目運算符的優(yōu)先級大于賦值運算
無論是正負(fù)數(shù) 移位操作都等于直接乘除對應(yīng)的值。

scanf 讀入%md時 如果讀入的數(shù)據(jù)不足m 則直接忽視m的要求即可

2.5:

今日計劃C語言到150~160頁 順便回去看看一直沒看的計算機網(wǎng)絡(luò) 唉

以下代碼可以實現(xiàn)循環(huán)讀入,直到a為234為止跳出循環(huán)

void main ()
{
    int a=0;
    for(a=0;a!=234;)
    {
        scanf("%d",&a);
    }
}

九九乘法表很簡單 這里就不再贅述
下面是 十進(jìn)制轉(zhuǎn)化為2進(jìn)制

void main ()
{
   int a;
   scanf("%d",&a);
   printf("%x\n",a);
   for(int i=0;i<32;i++)
   {
       unsigned int temp=0; //務(wù)必記住 這里一定要設(shè)置為unsigned 數(shù) 
       //否則無法得到正確結(jié)果 因為負(fù)數(shù)移位編譯環(huán)境不同結(jié)果可能不同
       temp=a&0x80000000;
       printf("%1x",temp>>31);
       if(i%4==3)  //此處是為了每四位輸出一個空格方便校驗
       {
           printf(" ");
       }
       a<<=1;
       //printf(" %x\n",a);
   }
}

當(dāng)然了 采用標(biāo)準(zhǔn)的公式法也是可以的,但是需要遞歸。

void function(int a)
{
    int temp=a%2;
    a=a/2;
    if(a!=0)
    {
        function(a);
    }
    printf("%d",temp);
}
void main ()
{
   int a;
   scanf("%d",&a);
   printf("%x\n",a);
   if(a>=0)
   {
        function(a);
   }
   else{
    // 如果是負(fù)數(shù)有點麻煩 、
    // 需要數(shù)組 如果是c++我直接就寫上了 以后有空再寫吧
   }
}

%04x 表示不足4位用0填充
判斷是否在某一位包含特定數(shù)字的標(biāo)準(zhǔn)寫法

void main ()
{
    int a;
    scanf("%d",&a);
    printf("a=%d\n",a);
    for(int i=0;i<=100;i++)
    {
        int j=i;
        int flag1=1,flag2=1;
        while(flag1&&j>0)  //關(guān)鍵就在這里,%10判斷是否相等,不相等再/10 即可
        {
            if(j%10==a)
            {
                flag1=0;
                break;
            }
            j/=10;  
        }
        if(flag1==0)
        {
            j=i;
            j*=j;
            while(flag2&&j>0)
            {
                if(j%10==a)
                {
                    flag2=0;
                    break;
                }
                j/=10;
            }
        }
        if(flag2==0)
        {
            printf("%d, %d\n",i,i*i);
        }
    }
}

下運算為輸出十六進(jìn)制從右到左的第k位

void main ()
{
    int a;
    unsigned b;
    scanf("%d",&a);
    b=(unsigned)a;
    printf("%x\n",b);

    int k;
    scanf("%d",&k);
    b>>=4*(k-1);
    b=b&0xf;
    printf("%x",b);
}

continue語句 將推轉(zhuǎn)出循環(huán)結(jié)構(gòu),忽略continue后面的語句,直接下一次循環(huán),在while語句則之間進(jìn)去檢測控制表達(dá)式,而for語句則是直接跳轉(zhuǎn)語句3,然后進(jìn)行判斷

2.6:

顯然 2.5號的任務(wù)和自己的執(zhí)行力相比是不切實際的,不知道今天能不能補上2.5號的坑。

goto語句無法實現(xiàn)由循環(huán)外跳轉(zhuǎn)到循環(huán)內(nèi)的效果,此不合法。

輸出日歷例題

#include<stdio.h>
void main ()
{
   int year,one_month,one_day,xingqi;
   scanf("%d %d %d %d",&year,&one_month,&one_day,&xingqi);
   int flag=(year%4==0&&year%100!=0)||(year%400==0);

   int inputmonth;
   printf("---------------------\n");
   scanf("%d",&inputmonth);
   int start=1,end=0;
   int month[12]={31,28+flag,31,30,31,30,31,31,30,31,30,31};
   for(int i=0;i<inputmonth-1;i++)
   {
       start+=month[i];
   }
   for(int i=0;i<inputmonth;i++)
   {
       end+=month[i];
   }
   printf("%d,%d\n",start,end);
   for(int i=0;i<7;i++)
   {
       printf("    星期%d",i+1);
   }
   printf("\n");
   int start_day=(start+xingqi-1)%7;
   if(start_day==0)
   {
       start_day=7;
   }
   printf("%*d",(start_day)*9,1); //這個我想這本書沒有教過這個東西的用法,
   //實際上是(start_day)*9是 *的內(nèi)容 也就是后面兩個數(shù)據(jù)一個用來指定輸出寬度
   for(int i=2;i<=end-start+1;i++)
   {
        //
        printf("%9d",i);
        start_day++;
        if(start_day%7==0)
        {
            printf("\n");
        }
   }
}

實際效果:


實際效果

不使用原代碼的主要原因是原代碼實在是寫的太復(fù)雜。。。。。

圖書管理系統(tǒng)就不寫了,實在沒什么實現(xiàn)的難度,就不浪費自己時間了。

課后題3.7: 看成加減乘除了 那還是比較麻煩的,通常是用棧來做,但是畢竟不像C++可以直接stack懟臉,還要自己弄,只有加減法就很簡單了,如下(好像要求是浮點數(shù),算了就這樣吧

void main ()
{
    int sum1;
    char yunsuan;
    scanf("%d",&sum1);
    char oldyunsuan='#';
    while((yunsuan=getchar())!=';')
    {
        //只要運算符號不是;就繼續(xù)正常運算
        int sum2;
        scanf("%d",&sum2);
        //此處獲得兩個運算符號
        //printf("%d,%d",sum1,sum2);
        switch(yunsuan)
        {
        case '+':
            sum1+=sum2;
            break;
        case '-':
            sum1-=sum2;
            break;
        }

    }
    printf("%d",sum1);
}

3.8 (下次這種題目還是不寫了吧。。)

void main ()
{
   double a;
   scanf("%lf",&a);
   double sum=0;
   for(int i=0;i<=15;i++)
   {
       double sumtempfenmu=1;
       for(int j=1;j<=i;j++)
       {
           sumtempfenmu*=j;
       }
       sum+=pow(a,i)/sumtempfenmu;
   }
   printf("%f",sum);
}

質(zhì)數(shù) 畢竟早就忘了怎么分配動態(tài)數(shù)組了 大學(xué)到底學(xué)了個啥玩意
你是不是nt

#include<stdio.h>
void main ()
{
    //經(jīng)典判斷質(zhì)數(shù)
    //去年復(fù)試就腦癱了 1不是質(zhì)數(shù)哥哥
    int a[50];
    int count=0;
    for(int i=2;i<=100;i++)
    {
        if(count==0) //如果count=0顯然這個數(shù)一定是質(zhì)數(shù)
        {
            a[count++]=i;
        }
        else
        {
            int flag=1;
            for(int j=0;j<count;j++)
            {
                if(i%a[j]==0) //如果沒有余數(shù)一定不是質(zhì)數(shù)
                {
                    flag=0;
                    break;
                }
            }
            if(flag)
            {
                a[count++]=i;
            }
        }
    }
    for(int i=0;i<count;i++)
    {
        printf("%d\n",a[i]);
    }
}

3.17 移位操作 這題其實有點意思

我是用for循環(huán)做到每步移位的 看了一眼答案 其實可以一步到位

#include<stdio.h>
void main ()
{
    int i,j;
    scanf("%d %d",&i,&j);
    printf("%x,%d\n",i,j);
   //為了簡單起見我們統(tǒng)一認(rèn)為i是無符號數(shù) 否則何來循環(huán)移位這一說
    unsigned int temp=i;
   if(j>0) //將i徐娜換左移
   {
        for(int z=0;z<j;z++) //左移n位
        {
            unsigned int single=temp&0x80000000;
            single>>=31;
            temp<<=1;
            temp=temp|single;
        }
   }
   else //循環(huán)右移
   {
        for(int z=0;z<j;z++)
        {
            unsigned int single=temp&0x00000001;
            single<<=31;
            temp>>=1;
            temp=temp|single;
        }
   }
   printf("%x",temp);
}

如果不采用循環(huán)則使用下列格式即可

#include<stdio.h>
void main ()
{
    int i,j;
    scanf("%d %d",&i,&j);
    printf("%x,%d\n",i,j);
   //為了簡單起見我們統(tǒng)一認(rèn)為i是無符號數(shù) 否則何來循環(huán)移位這一說
    unsigned int temp=i;
   if(j>0) //將i徐娜換左移
   {
       //如果循環(huán)左移 那么就需要截取最右側(cè)的j位
       //最簡單的辦法就是將這個東西右移32-j位
       unsigned temp2=temp>>(32-j);
       temp<<=j;
       temp=temp|temp2;
   }
   else //循環(huán)右移
   {
        j=-j; //先調(diào)整為個正數(shù)
        unsigned temp2=temp<<(32-j);
        temp>>=j;
        temp=temp|temp2;
   }
   printf("%x",temp);
}

第三章完結(jié)。

2.6日總結(jié):

今日完成了第三章的復(fù)習(xí)132頁 課后題答案在51頁到66頁 進(jìn)度還是差很多 明天要出去,帶本計網(wǎng)看看吧,電腦就不帶了。

2.9:

C語言 黃(153頁)
靜態(tài)數(shù)組定義,在定義大小時,大小必須是一個常量表達(dá)式,也就是一個整形常量(實際上codeblocks 可以支持非常量實現(xiàn) vs則不可以)

也就是下面這個東西,本質(zhì)上時不符合C++/C規(guī)范的,但是部分編譯器也可以正確運行。

int p;
scanf("%d",&p);
int a[p];

如果初始化數(shù)組變量時省略數(shù)組大小,則自動默認(rèn)設(shè)置為初始化變量的個數(shù)。

二維數(shù)組,在全部賦值的情況下,可以省略第一維的定義長度,但是不可以省略第二維的定義長度。

要注意的是,看似這兩種賦值方法是等價的,但實際上組成的數(shù)組長度是不同的,并且后者如果沒有留出給 '\n' 的空間,還會導(dǎo)致編譯錯誤。


image.png

這里要指出的是codeblocks 所用的mingv編譯器非常的包容,大概娘化了也肯定是個大姐姐,即使你第二種方法越界了,也不會報編譯錯誤,但是vs則不行,大概是個銼刀吧。

C語言的scanf讀入字符串時不能包入類似分隔符和回車符的空白符號。
但是gets則可以成功的讀入空格字符,在遇到換行符時則會停止讀入。

除此之外,使用gets 或者 scanf中的%s讀入字符串時,不需要使用取地址符號,因為數(shù)組名本身就代表了數(shù)組首地址。

對于printf采用%s格式輸出時,則一旦遇到\0符號即立刻停止輸出,不論\0之后是否還有有意義內(nèi)容,而puts則會將字符串結(jié)束標(biāo)記的\0轉(zhuǎn)換為\n,實現(xiàn)自動換行。

接下來是大家并不喜聞樂見的字符串處理函數(shù):

  1. 字符串長度測量函數(shù) strlen
    使用方法為 strlen(字符數(shù)組名)
  2. 字符串復(fù)制函數(shù) strcpy
    即將字符串2的所有字符一個一個復(fù)制到字符數(shù)組1中,直到遇到結(jié)束標(biāo)志“\0”為止,并且同時也寫入結(jié)束標(biāo)志。
    strcpy(A,B) 其會將B的內(nèi)容復(fù)制到A中,

然后是常見錯誤:
word1=word2 編譯錯誤。

strncpy 可將字符串2的前n個字符復(fù)制到字符串1中。
strncpy(字符串1,字符串2,復(fù)制的字符個數(shù));

字符串連接函數(shù) strcat
strcat(數(shù)組一,數(shù)組二) 即取消第一個字符數(shù)組中的字符串的結(jié)束標(biāo)志 “\0”,把第二個字符串拼接到第一個字符串后面,并且把拼接的結(jié)果存放到第一個字符數(shù)組中。也就是整個過程中,第二個數(shù)組不會發(fā)生變化,而第一個則會成為拼接結(jié)果。

字符串比較函數(shù) strcmp
這個東西會將第一個字符串和第二個字符串進(jìn)行大小的比較:
如果兩個字符串相等,則返回0
如果1大于2,則返回一個正整數(shù)
如果1小于2,則返回一個負(fù)整數(shù)

strstr 用來查找一中是否有2的子串
strchr 用來查找一中是否有2這個字符
二者一旦查找到結(jié)果,返回第一個匹配對象以及其之后的所有字符。

atof atoi 將字符串轉(zhuǎn)化為浮點數(shù)和整數(shù)
itoa 將值轉(zhuǎn)化為字符串 特指整型
其有三個參數(shù) 第一個為轉(zhuǎn)化的整形數(shù)字,第二個為字符數(shù)組名,第三個參數(shù)為進(jìn)制。

2.12:

字符串電報轉(zhuǎn)換

#include<stdio.h>
#include<string.h>
void main ()
{
    char worinige[100];
    gets(worinige);
    puts(worinige);
    for(int i=0;i<strlen(worinige);i++)
    {
        if(worinige[i]>='A'&&worinige[i]<='Z')
        {
            //?′?a′óD′×???
            worinige[i]=(worinige[i]-'A'+27)*3%52;
        }
        else if(worinige[i]<='z'&&worinige[i]>='a')
        {
            worinige[i]=(worinige[i]-'a'+1)*3%52;
        }
    }
    for(int i=0;i<strlen(worinige);i++)
    {
        if(worinige[i]<=26)
        {
            worinige[i]=worinige[i]-1+'a';
        }
        else
        {
            worinige[i]=worinige[i]-27+'A';
        }
    }
    puts(worinige);
}

定義數(shù)組時直接定義變量,并為變量分配了相應(yīng)的內(nèi)存空間,定義結(jié)構(gòu)體則類似于定義一個模板。

無法直接用scanf和printf輸出結(jié)構(gòu)體變量,但是可以相互之間用等號賦值。

務(wù)必要知道的是,如果結(jié)構(gòu)體內(nèi)有字符數(shù)組變量,那么scanf時不需要加上&,這點務(wù)須注意。

結(jié)構(gòu)體的初始化:

void main ()
{
   struct wori{
    int x;
    int y;
    }ppp={10,20};
    printf("%d",ppp.x);
}

結(jié)構(gòu)體是可以在函數(shù)體內(nèi)定義的,并不是一定要定義成全局的。

使用哨兵標(biāo)記法,可以免去查找過程中每一步都要檢測數(shù)組是否越界的問題。
也就是設(shè)置A[0]為x,從后往前依次判斷即可。

void main ()
{
   int a[10];
   for(int i=1;i<10;i++)
   {
       scanf("%d",&a[i]);
   }
   int x;
   scanf("%d",&x);
   a[0]=x;
   int i;
   for(i=9;a[i]!=x;i--);
   printf("%d",i);
}

折半查找 折半查找的注意之點在于while循環(huán)中判斷l(xiāng)eft和right大小時,二者應(yīng)當(dāng)是小于等于的關(guān)系。

#include<stdio.h>
#include<string.h>


void main ()
{
   int a[10];
   for(int i=0;i<10;i++)
   {
       scanf("%d",&a[i]);
   }
   int x;
   scanf("%d",&x);
   printf("-----------------------------------------\n");
   int left=0,right=9;
   int mid=(left+right)/2;
   while(left<=right)
   {
        mid=(left+right)/2;
    //    printf("%d",a[mid]);
        if(a[mid]<x)
        {
            left=mid+1;
        }
        else if(a[mid]>x)
        {
            right=mid-1;
        }
        else
        {
            printf("%d is the %d number",x,mid);
            break;
        }
   }
}

直接插入排序
說實話我都忘記了這個東西怎么弄了

#include<stdio.h>
#include<string.h>


void main ()
{
   int a[10];
   for(int i=0;i<10;i++)
   {
       scanf("%d",&a[i]);
   }
   printf("-----------------------------------------\n");

   for(int i=1;i<10;i++)
   {
       int temp=a[i];
       int j;
       //這個東西用來記錄當(dāng)前的值,因為一旦移位就會改變a[i]的值
       for(j=i-1;j>=0;j--)
       {
           if(temp<a[j]) //如果當(dāng)前值較小
           {
               a[j+1]=a[j];
           }
           else
           {
               break;
           }
       }
       //for循環(huán)停止后, 即表明temp大于當(dāng)前的a[j],那么temp適合的位置就是j+1
       a[j+1]=temp;
   }
   printf("\n");
   for(int i=0;i<10;i++)
   {
       printf("%d ",a[i]);
   }
   printf("\n");
}

這里有一個問題,其實就是哨兵問題,如果設(shè)置哨兵,那么a[0]就代替了temp的位置并且同時控制了for循環(huán)的結(jié)束,因為我比較反感數(shù)組不從0開始這個事情,就不寫了。

printf() 中%* 用來動態(tài)指定輸出寬度
scanf() 中%* 用來省略接下來的輸入
strstr函數(shù)

void main ()
{
    char sp[50];
    char pp[21];
    gets(sp);
    gets(pp);
    puts(sp);;
    puts(pp);
    printf("%s",strstr(sp,pp)); //如果不匹配,則會返回null
}

strstr 字符串匹配
strctr 字符匹配
strcmp 字符比較
strcpy 字符復(fù)制
strncpy 字符前n位復(fù)制
strcat 字符拼接

字符串比較和賦值
當(dāng)然了 這個賦值是不必要的,完全可以用結(jié)構(gòu)體的等號直接賦值。

#include<stdio.h>
#include<string.h>

typedef struct student
{
    char name[21];
}student;
void main()
{
    student sts[10];
    for(int i=0;i<10;i++)
    {
        char temp[21];
        scanf("%s",temp);
        int j;
        for(j=i-1;j>=0;j--)
        {
            if(strcmp(temp,sts[j].name)<0)
            {
                strcpy(sts[j+1].name,sts[j].name);
            }
            else
            {
                break; //直接插入排序 務(wù)必不要忘記這個break;
            }
        }
        strcpy(sts[j+1].name,temp);
        for(int p=0;p<=i;p++)
        {
            puts(sts[p].name);
        }
        puts("-----------------------");
    }
}

2.13:

第四章習(xí)題:
4.2: 開燈

#include<stdio.h>
#include<string.h>
void main()
{
    int a;
    scanf("%d",&a); //輸入a=10;
    //因為數(shù)組大小必須設(shè)置為常量,C++還是寫成 int* p=new int[num];
    //這樣比較好,但是C語言這樣寫是不行的,所以這里暫時就不寫動態(tài)構(gòu)造數(shù)組了。
    int shuzu[10+1]={0};
    for(int i=1;i<=a;i++)
    {
        for(int j=1;j<=a;j++)
        {
            if(i>=j&&i%j==0)
            {
               shuzu[i]++;
            }
        }
        if(shuzu[i]%2==1)
        {
            printf("the %d light is open\n",i);
        }
    }
}

4.3:簡單選擇排序

#include<stdio.h>
#include<string.h>
void main()
{
    //簡單選擇排序
    int a[10];
    for(int i=0;i<10;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=0;i<10;i++)
    {
        int max=a[0];
        int x=0;
        for(int j=0;j<10-i;j++)
        {
            if(max<a[j])
            {
                max=a[j];
                x=j;
            }
        }
        int temp;
        temp=a[10-i-1];
        a[10-i-1]=max;
        a[x]=temp;
    }
    for(int i=0;i<10;i++)
    {
        printf("%d ",a[i]);
    }
}

4.4: n階幻方

#include<stdio.h>
#include<string.h>
typedef struct point
{
    int x;
    int y;
}point;
void main()
{
    //4.4 幻方
    //這里在這里我們設(shè)置為5 還是那個沒有教動態(tài)設(shè)置數(shù)組的問題
    int a[7][7]={0};
    //我們設(shè)置為7 答案設(shè)置為5 我們設(shè)置的大一點
    int n=7;
    point start;
    start.x=0;
    start.y=(0+n-1)/2;
    int now=1;
    while(now<=n*n)
    {

        a[start.x][start.y]=now;
        now++;
        //正常情況下x 應(yīng)該-- y應(yīng)當(dāng)++ 這樣才會往右上角移動
        if(start.x==0&&start.y!=n-1)
        {
            //這表示這個點向上越界
            start.x=n-1;
            start.y++;
        }
        else if(start.y==n-1&&start.x!=0) //右側(cè)越界
        {
            start.x--;
            start.y=0;
        }
        else if(start.x==0&&start.y==n-1)
        {
            start.x++;
        }
        else
        {
            printf("%d %d %d\n",start.x,start.y,now);
            if(a[start.x-1][start.y+1]==0) //如果這個點沒有數(shù)
            {
                start.x--;
                start.y++;
            }
            else
            {
                start.x++;
            }
        }
        for(int i=0;i<=n-1;i++)
        {
            for(int j=0;j<=n-1;j++)
            {
                printf("%4d",a[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    for(int i=0;i<=n-1;i++)
    {
        for(int j=0;j<=n-1;j++)
        {
            printf("%4d",a[i][j]);
        }
        printf("\n");
    }
}

4.5:
這題比較簡單,就不寫了 要注意的是strlen是不會把\n計算到字符串長度中的,這點還是要注意一下
4.6:
識別空格問題,判斷單詞個數(shù)的問題
這個東西判斷的要領(lǐng)就是只要是由空格變?yōu)榉强崭?就算作一個單詞
答案的寫法我看了半天,大概是統(tǒng)計新空格的個數(shù),他認(rèn)為每個單詞后面都有一個空格,所以要判斷最后的字符是不是空格。

#include<stdio.h>
#include<string.h>

void main()
{
    char strings[1000];
    gets(strings);
    int lengths=strlen(strings);
    int flag=1;
    int count=0;
    int i=0;
    //我覺得一開始想的太復(fù)雜了
    //我覺得設(shè)置flag 只需要統(tǒng)計flag從1變成0的次數(shù)就可以了
    while(i<lengths)
    {
        if(strings[i]==' ')  //flag=1變化為0 時計算一個字符 且初值設(shè)為1 可以防止開頭有空格或者沒空格的情況
        {
            flag=1;
        }
        else
        {
            if(flag==1)
            {
                count++;
                flag=0;
            }
        }
        i++;
        //如果結(jié)尾有空格 由于flag只會從1變化為0 但是變化不回1 所以不會計數(shù)
    }
    printf("%d",count);
}
測試用例

三點共線:

#include<stdio.h>
#include<string.h>
#include<math.h>
typedef struct point{
    double x;
    double y;
}point;
int equal(double x,double y)
{
    if(fabs(x-y)<1e-7)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
void main()
{
   //學(xué)生管理系統(tǒng)我們就不寫了
   point point1,point2,point3;
   scanf("%lf%lf%lf%lf%lf%lf",&point1.x,&point1.y,&point2.x,&point2.y,&point3.x,&point3.y);
   double length;
   length=sqrt(pow((point1.x-point2.x),2)+pow((point1.y-point2.y),2));
   printf("the length is %f\n",length);
   if(equal(point1.x,point2.x))
   {
       //如果前兩個點豎向共線
       //那么就不存在k值,所以就需要判斷是否三點共線
       if(equal(point2.x,point3.x))
       {
           printf("a line and shuline\n");
       }
       else
       {
           printf("no a line\n");
       }
   }
   else{
        double k=(point1.y-point2.y)/(point1.x-point2.x);
        double b=point1.y-k*point1.x;
        double temp=point3.x*k+b;
        printf("%f %f\n",k,b);
        if(equal(temp,point3.y))
        {
            printf("a line\n");
        }
        else
        {
            printf("no a line\n");
        }
   }
}

4.10 分子彈問題
要注意分發(fā)子彈問題要同步發(fā)放。
這個我是用數(shù)組來額外存儲空間的,但是同樣可以只用一個int來代替這個數(shù)組。

void main()
{
   int a[10]={10,2,8,22,16,4,10,6,14,20};
   int flag=0;
   int count=0;
   while(flag==0)
   {
       int temp[10];
       for(int i=0;i<10;i++)
       {
           temp[i]=a[i];
       }
       for(int i=0;i<10;i++)
       {
           if(temp[i]%2==1)
           {
               temp[i]++;
           }
       }
       for(int i=0;i<10;i++)
       {
           a[i]=temp[i]/2+temp[(i+1)%10]/2;
       }
       count++;
       flag=1;
       for(int i=0;i<10;i++)
       {
           if(a[i]!=a[(i+1)%10])
           {
               flag=0;
           }
       }
       for(int i=0;i<10;i++)
       {
           printf("%4d",a[i]);
       }
        printf("\n");
   }
   printf("分發(fā)次數(shù)為%4d\n",count);
}

如果使用int來代替數(shù)組,則需要反向思維,從后往前考慮(從前往后則無法實現(xiàn)),從后往前則不需要記錄這個數(shù)組的內(nèi)容,代碼如下:

void main()
{
   int a[10]={10,2,8,22,16,4,10,6,14,20};
   int flag=0;
   int count=0;
   while(flag==0)
   {
       int temp;
       for(int i=0;i<10;i++)
       {
           if(a[i]%2==1)
           {
               a[i]++;
           }
       }
       //首先重置為偶數(shù)才行
       temp=a[9];
       for(int i=9;i>0;i--)
       {
           a[i]=a[i]/2+a[i-1]/2;
       }
       a[0]=a[0]/2+temp/2;
       flag=1;
       count++;
       for(int i=0;i<10;i++)
       {
           if(a[i]!=a[(i+1)%10])
           {
               flag=0;
           }
       }
       for(int i=0;i<10;i++)
       {
           printf("%4d",a[i]);
       }
        printf("\n");
   }
   printf("the count is %4d\n",count);
}

4.11 保齡球問題:
實在不是很能理解這個題目和答案的關(guān)系,我個人傾向于原題是這么個邏輯:
(1) 若某一輪的第一次滾球就擊倒全部十個柱,則本輪不再滾球。(若是第十輪則還需另加兩次滾球)。該輪得分為本次倒柱數(shù) 10 與以后兩次滾球所擊倒柱數(shù)之和。
(2) 若某一輪的第一次滾球未擊倒十個柱,則可對剩下未倒的柱再滾球一次。如果這兩次滾球擊倒全部十個柱,則本輪不再滾球(若是第十輪則還需另加一次滾球),該輪得分為本次倒柱數(shù)10與以后一次滾球所擊倒柱數(shù)之和。
(3) 若某一輪的兩次滾球未擊倒全部十個柱,則本輪不再繼續(xù)滾球,該輪得分為這兩次滾球擊倒的柱數(shù)這和。
總之,若一輪中一次滾球或兩次滾球擊倒十個柱,則本輪得分是本輪首次滾球開始的連續(xù)三次滾球擊倒柱數(shù)之和(其中有一次或兩次不是本輪滾球)。若一輪內(nèi)二次滾球擊倒柱數(shù)不足十個,則本輪得分即為這兩次擊倒柱數(shù)之和。

#include<stdio.h>
#include<string.h>
#include<math.h>

int fequal(double x,double y)
{
    if(fabs(x-y)<1e-7)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void main()
{
    int score[10]={0};
    int state1=0,state2=0,state=0;
    int nowscore=0;
    for(int i=0;i<10;i++)
    {
        printf("------------this is the %d round-----------\n",i);
        scanf("%d",&nowscore);
        score[i]=nowscore;
        if(state1==2&&state2==2) //如果兩個好球 那么就需要加上第三輪的第一個球
        {
            score[i-2]+=nowscore;
        }
        if(state2==2||state2==1) //第二輪球無論是什么 都要加上這個球
        {
            score[i-1]+=nowscore;
        }
        if(nowscore==10)
        {
            state=2;
        }
        else
        {
            scanf("%d",&nowscore);
            score[i]+=nowscore;
            if(score[i]==10)
            {
                state=1;
            }
            else{
                state=0;
            }
            if(state2==2) //上一輪是一個好球,那么就要加上這一輪的兩個球
            {
                score[i-1]+=nowscore;
            }
        }
        state1=state2;
        state2=state;

    }
    //前面九輪都得以處理 但是因為第十輪有點問題
    if(state2==1) //這個表示第十輪為成功
    {
        scanf("%d",&nowscore);
        score[9]=score[9]+nowscore;
    }
    else if(state2==2) //這個表示第十輪為好球 獎勵兩個球
    {
        scanf("%d",&nowscore);
        score[9]+=nowscore;
        if(state1==2) //這個表示第九輪也是好球
        {
            score[8]+=nowscore;
        }
        scanf("%d",&nowscore);
        score[9]+=nowscore;
    }
    int total=0;
    printf("---------------------------\n");
    for(int j=0;j<10;j++)
    {
        printf("%d\n",score[j]);
        total+=score[j];
    }
    printf("%d",total);
}

搞明白了也不是很復(fù)雜,就這么大點事情。

4.12: 素數(shù)差問題,問題不大過程搞得很復(fù)雜,實在沒必要
這本書的課后題目多多少少有點問題,大概都是外國教材翻譯過來的,這個翻譯水平多多少少有點拉。

void main()
{
    int a[2000];
    int count=0;
    a[0]=2;
    count=1;
    for(int i=3;i<2000;i++)
    {
        int flag=1;
        for(int j=0;j<count;j++)
        {
            if(i%a[j]==0) //如果沒有余數(shù) 就表明不是素數(shù)
            {
                flag=0;
            }
        }
        if(flag==1)
        {
            a[count]=i;
            count++;
        }
    }
    int bushu[2000];
    for(int i=0;i<count-1;i++)
    {
        bushu[i]=a[i+1]-a[i];
    }
    for(int i=0;i<count-1;i++)
    {
        printf("%6d",bushu[i]);
        if(i%10==0)
        {
            printf("\n");
        }
    }
    printf("\n");
    for(int i=0;i<count-1;i++)
    {
        int sum=0;
        for(int j=i;j<count-1;j++)
        {
            sum+=bushu[j];
            if(sum==1898)
            {
                printf("start is %d and the end is %d\n",a[i],a[j+1]);
            }
        }
    }
}

第五章:
指針變量的類型指的是指針變量指向的變量的類型,而不是自身的類型。
既然教材里提到 常量指針 我就提一下
const int* p
int* const p
兩個區(qū)別,第一個是表明*p是常量 也就是p指向的內(nèi)容是一個常量不可改變,但是p可以指向另外一個常量
第二個是表明p是常量,也就是p自身的內(nèi)容不可改變,比如p指向了整形a,那么p就不可以再指向別人,但是a的值可以被修改。

p++ 結(jié)合順序由于++ 和 同優(yōu)先級,并且從右往左,所以原式等于(p++)
如果是v=
p++ 那么由于p先執(zhí)行++運算 但是并不立刻改變p的值,所以實際上v得到的是p指針指向的變量的值。

而v=++p 則先進(jìn)行++p 再進(jìn)行運算,所以將p下一個地址的變量值賦值給v

指針相減運算,兩個指向相同數(shù)據(jù)類型的指針相減,差表示兩個指針?biāo)赶虻臄?shù)據(jù)元素之間所相差的元素個數(shù)。
這點可能難以理解,以下實例可以證明:

實例

即兩指針的差會自動除以當(dāng)前變量類型的長度。
設(shè)置int* p=a; //a為數(shù)組名
p[1]和a[1]是合法且等價的。

2.15:

指針這里有很多問題,當(dāng)年學(xué)的時候就沒太搞明白
假設(shè)二維數(shù)組a[3][4] 那么p=a 等價于p=a[0] 等價于p=&a[0][0]
但是有些東西就很奇葩了,比如說p=&a p=&a[0]的 雖然p的值都完全相同,但是其意義則完全不同。

同時要注意的是,定義多維數(shù)組,如果定義數(shù)組的同時初始化,最高位可以省略讓編譯器自動填充,但是后面的位數(shù)則不能省略。

int a[][3]={1,2,3,4,5,6,8,9,10,11,12}; //這樣是合法的

這里似乎不同編譯器執(zhí)行的結(jié)果完全不同,實際上

int a[][3]={1,2,3,4,5,6,8,9,10,11,12};
    int *p1,*p2,*p3,*p4,*p5;
    p1=a;
    p2=a[0];
    p3=&a[0][0];
    p4=&a;
    p5=&a[0];
    printf("%d,%d,%d,%d,%d\n",p1,p2,p3,p4,p5);
    printf("%d,%d,%d,%d,%d\n",p1+1,p2+1,p3+1,p4+1,p5+1);

在mingw里面運行是沒什么問題的,但是VS是不能運行的,因為指針賦值類型不同,
按照當(dāng)前的C標(biāo)準(zhǔn),這個程序最標(biāo)準(zhǔn)的寫法應(yīng)該是這樣的

    int a[][3] = { 1,2,3,4,5,6,8,9,10,11,12 };
    int (*p1)[3];
    int* p2;
    int* p3;
    int (*p4)[4][3] ;
    int (*p5)[3];
    p1 = a; //實際上 a等于&a[0] a等于數(shù)組第一個元素的地址
    p5 = &a[0];
    p2 = a[0]; //a[0]等價于 &a[0][0]
    p3 = &a[0][0];
    p4 = &a;
    printf("%d,%d,%d,%d,%d\n", p1, p2, p3, p4, p5);
    printf("%d,%d,%d,%d,%d\n", p1 + 1, p2 + 1, p3 + 1, p4 + 1, p5 + 1);

也就是實際上 a等價于&a[0] a[0]等價于&a[0][0]

如果p是一個結(jié)構(gòu)體指針,那么調(diào)用結(jié)構(gòu)體內(nèi)變量應(yīng)該使用 (p).data
因為 . 的運算優(yōu)先級要高于
因此必須要用括號括起來。
如果使用 -> 運算符,就完全可以不用考慮這個括號問題

然后是檢測字符串指針內(nèi)容
while(*p) 只有指向內(nèi)容是\0時才會判斷為假,否則都為真。

2.16:

例題5-10 合并字符串

void main()
{
    //合并字符串
    char a[30],b[30];
    scanf("%s %s",a,b);
    printf("%s\n%s\n",a,b);
    char *pa,*pb;
    pa=a;
    pb=b;
    while(*pa)
    {
        pa++;
    }
    while(*pb)
    {
        *pa++=*pb++;
    }
    *pa='\0';
    printf("%s\n%s\n",a,b);
}

字符串排序 先用冒泡塞了一遍,又用直插塞了回去,大概就是這么個過程吧。

#include<stdio.h>
#include<string.h>
#include<math.h>
void main()
{
    char p[10][15];
    for(int i=0;i<10;i++)
    {
        scanf("%s",p[i]);
    }
    printf("----------------------------- ---------------------------------\n");
    for(int i=0;i<10;i++)
    {
        printf("%15s",p[i]);
    }
    printf("\n----------------------------- ---------------------------------\n");
    for(int i=0;i<9;i++)
    {
        int flag=0;
        //首先是冒泡排序
        for(int j=0;j<10-1-i;j++)
        {
            if(strcmp(p[j],p[j+1])>0)
            {
                char temp[15];
                strcpy(temp,p[j]);
                strcpy(p[j],p[j+1]);
                strcpy(p[j+1],temp);
                flag=1;
            }
        }
        if(flag==0)
        {
            break;
        }
    }
    for(int i=0;i<10;i++)
    {
        printf("%15s",p[i]);
    }
    printf("\n----------------------------- ---------------------------------\n");
    for(int i=1;i<10;i++)
    {
        char temp[15];
        strcpy(temp,p[i]);
        int j;
        for(j=i-1;j>=0;j--)
        {
            if(strcmp(p[j],temp)<0)
            {
                strcpy(p[j+1],p[j]);
            }
            else
            {
                break;
            }
        }
         strcpy(p[j+1],temp);
    }
     for(int i=0;i<10;i++)
    {
        printf("%15s",p[i]);
    }
    printf("\n----------------------------- ---------------------------------\n");
}

簡單選擇排序本身最大的優(yōu)勢就是較少的交換次數(shù),但是本書為了減少額外的一個存儲空間,大大加大了交換次數(shù),實在是.....一言難盡。

刪除字符串1中包含的字符串2的字符

#include<stdio.h>
#include<string.h>
#include<math.h>
void main()
{
    char a[30],b[30];
    char *p,*q;
    p=a;
    q=b;
    gets(a);
    gets(b);
    int deletenum=0;
    for(p=a;*p!='\0';p++)
    {
        for(q=b;*q!='\0';q++)
        {
            if(*p!=*q)
            {
                printf("-%c %c-\n",*p,*q);
                //如果兩者不相等
                *(p-deletenum)=*p;
            }
            else
            {
                deletenum++;
                break;
            }
        }
    }
    *(p-deletenum)='\0';
    printf("\n%s",a);
}

下面是簡化版本

#include<stdio.h>
#include<string.h>
#include<math.h>
void main()
{
    char a[30],b[30];
    char *p,*q;
    p=a;
    q=b;
    gets(a);
    gets(b);
    int deletenum=0;

    for(p=a;*p!='\0';p++)
    {
        int flag=0;
        for(q=b;*q!='\0';q++)
        {
            if(*p==*q)
            {
                deletenum++;
                flag=1;
                break;
            }
        }
        if(flag==0)
        {
            *(p-deletenum)=*p;
        }
    }
    *(p-deletenum)='\0';
    printf("\n%s",a);
}

第五章習(xí)題
5.2

void main()
{
    char *point[5]={
        "first",
        "second",
        "third",
        "forth"
    };
    while(*point[2])
    {
        printf("%c",*point[2]++); //這里先執(zhí)行[] 再執(zhí)行++ 再執(zhí)行*
        //因此這個式子等于取數(shù)組內(nèi)的地址,輸出值,然后將數(shù)組內(nèi)地址執(zhí)行”+1“操作
    }
}

5.4

void main()
{
    int data[12]={12,34,56,12,34,56,3,54,6,7,89,12};
    int sum=0;
    int* p=data;
    for(int i=0;i<12;i++)
    {
        sum+=*p++;
    }
    printf("%d",sum);
}

檢測字符串2在字符串1中出現(xiàn)的位置和次數(shù)
其實沒答案里面寫的那么復(fù)雜,這樣就好。

#include<stdio.h>
#include<string.h>
#include<math.h>
void main()
{
    char string1[100];
    char string2[100];
    gets(string1);
    gets(string2);
    char* p1=string1, *p2=string2;
    char* pfind=NULL;
    char* temp=p1;
    int length=strlen(p2);
    int place[100];
    int count=0;
    while(pfind=strstr(temp,p2))
    {
        place[count]=strlen(p1)-strlen(pfind);
        count++;
        temp=pfind+strlen(p2);
    }
    printf("string1 has %d string2\n",count);
    for(int i=0;i<count;i++)
    {
        printf("the %d place is %d\n",i+1,place[i]);
    }
}

比較兩個字符串是否相等
額 你直接strcmp不就好了嗎
我不寫了,有C庫函數(shù),真沒必要一個一個字符比較。

第六章:
函數(shù)不允許嵌套定義
但是可以嵌套調(diào)用,這是很淺顯的道理。

main函數(shù)雖然說不可以被其他函數(shù)調(diào)用,但是main函數(shù)本身實際上是可以調(diào)用main函數(shù)自身的。

如何省略函數(shù)原型:

  1. 如果被調(diào)函數(shù)的返回值是整形或者是字符型,不必考慮被調(diào)函數(shù)的位置,
  2. 如果被調(diào)函數(shù)的定義出現(xiàn)在主調(diào)函數(shù)之前
  3. 提前說明

C99標(biāo)準(zhǔn)的確可以實現(xiàn)第一條,但是C++ 11之后的標(biāo)準(zhǔn)則不可
同時第一條 如果是char類型作為函數(shù)的返回值,依然編譯錯誤

C語言 如果實參數(shù)量和形參不匹配,編譯不會報錯
不過這上面的東西都是一些陳芝麻爛谷子地事情,所以我覺得弄不弄清楚都差不多,反正現(xiàn)在也沒人會這樣寫。

然后參數(shù)調(diào)用時參數(shù)運行的順序也是沒有規(guī)定的,大部分編譯器統(tǒng)一從右往左算,而最離譜的a++ 以及 ++a 這種東西
++a 這種東西 是算完后,等到最后會從內(nèi)存里面取數(shù),而a++則是直接將a的運算結(jié)果導(dǎo)入,啊,實際上討論這個東西實在是沒什么意義。

 int a=10;
 printf("%d %d %d %d",a++,++a,a,a++);

在mingw 和 vs 中輸出的值都為 12 13 13 10
而書上的例子并沒有實際意義

2.17:

將數(shù)組名稱作為參數(shù)傳遞時,其傳遞的是數(shù)組的頭地址,而不是整個數(shù)組的值傳遞。

數(shù)組名作為函數(shù)參數(shù)時:

  1. 形參數(shù)組和實參數(shù)組的類型必須一致,
  2. 形參數(shù)組和實參數(shù)組的長度可以不相同,因為在調(diào)用時,只傳送首地址而不檢查形參數(shù)組的長度。
  3. 因此在函數(shù)形參表中,可以不給出形參數(shù)組的長度。

傳遞二維/高維數(shù)組時,可以省略第一維的長度。
函數(shù)指針
int (*p)(int a,int b)
唯一需要注意的就是函數(shù)指針這個括號

漢諾塔遞歸問題

#include<stdio.h>
#include<stdlib.h>
void HNT(int m,char start,char mid,char end)
{
    if(m==1)
    {
        printf("%c -> %c\n",start,end);
    }
    else
    {
        HNT(m-1,start,end,mid);
        HNT(1,start,mid,end);
        HNT(m-1,mid,start,end);
    }
}
int main()
{
    printf("漢諾塔問題\n");
    int number=4;
    HNT(number,'a','b','c');
}

命令行 argc表示命令行參數(shù)的個數(shù),包括可執(zhí)行程序名本身,argv[] 定義為指向字符串常量的指針數(shù)組,數(shù)組元素是分別指向命令行中可執(zhí)行文件名和各個命令行參數(shù)字符串的指針。
正如 本章實例所說:



那么argc標(biāo)注的參數(shù)個數(shù)為3 而argv字符串指針數(shù)組,這個數(shù)組內(nèi)元素的個數(shù)為argc+1 第一個表示可執(zhí)行文件名,后面為輸入?yún)?shù),最后一個為空表示結(jié)束。

命令行參數(shù) 本書教學(xué)部分就講的不清不白的,不看了(本身也是自選內(nèi)容)

按序輸出五個國家的名稱

#include<stdio.h>
#include<stdlib.h>
void sortCountryname(char name[][100],int low,int line)
{
    for(int i=1;i<low;i++)
    {
        char temp[100];
        strcpy(temp,name[i]);
        int j=0;
        for(j=i-1;j>=0;j--)
        {
            if(strcmp(temp,name[j])<0)
            {
                strcpy(name[j+1],name[j]);
            }
            else
            {
                break;
            }
        }
        strcpy(name[j+1],temp);
    }
}
int main()
{
    char countryname[5][100];
    for(int i=0;i<5;i++)
    {
        gets(countryname[i]);
    }
    puts("----------------------------");
    sortCountryname(countryname,5,100);
    for(int i=0;i<5;i++)
    {
        puts(countryname[i]);
    }
}

唉 到底什么時候才會講動態(tài)分配內(nèi)存,我傻了。

遞歸函數(shù)并不能節(jié)省內(nèi)存空間和提高運行速度。
第六章習(xí)題處理
6.3 處理字符串

#include<stdio.h>
#include<stdlib.h>

void produce(char* strings)
{
    int length=strlen(strings);
    int count=0;
    char old=NULL;
    int i;
    for(i=0;i<length;i++)
    {
        if((strings[i]>'0'&&strings[i]<'9')||(strings[i]>'a'&&strings[i]<'z')||(strings[i]>'A'&&strings[i]<'Z'))
        {
            old=strings[i];
            strings[i-count]=strings[i];
        }
        else
        {
            if(strings[i]==old)
            {
                count++;
            }
            else
            {
                strings[i-count]=strings[i];
                old=strings[i];
            }
        }

    }
    strings[i-count]='\0';
}
int main()
{
    char strings[100];
    gets(strings);
    puts(strings);
    produce(strings);
    puts(strings);
}

6.4 百十個位數(shù) 乘積

void produce(int num)
{
    int gewei=0;
    int shiwei=0;
    int baiwei=0;
    gewei=num%10;
    shiwei=(num/10)%10;
    baiwei=(num/100)%10;
    int sum=pow(gewei,3)+pow(shiwei,3)+pow(baiwei,3);
    if(sum==num)
    {
        printf("%4d\n",sum);
    }
}

int main()
{
    for(int i=0;i<=999;i++)
    {
        produce(i);
    }
}

6.5 二元一次方程解

#include<stdio.h>
#include<stdlib.h>

void produce(float a,float b,int c)
{

    float det=pow(b,2)-4.0*a*c;
    float x1;
    float x2;
    if(det<0)
    {
        printf("對不起,在實數(shù)域內(nèi)沒有合適的解\n");
    }
    else
    {
        det=sqrt(det);
        x1=(-b+det)/(2*a);
        x2=(-b-det)/(2*a);
        printf("x1=%10.4f x2=%10.4f",x1,x2);
    }
}

int main()
{
    float a,b,c;
    scanf("%f %f %f",&a,&b,&c);
    produce(a,b,c);
}

6.6 最小公倍數(shù)

#include<stdio.h>
#include<stdlib.h>

int zuixiaogongyueshu(int a,int b)
{
   int p=0;
   while(a%b!=0)
   {
       //如果a%b==0 就代表結(jié)束運算
       int temp=a%b;
       a=b;
       b=temp;
   }
   return b;
}
int find(int a,int b)
{
    return a*b/zuixiaogongyueshu(a,b);

}

int main()
{
    int a[5];
    for(int i=0;i<5;i++)
    {
        scanf("%d",&a[i]);
    }
    int temp=a[0];
    for(int i=1;i<5;i++)
    {
        temp=find(temp,a[i]);
        printf("--%d--\n",temp);
    }
    printf("%d",temp);
}

求一到三萬的所有質(zhì)數(shù)

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int a[10000];
    int count=0;
    for(int i=2;i<=30000;i++)
    {
        if(count==0)
        {
            a[count]=i;
            count++;
        }
        else
        {
            int flag=0;
            for(int j=0;j<count;j++)
            {
                if(i%a[j]==0)
                {
                    flag=1;
                    break;
                }
            }
            if(flag==0)
            {
                a[count]=i;
                count++;
            }
        }
    }
    int temp=0;
    for(int i=0;i<count;i++)
    {
        if(temp==1&&i%10==9)
        {
            printf("\n");
        }
        else
        {
            temp=1;
            printf("%6d",a[i]);
        }
    }
}

求完備數(shù)

#include<stdio.h>
#include<stdlib.h>

void find(int num)
{
    int sum=0;
    int a[100];
    int count=0;
    for(int i=1;i<num;i++)
    {
        if(num%i==0)
        {
            sum+=i;
            a[count]=i;
            count++;
        }
    }
    if(sum==num)
    {
        printf("%6d",num);
        for(int i=0;i<count;i++)
        {
            printf("%6d",a[i]);
        }
        printf("\n");
    }

}
int main()
{
    for(int i=1;i<30000;i++)
    {
        find(i);
    }
}

6.8 互滿數(shù)

#include<stdio.h>
#include<stdlib.h>

int find(int num)
{
    int sum=0;
    int a[300];
    int count=0;
    for(int i=1;i<num;i++)
    {
        if(num%i==0)
        {
            sum+=i;
            a[count]=i;
            count++;
        }
    }
    return sum;
}
int main()
{
    int p=0;
    for(int i=1;i<30000;i++)
    {
        p=find(i);
        if(i<p&&i==find(p))
        {
            printf("%7d %7d\n",i,p);
        }
    }
}

2.20:

6.11 字符串比較函數(shù)

#include<stdio.h>
#include<stdlib.h>
void bijiao(char*a,char *b)
{
    while(*a!='\0'&&*b!='\0')
    {
        if(*a>*b)
        {
            printf("a>b");
            return;
        }
        else if(*a<*b)
        {
            printf("a<b");
            return;
        }
        a++;
        b++;
    }
    if(*a)
    {
        printf("a b 前端完全相等 但是a更長 所以a大");
    }
    else if(*b)
    {
        printf("b更大");
    }
    else
    {
        printf("a==b");
    }
}
int main()
{
    char a[100],b[100];
    gets(a);
    gets(b);
    if(strcmp(a,b)==0)
    {
        printf("a和b相等\n");
    }
    else if(strcmp(a,b)>0)
    {
        printf("a>b\n");
    }
    else
    {
        printf("a<b\n");
    }
    bijiao(a,b);
}

輸出組合數(shù) 并且輸出所有可能的組合
這道題 有點意思 這題需要拿數(shù)組做 之前沒想起來

#include<stdio.h>
#include<stdlib.h>
int jiecheng(int k)
{
    int sum=1;
    for(int i=1;i<=k;i++)
    {
        sum*=i;
    }
    printf("%4d",sum);
    return sum;
}
void function2(int n,int k,int* a)
{
    if(k>=1)
    {
        for(int i=n;i-k>=0;i--)
        {
            a[k]=i;
            function2(i-1,k-1,a);
        }
    }
    else
    {
        for(int i=a[0];i>=1;i--)
        {
            printf("%4d",a[i]);
        }
        printf("\n");
    }

}
void function(int k,int n)
{
    int p=jiecheng(n)/(jiecheng(k)*jiecheng(n-k));
    printf("共有%d種組合\n",p);
    int a[10];
    a[0]=k;
    function2(n,k,a);
}
int main()
{
   int n;
   int k;
   scanf("%d %d",&n,&k);
   function(k,n);
}

排序輸出

#include<stdio.h>
#include<stdlib.h>
void function2(int n,int k,int* a,int *flag)
{
    if(k>=1)
    {
        for(int i=1;i<=n;i++)
        {
            if(flag[i]==0)
            {
                flag[i]=1;
                a[k]=i;
                function2(n,k-1,a,flag);
                flag[i]=0;
            }
            else
            {
                continue;
            }
        }
    }
    else
    {
        for(int i=a[0];i>=1;i--)
        {
            printf("%4d",a[i]);
        }
        printf("\n");
    }
}
void function(int k,int n)
{
    int a[10];
    a[0]=k;
    int flag[10]={0};
    function2(n,k,a,flag);
}
int main()
{
   int n;
   int k;
   scanf("%d %d",&n,&k);
   function(k,n);

}

這里涉及到字符的組合排序問題 下面將拓展這個算法的實際內(nèi)容
參考內(nèi)容為:
https://blog.csdn.net/qq_42552533/article/details/88606550?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&dist_request_id=d5755e2c-0ba8-445b-9ca8-d4eeb77b9868&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control

#include<stdio.h>
#include<stdlib.h>
void swap(char* p,char *q)
{
    char temp=*p;
    *p=*q;
    *q=temp;
}
void core_function(char* a,int left,int right)
{
    if(left<right)
    {
        for(int i=left; i<=right; i++)
        {
            swap(&a[left],&a[i]);
            core_function(a,left+1,right);
            swap(&a[left],&a[i]);
        }
    }
    else
    {
        puts(a);
    }

}
void function(char* a,int length)
{
    core_function(a,0,length-1);
}
int main()
{
    char a[40];
    gets(a);
    int length=strlen(a);
    function(a,length);
}

如果要實現(xiàn)含有重復(fù)字符的篩查,交換前需要判斷,left和right(包括left左邊界是否有和right邊界相同的元素,如果有,則不發(fā)生交換)

#include<stdio.h>
#include<stdlib.h>
void swap(char* p,char *q)
{
    char temp=*p;
    *p=*q;
    *q=temp;
}
int judge_ISorNot_swap(char* a,int left,int right)
{
    int flag=1;
    for(int i=left; i<right; i++)
    {
        if(a[i]==a[right])
        {
            flag=0;
        }
    }
    return flag;
}
void core_function(char* a,int left,int right)
{
    if(left<right)
    {
        for(int i=left; i<=right; i++)
        {
            if(judge_ISorNot_swap(a,left,i))
            {
                swap(&a[left],&a[i]);
                core_function(a,left+1,right);
                swap(&a[left],&a[i]);
            }
        }
    }
    else
    {
        puts(a);
    }

}
void function(char* a,int length)
{
    core_function(a,0,length-1);
}
int main()
{
    char a[40];
    gets(a);
    int length=strlen(a);
    function(a,length);
}

隨機數(shù)之圓周率

#include<stdio.h>
#include<stdlib.h>

int function()
{


    float x1f=rand()*1.0/RAND_MAX;
    float x2f=rand()*1.0/RAND_MAX;

   // printf("%10f %10f\n",x1f,x2f);
    if(pow(x1f,2)+pow(x2f,2)<1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
int main()
{
    srand(time(NULL));
    int i=0;
    int sum=0;
    while(i<100000)
    {
        sum+=function();
        i++;
    }
    printf("%f",sum*4.0f/100000);
}

身份證比較 這題不算很難 細(xì)節(jié)我就不寫了
但是要注意的是如果不使用for循環(huán)挨個挨個賦值,使用strncpy 務(wù)必注意最后加上 \0 否則會粘貼后的字符串沒有截斷標(biāo)志,會出現(xiàn)很多問題。

extern 可以用來擴展 全局變量的作用范圍
例如m是在程序中部定義的全局變量 使用extern即可將其作用擴展到指定的函數(shù)內(nèi)(該函數(shù)比m定義要早)
同時 extern進(jìn)行引用時,可以不標(biāo)注變量類型。

同時如果局部變量和外部變量重名,那么外部變量會被屏蔽在函數(shù)內(nèi)無法被訪問。

要指出的是 外部變量一定是全局變量。
只有自動變量和形參可以作為寄存器變量,調(diào)用時分配寄存器,調(diào)用結(jié)束后釋放寄存器。

這里要指出的是:只要不是在函數(shù)內(nèi)部定義的變量就是外部變量,所以外部變量的定義還是蠻大的,extern關(guān)鍵字只是為了擴大作用域罷了,不是加上extern才叫外部變量,同時static也可以用來修飾外部變量,就是全局靜態(tài)變量,一旦設(shè)置為全局靜態(tài)變量,那么就只能在當(dāng)前.c文件內(nèi)使用,

外部變量定義時如果缺失初試值,缺省值自動設(shè)置為0.

靜態(tài)變量,不論是局部靜態(tài)變量還是全局靜態(tài)變量,初始化只會初始化一次,即是定義的那一次會初始化一次初值。
例如下面代碼:

void printfx()
{
    static int p=10;
    printf("%d\n",p++);
}
int main()
{
    int i=0;
    while(i<10)
    {
        i++;
        printfx();
    }
}

輸出結(jié)果從10到19,而不是每次都會執(zhí)行p=10。

malloc函數(shù)的返回值是void* 類型,如果分配成功,函數(shù)返回一個指向該區(qū)域起始地址的指針,如果內(nèi)存不夠,那么返回NULL。
所以分配動態(tài)空間時,需要對指針的類型進(jìn)行轉(zhuǎn)換,例如:
int* p=(int*)malloc(sizeof(int)*4);

calloc函數(shù)和malloc作用相同,但是調(diào)用參數(shù)有兩個,第一個是n表示分配n個空間,第二個是size,表示單個空間的大小。
int* p=(int*)calloc(4,sizeof(int))
分配完內(nèi)存后,使用free函數(shù)即可釋放掉動態(tài)申請的存儲空間,

realloc函數(shù) 原型如下
p= realloc(p, size) // void* realloc(void* p, unsigned int size)
作用是重新分配內(nèi)存,如果后開辟的內(nèi)存比原內(nèi)存要大,則完全復(fù)制原內(nèi)存種內(nèi)容,如果要小,則只復(fù)制指定size的內(nèi)容。
重分配內(nèi)存之后,后分配的內(nèi)存起始地址和源地址不一定相同。

2.21:

預(yù)處理程序僅僅在當(dāng)前文件有效
預(yù)處理程序中,例如:
#define CESHI "hello my brother! "
CESHI將代表后方的字符串,如果字符串過長,既可以使用\符號來將其擴展到下一行
例如:

#define CESHI "8843e\
886\
221\
dianzikeji"

通過這種在某位增加反斜杠的方式可以拓展長度
宏定義允許嵌套
例如:

#define ONE 1
#define TWO ONE+ONE

TWO代表的就是2
define的進(jìn)階用法,參數(shù)調(diào)用:

#define MAX(a,b) a>b?a:b 
// 不需要指明 a和b的類型
// 不需要強調(diào)返回值
// MAX與左括號之間不允許有空格

宏定義時,最好將整個表達(dá)式和各個參數(shù)用圓括號括起來,否則宏定義可能會產(chǎn)生不可預(yù)見的錯誤,
例如:

#include<stdio.h>
#include<stdlib.h>
#define EVEN(a) a%2==0?1:0
int m=10;
int main()
{
    //顯然 按照正常的理解
    //9+1=10那么顯然%2==0 所以應(yīng)當(dāng)輸出1
    printf("%d",EVEN(9+1));
    //但是實際結(jié)果是0,因為其最后調(diào)用結(jié)果是 9+1%2==0?1:0 先計算%再計算+最后計算==的情況下,顯然結(jié)果不是0
    //所以輸出的結(jié)果應(yīng)該是0
}

帶參數(shù)的宏定義只是程序預(yù)處理時進(jìn)行簡單的替換,沒有變量類型的要求,可適用于任何類型的參數(shù),
使用宏的優(yōu)點就是運行速度快,因為在預(yù)處理階段就被展開,省去了函數(shù)調(diào)用時的開銷,但同時也使得程序代碼的長度增大,而函數(shù)調(diào)用則由于函數(shù)只會被定義一次,在目標(biāo)程序中只占用同樣的存儲空間,節(jié)省了存儲空間,但是因為調(diào)用的時候涉及到參數(shù)的傳遞和返回,現(xiàn)場的保存和恢復(fù),其都需要額外的時間開銷。

如果要撤銷宏定義,則需要使用#undef 宏標(biāo)識符
條件編譯:
#if
#else
#endif
要注意的是 if 的條件判斷式中只能使用常量或者宏替換名組成判斷表達(dá)式,而不能使用變量,因為其根本就是在編譯階段前進(jìn)行的條件編譯。
同時 條件編譯還可以使用
#ifdef
#ifndef
來根據(jù)是否已經(jīng)定義過/未定義過某些宏定義來進(jìn)行相應(yīng)的編譯處理

任意進(jìn)制轉(zhuǎn)換 這道例題還是滿有價值的,

#include<stdio.h>
#include<stdlib.h>
void function(int convertnum,int mod)
{
    extern char a[];
    if(convertnum/mod==0)
    {
        printf("%c",a[convertnum]);
    }
    else
    {
        function(convertnum/mod,mod);
        printf("%c",a[convertnum%mod]);
    }
}
char a[]="0123456789ABCDEF";
void main()
{

    int convert;
    scanf("%d",&convert);
    puts("-------------------------------------------");
    int mod;
    scanf("%d",&mod);
    function(convert,mod);
    puts("-------------------------------------------");
    printf("%d",0314);
}

額 7.3 7.4 我結(jié)合起來隨便寫了一下
出現(xiàn)了一個編譯錯誤就是 全局變量或者靜態(tài)變量(帶static)的初始化都不可以使用變量
主要原因就是標(biāo)準(zhǔn)C定義靜態(tài)變量/全局變量的時候,事先在全局內(nèi)存區(qū)分配內(nèi)存,然后就會立刻進(jìn)行初始化操作(在編譯階段,即代碼執(zhí)行之前) 這個時候變量還沒有確定的值,自然無法完成初始化操作。

// main.c
#include<stdio.h>
#include<stdlib.h>

extern int* data;
extern int num;
void swap(int* p,int* q)
{
    int temp=*q;
    *q=*p;
    *p=temp;
}
void main()
{
    USE();
    int flag=0;
    for(int i=0;i<num-1;i++)
    {
        for(int j=0;j<num-1-i;j++)
        {
            if(data[j]>data[j+1])
            {
                swap(data+j,data+j+1);
                flag=1;
            }
        }
        if(flag==0)
        {
            break;
        }
    }
    for(int i=0;i<20;i++)
    {
        printf("%4d",*(data+i));
    }
}
//------------------------------------------------
//twice.c
//------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
int* data=0;
int num=20;
void USE()
{
    data=calloc(20,sizeof(int));//就是這行代碼并不能寫在data定義的后面
    for(int i=0;i<20;i++)
    {
        scanf("%d",data+i);
    }

}

看群消息學(xué)了一個冷知識

int a,b;
b=(a=9);

此時 b和a的值都是9

2.22:

位域 位域變量C99規(guī)定只能是int 或者是 unsigned int
‘這里要提到一個問題,就是*p.a 是先執(zhí)行.運算然后才執(zhí)行*運算

位域運算過程中,不允許取一個位域變量的地址
不允許超過整形邊界
位域的詳細(xì)說明鏈接:
https://blog.csdn.net/yixixi/article/details/2961293 //這個詳細(xì)描述了位域的規(guī)則
https://blog.csdn.net/u010575913/article/details/22886667 //這個舉例了一些位域大小的判斷例題
下面為復(fù)制過來的規(guī)則說明:

  1. 如果相鄰位域字段的類型相同,且其位寬之和小于類型的sizeof大小,則后面的字 段將緊鄰前一個字段存儲,直到不能容納為止;

  2. 如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字 段將從新的存儲單元開始,其偏移量為其類型大小的整數(shù)倍;

  3. 如果相鄰的位域字段的類型不同,則各編譯器的具體實現(xiàn)有差異,VC6采取不壓縮方 式,Dev-C++采取壓縮方式;

  4. 如果位域字段之間穿插著非位域字段,則不進(jìn)行壓縮;

  5. 整個結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍。

位域?qū)崿F(xiàn)奇偶校驗位輸出:

#include<stdio.h>
#include<stdlib.h>
typedef struct test
{
    unsigned C0:1;
    unsigned C1:1;
    unsigned C2:1;
    unsigned C3:1;
    unsigned C4:1;
    unsigned C5:1;
    unsigned C6:1;
    unsigned C7:1;
}test;
int main()
{
    char num[10]="123456789";
    for(int i=0;i<10;i++)
    {
        test* p=num+i;
        int sum=p->C0+p->C1+p->C2+p->C3+p->C4+p->C5+p->C6+p->C7;
        sum=sum%2;
        printf("%c%d%d%d%d%d%d%d%d%d\n",num[i],sum,p->C0,p->C1,p->C2,p->C3,p->C4,p->C5,p->C6,p->C7);
    }
}

從這里我們可以看出來現(xiàn)在的windows系統(tǒng)中,都是小端存儲,即低字節(jié)處存放低位信息,例如:
1 ascii碼為 49 為00110001
但是本例將字符地址賦值給test型指針后,依次輸出(按照地址由低到高)C0 C1 C2 ........結(jié)果為10001100
所以可見高位被存儲到高位地址,低位被存儲到低位地址。

所謂大端和小端,指的就是低地址內(nèi)存放的是高位字節(jié)還是低位字節(jié)。

結(jié)構(gòu)體嵌套

#include<stdio.h>
#include<stdlib.h>
typedef struct test
{
    unsigned C0:1;
    unsigned C1:1;
    unsigned C2:1;
    unsigned C3:1;
    unsigned C4:1;
    unsigned C5:1;
    unsigned C6:1;
    unsigned C7:1;
}test;
typedef struct test2
{
    int year;
    int month;
    int day;
}data;
typedef struct test3
{
    data data1;
    int ppp;
}databig;
int main()
{
    databig big={1,2,3,890}; //注意結(jié)構(gòu)體變量的初始化方式。
    printf("%d %d %d %d",big.data1.year,big.data1.month,big.data1.day,big.ppp);
}

聯(lián)合和結(jié)構(gòu)的主要區(qū)別在于:聯(lián)合類型變量所用的空間不是各個成員所需的存儲空間總和,而是聯(lián)合成員中存儲空間最大的成員所要求的字節(jié)數(shù)。

2.23:

聯(lián)合
本身這個東西沒什么好說的

#include<stdio.h>
#include<stdlib.h>
union test{
    int a;
    double b;
    char c;
};
int main()
{
    union test p={10};;//要注意的是 這種賦值方式是可以的
    //同樣這樣也是可以的 union test p.a=10
    //但是這樣是不可以的 union test p=10;
    printf("%d",p.a);
}

這個厲害了 真的開眼了
利用聯(lián)合交換指定數(shù)據(jù)的前后字節(jié)

#include<stdio.h>
#include<stdlib.h>
union test{
    int p;
    struct tests{
        char word1;
        char word2;
        char word3;
        char word4;
    }testp;
};
int main()
{
    union test test1,test2;
    int x;
    scanf("%x",&test1.p);
    printf("%x\n",test1.p);
    test2.testp.word1=test1.testp.word4;
    test2.testp.word2=test1.testp.word3;
    test2.testp.word3=test1.testp.word2;
    test2.testp.word4=test1.testp.word1;
    printf("%x\n",test2.p);
}

輸出結(jié)果:
輸出結(jié)果

枚舉類型:
enum test{black,white,yellow};

#include<stdio.h>
#include<stdlib.h>
enum color{yellow,green,blue,red,black};
int main()
{
    enum color c=yellow;
    enum color p=green;
    enum color s=white; //這一行將不能執(zhí)行
}

要注意的是 enum 本質(zhì)上是將 枚舉的各個變量依次賦值為 01234......
但如果不實用默認(rèn)賦值,例如:
enum test{one,two,three,four=9,five,six}
這樣會使得枚舉變量依次代表0 1 2 9 10 11 12

依次輸出枚舉變量

enum color{yellow,green,blue=8,red,black};
int main()
{
    enum color p;
    for(p=yellow;p<=black;p++)
    {
        printf("%d",p);
    }
}

輸出結(jié)果將從0到10,和我原來的預(yù)計還是挺不一樣的。

C語言的文件系統(tǒng)分為緩沖型文件系統(tǒng)和非緩沖型文件系統(tǒng)
前者的輸入輸出函數(shù)稱為流式I/O函數(shù) 后者的輸出函數(shù)成為低級I/O函數(shù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift簡介 Swift,蘋果于2014年WWDC(蘋果開發(fā)者大會)發(fā)布的新開發(fā)語言,可與Objective-C...
    逐水而上閱讀 231評論 0 0
  • 引言 今天,開始系統(tǒng)學(xué)習(xí)Swift,以前都是零零散散的看看的let和var的區(qū)別、泛型,只知道它是一個面向協(xié)議且類...
    shiyueZ閱讀 3,830評論 0 11
  • 一、Java 簡介 Java是由Sun Microsystems公司于1995年5月推出的Java面向?qū)ο蟪绦蛟O(shè)計...
    子非魚_t_閱讀 4,543評論 1 44
  • JAVA后端開發(fā)學(xué)習(xí)路線列表 1. 一個簡單的JAVA應(yīng)用程序 程序執(zhí)行后,控制臺上將會顯示hello world...
    swing0閱讀 719評論 0 1
  • 推薦指數(shù): 6.0 書籍主旨關(guān)鍵詞:特權(quán)、焦點、注意力、語言聯(lián)想、情景聯(lián)想 觀點: 1.統(tǒng)計學(xué)現(xiàn)在叫數(shù)據(jù)分析,社會...
    Jenaral閱讀 5,967評論 0 5

友情鏈接更多精彩內(nèi)容