1. 程式人生 > >C#程式設計基礎面試題(.NET開發人員必備)

C#程式設計基礎面試題(.NET開發人員必備)

1. C/S結構模式與B/S結構模式的主要區別是什麼? 
  【解答】 
  首先,在系統的效能方面。只要擁有可上網的瀏覽器,就可以使用B/S系統。不過,B/S結構的客戶端只能完成瀏覽、查詢、資料輸入等簡單功能,絕大部分工作要由伺服器承擔,這就對伺服器提出了很高的要求,無形中增加了使用者在這一方面的投入。採用C/S結構時,客戶端和伺服器都承擔部分工作,有效利用了客戶端和伺服器端的資源,使使用者不必在硬體上有更多的投入。另外,瀏覽器頁面不便於修改,這為使用者定製自己的檔案時帶來了不便,比如使用者想自定義一個報表,用B/S結構的系統就比較難完成。 

  其次,在系統的開發方面,C/S結構的開發對開發者提出了較高的要求,整個開發過程比較複雜。與B/S結構相比,C/S技術的歷史更為“悠久”,從技術成熟度和開發人員普遍掌握的水平來看更為成熟。 

  第三,系統升級方面。C/S結構中若有某一模組發生改變,可能要關聯到其它模組的變動,使系統升級的成本較大;而B/S結構在開發、維護階段幾乎所有的工作都集中在伺服器端,只需更新伺服器端的軟體就可以了。如果系統升級比較頻繁,那麼B/S架構的產品就具有維護工作量少的優勢。 


  第四,安全性方面。在安全性上,B/S結構則略顯不足,畢竟現在網路安全係數不高,只要擁有密碼,任何人都可以進入到使用者的系統中;而C/S結構由於需要特定的客戶端軟體,並且一般來說都要對客戶端加密,甚至可以限定只有某一臺計算機可以使用這個客戶端,因而對安全性有更多的保障。 

  2. 可以用C#編寫哪些型別的應用程式? 

  【解答】 

  1) 控制檯應用程式。 

  2) Windows應用程式。 

  3) 水晶報表應用程式。 

  4) ASP.NET Web應用程式。 

  5) ASP.NET Web服務應用程式。 

  6) ASP.NET 水晶報表Web應用程式。 

  7) 智慧裝置應用程式。 


  3. 什麼是名稱空間?名稱空間和類庫的關係是什麼? 

  【解答】 

  1) 名稱空間是對類的一種邏輯上的分組,即將類按照某種關係或聯絡劃分到不同的名稱空間下。 


  2) 名稱空間又可以包含其它的名稱空間,例如System.Windows.Forms,是指System名稱空間下有Windows名稱空間,Windows名稱空間下有Forms名稱空間。 


  3) 所有類庫都在規定的名稱空間下。 


