天天看點

c語言scanf傳回值被忽略_大學C語言考試易錯知識點總結運算符相關函數相關變量相關數組相關結構體相關庫函數相關預編譯相關

作者:cggwz

來源:https://blog.csdn.net/cggwz/article/details/103740713?utm_medium=distribute.pc_relevant.none-task-blog-utm_term-2&spm=1001.2101.3001.4242

文章目錄

  • 運算符相關
    • 自增(減)前字尾
    • 邏輯運算符的短路問題
    • 指派運算符的傳回值問題
    • 運算符優先級的問題
    • sizeof()的傳回值問題
  • 函數相關
    • 函數聲明問題
    • mian函數參數問題
  • 變量相關
    • 用字元串初始化字元數組
    • 賦初值問題
    • 轉義字元問題
    • 常用ASCII碼記憶
    • 字元串常量占用記憶體問題
    • 字元變量值的問題
    • 變量類型的範圍計算問題
    • 字元串常量拼接問題
  • 數組相關
    • 數組下标越界
    • 二維數組中行列計算問題
    • 字元數組指派問題
  • 結構體相關
    • 結構體所包含的變量不可初始化
    • 檢視結構體内部變量所占記憶體大小
  • 庫函數相關
    • 絕對值函數
    • scanf()和printf()的傳回值問題
    • fclose()的傳回值問題
  • 預編譯相關
    • 注意宏定義的替換原則
  • 後記

現在不少大學都把C語言作為一門必學的程式設計語言。C語言考試呢,并不能決定你的實踐能力怎麼樣,他考的很多點,我們不知道,也可以在寫代碼時避免,我們舉個最簡單的例子,運算符優先級,這恐怕是必考的内容了。但實際上我們寫代碼并不需要背下這個,我們完全可以通過多加幾個括号解決問題。但是考試它并不會管這些,考試是别人出的題,是以代碼也是它的。而我們也需要一個較高的分數,那麼我們應該怎麼辦呢?

沒錯,這篇部落格就是為了這個而誕生的。從cggwz個人的刷題經曆,總結出易錯的一些點,提醒大家在考試中注意,那麼廢話不多說,我們開始吧!

(再強調一遍:這裡大部分是出卷人可能的設誤點,而不一定是你自己寫代碼的易錯點)

運算符相關

自增(減)前字尾

我們以自增為例,字首和字尾的差别有兩點:

  1. 優先級不同,字尾優先級更高
  2. 傳回值不同

雖說優先級不同,但是在兩者之間也就邏輯非和按位取反,貌似不會有太大影響。

而重點是傳回值,也就是說,

++x

傳回的是x+1,而

x++

傳回的是原來的x。

而x本身的值都會在傳回值以後立刻改變,也就是執行這個表達式後立即改變,比如:

#include
int main(){
	int x=0,y=2,z=1;
	x=z++ + z;
	printf("%d",x);
	return 0;
}
           

這個輸出結果就是3,而不是2.

邏輯運算符的短路問題

C語言在計算邏輯運算符的時候是采取短路機制的,也就是說,如果已經可以判斷這個表達式的最終結果,那麼就不再判斷接下來的表達式,相應地,那些表達式也不會被執行。而出題人則喜歡通過放置一些指派語句在後面,某些學生會因為忽略了短路機制,而誤以為會執行,進而出錯,我們看個例子:

這裡輸出是2嗎?

并不是,是3.

因為

--z

傳回的值是0,而後面的邏輯運算符是&&,也就是說無論後面一個語句真假與否,這個表達式都是假,是以就會觸發短路機制,不再計算後面的

++x

,進而x的值不會改變。

我們來看個變式:

相信你現在應該能知道結果了,輸出就是2.中間的那個–x并不會因為它在中間而被執行。

指派運算符的傳回值問題

我們知道C語言中的指派運算符是有傳回值的。

它們的傳回值是指派後被指派變量的值,而不是指派符号右邊的表達式的值。

比如

int a=10;a+=3;

這裡的+=傳回的就不是3,而是13.

這也适用于類型轉換問題,比如

double a;a=2;

這裡這個指派語句的傳回值就是2.0,而不是2.

運算符優先級的問題

考試前必須要掌握的内容之一。

但是顯然,我這裡不會把一大張表放出來,要是需要看看課本就好了。

這裡我是想總結一下這張表,讓大家更容易的“記住”這張表。

我們也會順帶地總結一下結合方向。

現在請翻開你的教材或是百度找到一張表,我們準備開車了。

首先第一梯隊,優先級最高的,是一些指代所屬關系的運算符,比如[]、->、.。在加上一個圓括号。這個應該很好了解。圓括号如同一個老大哥,它在改變運算順序這方面具有絕對的話語權,自然會在第一梯隊,而這個老大哥也是懂人情的,->、.這類符号就好像是調用父對象裡的一個子對象,把人家父子關系拆散恐怕不是一個老大哥應該做的,是以它們也屬于第一梯隊。

它們的優先級是最高的。

