1. 程式人生 > >第二週學習內容

第二週學習內容

陣列練習

練習:首先遍歷nums1,用一個變數count統計非0的個數 建立一個長度為count的新陣列nums2 遍歷num1,把非0的值依次填入nums2中

        int[] nums1 = { 2, 3, 0, 5, 0, 6, -1 };
        int count = 0;
        for (int i = 0; i < nums1.Length; i++)
        {
            if (nums1[i] != 0)
            {
                count++;
            }
        }
        //Console.WriteLine(count);
        int[] nums2 = new int[count];
        int newIndex = 0;//記錄新資料的拷貝資料
        for (int i = 0; i < nums1.Length; i++)
        {
            if (nums1[i] != 0)
            {
                nums2[newIndex] = nums1[i];
                newIndex++;//新陣列的位置向前挪一下
            }
        }
        for (int i = 0; i < nums2.Length; i++)
        {
            Console.WriteLine(nums2[i]);
        }
        Console.ReadKey();

練習: 將一個字串陣列{“3”,“a”,“8”,“haha”}輸出為|分割的字串,“3|a|8|haha”

        string[] strs = { "3", "a", "8", "haha" };
        string s = "";//和string s;有區別
        for (int i = 0; i < strs.Length - 1; i++)
        {
            string str = strs[i];
            s = s + str + "|";//讀一個變數前,這個變數必須被賦值
        }
        s = s + strs[strs.Length - 1];//加上最後一個
        Console.WriteLine(s);
        Console.ReadKey();

foreach迴圈

foreach(型別 變數名 in 陣列名) 對陣列進行逐個遍歷 和for的區別:for可以不逐個遍歷,比如每隔一個遍歷一個,或者可以從後向前遍歷

依次遍歷names陣列中的內容,對於每條資料都執行{}中的程式碼, 每次遍歷的陣列用in前面的變量表示,變數的型別是陣列的型別

    string[] names = { "tom", "jerry", "lily" };
        //for (int i = 0; i < names.Length; i++)
        //{
        //    string str = names[i];
        //    Console.WriteLine(str);
        //}
     foreach (string str in names)
           {
            Console.WriteLine(str);
           }    

遍歷陣列

        int[] nums = { 3, 5, 9 };
        foreach (int n in nums)
        {
            Console.WriteLine(n);
        }

練習:分別列印陣列中的名字

        string[] names = { "tom", "jerry", "lily" };
         foreach (string name in names)
        {
            Console.WriteLine("我的名字{0}", name);
        }
        Console.ReadKey();

函式

函式就是將一堆程式碼進行重用的一種機制; 函式就是一段程式碼,這段程式碼可能有輸入的值(引數),可能會返回值。 函式:static 返回值型別 函式名(引數列表) 不用函式編寫使用者輸入兩個數,並輸出它們的和。

static void Main(string[] args)
    {
        Console.WriteLine("請輸入第一個數");
        string s1 = Console.ReadLine();
        int i1 = Convert.ToInt32(s1);
        Console.WriteLine("請輸入第二個數");
        string s2 = Console.ReadLine();
        int i2 = Convert.ToInt32(s2);
        int i3 = i1 + i2;
        Console.WriteLine(i3);
        Console.ReadKey();
    }

用函式編寫一:

    static void Main(string[] args)
    {
        int i1 = ReadInt("請輸入第一個數");
        int i2 = ReadInt("請輸入第二個數");
        ReadInt("請輸入第一個數");//沒有返回值也行,但沒啥用
        int i3 = i1 + i2;
       Console.WriteLine(i3);
        Console.ReadKey();
    }
    static int ReadInt(string msg)//返回值型別 函式名(引數列表)
    {
        Console.WriteLine(msg);
        string s = Console.ReadLine();
        int i = Convert.ToInt32(s);
        return i;
    }

練習函式編寫兩個數的和

      static void Main(string[] args)
    {
        int i = Add(5, 6);
        Console.WriteLine(i);
        Console.ReadKey();
    }
         static int Add(int i1, int i2)
    {
        return i1 + i2;
    }

沒有返回值的函式用 void

    static void SayHello()//表示函式沒有返回值
    {
        Console.WriteLine("早上好");
        Console.WriteLine("中午好");
        Console.WriteLine("下午好");
    }