1. C#支援的資料型別有那些?與C++相比有哪些特點? 


  【解答】 


  C#支援的資料型別有: 


  (1) 值型別 


  包括:簡單型別、結構型別、列舉型別。其中,簡單型別又分為:整型、布林型、字元型、浮點型、小數型。 


  (2) 引用型別 


  包括:物件型別、類型別、介面、元資料、字串型別、陣列。 


  與C++相比,C#的主要特點有: 


  1) C#語言自C/C++演變而來。但是,它是完全按照面向物件的思想來設計的,並保證了型別的安全性。 


  2) C#簡化了C++在類、名稱空間、方法過載和異常處理等方面的使用。摒棄了C++的複雜性,使它更易用、更少出錯。 


  3) C#減少了C++的一些特性,不再有巨集、多重繼承。特別對企業開發者來說,上述功能只會產生更多的麻煩而不是效益。 


  4) C#採用嚴格的型別安全、版本控制、垃圾收集(garbage collect)等等。所有的這些功能的目標都是瞄準了開發面向元件的軟體開發。 


  5) C#中不再有“::”、“.”、和“->”操作符,僅使用單個操作符“.”。 


  6) C#使用統一的型別系統,摒棄了C++多變的型別系統。 


  7) 在C#中,不能在類的外部定義全域性函式、變數或者是常量等。所有的東西都必須封裝在類中,包括例項成員或靜態成員。從而使C#程式碼更加易讀且有助於減少潛在的命名衝突。 


  8) 在C#中,不能使用沒有初始化的變數。從而避免了由於使用不經初始化的變數而導致的計算結果錯誤。 


  2. C#語言中,值型別和引用型別有何不同? 


  【解答】 


  值型別和引用型別的區別在於,值型別的變數直接存放實際的資料,而引用型別的變數存放的則是資料的地址,即物件的引用。 


  值型別變數直接把變數的值儲存在堆疊中,引用型別的變數把實際資料的地址儲存在堆疊中,而實際資料則儲存在堆中。注意,堆和堆疊是兩個不同的概念,在記憶體中的儲存位置也不相同,堆一般用於儲存可變長度的資料,如字串型別;而堆疊則用於儲存固定長度的資料,如整型型別的資料int(每個int變數佔用四個位元組)。由資料儲存的位置可以得知,當把一個值變數賦給另一個值變數時,會在堆疊中儲存兩個完全相同的值;而把一個引用變數賦給另一個引用變數,則會在堆疊中儲存對同一個堆位置的兩個引用,即在堆疊中儲存的是同一個堆的地址。在進行資料操作時,對於值型別,由於每個變數都有自己的值,因此對一個變數的操作不會影響到其它變數;對於引用型別的變數,對一個變數的資料進行操作就是對這個變數在堆中的資料進行操作,如果兩個引用型別的變數引用同一個物件,實際含義就是它們在堆疊中儲存的堆的地址相同,因此對一個變數的操作就會影響到引用同一個物件的另一個變數。 


  3. 結構和類的區別是什麼? 


  【解答】 


  1) 結構是一個值型別,儲存在棧上,而類是一個引用型別,儲存在受管制的堆上。 


  2) 對結構中的資料進行操作比對類或物件中的資料進行操作速度要快。 


  3) 一般用結構儲存多種型別的資料,當建立一個很多類或物件共用的小型物件時,使用結構效率更高。 


  4. C#中的陣列型別有何特點? 


  【解答】 


  1) 陣列一般用於儲存同一種類型的資料,包括Object型別。 


  2) 陣列是一種引用型別,而不是值型別。 


  3) C#中除了可以有一維陣列、多維陣列外,還有交錯型陣列。 


  5. C#中不同整型之間進行轉換的原則是什麼? 


  【解答】 


  在整型之間進行轉換時,小範圍型別可以隱式轉換為大範圍型別,但大範圍型別轉換為小範圍型別時需要使用顯式轉換。 


  6. 簡述裝箱和拆箱的過程。 


  【解答】 


  裝箱是將值型別隱式地轉換為object型別或者轉換為由該值型別實現了的介面型別。裝箱一個數值會為其分配一個物件例項,並把該數值拷貝到新物件中。拆箱是顯式地把object型別轉換成值型別,或者把值型別實現了的介面型別轉換成該值型別。 


  7. 下列寫法哪些是錯誤的?為什麼? 


  1) if (nMyValue1=5) i=1; 


  2) if(nMyValue2==1)i=1; 


  3) int[] myInt={1,2,3}; 


  foreach(int test in myInt) 


  { 


  test++; 


  Console.WriteLine(temp); 


  } 


  4) int[] myInt1={1,2,3}; 


  foreach(int test in myInt1) 


  { 


  Console>WriteLine(test); 


  } 


  【解答】 


  1) 錯誤。if中的條件表示式結果不是布林型。 


  2) 正確。 


  3) 錯誤一:temp沒有定義。 


  錯誤二:在foreach塊內,test作為列舉成員是隻讀的,不能使用test++修改其值。 


  4) 錯誤。Console後應該是點,而不應該是大於號。 


  8. 錯誤和異常有什麼區別,為什麼要進行異常處理,用於異常處理的語句有哪些? 


  【解答】 


  錯誤是指在執行程式碼過程中發生的事件,它中斷或干擾程式碼的正常流程並建立異常物件。當錯誤中斷流程時,該程式將嘗試尋找異常處理程式(一段告訴程式如何對錯誤做出響應的程式碼),以幫助程式恢復流程。換句話說,錯誤是一個事件,而異常是該事件建立的物件。 


  當使用短語“產生異常”時,表示存在問題的方法發生錯誤,並建立異常物件(包含該錯誤的資訊及發生的時間和位置)來響應該錯誤。導致出現錯誤和隨後異常的因素包括使用者錯誤、資源失敗和程式設計邏輯失敗。這些錯誤與程式碼實現特定任務的方法有關,而與該任務的目的無關。 


  如果不進行異常處理,即不對錯誤做出響應,程式的健壯性就會大打折扣,甚至無法保證正常執行,所以必須要進行異常處理。 


  用於異常處理的語句有:try-catch語句、try-catch-finally語句、throw語句。 


  9. 編寫一個控制檯應用程式,輸出1到5的平方值,要求: 


  1) 用for語句實現。 


  2) 用while語句實現。 


  3) 用do-while語句實現。 


  【解答】 




  using System;  
  using System.Collections.Generic;  
  using System.Text;  
  namespace outputSquareValue  
  {  
  class Program  
  {  
  static void Main()  
  {  
  //用for語句實現  
  for (int i = 1; i <= 5; i++)  
  {  
  Console.WriteLine("{0}的平方值為{1}", i, i * i);  
  }  
  //用while語句實現  
  int j = 0;  
  while (j++ < 5)  
  {  
  Console.WriteLine("{0}的平方值為{1}", j, j * j);  
  }  
  //用do-while語句實現  
  int k = 1;  
  do  
  {  
  Console.WriteLine("{0}的平方值為{1}", k, k * k);  
  } while (k++ < 5);  
  Console.ReadLine();  
  }  
  }  
  } 


  10. 編寫一個控制檯應用程式,要求使用者輸入5個大寫字母,如果使用者輸入的資訊不滿足要求,提示幫助資訊並要求重新輸入。 


  【解答】 




  using System;  
  using System.Collections.Generic;  
  using System.Text;  
  namespace inputCapitalLetter  
  {  
  class Program  
  {  
  static void Main()  
  {  
  bool ok = false;  
  while (ok == false)  
  {  
  Console.Write("請輸入5個大寫字母:");  
  string str = Console.ReadLine();  
  if (str.Length != 5)  
  {  
  Console.WriteLine("你輸入的字元個數不是5個,請重新輸入。");  
  }  
  else  
  {  
  ok = true;  
  for (int i = 0; i < 5; i++)  
  {  
  char c = str[i];  
  if (c < 'A' || c > 'Z')  
  {  
  Console.WriteLine("第{0}個字元“{1}”不是大寫字母,請重新輸入。", i + 1, c);  
  ok = false;  
  break;  
  }  
  }  
  }  
  }  
  }  
  }  
  } 


  11. 編寫一個控制檯應用程式,要求完成下列功能。 


  1) 接收一個整數n。 


  2) 如果接收的值n為正數,輸出1到n間的全部整數。 


  3) 如果接收的值為負值,用break或者return退出程式。 


  4) 轉到(1)繼續接收下一個整數。 


  【解答】 




  using System;  
  using System.Collections.Generic;  
  using System.Text;  
  namespace testOutput  
  {  
  class Program  
  {  
  static void Main()  
  {  
  while (true)  
  {  
  Console.Write("請輸入一個整數(負值結束):");  
  string str = Console.ReadLine();  
  try  
  {  
  int i = Int32.Parse(str);  
  if (i < 0) break;  
  for (int j = 1; j <= i; j++) Console.WriteLine(j);  
  }  
  catch  
  {  
  Console.WriteLine("你輸入的不是數字或超出整數的表示範圍,請重新輸入");  
  }  
  }  
  }  
  }  
  } 


  12. 編寫一個控制檯應用程式,求1000之內的所有“完數”。所謂“完數”是指一個數恰好等於它的所有因子之和。例如,6是完數,因為6=1+2+3。 


  【解答】 




  using System;  
  using System.Collections.Generic;  
  using System.Text;  
  namespace completeNumber  
  {  
  class Program  
  {  
  static void Main(string[] args)  
  {  
  for (int i = 2; i <= 1000; i++)  
  {  
  int s = 1;  
  string str = "1";  
  for (int j = 2; j <= (int)Math.Sqrt(i); j++)  
  {  
  if (j * (i / j) == i)  
  {  
  if (j != i / j)  
  {  
  s += j + i / j;  
  str += string.Format("+{0}+{1}", j, i / j);  
  }  
  else  
  {  
  s += j;  
  str += string.Format("+{0}", j);  
  }  
  }  
  }  
  if (s == i) Console.WriteLine("{0}={1}", i, str);  
  }  
  Console.ReadLine();  
  }  
  }  
  }


