(01)基础强化:复习+练习

一、课前准备

    1、参考资料
        《C#图解教程》细而全
        《传智播客面试宝典》
        《C#语言规范》
    
    2、如何学C#
    
        杨中科是谁?
        
        如何选择语言?
            做的是程序员,不是C#程序员。选定C#后,不要纠结,要深入学习学懂,这样转
        语言时非常容易。现在选定C#,就需要学深学懂。
        
        为什么不会做练习?
            如游泳,老师光教,不下水练习。再怎么教也不会游泳。
            反复练习,温故而知新。做笔记复习很重要。每一次的复习才是收获。
        
    3、课程中加*的有难度,并不要求全掌握,先把常规内容学会。
        
        进阶系列难度所处的范围大概如下:
        (01)基础强化:复习+练习_第1张图片
        

 


        
        
二、复习检测
    


    1、声明两个变量:int n1= 10,n2= 20要求将两个变量交换,最后输出n1为 20,n2为 10。
        扩展(*):不使用第三个变量如何交换?

        int n1 = 10, n2 = 20;
        n1 = n1 + n2;
        n2 = n1 - n2;
        n1 = n1 - n2;
        Console.WriteLine($"{n1},{n2}");


        
        技巧:
            异或:有且只有一个为1时为1,否则为0.
            例:1^0=1,1^1^=0,0^1=1,0^0=0, 可以看出异或对于数的顺序不敏感。
            同时注意一下:1^0^0=1,1^1^1=1,1^0^1=0,1^1^0=0
            
            可以去体会一下两点:
            1)异若的顺序不影响结果值;
            2)关键:一个数连续异或同一个数,等于原数。例如 3^4^4=3
                        注意顺序不影响:4^3^4=3
            
            因此本题可用异或来解答:
            int a = 10, b = 20;
            a = a ^ b;//a=(a^b)
            b = a ^ b;//相当于b=(a^b)^b=a^b^b=a,即此时b=a了
            a = a ^ b;//相当于a=(a^b)^(a)=a^b^a=b
            
        
    
    2、用方法来实现:将上题封装一个方法来做,方法有两个参数分别为num1,num2。将num1
        与num2交换。提示:方法有两个参数n1,2在方法中将n1与n2进行交换,使用ref。(*)

        private static void Main(string[] args)
        {
            int n1 = 10, n2 = 20;
            Exchange(ref n1, ref n2);
            Console.WriteLine($"{n1},{n2}");
            Console.ReadKey();
        }

        private static void Exchange(ref int n1, ref int n2)
        {
            n1 = n1 + n2;
            n2 = n1 - n2;
            n1 = n1 - n2;
        }


        
        技巧:vs2022
        快速生成函数/方法:在主函数中输完函数后如上例Exchange(ref n1, ref n2);这样转
        时,按下Alt+Enter,弹出的小菜单中选择生成方法,即可快速生成。
        
        
    3、请用户输入一个字符串,计算字符串中的字符个数,并输出。

        private static void Main(string[] args)
        {
            Console.WriteLine("请输入一个字符串:");
            string s = Console.ReadLine();
            Console.WriteLine($"{s}共有{s.Length}个字符");
            Console.ReadKey();
        }


    
    4、用方法来实现:计算两个数的最大值。思考:方法的参数? 返回值? 
        扩展(*): 计算任意多个数间的最大值(提示:使用可变参数,params)。

        private static void Main(string[] args)
        {
            Console.WriteLine(GetMax(10, 20));
            Console.WriteLine(GetMax(10, 20, 30));
            Console.WriteLine(GetMax(10, 20, 30, 40));

            Console.ReadKey();
        }

        private static int GetMax(params int[] n)
        {
            int max = n[0];

            for (int i = 1; i < n.Length; i++)
            {
                if (n[i] > max)
                {
                    max = n[i];
                }
            }
            return max;
        }


        
    5、用方法来实现:计算 1-100 之间的所有整数的和。
    6、用方法来实现:计算 1-100 之间的所有奇数的和。
    7、用方法来实现:判断一个给定的整数是否为“质数”。
    8、用方法来实现: 计算 1-100 之间的所有质数《素数)的和1060。

        private static void Main(string[] args)
        {
            Console.WriteLine(GetSum(100));

            Console.ReadKey();
        }

        private static int GetSum(int n)
        {
            int sum = 0;

            for (int i = 1; i <= n; i++)
            {
                if (IsPrime(i))
                {
                    sum += i;
                }
            }
            return sum;
        }

        private static bool IsPrime(int n)
        {
            if (n == 1) return false;
            else if (n == 2) return true;
            else //n>2
            {
                for (int i = 2; i <= Math.Sqrt(n); i++)
                {
                    if (n % i == 0)
                    {
                        return false;
                    }
                }
                return true;
            }
        }


    
        技巧:
            凡是找与数学有关的函数,用Math。
    
    9、用方法来实现:有一个整数数组:{1,3,5,7,9,2,4,6,8,10},找出其中最大值,并输出.
        不能调用数组的Max()方法。    

        private static void Main(string[] args)
        {
            int[] n = new int[] { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 };

            Console.WriteLine(GetMax(n));
            Console.ReadKey();
        }

        private static int GetMax(int[] n)
        {
            int max = n[0];
            for (int i = 0; i < n.Length; i++)
            {
                if (max < n[i])
                {
                    max = n[i];
                }
            }
            return max;
        }


        
    10、用方法来实现:有一个字符数组{"马龙","迈克尔乔丹","雷吉米勒","蒂姆邓肯",
        "科比布莱思特"},请输出最长的字符串

        private static void Main(string[] args)
        {
            string[] s = new string[] { "马龙", "迈克尔乔丹", "雷吉米勒", "蒂姆邓肯", "科比布莱思特" };
            Console.WriteLine(s[GetMax(s)]);

            Console.ReadKey();
        }

        private static int GetMax(string[] n)//返回最长字串的索引
        {
            int max = 0;
            for (int i = 0; i < n.Length; i++)
            {
                if (n[max].Length < n[i].Length)
                {
                    max = i;
                }
            }
            return max;
        }


        
        
    11、用方法实现:请计算出一个整形数组的平均值,{1,3,5,7,93,33,4,4,6,8,10}。要求:
        计算结果如果有小数,则显示小数点后两位(四舍五入)

        private static void Main(string[] args)
        {
            int[] n = { 1, 3, 5, 7, 93, 33, 4, 4, 6, 8, 10 };
            Console.WriteLine(GetAvg(n));

            Console.ReadKey();
        }

        private static double GetAvg(int[] n)
        {
            double sum = 0;
            for (int i = 0; i < n.Length; i++)
            {
                sum += n[i];
            }
            return Math.Round(sum / n.Length, 2);
        }


        
        
    12、请通过冒泡排序法对整数数组{1,3,5,7,99,2,4,6,8,10}实现升序排序。

        private static void Main(string[] args)
        {
            int[] n = { 1, 3, 5, 7, 99, 2, 4, 6, 8, 10 };
            int temp;
            for (int i = 0; i < n.Length - 1; i++)
            {
                for (int j = i + 1; j < n.Length; j++)
                {
                    if (n[i] > n[j])
                    {
                        temp = n[i];
                        n[i] = n[j];
                        n[j] = temp;
                    }
                }
            }
            for (int i = 0; i < n.Length; i++)
            {
                Console.Write(n[i] + " ");
            }
            Console.ReadKey();
        }


    
    
    13、有如下字符串:患者:“大夫,我咳嗽得很重。";大夫:"你多大年龄?";患者:"七十五
        岁。";大夫:"二十岁咳嗽吗";患者:"不咳嗽。";大夫:"四十岁时咳嗽吗?";患者:"
        也不咳嗽。";大夫:"那现在不咳嗽,还要等到什么时咳嗽?";。
        需求:统计"咳嗽"出现次数,以及每次咳嗽出现的索引位置。
        扩展(*):统计每个字符出现的次数。

        private static void Main(string[] args)
        {
            string s = "患者:“大夫,我咳嗽得很重。\";大夫:\"你多大年龄?\";" +
                "患者:\"七十五\r\n\t\t岁。\";大夫:\"二十岁咳嗽吗\";患者:\"不咳" +
                "嗽。\";大夫:\"四十岁时咳嗽吗?\";患者:\"\r\n\t\t也不咳嗽。\";大" +
                "夫:\"那现在不咳嗽,还要等到什么时咳嗽?\";";
            int count = 0, n = 0, index = 0;
            while ((index = s.IndexOf("咳嗽", index)) != -1)
            {
                count++;
                Console.WriteLine("第{0}次出现的位置是{1}", count, index);
                index += 2;
            }
            
            Dictionary dic = new Dictionary();
            for (int i = 0; i < s.Length; i++)
            {
                if (dic.ContainsKey(s[i]))
                {
                    dic[s[i]]++;
                }
                else
                {
                    dic[s[i]] = 1;
                }
            }
            foreach (KeyValuePair item in dic)
            {
                Console.WriteLine($"{item.Key}:{item.Value}");
            }
            
            
            Console.ReadKey();
        }


    
        思路:
            判断字符串中有且只有一个这样的字符:  IndexOf()=LastIndexOf()
            即从左找到的索引等于从右找的索引,且不能为-1
            
    
    14、将字符串" hello     word,你 好 世界   !   "两端空格去掉,并且将其中的所有其
        它空格都替换成一个空格,输出结果为:"hello world,你 好 世界!".

        private static void Main(string[] args)
        {
            string s = " hello     word,你 好 世界   !   ";
            string[] s1 = s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            Console.WriteLine(string.Join(" ", s1));
            Console.ReadKey();
        }


    
        技巧:
            调试时,执行到光标定位处:Ctrl+F10
        
        
        
    15、制作一个控制台小程序。要求用户可以在控制台录入每个学生的姓名,当用户输入quit
        (不区分大小写)时,程序停止接受用户的输入,并且显示出用户输入的学生的个数,以
        及每个学生的姓名。
        样例:请输入姓名:
               张三
               请输入姓名:
               李四
               ....
                quit
            一共录入4个学生,姓名分别为张三,李四....

        private static void Main(string[] args)
        {
            List list = new List();
            string s = string.Empty;
            do
            {
                Console.WriteLine("请输入姓名:");
                s = Console.ReadLine();
                list.Add(s);
            } while (s.ToLower() != "quit");

            list.RemoveAt(list.Count - 1);//最后一个quit去除
            string[] s1 = list.ToArray();
            Console.WriteLine($"一共录入学生{list.Count}个,分别是{string.Join(" ", s1)}");

            Console.ReadKey();
        }


    
        
    16、同上,再增加一个姓"王"的同学的个数,此处不考虑复姓问题。

        private static void Main(string[] args)
        {
            List list = new List();
            string s;
            do
            {
                Console.WriteLine("请输入姓名:");
                s = Console.ReadLine();
                list.Add(s);
            } while (s.ToLower() != "quit");
            list.RemoveAt(list.Count - 1);//最后一个quit去除

            List list2 = new List();
            foreach (string s1 in list)
            {
                if (s1.StartsWith("王"))
                {
                    list2.Add(s1);
                }
            }
            Console.Write("王姓同学共{0}个,分别是:", list2.Count);
            foreach (string s1 in list2)
            {
                Console.Write(s + " ");
            }

            Console.ReadKey();
        }


    
    
    17、将普通日期格式:2011年6月4日转为:二零一一年六月四日。
        暂不考虑10日,13日,23日等带十的问题。

        private static void Main(string[] args)
        {
            Dictionary dic = new Dictionary() { { '0', '零' }, { '1', '壹' }, { '2', '贰' },
             { '3', '叁' },{ '4', '肆' }, { '5', '伍' }, { '6', '陆' }, { '7', '柒' }, { '8', '捌' }, { '9', '玖' },};
            string s = "2011年6月4日", s1 = "";

            for (int i = 0; i < s.Length; i++)
            {
                switch (s[i])
                {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        s1 += dic[s[i]];
                        break;

                    default:
                        s1 += s[i];
                        break;
                }
            }
            Console.WriteLine(s1);

            Console.ReadKey();
        }


        
        
        
    18、创建一个Person类,属性:姓名,性别,年龄;方法SayHi().再创建一个Employee类
        继承Person类,扩展属性Salary,重写SayHi方法。

        internal class Program
        {
            private static void Main(string[] args)
            {
                Employee p = new Employee() { Name = "张三", Gender = '男', Age = 28, Salary = 2342.23 };
                p.SayHi();

                Console.ReadKey();
            }

            public class Person
            {
                public string Name { get; set; }
                public char Gender { get; set; }
                public int Age { get; set; }

                public void SayHi()
                {
                    Console.WriteLine("Hello");
                }
            }

            public class Employee : Person
            {
                public double Salary { get; set; }

                public new void SayHi()
                {
                    Console.WriteLine("hellow one");
                }
            }
        }


    
        提示:
            属性并不能存储数据,自动属性的背后也是有一个隐藏的字段进行存储数据。
            
            
    
    19、编写一个类:ItcastClass,类中有私有字段_name,字符串数组类型,长度5,并且有5个
        默认的姓名。要求:为ItcastClass类编写一个索引器,要求索引器能够通过下标来访
        问_names中的问题。

        internal class ItcastClass
        {
            public int Count//返回索引器长度,只读
            {
                get
                {
                    return _name.Length;
                }
            }

            private string[] _name = { "苏坤", "蒋坤", "杨中科", "马伦", "赵剑宇" };//杨洪波

            public string this[int n]
            {
                get
                {
                    if (n >= 0 && n <= _name.Length - 1)
                    {
                        return _name[n];
                    }
                    throw new ArgumentException();
                }
                set
                {
                    if (n < 0 || n >= _name.Length)
                    {
                        throw new ArgumentException();
                    }
                    _name[n] = value;
                }
            }

            //public string this[string str]//索引器重载
            //{
            //}

            //public string Item  //已经有索引器Item了
            //{
            //}
        }


        
        
        
        分析:类中有数组5个为私有,不能直接访问,可通过其它如属性进行间接访问。
            1)索引器用[]代替字段或属性的间接引用,直接用对象名加[]即可表达该值
            2)索引器不能有具体的名称,应该用this进行代替。
            3)索引器[]中的参数也应该进行设置。里面参数可以是多个,例如二维数组。
            4)索引器[]中的参数应该在属性中进行过滤设置。
            5)索引器可以重载,参数的类型个数可以不同。
            5)索引器的count应单独设置一个属性(只读)
                
            小结:
                索引器其实就是一个属性,是一个非常特殊的属性,常规情况索引器其实都是一个
                名叫Item的属性