接下來第二梯隊主要是我們的單目運算符。比如正負号、指針符号、取位址、自加自減之類。它們通常是緊緊貼着它們作用的對象的(單目),那關系親密地如同情侶。雖然狗糧不好吃,但是不能因為嫉妒就拆散人家呀(誰說的,我就覺得可以),是以它們的優先級也是比較高的,屬于第二梯隊。

第三梯隊就是我們的四大金剛啦——加減乘除,哦不,我們不能忘了我們除法的好兄弟——取餘。是以它們五個就是我們的第三梯隊,我們可以把它們叫做算術運算符。這五大金剛可是從國小就開始陪伴我們了,自然在考慮完父子情、情侶情之後要考慮它們幾個了。

第四梯隊是位運算的左移和右移運算符。這兩個家夥雖然名氣沒有上面五大金剛大,但是它們也是可以改變變量的值呢,也可以算得上小金剛了。是以,第四梯隊,當之無愧。

第五梯隊是關系運算符,也就是表示大于小于不等這類符号。它們雖然也很早就開始陪伴我們,名氣也不小,但是畢竟是比較運算的結果,自然要等前兩個梯隊運算完,才能比較,那就隻好屈居它們後面啦。

第六梯隊是位運算的按位與、或、異或。理論上它們也是改變數值的呀,為什麼不在前面的梯隊呢?我們可以看看它們的樣子:&、|,正好是我們下面一個梯隊的一半,二者的關系情同手足,成功固然美好,但是一份兄弟情,哪是成功可以換來的?它們自然願意留在兄弟身旁,相依相助。

第七梯隊是邏輯運算符,加上唯一一個三目運算符——條件運算符。它們連接配接的多半是關系運算符的結果,自然就得在關系運算符後面啦!

第八梯隊可是一個大部隊,指派運算符。它們當然得殿後啦,它們可是把前面的運算結果儲存下來的必經之路。它們就如同慈愛的父母,默默地收拾前面這些孩子算出來的各種資料,并把它們認真地儲存下來。我們的父母在我們小時候,不也是這樣的嗎?

咦?我們好像還漏一個,沒錯,逗号運算符。存在感太低啦!就放在最後一個吧!(我想你們大部分人也很少用它)。

這樣我們的優先級就徹底理清楚啦!

總結一下:

分量、下标運算符、圓括号>單目運算符>算數運算符(五大金剛加兩個小金剛)>關系運算符>位運算符(與或異或)>邏輯運算符(含條件運算符)>指派運算符>逗号運算符

這個總結并不嚴謹,因為有些運算符并不是在一起的,是以要注意對我說的故事的了解,再結合表看看背背就OK了。

下面再說一下結合方向。

這個還是很好總結的,除了字尾自加自減的所有單目運算符、條件運算符、指派運算符是右結合,其他的符号全是左結合。

這個還是很好了解的,那些單目運算符通常寫在作用對象的左邊,自然是從右向左結合,指派符号也是把右邊的數值賦給左邊,是以也是從右向左,條件運算符……這麼特殊的一個,記一下就好了。

這樣我們就成功地解決了這張令人頭疼的表。怎麼樣?不困難吧?

sizeof()的傳回值問題

首先強調一下,這個不是函數,雖然它看起來很像。

它運算得到的值是括号内的東西所占的記憶體大小,它是一個int型的值。是以sizeof()的表達式是int型表達式。

函數相關

函數聲明問題

我們知道C語言裡是需要函數聲明的,如果函數放在主調函數的後面,就需要在主調函數前進行原型聲明。

但是不知道有沒有像我一樣,由于長期把函數放在主調函數的前面(少打幾行字),而在考試時容易忘記聲明這件事。其實網上有不少資訊學競賽題的代碼,它們絕大多數都是把函數放在主調函數前面,是以這裡也算是一個提醒吧。

mian函數參數問題

我們知道main函數有三個參數argc,argv,envp

我們主要提示一下前面兩個。

現在如果我們在指令行執行如下語句:

D:\cgg.exe how are you!

這麼執行後,argv是4,而不是3,因為

D:\cgg.exe

也是一個參數,而它就儲存在argv[0]中。

這一點千萬不能忘記。

變量相關

用字元串初始化字元數組

主要是長度的問題,我們知道C中的字元串是以一個空字元作為字元串的結尾标志。是以,我們在指派時,要注意字元數組的長度要比字元串的長度多1。比如下面這段代碼是無法通過編譯的:

#include
int main(){
	char a[4]="abcd";
	return 0;
}
           

而我們隻需要把a的長度改為5就好了。

賦初值問題

這是一個老生常談的問題,但是還是很容易被忽略。是以在這裡再說一下。當遇到一些計算求值類的題,一定要注意把變量初始化,賦初值,比如0.

轉義字元問題

我們知道C語言中是有轉義字元的。轉義字元以\開頭,是以,我們是不能在一對單引号中間直接放置右斜杠的,還有就是注意,斜杠後如果是十六進制的表示碼,開頭是x或X,而不是0x或0X

常用ASCII碼記憶

常用的無非是大小寫字母和數字,這時一定需要記住的(除非你是上機考試)。

字元 ASCII值
A 65
a 97
48
CR(回車) 13
空格 32

字元串常量占用記憶體問題