C#網路應用程式設計基礎練習題與答案 
1. 編寫一個控制檯應用程式,完成下列功能。 


  1) 建立一個類,用無引數的建構函式輸出該類的類名。 


  2) 增加一個過載的建構函式,帶有一個string型別的引數,在此建構函式中將傳遞的字串打印出來。 


  3) 在Main方法中建立屬於這個類的一個物件,不傳遞引數。 


  4) 在Main方法中建立屬於這個類的另一個物件,傳遞一個字串“This is a string.”。 


  5) 在Main方法中宣告型別為這個類的一個具有5個物件的陣列,但不要實際建立分配到數組裡的物件。 


  6) 寫出執行程式應該輸出的結果。 


  【解答】 




  using System;  
  class Test1  
  {  
  public Test1()  
  {  
  Console.WriteLine(this);  
  }  
  public Test1(string str)  
  {  
  Console.WriteLine(str);  
  }  
  public static void Main()  
  {  
  Test1 t1 = new Test1();  
  Test1 t2 = new Test1("This is a string.");  
  Test1[] t3 = new Test1[5];  
  }  
  } 


  輸出結果: 


  Test1 


  This is a string. 


  2. 編寫一個控制檯應用程式,定義一個類MyClass,類中包含有public、private以及protected資料成員及方法。然後定義一個從MyClass類繼承的類MyMain,將Main方法放在MyMain中,在Main方法中建立MyClass類的一個物件,並分別訪問類中的資料成員及方法。要求註明在試圖訪問所有類成員時哪些語句會產生編譯錯誤。 


  【解答】 




  using System;  
  class MyClass  
  {  
  public int i;  
  private int j;  
  protected int k;  
  public void method1()  
  {  
  Console.WriteLine("public method.");  
  }  
  private void method2()  
  {  
  Console.WriteLine("private method.");  
  }  
  protected void method3()  
  {  
  Console.WriteLine("protected method.");  
  }  
  }  
  class MyMain : MyClass  
  {  
  public static void Main()  
  {  
  MyClass t = new MyClass();  
  Console.WriteLine("i={0}", t.i);  
  Console.WriteLine("j={0}", t.j); //會出現編譯錯誤,私有成員不允許在其它類中訪問  
  Console.WriteLine("k={0}", t.k); //會出現編譯錯誤,應該建立MyMain的物件,然  
  //後通過MyMain的物件訪問  
  t.method1();  
  t.method2(); //會出現編譯錯誤,私有的方法不允許在其它類中呼叫  
  t.method3(); //會出現編譯錯誤,應該建立MyMain的物件,然後通過MyMain的  
  //物件呼叫該方法  
  }  
  } 


  3. 建立一個類包含有protected資料。在相同的檔案裡建立第二個類,用一個方法操縱第一個類裡的protected資料。 


  【解答】 




  using System;  
  class Class1  
  {  
  protected int i = 5;  
  protected void MyMethod()  
  {  
  Console.WriteLine("protected method.");  
  }  
  }  
  class Class2 : Class1  
  {  
  private void NewMethod()  
  {  
  Console.WriteLine(this.i);  
  this.i += 10;  
  Console.WriteLine(this.i);  
  }  
  public static void Main()  
  {  
  Class2 t = new Class2();  
  t.NewMethod();  
  }  
  } 


  4. 分別寫出下列語句執行的結果。 


  1) Console.WriteLine("{0}--{0:p}good",12.34F); 


  2) Console.WriteLine("{0}--{0:####}good",0); 


  3) Console.WriteLine("{0}--{0:00000}good",456); 


  【解答】 


  12.34--1,234.00%good 


  0--good 


  456--00456good 


  5. 編寫一個控制檯應用程式,計算 


  要求精度為10-8。 


  【解答】 




  using System;  
  class Test5  
  {  
  public static void Main()  
  {  
  int n = 50;  
  double x = 3;  
  double s = 0;  
  double a = 1;  
  for (int i = 1; i <= n; i++)  
  {  
  a *= i;  
  s += Math.Pow(-1, i + 1) * Math.Pow(x, i) / a;  
  }  
  Console.WriteLine("n={0},s={1:0.00000000}", n, s);  
  }  
  } 


  6. 編寫一個控制檯應用程式,接收一個長度大於3的字串,完成下列功能 


  1) 輸出字串的長度。 


  2) 輸出字串中第一個出現字母a的位置。 


  3) 在字串的第3個字元後面插入子串“hello”,輸出新字串。 


  4) 將字串“hello”替換為“me”,輸出新字串。 


  5) 以字元“m”為分隔符,將字串分離,並輸出分離後的字串。 


  【解答】 

  using System;  
  class Test6  
  {  
  public static void Main()  
  {  
  string str = "";  
  while (str.Length <= 3)  
  {  
  Console.Write("請輸入一個長度大於3的字串:");  
  str = Console.ReadLine();  
  }  
  //(1)  
  Console.WriteLine("字串的長度為:{0}", str.Length);  
  //(2)  
  int i = str.IndexOf('a');  
  if (i > -1)  
  {  
  Console.WriteLine("第一個出現字母a的位置是:{0}", i);  
  }  
  else  
  {  
  Console.WriteLine("字串中不包含字母a。");  
  }  
  //(3)  
  string str1 = str.Insert(3, "hello"); //在第3個(初始序號為)字元前插入hello  
  Console.WriteLine("插入hello後的結果為:{0}", str1);  
  //(4)  
  string str2 = str1.Replace("hello", "me");  
  Console.WriteLine("將hello替換為me後的結果為:{0}", str2);  
  //(5)  
  string[] arr = str2.Split('m');  
  Console.WriteLine("以m為分隔符分離後的字串有:");  
  for (int j = 0; j < arr.Length; j++)  
  {  
  Console.WriteLine(arr[j]);  
  }  
  }  
  } 