.通过反编译内部可以查看到。
                因此如果在类中再写一个Item的属性,会报错。同理Count也必须是唯一的。
                
                
    20、案例:使用WinForm窗体,制作一个简易计算器,默认为“请选择"。要求具有+-*/功能.
        当用户点击“等于”按钮时,如果输入的为非数字则提示用户。

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                comboBox1.Items.Add("请选择");
                comboBox1.Items.Add("+");
                comboBox1.Items.Add("-");
                comboBox1.Items.Add("*");
                comboBox1.Items.Add("/");
                comboBox1.SelectedIndex = 0;
            }

            private bool IsNum(string str)
            {
                try
                {
                    double d = Convert.ToDouble(str);
                }
                catch (Exception)
                {
                    return false;
                }
                return true;
            }

            private void button1_Click(object sender, EventArgs e)
            {
                if (IsNum(textBox1.Text) && IsNum(textBox2.Text))
                {
                    switch (comboBox1.Text)
                    {
                        case "+":
                            label1.Text = (Convert.ToDouble(textBox1.Text) + Convert.ToDouble(textBox2.Text)).ToString();
                            break;

                        case "-":
                            label1.Text = (Convert.ToDouble(textBox1.Text) - Convert.ToDouble(textBox2.Text)).ToString();
                            break;

                        case "*":
                            label1.Text = (Convert.ToDouble(textBox1.Text) * Convert.ToDouble(textBox2.Text)).ToString();
                            break;

                        case "/":
                            if (textBox2.Text == "0")
                            {
                                MessageBox.Show("除数不能为0");
                                return;
                            }
                            double d = Convert.ToDouble(textBox1.Text) / Convert.ToDouble(textBox2.Text);
                            d = Math.Round(d, 3);
                            label1.Text = d.ToString();
                            break;

                        default:
                            MessageBox.Show("请选择正确的运算符");
                            break;
                    }
                }
                else
                {
                    MessageBox.Show("输入不是数字");
                }
            }
        }


    
    
        技巧:
            如何查看vs自身函数的代码。例如查看Convert.ToInt32(string)
            方法一:鼠标放在该函数中,直接按F12,即定位到对应的函数的代码中。
            方法二:打开.Net Reflector(网上下载),点击工具栏的搜索,输入Convert,
                回车,在右侧已经过滤的结果中双击Convert后,在左侧的对应的函数名
                中找到ToInt32(string):Int32,点击它,则右侧下方出现对应的代码。
    
    21、编写代码说明什么是方法重载。要求,至少编写3个方法。

        private static void Main(string[] args)
        {
            int n = 3; double n1 = 4.0; string n2 = "5";
            GetNum(n);
            GetNum(n1);
            GetNum(n2);

            Console.ReadKey();
        }

        public static void GetNum(int n)
        {
            n++;
            Console.WriteLine(n);
        }

        public static void GetNum(double n)
        {
            n++;
            Console.WriteLine(n);
        }

        public static void GetNum(string n)
        {
            n += "1";
            Console.WriteLine(n);
        }


        
        
        提示:
            重载只看方法名与参数(个数与类型),与返回值无关。
            
    
    22、请将字符串数组{"中国","美国","巴西","澳大利亚","加拿大"}中的内容反转,然后
        输出反转后的数组。不能用数组的Reverse()方法.

        private static void Main(string[] args)
        {
            string[] s = { "中国", "美国", "巴西", "澳大利亚", "加拿大" };
            
            for (int i = 0; i < s.Length / 2; i++)
            {
                string temp = s[i];
                s[i] = s[s.Length - 1 - i];
                s[s.Length - 1 - i] = temp;
            }
            Console.WriteLine(string.Join(" ", s));
            
            Console.ReadKey();
        }


        
        技巧:
            做项目时,不再局限自己写算法,能用系统的方法就用。
            比如本题可以用Reverse()时就用,毕竟都是经广大程序员使用认证的,效率更好。
        
    后面数据库时再做下面的题:
    23、请在数据库中新建一张表(T_Student),该表中有3列(自动编号,姓名,年龄),向
        该表中手动插入若干条数据,然后通过ado.net将该表中的数据显示到程序中来,可以
        使用DataGridView控件显示数据。

    24、请写一个SQL语句:从user表中取出name列中的起始字符是"北京"的全部记录。

    25、写出一条SQL语句:取出表A中第31到第40条记录(SQLServer以自动增长的ID作为主键)
        注意:ID可能不是连续的。
    