我們知道C中的字元串一定是以空字元‘\0’結尾,而這個空字元是不顯示的。是以有的出題老師會在這裡設坑,比如:"abcde"占的記憶體大小是多少位元組?雖然是五個字元,但是實際上還有一個空字元,總共是6位元組。

字元變量值的問題

我們經常會遇到這樣的題,問你某個字元的值是什麼。

這時我們需要尤其小心,尤其是選擇題。

我們舉個例子來說:

char a='C'

a的值是什麼?

是C嗎?

如果你說是,那就錯了。

我們隻能說a的值是‘C’或者67.

想必你應該能明白我想說什麼了。

單引号是不能省去的,這一點尤其重要,缺少了單引号,它就不再是一個字元了。

這一點很容易忽略,尤其是選擇題,看到C這個選項,一激動就選上了。那就慘了。

變量類型的範圍計算問題

這裡隻提醒一點,計算範圍的時候不要忘記對于有符号的數,有一位符号位。

字元串常量拼接問題

在C語言中是允許進行字元串拼接的。

也就是說,如果兩對引号包含的字元串放在一起,則會被解釋成一個字元串。

比如:

#include
int main(){
	char a[15]="hello""world";
	char b[15]="hel""lo""world";
	printf("%s",b);
	return 0;
}
           

這兩個字元串都是合法的,且和“helloworld”等價。

數組相關

數組下标越界

這個……恐怕是個程式員都會出過的bug,從你初學程式設計語言到你退休。

考試也可能會出現這個問題,多半是在for循環裡出現。

二維數組中行列計算問題

我們可能會經常看到這樣的題,就是另一個指針等于二維數組中的某個位址單元,然後對指針進行加一之類的操作,然後問輸出的值。

而我們知道這裡會有兩種不同的效果,一種是行計算,一種是列計算,二者的含義是,行計算,每次加一,位址會移動一行;而列計算,每次加一,位址隻會移動一格。

比如:

這裡輸出的就是第二個字元串I

具體的分類為:

類型 計算方式
a 計算行
&a[0][0] 計算列
a[0] 計算列
*a 計算列

字元數組指派問題

我們知道我們可以這樣聲明一個字元數組:

但是,字元數組在被定義之後,是不被允許這樣直接指派的。

比如下面這段代碼是不會通過編譯的:

a="helloworld!";

結構體相關

結構體所包含的變量不可初始化

這一點在C++中是被允許的,但是C中是不允許的。

是以習慣了寫C++的同學尤其需要注意。

不要忘記了。

檢視結構體内部變量所占記憶體大小

這裡我們隻舉個例子,比如我們有ABC這個結構體,它有變量x,

sizeof(((struct ABC*)0)->x)

得到的就是x占用的記憶體大小。

這裡的0,隻要是int型的量就可以。

庫函數相關

絕對值函數

注意math.h中有兩個絕對值函數,一個是abs(),另一個是fabs()

其中前者是處理整型變量的,而後者是處理浮點型變量的

scanf()和printf()的傳回值問題

我們通常會把它們當作輸入輸出語句使用,單獨成行,總是自動忽略它們的傳回值,但其實它們是有傳回值的。

那麼它們的傳回值是什麼呢?

printf的傳回值是輸出的資料個數,而scanf的傳回值則是讀入的資料個數。

我們可以來看個例題:

#include
int main(){
	int x;
	printf("2:%d",printf("1:%d,",scanf("%d",&x)));
	return 0;
           

}

請問它的輸出結果是什麼?

答案是

1:1,2:4

為什麼是4?不知道你是不是想這麼問。

printf中所說的資料個數,其實是把輸出的每個字元都看成一個單獨的資料,也就是有多少字元加上我們傳入的資料,就是它的傳回值。

fclose()的傳回值問題

和scanf、printf一樣,我們經常忽略fclose的傳回值,其實他也是有傳回值的。

如果成功關閉流,那麼傳回0,如果未成功關閉則傳回-1。

預編譯相關

注意宏定義的替換原則

我們知道宏定義實際上隻是字元串的替換,并不是函數一樣的東西,是以我們在做題時也需要嚴格替換,替換完成之前,不要進行任何計算。

我們舉個例子:

c語言scanf傳回值被忽略_大學C語言考試易錯知識點總結運算符相關函數相關變量相關數組相關結構體相關庫函數相關預編譯相關

答案是多少?54?那就錯了。實際上應該是48.

這裡我們不能把5+1算出來6再帶入,而是直接代入,這樣你就會發現,5和1不是直接加在一起的。

免責聲明:本文系網絡轉載,版權歸原作者所有。如涉及作品版權問題,請我聯系,感謝!

往期推薦好文

★C語言程式設計工具的選擇 

★求1000以内的水仙花數

★i++和++i有什麼差別?

★「建議收藏」C語言程式設計判斷回文數

★看完你就明白:什麼情況下該用int main(int argc, char *argv[])而不是int     main(void)

★C語言程式設計:列印一個圓形

★福利:50本C語言電子書免費送了!

★C語言程式設計求解:1到1000之間所有的素數

★[必讀]C語言學習者常見問題及回答