1. 與結構化程式設計方法相比,面向物件程式設計有哪些優點? 


  【解答】 


  (1) 以過程為中心和物件為中心的比較 


  結構化程式設計方法是以過程為中心的,當面對一個問題時,該方法側重於問題解決過程的層次結構。面向物件的分析和設計方法側重於物件。物件具有特定的行為和屬性,行為和屬性決定了物件與其他物件的互動作用方式,以及物件本身的行為方式。 


  (2) 公開資料和隱藏資料的比較 


  結構化程式設計方法對資料和過程僅僅進行簡單的包裝,這些資料和過程是公開的,或者說程式中的其他程式碼可以訪問這些資料和過程。面向物件的實現隱藏了特定的資料,並且只把物件的特定行為公開給使用者。實現這些特定行為的程式碼對使用者來說是不可見的,使用者只能訪問這些公開的行為。 


  (3) 單一單元和標準單元的比較 


  結構化程式設計方法是基於單一程式碼單元的。面向物件的程式設計方法允許物件是獨立的。 


  (4) 一次性使用和可重用的比較 


  根據不同的實現,結構化過程可能無法重用。而面向物件的方法,物件是一個模組單元。具有完備的實體,因此可以具有高度的可重用性。 


  (5) 有序演算法和無序演算法的比較 


  結構化程式設計方法所開發的程式,其結構往往是線性的(或者說是自頂向下的)。而面向物件的應用程式是一種基於訊息或者事件驅動的程式型別。每個物件都可以向其他物件傳送訊息。Windows作業系統就是這樣的程式。 


  2. 簡要回答下列問題。 


  1) 舉例說明new關鍵字可用於那些方面? 


  2) sealed關鍵字的作用是什麼?什麼情況下需要使用sealed關鍵字? 


  3) 哪些關鍵字可以用於版本控制? 


  【解答】 


  1) 在C#中,new關鍵字可用作運算子或修飾符。作為運算子用於在堆上建立物件和呼叫建構函式。作為修飾符用於隱藏基類成員的繼承成員。 


  2) 在類宣告中使用sealed修飾符可防止其它類繼承此類。在方法宣告中使用sealed修飾符可防止擴充類重寫此方法。 


  sealed修飾符主要用於防止非有意的派生,但是它還能促使某些執行時優化。具體說來,由於密封類永遠不會有任何派生類,所以對密封類的例項的虛擬函式成員的呼叫可以轉換為非虛擬呼叫來處理。 


  3) override關鍵字和new關鍵字均可用於版本控制。 


  在C#中,預設情況下方法不是虛擬的。若要使方法成為虛擬方法,必須在基類的方法宣告中使用virtual修飾符。然後,派生類可以使用override關鍵字重寫基類中的虛擬方法,或使用new關鍵字隱藏基類中的虛擬方法。如果override關鍵字和new關鍵字均未指定,編譯器將發出警告,並且派生類中的方法將隱藏基類中的方法。 


  3. 簡要回答抽象類和介面的主要區別。 


  【解答】 


  抽象類和介面的一個主要差別是:類可以實現多個介面,但僅能從一個抽象類或任何其它型別的類繼承。 


  4. 使用委託的優點是什麼?委託和事件有什麼區別和聯絡? 


  【解答】 


  C#中的委託類似於C或C++中的函式指標。使用委託使程式設計師可以將方法引用封裝在委託物件內。然後可以將該委託物件傳遞給可呼叫所引用方法的程式碼,而不必在編譯時知道將呼叫哪個方法。與C或C++中的函式指標不同,委託是面向物件,而且是型別安全的。 


  C#中的“事件”是當物件發生某些事情時,類向該類的客戶提供通知的一種方法。事件最常見的用途是用於圖形使用者介面;通常,表示介面中的控制元件的類具有一些事件,當用戶對控制元件進行某些操作(如單擊某個按鈕)時,將通知這些事件。 


  使用委託來宣告事件。委託物件封裝一個方法,以便可以匿名呼叫該方法。事件是類允許客戶為其提供方法(事件發生時應呼叫這些方法)的委託的一種方法。事件發生時,將呼叫其客戶提供給它的委託。 


  5. 編寫一個控制檯應用程式,完成下列功能,並回答提出的問題。 


  1) 建立一個類A,在建構函式中輸出“A”,再建立一個類B,在建構函式中輸出“B”。 


  2) 從A繼承一個名為C的新類,並在C內建立一個成員B。不要為C建立建構函式。 


  3) 在Main方法中建立類C的一個物件,寫出執行程式後輸出的結果。 


  4) 如果在C中也建立一個建構函式輸出“C”,整個程式執行的結果又是什麼? 


  【解答】 


  using System;  
  public class A  
  {  
  public A()  
  {  
  Console.WriteLine("A");  
  }  
  }  
  public class B  
  {  
  public B()  
  {  
  Console.WriteLine("B");  
  }  
  }  
  public class C : A  
  {  
  B newb = new B();  
  }  
  class MainClass  
  {  
  public static void Main()  
  {  
  C newc = new C();  
  Console.ReadLine();  
  }  
  } 


  輸出結果: 


  B 


  A 


  如果在C中也建立一個建構函式輸出“C”,即新增: 




  public C()  
  {  
  Console.WriteLine("C");  
  } 


  則整個程式執行的結果為: 


  B 


  A 


  C 


  6. 編寫一個控制檯應用程式,完成下列功能,並寫出執行程式後輸出的結果。 


  1) 建立一個類A,在A中編寫一個可以被重寫的帶int型別引數的方法MyMethod, 


  並在該方法中輸出傳遞的整型值加10後的結果。 


  2) 再建立一個類B,使其繼承自類A,然後重寫A中的MyMethod方法,將A中接 


  收的整型值加50,並輸出結果。 


  3) 在Main方法中分別建立類A和類B的物件,並分別呼叫MyMethod方法。 


  【解答】 




  using System;  
  public class A  
  {  
  public virtual void MyMethod(int num)  
  {  
  num += 10;  
  Console.WriteLine(num);  
  }  
  }  
  public class B : A  
  {  
  public override void MyMethod(int num)  
  {  
  num += 50;  
  Console.WriteLine(num);  
  }  
  }  
  class MainClass  
  {  
  public static void Main()  
  {  
  A newa = new A();  
  newa.MyMethod(2);  
  B newb = new B();  
  newb.MyMethod(2);  
  Console.ReadLine();  
  }  
  } 


  輸出結果: 


  12 


  52 


  7. 假設Node類的每一個節點包括有兩個欄位:m_data(引用節點的資料)和m_next(引用連結列表中的下一項)。這兩個欄位都是由建構函式方法設定的。該類有兩個功能,第一個功能是通過名為Data和Next的只讀屬性訪問m_data和m_next欄位。第二個功能是對System.Object的ToString虛擬方法進行重寫。試分別用類和泛型兩種方法編寫程式實現上述功能。 


  【解答】 




  using System;  
  class Node  
  {  
  Object m_data;  
  Node m_next;  
  public Node(Object data, Node next)  
  {  
  m_data = data;  
  m_next = next;  
  }  
  // 訪問結點資料  
  public Object Data  
  {  
  get { return m_data; }  
  }  
  // 訪問下一個結點  
  public Node Next  
  {  
  get { return m_next; }  
  }  
  // 獲取結點資料描述  
  public override String ToString()  
  {  
  return m_data.ToString();  
  }  
  }  
  // 連結串列結點類的泛型定義  
  class Node  
  {  
  T m_data;  
  Node m_next;  
  public Node(T data, Node next)  
  {  
  m_data = data;  
  m_next = next;  
  }  
  // 訪問結點資料  
  public T Data  
  {  
  get { return m_data; }  
  set { m_data = value; }  
  }  
  // 訪問下一個結點  
  public Node Next  
  {  
  get { return m_next; }  
  set { m_next = value; }  
  }  
  // 獲取結點資料描述  
  public override String ToString()  
  {  
  return m_data.ToString();  
  }  
  }  
  // 使用結點型別或泛型結點型別  
  class LinkedList  
  {  
  static void Main(string[] args)  
  {  
  //// 建立整數連結串列  
  //Node head = new Node(5, null);  
  //head = new Node(10, head);  
  //head = new Node(15, head);  
  ////遍歷連結串列求整數和  
  //Int32 sum = 0;  
  //for (Node current = head; current != null;  
  // current = current.Next)  
  //{  
  // sum += (Int32)current.Data;  
  //}  
  //// 輸出結果  
  //Console.WriteLine("Sum of nodes = {0}", sum);  
  // 用泛型建立整數連結串列  
  Node head = new Node(5, null);  
  head = new Node(10, head);  
  head = new Node(15, head);  
  // 遍歷求和  
  Int32 sum = 0;  
  for (Node current = head; current != null;  
  current = current.Next)  
  {  
  sum += current.Data;  
  }  
  // 輸出  
  Console.WriteLine("Sum of nodes = {0}", sum.ToString());  
  }  
  } 
#網路應用程式設計基礎練習題與答案(5) 