練習:提供一個函式,將使用者提供的一個字串重複n遍形成一個新的字串"abc"3,返回給呼叫者一個字串"abcabcabc"

    static void Main(string[] args)
    {
         Console.WriteLine("請輸入字串");
         string s=Console.ReadLine();
         int n = ReadInt("請輸入次數");
        string resuit= Rpeat(s, n);
        //函式內部不關心引數怎麼來的,也不關心返回值幹什麼用
        Console.WriteLine(resuit);
        Console.ReadKey();
    }
    //注意引數命名規則
    //不要在函式內部幫呼叫者WriteLine,不要幫呼叫者ReadLine
    //呼叫函式的地方的引數名字和函式宣告時的名字沒有對應關係
    static string Rpeat(string s, int n)
     {
        string t= "";
        for(int i=0;i<n;i++)
        {
            t = t + s;
        }
        return t;//把計算的結果返回
    }

練習:編寫一個函式,將使用者提供的兩個整數中的的最大值返回

    static int mMax(int n1, int n2)
    {
        if (n1 > n2)
        {
            return n1;
        }
        else
        {
            return n2;
            //return"aaa";//函式答應返回int就必須返回int
            //不能不返回,不能返回其他型別
        }
    }

練習:return和break區別

      static void Hello()
    {
        for (int i = 0; i < 10; i++)
        {
            if (i == 3)
            {
                //break;
                return;
            }
            Console.WriteLine("aaaaa");
        }
        Console.WriteLine("Hello完成");
    }
   break會執行"Hello完成"   return不執行     

函式返回值易錯點

一個函式如果“答應”返回一個非void型別的值,則函式的所有路徑都要有返回值。比如將對輸入年齡轉換為年齡段描述的函式。 while()中賦值也不行,因為可能while一個迴圈都不執行。 錯誤一:所以路徑都要有返回值,不能存在沒有返回值的情況

    static int DoIt(int i)
    {
        if (i < 0) 
        {
            return 0 - 1;
       }
        else if (i>=0&&i<=10)
        {
           return 30;
        }
    }

錯誤二:存在沒有返回值的情況

    static int DoIt(int n)
    {
       for (int i = 0; i < n; i++)
        {
           return i;
        }
    }
    練習:
    static void Main(string[] args)
    {
     int[] nums = { 3, 6, 8 };
     Console.WriteLine(Sum(nums));//函式要求提供什麼資料,必須提供什麼資料
      Console.ReadKey();
     }
     static int Sum(int[] values)
     {
        int sum = 0;
        foreach (int i in values)
        {
            sum = sum + i;
        }
        return sum;
      }

練習:編寫一個從百度MP3下載音樂函式需要定哪些引數, 假設http://mp3.baidu.com/***.mp3

    static bool DownLoadMp3(string filename, string localfilename)
    //兩個,歌名,下載到哪去
    {
        string ur1 = "http://mp3.baidu.com/filename.mp3";
    }

練習:呼叫者提供一個字串陣列,和一個字串,把字串陣列用這個字串分割起來

    static void Main(string[] args)
    {
        string [] strs = { "a", "c", "d" };
        string s = "()";
        string t = FenGe(strs ,s);
        Console.WriteLine(t);
        Console.ReadKey();
    }
    static string FenGe(string[] strs, string s)
    {
        string t = "";
        foreach (string str in strs)
        {
            t = t+str + s;
        }
        return t;
    }

函式過載

構成過載的條件: 同名的兩個函式的簽名(引數的型別、順序、返回值的型別)不能完全一樣;和引數的名字無關;函式的過載不關返回值型別 。 例子:

static void Next(int i)
    {
        Console.WriteLine(i+i);
    }
    
    static void next(int i)
    {
        Console.WriteLine(i + i);
    }
    
    //overload過載
    static void Next(string  boss)
    {
        if (boss == "毛")
        {
            Console.WriteLine("鄧");
        }
        
  只有引數的型別、順序不一致才能函式重名,函式返回值型別一直與否沒有關係
   static int Next(string boss)//錯誤
    { 
    }

可變引數(params)

引數陣列: int sum(params int[] values) int sum(string name,params int[] values) 可變引數陣列必須是在最後一個

引數預設值(C#4.0) :void SayHello(string name,int age=20) 用過載來實現引數預設值的效果,在建構函式中用的特別多。

編寫一個讓使用者輸入一個數組並輸出其中的最大值,使用可變引數就可以不用定義一個數組,可以直接輸入一組數。

 static void Main(string[] args)
    {
        //int[] values = { 3,5,7,5,7,9,9};
        //int i = Max(values);
        //int i = Max(1, 2, 3);
        int j = Max(true,"",3, 5, 7, 1, 9);
        Console.WriteLine(j);
        Console.ReadKey();
    }
     //個數不確定的可變引數以陣列的形式傳遞
    //可變引數一定要放在最後一個
    static int Max(bool b,string msg,params int[] values)
    {
        Console.WriteLine(msg);
        int max = 0;
        foreach (int value in values)
        {
            if (value > max)
            {
                max = value;
            }
        }
        return max ;
    }
    //設定引數預設值
    static void SayHello(string name,int age=20,bool gender=true )
        {
             Console.WriteLine("我是{0},我芳齡{1}",name,age );
        }

函式的ref、out引數

函式引數預設是值傳遞的,也就是“複製一份”。 ref必須先初始化,因為是引用,所以必須先“有”,才能引用; 而out則是內部為外部賦值,所以不需要初始化,而且外部初始化也沒用。 ref應用場景內部對外部的值進行改變; out則是內部為外部變數賦值,out一般用在函式有多個返回值的場所。 ref就是為了能折騰變數本身 例如:沒有使用ref,變數本身的值不會變。

   static void Main(string[] args)
    {
        int i = 1;
        DotIt(i);
        Console.WriteLine(i);//輸出1、2、1
        Console.ReadKey();
    }
    //int i傳進來的時候是複製了一份傳進來,折騰的是複製品
    static void DotIt(int i)
    {
        Console.WriteLine (i);
        i++;
        Console.WriteLine(i);
        i++;
    }
    使用ref
    static void Main(string[] args)
    { 
         int i1 = 10;
         int i2 = 20;
         
         //Swap(i1,i2 );//折騰的是複製品
        //用ref之前必須給變數賦值
        
        Swap(ref i1,ref i2);//傳遞引用。給ref傳遞引數時也要加上ref
        Console.WriteLine("i1={0},i2={1}",i1,i2)
        Console.ReadKey();
    }
      static void Swap(ref int i1, ref int i2)//reference
    {
        //標記為ref就是要求呼叫者傳遞變數的引用
        int temp = i1;
        i1 = i2;
        i2 = temp;
        
       //static void Swap(int i1, int i2)
        //{
       //    int temp = i1;
       //    i1 = i2;
       //    i2 = temp;
    }

out:就起到一個函式有兩個返回值

   static void Main(string[] args)
    {
        bool b;//不需要為out賦值
        int i= Parse(Console.ReadLine(),out b);
        if(b)//和if(b==true)一樣
        {
            Console.WriteLine ("成功,i={0}",i);
        }
        else 
        {
             Console.WriteLine ("錯誤");
        }
        Console.ReadKey();
    }
static int Parse(string s,out bool success)
    {
        if(s=="一")
        {
            success=true;
            return 1;
        }
        else if(s=="二")
        {
            success=true;
            return 2;
        }
        else
        {
            success=false ;
             return -1;
        }

例如: 把使用者輸入的字串轉換成數,如果使用者輸入的不是數,用Convert.ToInt32()轉換就會報錯。可以用int.TryParse(s, out i)

   static void Main(string[] args)
    {
        string s = Console.ReadLine();
        int i=0;
        if (int.TryParse(s, out i))
        {
            Console.WriteLine("成功" + i);
        }
        else
        {
            Console.WriteLine("輸入錯誤" );
        }
        //int i = Convert.ToInt32(s);
        //i++;
        //Console.WriteLine(i);
        Console.ReadKey();
    }

字串

char型別:用單引號包含字元,單引號中放且只能放一個字元。(‘a’) 單個字元也可以表示為字串,還可以有長度為0的字串。 null(表示空)和""(長度為0);‘f’(字元)和“f”(字串)的區別。 練習:String.IsNullOrEmpty

 string s = "   ";//不是empty
        if(s==null||s==""||s==string.Empty )
         {
         }
          if (string.IsNullOrEmpty(s))//等價與s==null||s==""
        {
            Console.WriteLine("空");
        }

使用s.Length屬性來獲得字串中的字元個數

       String s = "asadsfdfsdfdf";
        Console.WriteLine(s.Length);

string可以看做是char的只讀陣列。char c = s[1];。 例子:遍歷輸出string中的每個元素。

      string s = "asfadsfdf";
        foreach (char c in s)
        {
            Console.WriteLine(c);
        }

C#中字串有一個重要的特性:不可變性,字串一旦宣告就不再可以改變。所以只能通過索引來讀取指定位置的char,不能對指定位置的char進行修改。

        String s = "asadsfdfsdfdf"
        char c = s[3];//讀取序號為0的位置的char,注意char的型別
        Console.WriteLine(c);
        //s[3]='1'//只能讀,不能改

     char[] chars = { 'a', 'b', 'c' };
     chars[1] = '1';
     //字串是不可變的,所以要先生成一個chae[],再對char[]進行修改
   //再根據char[]生成的新的字串,但是原來的字串沒有改變(他就在那)

如果要對char進行修改,那麼就必須建立一個新的字串,用s. ToCharArray()方法得到字串的char陣列,對陣列進行修改後,呼叫new string(char[])這個建構函式來建立char陣列的字串。一旦字串被建立,那麼char陣列的修改也不會造成字串的變化。 例子:將字串中的第三位替換為w。

        string s = "asfsafdafdsfsd";
        char[] chars = s.ToCharArray();
        chars[2] = 'w';//是直接改char[]陣列
        string s1 = new string(chars);
        Console.WriteLine(s1);
        Console.WriteLine(s);

string s=“abc”,是宣告一個變數s,把s指向“abc“這個字串

例:時間格式轉換漢字大寫 比如: “2009年9月5日” 轉換成 “二零零九年九月五日”,輸入字串,返回字串。寫成一個函式

static void Main(string[] args)
    {
    string s = "2009年9月18日";
       string s1 = TOCHDate(s);
        Console.WriteLine(s1);
        Console.ReadKey();
    }
    static string TOCHDate(string date)
    {
        //{'零','一','二'},表驅動演算法
        char[] chars = date.ToCharArray();
        for (int i = 0; i < chars.Length; i++)
        {
            char ch = chars[i];
            switch (ch)
            {
                case '1':
                    chars[i] = '一';
                    break;
                case '2':
                    chars[i] = '二';
                    break;
                case '3':
                    chars[i] = '三';
                    break;
                case '4':
                    chars[i] = '四';
                    break;
                case '5':
                    chars[i] = '五';
                    break;
                case '6':
                    chars[i] = '六';
                    break;
                case '7':
                    chars[i] = '七';
                    break;
                case '8':
                    chars[i] = '八';
                    break;
                case '9':
                    chars[i] = '九';
                    break;
                case '0':
                    chars[i] = '零';
                    break;
            } 
        }
        return new string(chars);
    }

要區分變數名和變數指向的值的區別。程式中可以有很多字串,然後由字串變數指向他們,變數可以指向其他的字串,但是字串本身沒有變化。字串不可變性指的是記憶體中的字串不可變,而不是變數不變。

String類常用函式

ToLower():得到字串的小寫形式。 ToUpper():得到字串的大寫形式; 注意字串是不可變的,所以這些函式都不會直接改變字串的內容,而是把修改後的字串的值通過函式返回值的形式返回。s.ToLower()與s=s.ToLower() 例:得到字串小寫形式

        string s = "ChinaRen";
        s.ToLower();//字串是不可變的,所以轉換後的值通過返回值
        string s1 = s.ToLower();
        Console.WriteLine(s);
        Console.WriteLine(s1);

例:忽略大小寫比較使用者名稱

           Console.WriteLine("請輸入使用者名稱:");
        string name = Console.ReadLine();
        //忽略大小寫比較使用者名稱
        name = name.ToLower();//並沒有改變原先的字串,只是指向新的字串
        if (name == "admin")
        {
            Console.WriteLine("使用者名稱存在");
        }
        else
        {
            Console.WriteLine("使用者名稱不存在");
        }

去空格:Trim()

Trim()去掉字串兩端的空白(不會去掉中間的)。 例:去掉兩邊空格

        string s = "    ab  cd    ";
        Console.WriteLine(s.Length);
        s = s.Trim();//去掉兩邊的空格,不會去掉中間的
        Console.WriteLine(s.Length);
        Console.WriteLine(s);

忽略大小寫比較

s1.Equals(s2, StringComparison.OrdinalIgnoreCase),兩個字串進行不區分大小寫的比較。 例:兩個字串比較

        string s1 = "Admin";
        string s2 = "admin";
        Console.WriteLine(s1 == s2);
        Console.WriteLine(s1.ToLower() == s2.ToLower());
        //Ignore:忽略。Case:大小寫(CaseSensitive:大小寫敏感)
        Console.WriteLine(s1.Equals(s2, StringComparison.OrdinalIgnoreCase));

string s2 = string.Format("{0}年{1}月{2}日", year, month, day); 例: 用佔位符、格式生成新的字串

       // String.IsNullorEmpty()
        string s1=string.Format("我叫{0},我{1}歲","sun",100);
        Console.WriteLine(s1);

拼接string.Join("|", values)

拼接:string s1 = string.Join("|", values);//第一個引數是string型別分隔符 例:用"|"拼接字串

        string [] value={"aa","bb","cc"};
        string s=string.Join ("|",value );//用分隔符拼接字串陣列
        Console.WriteLine(s);

string[] Split(): 分割字串

string[] Split(params char[] separator):可以用可變引數

           string line = Console.ReadLine();//1,2,3,4,5,6
        string[] strs = line.Split(',', '|');//因為分隔結果可能是多個,所以string陣列
        foreach (string str in strs)
        {
            Console.WriteLine(str);
        }

string[] Split(char[] separator, StringSplitOptions options)按char分割符分割,不能用可變引數,可以移除結果中的空白字串,但不能去掉空格;

 string s="aaa,bbb,,cc,ddd,aaa,333,    90";
  //string [] strs=s.Split(',');
  //string[] strs = s.Split(',',',');
 char[] seps = {',', ',' };
   //移除空字串
  //因為過載中StringSplitOptions放到最後,所以不能分隔符必須用chae[]傳
   //不能用可變引數
  string[] strs = s.Split(seps,StringSplitOptions .RemoveEmptyEntries );
  foreach (string str in strs)
        {
            Console.WriteLine(str.Trim());//Trim去掉空格
        }

string[] Split(string[] separator, StringSplitOptions options)按照string分割符分割,移除空字串,但不能移除空格。

        string s = "aaa|*bbb|*ccc";
        string[] seps = { "|*"};//new string[5];
        string[] seps = new string[] { "|*"};
        //沒必要記住Split的這麼多用法,用的時候能轉到Split定義用起來就行
        string[] strs = s.Split(seps ,StringSplitOptions .RemoveEmptyEntries);
       string[] strs = s.Split(new string[] { "|*" }, StringSplitOptions.RemoveEmptyEntries);
        foreach (string str in strs)
        {
            Console.WriteLine(str.Trim());
        }

例子1:從日期字串(“2008-08-08”)中分析出年、月、日;2008年08月08日

        string pDate = Console.ReadLine();
        string[] strs = pDate.Split ('-');
        string date = string.Format("{0}年{1}月{2}日", strs[0], strs[1], strs[2]);
        Console.WriteLine(date);
        Console.ReadKey();

例子2:從一個記錄了學生成績的文字文件,每個學生成績是一行,每行是用|分割的資料,用|分割的域分別是姓名、年齡、成績,寫程式取出成績最高學生的姓名和成績。 參考:使用string[] lines = System.IO.File.ReadAllLines(@“c:\root.ini”, Encoding.Default);從文字檔案讀取資料,返回值為string陣列,每個元素是一行。

string[] lines = System.IO.File.ReadAllLines(@"F:\root.txt",Encoding.Default);
        int score = 0;
        string name="";
        foreach (string line in lines )
         {
             string[] strs = line.Split('|');
             int chenji = int.Parse(strs[2]);
             if (chenji >score)
             {
                 score = int.Parse(strs[2]);
                 name = strs[0];
             }
        }
        Console.WriteLine("姓名:{0}   成績:{1}",name,score);
        Console.ReadKey();