三、代码规范


    1、规则(如同法律,必须遵守否则报错。)
        例如,语法。
        
    2、规范(道德,大家都喜欢有道德的人)
        
        注释:
        Camel命名:普通变量(局部变量),字段
        Pascal命名:方法名,类名,属性名。
        
        定义变量或方法(名字要有意义)
            方法名:一般动词开头,方法是做一件事:Write(),Open(),Display()
                    或者以返回值进行命名,例如得到ID:GetID().
                    或者以起源或目标命名,例如:GetFileFrom(),WriteToDoc()
            变量名:按功能命名,按方法的返回值内容命名。
                    userName=GetUserName()
            
            写不来英文就写拼音,但必须是全拼,长点都可以,以便识别。
            例如:XieRuWenJian()写入文件,但不能简写成XRWJ()无法识别。
            
            尽量写便于识别的代码,不推荐艰深的代码。
    


四、.Net程序基本编译执行流程C#


    1、编写c#代码,保存为.cs文件。
    
    2、通过csc.exe程序来将.cs文件编译为.Net程序集(.exe或.dll)。
        此时的exe或dll并不是机器码(CPU不识别,不理解)
        >csc /out:c:\a.exe c:\Program.cs
    
    3、程序运行时通过JIT编译(Just In Time)即时编译,将程序集编译为cpu能理解的机器码,
        这时cpu才能执行。这个编译过程会与当前的机器有关(根据当前的机器的内存cup等)
        
        JIT程序运行到哪儿就编译到哪儿。例如,一个程序集有3个exe,本次只运行了1和3的
        exe,那它就只编译1和3的exe,至于2的exe下次如果运行它,则再进行编译它。也即
        并不是一股脑儿的全部编译。
    


五、代码片段


    输入cw,再按两下Tab,则直接输出Console.WriteLine();
    这个就叫代码片段,是快速输入代码的一种方式。
    
    自定义代码片段
        菜单中工具->代码片段管理器,弹出的窗体中选择语言CSharp,左下侧选择Visual C#
        随便选择一个代码片段,比如do,选中它,上面有一个位置目录,复制目录,在windows
        中打开这个目录,这里面就是代码片段保存的位置。
        
        找到do.snippet,复制到另一个目录中打开它,更改里面的名称以及快速键,还有光标
        停留位置,保存重命名为你的编辑的快速键。
        
        然后在代码片段管理器的左下方有一个导入,导入上面保存的片段即可添加这个快捷
        的代码片段。
        (最近发现直接复制到visual C#目录中也可以直接使用,不必导入)
    

你可能感兴趣的:(C#进阶,c#,.net)