1. 填空題 


  1) 使控制元件是否可以對使用者互動作出響應的屬性是 Enabled 。 


  2) 控制控制元件是否顯示的屬性是 Visible 。 


  3) 若要在文字框中輸入密碼,常指定 PasswordChar 屬性。 


  4) 若某複選框某時刻CheckState屬性的值為Indeterminate,則其屬性Checked的值為 Unchecked 。 


  5) 使用 Panel 或 GroupBox 控制元件可以將多個RadioButton控制元件分為兩個單選組。 


  6) 若不希望使用者在ComboBox控制元件中編輯文字,則應將屬性 DropDownStyle 的屬性值設定為DropDownList。 


  7) 用於設定MenuStrip控制元件中某選單項快捷鍵的屬性是 ShortcutKeys 。 


  8) 用於控制ListView控制元件中的各項顯示方式的屬性是 View 。 


  2. 判斷題 


  1) 控制元件就是屬性、方法和事件的集合封裝體。 ( 對 ) 


  2) TextBox控制元件只能用於單行文字的輸入。 ( 錯 ) 


  3) 通過RichTextBox控制元件只能夠與RTF檔案進行互動操作。 ( 錯 ) 


  4) CheckBox控制元件的Checked屬性與CheckState屬性的值始終是相同的。 ( 錯 ) 


  5) ToolTip元件用於顯示某指定控制元件的自定義提示資訊的。 ( 對 ) 


  3. 區別TextBox控制元件、MaskedTextBox控制元件、RichTextBox控制元件的使用場合。 


  【解答】 


  TextBox控制元件一般用於單段文字的編輯,可以設定為單行或多行的輸入模式,也可以用作密碼的輸入;MaskedTextBox控制元件主要用於特定格式的單段文字編輯,在輸入文字不符合格式要求的將會觸發其MaskInputRejected事件;RichTextBox控制元件除了具有TextBox的一般文字編輯功能外,還可以進行多段文字的高階編輯功能,如改變文字、段落的顯示格式、在文字中查詢特定字元和字串以及與Rtf檔案的互動等。 


  4. 簡要說明CheckBox控制元件和RadioButton控制元件的區別。 


  【解答】 


  CheckBox控制元件可為使用者提供選擇功能,常用的是二選一的選擇,如“真/假”或“是/否”;但該控制元件也可以通過屬性的設定作三選一的選擇。每一個CheckBox所代表的選擇都是獨立的,若有多個CheckBox控制元件構成一組選項時,則可以多個同時被選中,相互之間不影響,即複選。RadioButton控制元件,它與CheckBox控制元件功能類似,也是用於接收使用者的選擇,但它是以單項選擇的形式出現,即一組RadioButton按鈕中只能有一個處於選中狀態。一旦某一項被選中,則同組中其他RadioButton按鈕的選中狀態自動清除。 


  5. 設計一個Windows應用程式,窗體上有一個TextBox控制元件、一個Button控制元件。要求,每當使用者單擊按鈕時,文字框都會增加一行文字來反映單擊的次數,例如“第3次單擊按鈕”。 


  【解答】 


  1) 窗體介面如圖Ex5-5-1所示; 






  2) 窗體中主要控制元件屬性設定如表Ex5-5-1; 


表Ex5-5-1 窗體中的主要控制元件屬性 


控制元件 
 Name屬性 
 功能 
 其它屬性 
  
TextBox控制元件 
 textBox1 
 顯示資訊 
 ScrollBars=Vertical; Multiline=True 
  
Button控制元件 
 Button1 
 觸發新增資訊事件 
  
  
Button2 
 觸發結束新增事件 
  


  3) 主要事件程式碼。 




  ……  
  int i = 1;  
  bool Add = true;  
  ……private void button1_Click(object sender, EventArgs e)  
  {  
  if(Add) textBox1.Text += "第" + i + "次單擊按鈕\r\n";  
  i++;  
  }  
  private void button2_Click(object sender, EventArgs e)  
  {  
  Add = false;  
  } 


  6. 編寫一段程式,向ListBox控制元件listBox1中,自動新增10個數,每個數佔一項。 


  【解答】 


  主要程式碼如下: 




  public partial class Form1 : Form  
  {  
  int m = 1;  
  ……  
  private void button1_Click(object sender, EventArgs e)  
  {  
  for (int i = m ; i < m+10; i++)  
  {  
  listBox1.Items.Add(i);  
  }  
  m = m + 10;  
  }  
  } 


  7. 參照Windows系統“附件”中的“計算器”,自行編寫一個簡易的計算器。要求:可以實現由0~4構成的整數的加減運算。 


  【解答】 


  1) 窗體介面如圖Ex5-5-2所示; 






  2) 將InputNumber事件作為button0、button1、button2、button3、button4的Click事件。 


  完整程式碼如下: 




  using System;  
  using System.Collections.Generic;  
  using System.ComponentModel;  
  using System.Data;  
  using System.Drawing;  
  using System.Text;  
  using System.Windows.Forms;  
  namespace Exer2  
  {  
  public partial class FormCalculator : Form  
  {  
  enum calculateType { none, add, sub };  
  calculateType myCal = calculateType.none;  
  int x, y;  
  bool isY = false;  
  public FormCalculator()  
  {  
  InitializeComponent();  
  textBox.TextAlign = HorizontalAlignment.Right;  
  }  
  private void InputNumber(object sender, EventArgs e)  
  {  
  Button num = (Button)sender;  
  if (isY)  
  {  
  textBox.Clear();  
  isY = false;  
  }  
  textBox.Text += num.Text;  
  }  
  private void buttonEqual_Click(object sender, EventArgs e)  
  {  
  y = Convert.ToInt32(textBox.Text);  
  if (myCal == calculateType.add)  
  {  
  textBox.Text = Convert.ToString(x + y);  
  myCal = calculateType.none;  
  }  
  if (myCal == calculateType.sub)  
  {  
  textBox.Text = Convert.ToString(x - y);  
  myCal = calculateType.none;  
  }  
  isY = true;  
  }  
  private void addButton_Click(object sender, EventArgs e)  
  {  
  myCal = calculateType.add;  
  x = Convert.ToInt32(textBox.Text);  
  isY = true;  
  }  
  private void buttonSub_Click(object sender, EventArgs e)  
  {  
  myCal = calculateType.sub;  
  x = Convert.ToInt32(textBox.Text);  
  isY = true;  
  }  
  private void buttonClear_Click(object sender, EventArgs e)  
  {  
  textBox.Text = "";  
  myCal = calculateType.none;  
  isY = false;  
  }  
  }  
  } 


  8. 試利用TreeView、ListView等控制元件實現一個類似“資源管理器”的文件管理程式,用於檢視C:\Documents and Settings目錄下的檔案。 


  【解答】 


  1) 新建一個名為WindowsControlsExercise的專案,在【解決方案資源管理器】中重新命名檔案Form1.cs為Explorer.cs,並設定Form1窗體的Text屬性為“資源管理器”。 


  2) 向窗體中新增一個SplitContainer控制元件、一個ImageList控制元件、一個TreeView控制元件、一個ListView控制元件,頁面佈局及各控制元件屬性如圖Ex5-5-3所示。 






  3) 在【解決方案資源管理器】中,將imageList1控制元件中的兩個圖示檔案新增到應用程式目錄中,分別命名為folder.ico和doc.ico。 


  4) 在Explorer.cs程式碼檔案中新增名稱空間:using System.IO,並新增建構函式程式碼如下: 




  public Explorer()  
  {  
  InitializeComponent();  
  PopulateTreeView();  
  }  
  private void PopulateTreeView()  
  {  
  TreeNode rootNode;  
  DirectoryInfo info = new DirectoryInfo(@"C:\Documents and Settings");  
  if (info.Exists)  
  {  
  rootNode = new TreeNode(info.Name);  
  rootNode.Tag = info;  
  GetDirectories(info.GetDirectories(), rootNode);  
  treeView1.Nodes.Add(rootNode);  
  }  
  }  
  private void GetDirectories(DirectoryInfo[] subDirs, TreeNode nodeToAddTo)  
  {  
  TreeNode aNode;  
  DirectoryInfo[] subSubDirs;  
  foreach (DirectoryInfo subDir in subDirs)  
  {  
  aNode = new TreeNode(subDir.Name, 0, 0);  
  aNode.Tag = subDir;  
  aNode.ImageKey = "folder";  
  subSubDirs = subDir.GetDirectories();  
  if (subSubDirs.Length != 0)  
  {  
  GetDirectories(subSubDirs, aNode);  
  }  
  nodeToAddTo.Nodes.Add(aNode);  
  }  
  }  
  5) 新增treeView1的NodeMouseClick事件,使單擊treeView1中某個節點時,用該節點的內容來填充listView1。  
  private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)  
  {  
  TreeNode newSelected = e.Node;  
  listView1.Items.Clear();  
  DirectoryInfo nodeDirInfo = (DirectoryInfo)newSelected.Tag;  
  ListViewItem.ListViewSubItem[] subItems;  
  ListViewItem item = null;  
  foreach (DirectoryInfo dir in nodeDirInfo.GetDirectories())  
  {  
  item = new ListViewItem(dir.Name, 0);  
  subItems = new ListViewItem.ListViewSubItem[]  
  {new ListViewItem.ListViewSubItem(item, "Directory"),  
  new ListViewItem.ListViewSubItem(item,  
  dir.LastAccessTime.ToShortDateString())};  
  item.SubItems.AddRange(subItems);  
  listView1.Items.Add(item);  
  }  
  foreach (FileInfo file in nodeDirInfo.GetFiles())  
  {  
  item = new ListViewItem(file.Name, 1);  
  subItems = new ListViewItem.ListViewSubItem[]  
  { new ListViewItem.ListViewSubItem(item, "File"),  
  new ListViewItem.ListViewSubItem(item,  
  file.LastAccessTime.ToShortDateString())};  
  item.SubItems.AddRange(subItems);  
  listView1.Items.Add(item);  
  }  
  listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);  
  } 


  6) 按鍵編譯並執行。 


1. 簡要回答檔案和流之間的區別和聯絡。 


  【解答】 


  檔案(file)和流(stream)即有區別又有聯絡。檔案是在各種媒質上(可移動磁碟、硬碟、CD 等)永久儲存的資料的有序集合。它是一種進行資料讀寫操作的基本物件。通常情況下,檔案按照樹狀目錄進行組織,每個檔案都有檔名、檔案所在路徑、建立時間、訪問許可權等屬性。 


  流是位元組序列的抽象概念,例如檔案、輸入輸出裝置、內部程序通訊管道或者TCP/IP套接字等均可以看成流。流提供一種向後備儲存器寫入位元組和從後備儲存器讀取位元組的方式。 


  2. Directory類為我們提供了哪些目錄管理的功能,它們是通過哪些方法來實現的? 


  【解答】 


  Directory類為我們提供了對磁碟和目錄進行管理的功能,如複製、移動、重新命名、建立和刪除目錄,獲取和設定與目錄的建立、訪問及寫入操作相關的時間資訊。 


  如:CreateDirectory方法用於建立指定路徑中的所有目錄;Delete方法用於刪除指定的目錄;Move方法能夠重新命名或移動目錄;Exists方法用於確定給定路徑是否引用磁碟上的現有目錄;GetCurrentDirectory方法用於獲取應用程式的當前工作目錄;GetFiles方法用於返回指定目錄中的檔案的名稱等。 


  3. 編寫程式綜合應用Directory類的主要方法。首先確定指定的目錄是否存在,如果存在,則刪除該目錄;如果不存在,則建立該目錄。然後,移動此目錄,在其中建立一個檔案,並對檔案進行計數。 


  【解答】 


  程式清單如下: 




  using System;  
  using System.IO;  
  class Test  
  {  
  public static void Main()  
  {  
  string path = @"c:\MyDir";  
  string target = @"c:\TestDir";  
  try  
  {  
  if (!Directory.Exists(path))  
  {  
  Directory.CreateDirectory(path);  
  }  
  if (Directory.Exists(target))  
  {  
  Directory.Delete(target, true);  
  }  
  Directory.Move(path, target);  
  File.CreateText(target + @"\myfile.txt");  
  Console.WriteLine("在{0}中的檔案數目是{1}",  
  target, Directory.GetFiles(target).Length);  
  }  
  catch (Exception e)  
  {  
  Console.WriteLine("操作失敗: {0}", e.ToString());  
  }  
  finally {}  
  }  
  } 


  4. 編寫程式,將檔案複製到指定路徑,允許改寫同名的目標檔案。 


  【解答】 


  程式清單如下: 




  using System;  
  using System.IO;  
  class Test  
  {  
  public static void Main()  
  {  
  string path = @"c:\temp\MyTest.txt";  
  string path2 = path + "temp";  
  try  
  {  
  using (FileStream fs = File.Create(path)) {}  
  File.Delete(path2);  
  File.Copy(path, path2);  
  Console.WriteLine("{0}拷貝到:{1}", path, path2);  
  File.Copy(path, path2, true);  
  Console.WriteLine("第二次拷貝成功");  
  }  
  catch  
  {  
  Console.WriteLine("重複拷貝不允許");  
  }  
  }  
  } 


  5. 編寫程式,使用File類實現刪除當前目錄下的所有檔案。 


  【解答】 


  程式清單如下: 




  using System;  
  using System.IO;  
  class FileTest  
  {  
  public static void Main()  
  {  
  Console.WriteLine("確認刪除當前目錄下的所有檔案?");  
  Console.WriteLine("點選'Y'鍵繼續,其它鍵取消操作");  
  int a = Console.Read();  
  if(a == 'Y' || a == 'y'){  
  Console.WriteLine("正在刪除檔案...");  
  }  
  else  
  {  
  Console.WriteLine("使用者取消操作");  
  return;  
  }  
  DirectoryInfo dir = new DirectoryInfo (".");  
  foreach (FileInfo f in dir.GetFiles())  
  {  
  f.Delete();  
  }  
  }  
  } 
1. 解釋正則表示式 <a\s+href\s*=\s*""?([^"" >]+)""?>(.+)</a>各部分代表的含義。 


  【解答】 此正則表示式用於匹配原始檔中類似於搜狐新聞的字串,各部分表示的含義為: 


  \s+ 一個或多個空白字元 


  href 後接 HTML 定位點中的確切文字 


  \s* 零個或多個空白字元 


  = 後接 HTML 定位點中的確切文字 


  \s* 零個或多個空白字元 


  ""? 零或無引號(轉義的) 


  ( 定義子字串(定位點 URL)的組的起始點。 


  [^"" >]+ 任意字元的一個或多個匹配項,括號中的字元除外。 


  ) 定義子字串的第一組的結束 


  ""? 零或無引號(轉義的) 


  > 後接 HTML 定位點中的確切文字 


  (.+) 與任意字元(定位點文字)匹配的組。 


  結束 HTML 定位點的確切文字 


  2. 下面是檢查輸入字串是否為有效的電子郵件的正則表示式: 


  ^([\w-]+\.)*?[\w-]
[email protected]
[\w-]+\.([\w-]+\.)*?[\w]+$ 


  試解釋各部分的含義。 


  【解答】 


  [\w-]+ 


  一個或多個任意字元(a-z、A-Z、0-9 以及下劃線)或短劃線。在@字元兩邊,確保地址形式為[email protected]。 


  \. 


  一個轉義點號。(不帶反斜槓,一個點號與除換行符外的任意單個字元匹配。)以此確保域名中至少有一個點號。 


  *? 


  對前面的表示式,非貪婪(non-greedy,即最小)地查詢零次或多次匹配。 


  ([\w-]+\.)*? 


  以上三個表示式的組合: 


  對於包含一個或多個任意字元(a-z、A-Z、0-9 以及下劃線)或短劃線並且後面只跟一個點號的表示式,非貪婪地查詢零次或多次匹配。 


  3. 寫出符合下列要求的正則表示式: 


  1) 要求4-8個英文字母。 


  2) 不能包含字母,至少1個字元。 


  3) 至少3個數字。 


  4) 至少3個字元。 


  5) 至少3個英文字母。 


  6) 任意字元。 


  7) 3個字母或數字,如123,r3a等。 


  8) 3個點。 


  9) @前至少有1個字元,@後至少有3個字元。 


  10) 必須輸入左括號。 


  【解答】 


  1) [a-zA-Z]{4,8} 


  2) [^a-zA-Z]{1,} 


  3) [0-9]{3,} 


  4) {3,} 


  5) [a-zA-Z]{3,} 


  6) .{0,} 


  7) [A-Za-z0-9]{3} 


  8) \.{3} 


  9) .{1,}@ .{3,} 


  10) \( 


C#網路應用程式設計基礎練習題與答案(8) 
1. 使用保持連線的方式編寫程式,計算各年級平均成績,並顯示結果。 


  【解答】 




  using System;  
  using System.Collections.Generic;  
  using System.ComponentModel;  
  using System.Data;  
  using System.Drawing;  
  using System.Text;  
  using System.Windows.Forms;  
  using System.Data.SqlClient;  
  namespace 習題8_6_1  
  {  
  public partial class Form1 : Form  
  {  
  public Form1()  
  {  
  InitializeComponent();  
  }  
  //新增Button按鈕在ListBox中顯示結果  
  private void button1_Click(object sender, EventArgs e)  
  {  
  listBox1.Items.Add("年級 平均成績");  
  string connectionString = Properties.Settings.Default.MyDatabaseConnectionString;  
  //根據連線字串建立SqlConnection例項  
  SqlConnection conn = new SqlConnection(connectionString);  
  //建立SqlCommand例項,並設定SQL語句和使用的連線例項  
  SqlCommand cmd = new SqlCommand();  
  cmd.CommandText = "select substring(學號,1,2) as 年級,avg(成績) as 平均成績 from MyTable2 group by substring(學號,1,2)";  
  cmd.Connection = conn;  
  try  
  {  
  conn.Open();  
  SqlDataReader r = cmd.ExecuteReader();  
  while (r.Read() == true)  
  {  
  listBox1.Items.Add(string.Format("{0}級 {1}", r[0], r[1]));  
  }  
  r.Close();  
  }  
  catch (Exception err)  
  {  
  MessageBox.Show(err.Message, "計算成績失敗");  
  }  
  finally  
  {  
  conn.Close();  
  }  
  }  
  }  
  } 


  2. 使用保持連線的方式編寫程式,查詢MyTable2中不及格學生的學號,姓名,性別,成績。並將結果在ListBox中顯示出來。 


  【解答】 




  using System;  
  using System.Collections.Generic;  
  using System.ComponentModel;  
  using System.Data;  
  using System.Drawing;  
  using System.Text;  
  using System.Windows.Forms;  
  using System.Data.SqlClient;  
  namespace 習題8_6_2  
  {  
  public partial class Form1 : Form  
  {  
  public Form1()  
  {  
  InitializeComponent();  
  }  
  private void button1_Click(object sender, EventArgs e)  
  {  
  listBox1.Items.Add(" 學號 姓名 性別 成績");  
  string connectionString = Properties.Settings.Default.MyDatabaseConnectionString;  
  //根據連線字串建立SqlConnection例項  
  SqlConnection conn = new SqlConnection(connectionString);  
  //建立SqlCommand例項,並設定SQL語句和使用的連線例項  
  SqlCommand cmd = new SqlCommand();  
  cmd.CommandText =  
  "Select 學號,姓名,性別, 成績 From MyTable2 Where (成績<60)";  
  cmd.Connection = conn;  
  try  
  {  
  conn.Open();  
  SqlDataReader r = cmd.ExecuteReader();  
  while (r.Read() == true)  
  {  
  listBox1.Items.Add( string.Format("{0} {1} {2} {3}", r[0], r[1], r[2], r[3]));  
  }  
  r.Close();  
  }  
  catch (Exception err)  
  {  
  MessageBox.Show(err.Message, "查詢成績失敗");  
  }  
  finally  
  {  
  conn.Close();  
  }  
  }  
  }  
  } 


  3. 編寫程式,以“[編碼]名稱”的樣式在comboBox1中顯示MyTable1的內容。 


  【解答】 




  using System;  
  using System.Collections.Generic;  
  using System.ComponentModel;  
  using System.Data;  
  using System.Drawing;  
  using System.Text;  
  using System.Windows.Forms;  
  using System.Data.SqlClient;  
  namespace 習題8_6_3  
  {  
  public partial class Form1 : Form  
  {  
  public Form1()  
  {  
  InitializeComponent();  
  }  
  private void Form1_Load(object sender, EventArgs e)  
  {  
  string connectionString = Properties.Settings.Default.MyDatabaseConnectionString;  
  //根據連線字串建立SqlConnection例項  
  SqlConnection conn = new SqlConnection(connectionString);  
  //建立SqlCommand例項,並設定SQL語句和使用的連線例項  
  SqlCommand cmd = new SqlCommand();  
  cmd.CommandText = "Select * From MyTable1";  
  cmd.Connection = conn;  
  try  
  {  
  conn.Open();  
  SqlDataReader r = cmd.ExecuteReader();  
  while (r.Read() == true)  
  {  
  comboBox1.Items.Add(string.Format("[{0}] {1}", r[0], r[1]));  
  }  
  comboBox1.SelectedIndex = 0;  
  r.Close();  
  }  
  catch (Exception err)  
  {  
  MessageBox.Show(err.Message, "顯示資料失敗");  
  }  
  finally  
  {  
  conn.Close();  
  }  
  }  
  }  
  } 


  4. 在畫線處填上合適的內容,使程式變得正確完整。 




  string connString="server=localhost;Integrated Security=SSPI;database=pubs";  
  SqlConnection conn=____________________________  
  string strsql="select * from MyTable2";  
  SqlDataAdapter adapter=new SqlDataAdapter(_____________);  
  dataset=new DataSet();  
  adapter.Fill(________________,"MyTable2");  
  this.dataGridView1.DataSource=dataset.Tables["MyTable2"]; 


  【解答】 




  string connString="server=localhost;Integrated Security=SSPI;database=pubs";  
  SqlConnection conn= new SqlConnection(Properties.Settings.Default.MyDatabaseConnectionString);  
  string strsql="select * from MyTable2";  
  SqlDataAdapter adapter=new SqlDataAdapter(conn);  
  dataset=new DataSet();  
  adapter.Fill(dataset,"MyTable2");  
  this.dataGridView1.DataSource=dataset.Tables["MyTable2"]; 


  5. 已知資料庫中定義了一張person表,表的資料結構如下: 


  欄位名稱欄位型別欄位含義 


  id數字編號 


  xm文字姓名 


  xb文字性別 


  nl數字年齡 


  zip文字郵政編碼 


  用編寫程式碼的方法在DataGridView中顯示該資料表中年齡大於18的所有紀錄,顯示時以編號的升序排序,要求禁止使用者編輯資料。 


  【解答】 




  using System;  
  using System.Collections.Generic;  
  using System.ComponentModel;  
  using System.Data;  
  using System.Drawing;  
  using System.Text;  
  using System.Windows.Forms;  
  using System.Data.SqlClient;  
  namespace 習題8_6_5  
  {  
  public partial class Form1 : Form  
  {  
  public Form1()  
  {  
  InitializeComponent();  
  }  
  private void button1_Click(object sender, EventArgs e)  
  {  
  string connectionstring = Properties.Settings.Default.MyDatabaseConnectionString ;  
  SqlConnection conn = new SqlConnection(connectionstring);  
  try  
  {  
  conn.Open();  
  SqlDataAdapter adapter = new SqlDataAdapter(  
  "select id,xm,xb,nl from person where nl > 18 order by id", conn);  
  DataSet dataset = new DataSet();  
  //如果不指定表名,則系統自動生成一個預設的表名  
  adapter.Fill(dataset, "person");  
  //可以使用索引引用生成的表  
  dataGridView1.DataSource = dataset.Tables["person"];  
  adapter.Dispose();  
  }  
  catch (Exception err)  
  {  
  MessageBox.Show(err.Message);  
  }  
  finally  
  {  
  conn.Close();  
  }  
  }  
  private void Form1_Load(object sender, EventArgs e)  
  {  
  //不允許使用者直接在最下面的行新增新行  
  dataGridView1.AllowUserToAddRows = false;  
  //不允許使用者直接按Delete鍵刪除行  
  dataGridView1.AllowUserToDeleteRows = false;  
  }  
  }  
  } 


  6.例8-18的儲存過程定義中,將“@surname nvarchar(2),”改為“@surname nchar(2),”,是否仍然能夠得到正確結果,為什麼? 


  【解答】 


  不一定。因為如果傳遞的引數值為“王”,在儲存過程中會自動變為“王 ”。 


  7. 呼叫儲存過程,設計程式完成下列功能:任意給出一個漢字,統計MyTable2中所有包含該漢字的人數,並顯示統計結果。 


  【解答】 




  using System;  
  using System.Collections.Generic;  
  using System.ComponentModel;  
  using System.Data;  
  using System.Drawing;  
  using System.Text;  
  using System.Windows.Forms;  
  using System.Data.SqlClient;  
  namespace 習題8_6_7  
  {  
  public partial class Form1 : Form  
  {  
  public Form1()  
  {  
  InitializeComponent();  
  }  
  private void button1_Click(object sender, EventArgs e)  
  {  
  SqlConnection conn =  
  new SqlConnection(Properties.Settings.Default.MyDatabaseConnectionString);  
  SqlCommand cmd = new SqlCommand();  
  cmd.Connection = conn;  
  //設定SQL語句為儲存過程名,命令型別為儲存過程  
  cmd.CommandText = "SelectFilterStudentsNum";  
  cmd.CommandType = CommandType.StoredProcedure;  
  //新增儲存過程中引數需要的初始值,注意引數名要和儲存過程定義的引數名相同  
  if( textBox1.Text=="")  
  {  
  MessageBox.Show("請輸入有效資訊","錯誤");  
  textBox1.Focus();  
  return ;  
  }  
  cmd.Parameters.AddWithValue("@surname", textBox1.Text);  
  cmd.Parameters.AddWithValue("@record", 0);  
  //指定哪些引數需要返回結果  
  cmd.Parameters["@record"].Direction = ParameterDirection.Output;  
  try  
  {  
  conn.Open();  
  //執行儲存過程  
  cmd.ExecuteNonQuery();  
  //顯示返回的結果  
  MessageBox.Show(string.Format("有{0}條含 {1} 的記錄",  
  cmd.Parameters["@record"].Value,textBox1.Text));  
  }  
  catch (Exception err)  
  {  
  MessageBox.Show(err.Message);  
  }  
  finally  
  {  
  conn.Close();  
  }  
  }  
  }  
  } 
1. 簡述三類二維座標系統之間的相同點和區別。 


  【解答】 


  GDI+中的二維笛卡兒座標系統分為三類:全域性座標系統、頁面座標系統和裝置座標系統。 


  三類座標系統的相同點:它們都有座標原點以及向右和向下的x軸和y軸。 


  三類座標系統的區別:全域性座標系統可以進行旋轉、平移等操作。頁面座標系統與裝置座標系統都是以裝置的左上角為座標原點,X水平向右為正,Y垂直向下為正。頁面座標系統與裝置座標系統的差異在於X,Y的單位不同:頁面座標系中的X,Y單位可以任意設定,如英寸、毫米等;而裝置座標系中,只有一種單位,那就是點(point)或者畫素(pixel)。頁面座標系是不能更改的,它是一個參照標準,將全域性座標最終轉換為裝置座標。 


  2. 簡述建立Graphics類物件的三種方法。 


  【解答】 


  (1) 在窗體或控制元件的Paint事件中直接引用Graphics物件。在為窗體建立繪製程式碼時,一般使用此方法獲取對影象的引用。 


  (2) 從當前窗體獲取對Graphics物件的引用。注意這種物件只有在處理當前Windows窗體訊息的過程中有效。如果想在已經存在的窗體