代码_代码生成软件 - CSDN
代码 订阅
代码就是程序员用开发工具所支持的语言写出来的源文件,是一组由字符、符号或信号码元以离散形式表示信息的明确的规则体系。代码设计的原则包括唯一确定性、标准化和通用性、可扩充性与稳定性、便于识别与记忆、力求短小与格式统一以及容易修改等。 源代码是代码的分支,某种意义上来说,源代码相当于代码。现代程序语言中,源代码可以书籍或磁带形式出现,但最为常用格式是文本文件,这种典型格式的目的是为了编译出计算机程序。计算机源代码最终目的是将人类可读文本翻译成为计算机可执行的二进制指令,这种过程叫编译,它由通过编译器完成。 展开全文
代码就是程序员用开发工具所支持的语言写出来的源文件,是一组由字符、符号或信号码元以离散形式表示信息的明确的规则体系。代码设计的原则包括唯一确定性、标准化和通用性、可扩充性与稳定性、便于识别与记忆、力求短小与格式统一以及容易修改等。 源代码是代码的分支,某种意义上来说,源代码相当于代码。现代程序语言中,源代码可以书籍或磁带形式出现,但最为常用格式是文本文件,这种典型格式的目的是为了编译出计算机程序。计算机源代码最终目的是将人类可读文本翻译成为计算机可执行的二进制指令,这种过程叫编译,它由通过编译器完成。
信息
外文名
code
定    义
开发工具支持的语言写的源文件
拼    音
dài mǎ
中文名
代码
操作者
程序员
代码词语解释
供把资料和指示输入自动计算机或制表机的任何符号系统;亦指这种符号的记录(如靠打孔资料卡片或磁带上的受磁点)。
收起全文
精华内容
参与话题
  • c++经典代码大全

    千次下载 热门讨论 2020-07-30 23:33:29
    c++经典代码大全,别人向我推荐的,初学者可以看看。。
  • 各种游戏(源代码

    2020-07-29 14:20:14
    初学时不知道做些什么 那么就来做些游戏吧 内附有源代码 清楚明了
  • 代码大全(第二版)

    2020-07-29 14:18:17
    学习各种编码技巧,全面提高编码能力的必备书籍,经典中的经典
  • 最厉害的代码

    千次阅读 2018-07-29 23:30:27
    1.侧滑和切换 package ... import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction;...import and...

    1.侧滑和切换

    package com.example.administrator.mnykt;
    
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v4.widget.DrawerLayout;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.Gravity;
    import android.view.View;
    import android.widget.FrameLayout;
    import android.widget.ImageView;
    import android.widget.RadioGroup;
    
    import com.example.administrator.fragment.Frag1;
    import com.example.administrator.fragment.Frag2;
    import com.example.administrator.fragment.Frag3;
    import com.example.administrator.fragment.Frag4;
    
    import java.util.ArrayList;
    
    public class MainActivity extends AppCompatActivity {
    
        private Frag1 frag1;
        private Frag2 frag2;
        private Frag3 frag3;
        private Frag4 frag4;
        private ArrayList<Fragment> list;
    
        private RadioGroup radio_group;
        private FrameLayout fram_layout;
        private FragmentManager manager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final DrawerLayout d1 = (DrawerLayout) findViewById(R.id.d1);
            ImageView iv1 = (ImageView) findViewById(R.id.iv1);
            ImageView iv2 = (ImageView) findViewById(R.id.iv2);
            fram_layout = (FrameLayout) findViewById(R.id.fram_layout);
            radio_group = (RadioGroup) findViewById(R.id.radio_group);
            iv1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    d1.openDrawer(Gravity.LEFT);
                }
            });
            iv2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    d1.closeDrawer(Gravity.LEFT);
                }
            });
    
           final Frag1 frag1 = new Frag1();
            final Frag2 frag2 = new Frag2();
            final Frag3 frag3 = new Frag3();
            final Frag4 frag4 = new Frag4();
    
            manager = getSupportFragmentManager();
            manager.beginTransaction().replace(R.id.fram_layout,frag1).commit();
    
            radio_group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(RadioGroup group, int checkedId) {
                    FragmentTransaction transaction = manager.beginTransaction();
                    switch (checkedId){
                        case R.id.rb1:
                            transaction.replace(R.id.fram_layout,frag1);
                            break;
                        case R.id.rb2:
                            transaction.replace(R.id.fram_layout,frag2);
                            break;
                        case R.id.rb3:
                            transaction.replace(R.id.fram_layout,frag3);
                            break;
                        case R.id.rb4:
                            transaction.replace(R.id.fram_layout,frag4);
                            break;
                    }
                    transaction.commit();
                }
            });
        }
    }
    

    2.布局

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/d1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
    
        >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@color/colorPrimaryDark"
    
            >
            <ImageView
                android:id="@+id/iv1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@mipmap/ic_launcher"
                />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="主页面"
                android:layout_centerHorizontal="true"
                android:textSize="20sp"
                android:layout_marginTop="10dp"
                />
        </RelativeLayout>
        <FrameLayout
            android:id="@+id/fram_layout"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="8"
            />
        <RadioGroup
            android:id="@+id/radio_group"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="horizontal"
            >
            <RadioButton
                android:id="@+id/rb1"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:text="首页"
                android:button="@null"
                android:textSize="20sp"
                />
            <RadioButton
                android:id="@+id/rb2"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:text="关注"
                android:button="@null"
                android:textSize="20sp"
                />
            <RadioButton
                android:id="@+id/rb3"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:text="推荐"
                android:button="@null"
                android:textSize="20sp"
                />
            <RadioButton
                android:id="@+id/rb4"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:text="娱乐"
                android:button="@null"
                android:textSize="20sp"
                />
        </RadioGroup>
    </LinearLayout>
    
    <LinearLayout
        android:layout_width="350dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/colorPrimary"
        >
        <ImageView
            android:id="@+id/iv2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_launcher"
            />
    </LinearLayout>
    
    
    </android.support.v4.widget.DrawerLayout>

    3.fragment页面

    package com.example.administrator.fragment;
    
    import android.os.Bundle;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.support.v4.app.Fragment;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ListView;
    import android.widget.Toast;
    
    import com.example.administrator.adapter.Adapter;
    import com.example.administrator.bean.NewsBean;
    import com.example.administrator.helper.NewsDao;
    import com.example.administrator.helper.User;
    import com.example.administrator.mnykt.R;
    import com.example.administrator.utils.HttpUtils;
    import com.example.administrator.utils.NetUtils;
    import com.google.gson.Gson;
    import com.handmark.pulltorefresh.library.PullToRefreshBase;
    import com.handmark.pulltorefresh.library.PullToRefreshListView;
    
    import java.util.ArrayList;
    import java.util.HashSet;
    
    public class Frag1 extends Fragment implements HttpUtils.Netcallback {
    
        private PullToRefreshListView pulltorefsh;
        private String url = "http://ttpc.dftoutiao.com/jsonpc/refresh?type=";
        //private String bannerUrl = "http://www.xieast.com/api/banner.php";
        private int type = 5010;
        private ArrayList<NewsBean.DataBean> list;
        private Adapter adapter;
        private NewsDao newsDao;
        private HttpUtils httpUtils;
    
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = View.inflate(getContext(), R.layout.frag1, null);
             pulltorefsh = view.findViewById(R.id.pulltorefsh);
             pulltorefsh.setMode(PullToRefreshBase.Mode.BOTH);
             pulltorefsh.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListView>() {
                 @Override
                 public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
                     type=5010;
                     pulltorefsh.postDelayed(new Runnable() {
                         @Override
                         public void run() {
                             pulltorefsh.onRefreshComplete();
                         }
                     },2000);
                     getData();
                 }
    
                 @Override
                 public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
                   type++;
                     pulltorefsh.postDelayed(new Runnable() {
                         @Override
                         public void run() {
                             pulltorefsh.onRefreshComplete();
                         }
                     },2000);
                   getData();
                 }
             });
            //创建一个空的结合
            list = new ArrayList<>();
            //创建适配器
            adapter = new Adapter(getActivity(), list);
            pulltorefsh.setAdapter(adapter);
            //创建dao层
            newsDao = new NewsDao(getActivity());
            httpUtils = HttpUtils.getInstance();
            getData();
    
            //网络工具类
            return view;
        }
    
    
    
        private void getData() {
            User user = newsDao.query(url + type);
            if (user!=null){
                parserjson(user.json);
            }else{
               if (NetUtils.iswlzj(getActivity())){
                   httpUtils.getwangluo(url+type,this);
               }else{
                   Toast.makeText(getActivity(), "请连接网络", Toast.LENGTH_SHORT).show();
               }
            }
        }
    
        private void parserjson(String json) {
            Gson gson = new Gson();
            NewsBean newsBean = gson.fromJson(json, NewsBean.class);
            if (type==5010){
                list.clear();
            }
            list.addAll(newsBean.getData());
            HashSet hashSet = new HashSet(list);
            list.clear();
            list.addAll(hashSet);
            adapter.notifyDataSetChanged();
        }
    
        @Override
        public void onSuccess(String result) {
            Log.i("aaa","执行了success");
            //截取字段
            String json = result.replace("null(", "").replace(")", "");
           //把数据添加到数据库
            newsDao.insert(new User((url+type),json));
            Gson gson = new Gson();
            NewsBean newsBean = gson.fromJson(json, NewsBean.class);
            list.addAll(newsBean.getData());
    
        }
    
        @Override
        public void onError(String s) {
          Log.i("aaa",s);
        }
    
    }
    

    4.适配器

    package com.example.administrator.adapter;
    
    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import com.example.administrator.bean.NewsBean;
    import com.example.administrator.mnykt.R;
    import com.nostra13.universalimageloader.core.ImageLoader;
    
    import java.util.ArrayList;
    
    public class Adapter extends BaseAdapter {
        private Context context;
        private ArrayList<NewsBean.DataBean> list;
    
        public Adapter(Context context, ArrayList<NewsBean.DataBean> list) {
            this.context = context;
            this.list = list;
        }
        private final int TYPE_0=0;
        private final int TYPE_1=1;
    
    
    
    
        @Override
        public int getCount() {
            return list.size();
        }
    
        @Override
        public Object getItem(int position) {
            try {
                return list.get(position);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        @Override
        public long getItemId(int position) {
            return 0;
        }
    
        @Override
        public int getViewTypeCount() {
            return 2;
        }
    
        @Override
        public int getItemViewType(int position) {
            int p=position%2;
            if (p==0){
                return TYPE_0;
            }else{
                return TYPE_1;
            }
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            int type = getItemViewType(position);
            if (type==0){
                ViewHolder holder=null;
                if (convertView==null){
                    convertView = View.inflate(context, R.layout.item1, null);
                     holder = new ViewHolder();
                    holder.text_view = (TextView)convertView.findViewById(R.id.text_view);
                    holder.iv3 = (ImageView)convertView.findViewById(R.id.iv3);
                    convertView.setTag(holder);
                }else{
                    holder = (ViewHolder) convertView.getTag();
                }
                holder.text_view.setText(list.get(position).getBrief());
                ImageLoader.getInstance().displayImage(list.get(position).getMiniimg().get(0).getSrc(),holder.iv3);
                return convertView;
            }else if (type==1){
                ViewHolder holder=null;
                if (convertView==null){
                    convertView = View.inflate(context, R.layout.item2, null);
                    holder = new ViewHolder();
                    holder.text_view1 = (TextView)convertView.findViewById(R.id.text_view1);
                    holder.iv4 = (ImageView)convertView.findViewById(R.id.iv4);
                    holder.iv5 = (ImageView)convertView.findViewById(R.id.iv5);
                    holder.iv6 = (ImageView)convertView.findViewById(R.id.iv6);
                    convertView.setTag(holder);
                }else{
                    holder = (ViewHolder) convertView.getTag();
                }
                holder.text_view1.setText(list.get(position).getBrief());
                ImageLoader.getInstance().displayImage(list.get(position).getMiniimg().get(0).getSrc(),holder.iv4);
                ImageLoader.getInstance().displayImage(list.get(position).getMiniimg().get(0).getSrc(),holder.iv5);
                ImageLoader.getInstance().displayImage(list.get(position).getMiniimg().get(0).getSrc(),holder.iv6);
                return convertView;
            }
            return null;
        }
        public class ViewHolder{
    
            public TextView text_view;
            public ImageView iv3;
            public TextView text_view1;
            public ImageView iv4;
            public ImageView iv5;
            public ImageView iv6;
        }
    }
    
    展开全文
  • Java学习代码合集

    万次阅读 多人点赞 2019-07-17 10:49:41
    其实我学习java最根本的原因是:我是一个挺关注外在的人,虽然是个程序员,所以我很喜欢写出那些带有漂亮的界面的程序,因为C总是控制台,我不是很喜欢,在这份java代码合集中,我会记录自己学习Java界面化编程的...

    其实我学习java最根本的原因是:我是一个挺关注外在的人,虽然是个程序员,所以我很喜欢写出那些带有漂亮的界面的程序,因为C总是控制台,我不是很喜欢,在这份java代码合集中,我会记录自己学习Java界面化编程的点点滴滴。

    更新:因为C/C++是我主要使用语言,所有后来写界面主要用Qt写了,但我java也会继续学的。我只是给想学界面gui的同志一个思路。可以参考这篇文章Qt5 计算器的实现

    可能会有java初学者,我也是,说明,java是一个工程里可以有很多java类class,每一个类class都可以单独运行,不像C语言里只能有一个main()函数可以运行,这是我的代码合集程序结构:

    helloworld:

    class Javahelloworld {
        public static void main(String args[]){
            System.out.println("hello world\n");
        }
    }
    

    基本输入输出:

    import java.util.Scanner;
    public class ScannerTest {
        public static void main(String[] args){
            Scanner scanner=new Scanner(System.in);
            System.out.print("请输入一个数");
            int a=scanner.nextInt();
            System.out.printf("%d的平方是%d\n",a,a*a);
        }
    }
    

    Java图形化界面求数的平方:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;/**包含JFrame*/
    public class AppGraphInOut {
        public static  void main(String args[]){
            new AppFrame();
        }
    }
    
    class AppFrame extends  JFrame
    {
        JTextField in=new JTextField(10);
        JButton btn=new JButton("求平方");
        JLabel out=new JLabel("用于显示平方结果的标签");
        public AppFrame()
        {
            setLayout(new FlowLayout());
            getContentPane().add(in);
            getContentPane().add(btn);
            getContentPane().add(out);
            btn.addActionListener(new BtnActionAdapter());
            setSize(400,100);
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            setVisible(true);
        }
    
        class BtnActionAdapter implements ActionListener
        {
            public void actionPerformed(ActionEvent e)
            {
                String s=in.getText();
                double d=Double.parseDouble(s);
                double sq=d*d;
                out.setText(d+"的平方是:"+sq);
            }
        }
    }
    

    Java位运算:

    public class BitwiseOperators {
        public static  void main(String args[]){
            int a=0b1100;
            int b=0b1010;
            print("a    ",a);
            print("b    ",b);
            print("a&b  ",a&b);
            print("a|b  ",a|b);
            print("a^b  ",a^b);
            print("~a   ",~a);
            print("a<<2 ",a<<2);
            print("a>>2 ",a>>2);
            print("a>>>2    ",a>>>2);
        }
        static void print(String prefix,int n){
            String s=Integer.toBinaryString(n);
            while(s.length()<4)s="0"+s;
            System.out.print(prefix+" "+s+"\n");
        }
    }
    

    同心圆:

    import java.awt.*;
    import javax.swing.*;
    
    public class Circle99Frame extends JFrame {
        public static void main(String args[])
        {
            JFrame frame=new Circle99Frame();
            frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            frame.setSize(600,600);
            frame.setVisible(true);
        }
        public void paint(  Graphics g)
        {
            g.drawString("circle 99",20,20);
            int x0=getSize().width/2;
            int y0=getSize().height/2;
            for(int r=0;r<getSize().height/2;r+=10)
            {
                g.setColor(getRandomColor());
                g.drawOval(x0-r,y0-r,r*2,r*2);
            }
        }
        Color getRandomColor()
        {
            return new Color(
                    (int)(Math.random()*255),//random本身只产生(0~1)之间的小数,
                    (int)(Math.random()*255),
                    (int)(Math.random()*255)
            );
        }
    }
    

     

    下面呢是一个常见的简陋的登陆界面,这个程序是这个两个类class共同组成的程序,先看代码:

    
    import javax.swing.JFrame;
    
    import javax.swing.JPanel;
    
    public class DemoFrame extends JFrame{
    
        public DemoFrame(DemoPanel panel)
    
        {
    
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            this.setSize(300, 200);
    
            this.setTitle("Frame Demo");
    
            this.add(panel);
    
            this.setResizable(false);
    
            this.setVisible(true);
    
        }
    
    
    
        public static void main(String[] args)
    
        {
    
            DemoPanel panel = new DemoPanel();
    
            DemoFrame Frame = new DemoFrame(panel);
    
        }
    
    }  
    import java.awt.GridLayout;
    
    
    
    import javax.swing.JButton;
    
    import javax.swing.JLabel;
    
    import javax.swing.JPanel;
    
    import javax.swing.JPasswordField;
    
    import javax.swing.JTextField;
    
    
    
    public class DemoPanel extends JPanel{
    
    
    
        private JLabel labelUser, labelPassWd;            //标签      用户名,密码
    
        private JButton buttonLogin, buttonReset;         //按钮      登录,重置
    
        private JTextField textFieldUserName;             //文本框  用户名输入
    
        private JPasswordField passWdField;               //密码框  密码输入
    
        private JPanel panelUserName;
    
        private JPanel panelPassWd;
    
        private JPanel panelLoginButton;
    
    
    
        public DemoPanel(){
    
            this.labelUser = new JLabel("用户名");
    
            this.labelPassWd = new JLabel("密    码");
    
            this.buttonLogin = new JButton("登录");
    
            this.buttonReset = new JButton("重置");
    
            this.textFieldUserName = new JTextField(10);
    
            this.passWdField = new JPasswordField(10);
    
            this.panelPassWd = new JPanel();
    
            this.panelUserName = new JPanel();
    
            this.panelLoginButton = new JPanel();
    
    
    
            this.setLayout(new GridLayout(3, 1));  //网格式布局
    
    
    
            this.panelUserName.add(this.labelUser);
    
            this.panelUserName.add(this.textFieldUserName);
    
            this.panelPassWd.add(this.labelPassWd);
    
            this.panelPassWd.add(this.passWdField);
    
            this.panelLoginButton.add(buttonLogin);
    
            this.panelLoginButton.add(buttonReset);
    
    
    
            this.add(this.panelUserName);
    
            this.add(this.panelPassWd);
    
            this.add(this.panelLoginButton);
    
        }
    
    }

    程序结果如下 :

    简单的加法器:

    package TEST;
    
    
    
    import javax.swing.JOptionPane;  //导入类
    
    
    
    public class TEST
    
    {
    
        public static void main(String args[])
    
        {
    
            String input_pane1,input_pane2;
    
            int n1,n2,sum;
    
            input_pane1 = JOptionPane.showInputDialog("Please input the first number");  //输入框1
    
            input_pane2 = JOptionPane.showInputDialog("Please input the second number"); //输入框2
    
            n1 = Integer.parseInt(input_pane1); //获取输入框中输入数据的整数类型
    
            n2 = Integer.parseInt(input_pane2);//获取输入框中输入数据的整数类型
    
            sum = n1+n2;
    
            JOptionPane.showMessageDialog(null, "The sum is: "+sum,"Adding Device",JOptionPane.PLAIN_MESSAGE);
    
            //第1个参数:null 显示在中央
    
            //第2个参数:要显示的字符
    
            //第3个参数:标题栏信息
    
            //第4个参数:对话框类型
    
            System.exit(0);  //终结图形用户界面程序必须的
    
        }
    
    }

    结果如下:

    说到这里,我其实有些感触,记得上学期,我们做课程设计,当时一个同学的题目是写一个带界面的大数乘除运算器,关于大数乘除的方法,我有时间再总结一下,但是这个界面当时同学其实是不会的,但是现在看,如果单纯实现界面还是比较简单的,首先看我修改的第一个拙劣的界面版本模板:

    这样其实就好了很多,起码可以看到加数是哪些了,代码很简单,只需要在输出那行添加上n1和n2的信息就可以了。

    JOptionPane.showMessageDialog(null, n1+"+"+n2+" The sum is: "+sum,"Adding Device",JOptionPane.PLAIN_MESSAGE);
    

     

    展开全文
  • 什么是代码区、常量区、静态区(全局区)、堆区、栈区? 一直对这些区搞不清楚,每次听到这些区头都大了,感觉很混乱。下面就结合STM32内核来具体讨论分析这些区到底是什么回事,每种关键字定义的变量又到底是存在...

    什么是代码区、常量区、静态区(全局区)、堆区、栈区?

    一直对这些区搞不清楚,每次听到这些区头都大了,感觉很混乱。下面就结合STM32内核来具体讨论分析这些区到底是什么回事,每种关键字定义的变量又到底是存在什么区。
    如下图,是自己总结的内存分区的示意图。一般内存主要分为:代码区、常量区、静态区(全局区)、堆区、栈区这几个区域。
    这里写图片描述
    代码区:存放程序的代码,即CPU执行的机器指令,并且是只读的。
    常量区:存放常量(程序在运行的期间不能够被改变的量,例如: 10,字符串常量”abcde”, 数组的名字等)
    静态区(全局区):静态变量和全局变量的存储区域是一起的,一旦静态区的内存被分配, 静态区的内存直到程序全部结束之后才会被释放
    堆区:由程序员调用malloc()函数来主动申请的,需使用free()函数来释放内存,若申请了堆区内存,之后忘记释放内存,很容易造成内存泄漏
    栈区:存放函数内的局部变量,形参和函数返回值。栈区之中的数据的作用范围过了之后,系统就会回收自动管理栈区的内存(分配内存 , 回收内存),不需要开发人员来手动管理。栈区就像是一家客栈,里面有很多房间,客人来了之后自动分配房间,房间里的客人可以变动,是一种动态的数据变动。
    下面结合STM32内核和代码实际测试各关键字存储的区域和特点。
    本文使用是STM32L152芯片,keil V5环境下默认的内存配置见下图:
    这里写图片描述
    默认分配的ROM区域是0x8000000开始,大小是0x20000的一片区域,那么这篇区域是只读区域,不可修改,也就是存放的代码区和常量区。
    默认分配的RAM区域是0x20000000开始,大小是0x4000的一片区域,这篇区域是可读写区域,存放的是静态区、栈区和堆区。该芯片的内部分区如下图所示:
    这里写图片描述

    基于STM32内核的代码测试

    下面进行详细的测试,查看各关键字所在的各分区。

    代码区

    • 代码区的内存是由系统控制的
    • 代码区的存放 :程序中的函数编译后cpu指令
    • 代码区的地址:函数的地址,程序的入口地址,程序的名字
      函数的名称也是一个指针,可以通过查询函数名称所处的内存地址,查询函数存放的区域。
    void test(void)
    {
        printf("main:0x%p\n",main);//打印main函数的存放地址
    }

    这里写图片描述可以看到main函数确实存放在0x08002e81这片地址区域,在代码区中。

    常量区

    下面来分析一句代码:
    char *p = “abcdef”;
    这句代码和char *p; p= “abcdef”;是等价的。
    上面的两种定义方式的具体意思是:定义一个char * 型的指针p,p存放的是字符串常量”abcdef”的首地址,字符串常量”abcdef”是存放在常量区的,也就是p是指向常量区的。那么p指向的区域里面的内容是不可以得修改,只可以 *p来读取p指向的内容,当然也可以把指针p移走,指向其他区域。
    测试如下:

    void test(void)
    {   
        char *p="abcdef";
        printf("0x%p: %s\n", p , p);//打印指针p的地址和p指向的字符串内容
        p="qwedma";
        printf("0x%p: %s\n", p , p);//打印指针p的地址和p指向的字符串内容
        p[0]='1';                     //尝试把p指向的第一个字符q修改为1
        printf("0x%p: %s\n", p , p);//打印指针p的地址和p指向的字符串内容
    }

    这里写图片描述可以看到,abcdef字符串常量存放在0x08002ecc区域,p指针指向该区域,并把p指针移走指向qwedma字符串常量的首地址0x08002ee0。当尝试修改p指向的第一个字符,即把qwedma修改为1wedma,发现打印出来的内容并未改变,常量区的内容不可以改变。

    继续看这句 char str[] = “abcd”;这句话是定义了一个字符数组,但是这个str数组是存放在栈区的,然后再把字符串常量”abcd”拷贝到栈区的str数组内,那么此时的str是可以修改的。

    void test(void)
    {
        char str[] = "abcd";
        printf("0x%p: %s\n", str , str);
        str[0]='e';
        printf("0x%p: %s\n", str , str);
    }

    这里写图片描述 可以看到str是指向栈区的地址:0x200007c0,且指向的内容可以被修改,第一个字符a被修改为e。

    静态区(全局区)

    static int a;
    int c;
    void test(void)
    {
        static int b=1;
        b++;
        printf("b:0x%p: %d\n", &b , b);
    }
    int main()
    {
        printf("a: 0x%p: %d\n", &a , a);
        printf("c: 0x%p: %d\n", &c , c);
        for(uint8_t i=0;i<5;i++)
        {
            test();
        }
        return 0;
    }

    这里写图片描述a是静态全局变量,b静态局部变量,c是全局变量,它们都存放在静态区;a和c并未初始化,打印出来都是0,说明编译器自动把他们初始化为0;b在for循环中初始化5次,但实际效果是b仅初始化一次,后面每次调用b都是上次的值,且b的地址一直是不变的,编译器只会为第一次初始化的b分配内存,后面4次初始化是无效的。

    堆区

    堆区是调用malloc函数来申请内存空间,这部分空间使用完后需要调用free()函数来释放。
    void * mallc(size_t);函数的输入是分配的字节大小,返回是一个void*型的指针,该指针指向分配空间的首地址,void *型指针可以任意转换为其他类型的指针。

    void test(void)
    {   
        int *p1=malloc(4);//申请4字节的空间
        *p1=123;// 该空间赋值123
        printf("0x%p:%d\n",p1,*p1);
        printf("0x%p\n",&p1);
        free(p1);
        printf("0x%p:%d\n",p1,*p1);
        p1 = NULL;
        printf("0x%p\n",p1);
    }

    这里写图片描述
    int *p1=malloc(4);语句是申请了4个字节的空间,空间的首地址赋给指针p1,可以看到这个首地址是0x200003e8,存在是堆区;
    printf(“0x%p\n”,&p1);指针p1本身也是需要存放的,p1本身是存放在栈区的0x200009d0;
    free(p1);内存释放函数 free(开辟的内存的首地址) ,将内存标记为可用且将里面的内容清空为0,但指针p1还是指向这片空间。比较安全的做法是p1 = NULL;把p1指针释放,避免造成野指针。

    void test(void)
    {   
        int *p1=malloc(4);
        int *p2=malloc(4);
        printf("p1:0x%p\n",p1);
        printf("p2:0x%p\n",p2);
    }

    这里写图片描述p2的地址是大于p1的地址,验证堆区是向上生长的,后申请的空间地址会依次增加。

    栈区

    栈区由编译器自动分配释放,存放函数的参数值、返回值和局部变量,在程序运行过程中实时分配和释放,栈区由操作系统自动管理,无须手动管理。栈区是先进后出原则,即先进去的被堵在屋里的最里面,后进去的在门口,释放的时候门口的先出去。

    void test(void)
    {   
        int a;
        int b=0;    
        printf("a:0x%p:%d\n",&a,a);
        printf("b:0x%p:%d\n",&b,b);
    }

    这里写图片描述
    可以看到后定义的局部变量b地址是比a小的,即栈区是向下生长的;
    a变量没有进行初始化,打印出的a是垃圾值,编译器不会把局部变量初始化为0。但是,需要注意:如果你运行于debug调试模式,运行时机制会把你的栈空间全部初始化为0,这就是解释了为什么平时在debug时看到的未初始化的局部变量初始值是0.
    使用局部变量时,尽量要先进行初始化,避免垃圾值造成错乱。

    大小端测试

    数据在内存中存放,有大段模式和小端模式。
    小端模式(little-endian):低位字节存在低地址上,高位字节存在高地址上;
    大端模式( big-endian):低位字节存在高地址上,高位字节存在低地址上,刚好与小端模式相反。
    另:网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序

    static uint32_t m=0x87654321;
    char *p=(char*)&m;
    void test(void)
    {   
        printf("P  :0x%p: %x\n",p,*p);
        printf("P+1:0x%p: %x\n",p+1,*(p+1));
        printf("P+2:0x%p: %x\n",p+2,*(p+2));
        printf("P+3:0x%p: %x\n",p+3,*(p+3));
    }

    这里写图片描述低字节21放在低地址,高字节87放在高地址,与小端模式相符。

    keil中代码和数据量所占字节的查询

    keil软件勾选上生成批处理文件,在keil编译完成后,可以查看到代码和定义的数据所占的字节大小。

    这里写图片描述这里写图片描述
    如上图,Code是程序代码所占的字节,即代码区;
    RO-data 代表只读数据,程序中所定义的常量数据和字符串等都位于此处,即常量区;
    RW-data 代表已初始化的读写数据,程序中定义并且初始化的全局变量和静态变量位于此处,一部分静态区(全局区);
    ZI-data 代表未初始化的读写数据,程序中定义了但没有初始化的全局变量和静态变量位于此处,另一部分的静态区(全局区)。ZI英语是zero initial,就是程序中用到的变量并且被系统初始化为0的变量的字节数,keil编译器默认是把你没有初始化的变量都赋值一个0,这些变量在程序运行时是保存在RAM中的。
    Total ROM Size (Code + RO Data + RW Data)这样所写的程序占用的ROM的字节总数,也就是说程序所下载到ROM flash 中的大小。

    为什么Rom中还要存RW,因为掉电后RAM中所有数据都丢失了,每次上电RAM中的数据是被重新赋值的,每次这些固定的值就是存储在Rom中的,为什么不包含ZI段呢,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可,包含进去反而浪费存储空间。

    实际上,ROM中的指令至少应该有这样的功能:
    1. 将RW从ROM中搬到RAM中,因为RW是变量,变量不能存在ROM中。
    2. 将ZI所在的RAM区域全部清零,因为ZI区域并不在Image中,所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在ROM中。
    在程序运行的最初阶段,RO中的指令完成了这两项工作后C程序才能正常访问变量。否则只能运行不含变量的代码。

    展开全文
  • 代码编写规范

    千次阅读 2019-04-23 22:48:44
    排版格式2.1 类及其排版格式2.2 函数的声明与定义2.3 空行2.4 代码行2.5 代码行内的空格2.6 对齐2.7 长行拆分2.8 修饰符的位置2.9 代码段中的预处理格式2.10 被注释的代码2.11 注释3.命名规则4.表达式和基本语句4.1 ...

    1.目标

    我们所认为的优秀程序员应该具备的能力是什么?高效的算法,优良的架构,设计模式,面向对象等等,这些我们每天挂在嘴上,喊着要学习的技能。确实,能很好的掌握这些技能是成为优秀程序员的条件,但是作为程序员最根本,最基础的是代码编写,如何编写高质量,可靠的,规范的代码,是作为一名合格程序员的基础和根本,本规范规定了我们编写代码的格式,排版,注释,函数,变量,命名等,从这些最基础的编码规范来纠正我们的一些编码错误,要写出高质量的代码这些都是第一步,只有把这个基础打扎实,我们才可能“建设”稳健的“代码大厦”。

    2.排版格式

    程序排版格式虽然不是十分严格的规范要求,但整个项目都服从统一的编程风格,这样使所有人在阅读和理解代码时更加容易。格式虽然不会影响程序的功能,但会影响可读性。程序的排版格式追求清晰、美观,是程序风格的重要构成因素。可以把程序的排版格式比喻为“书法”。好的“书法”可让人对程序一目了然,看得兴致勃勃。差的程序“书法”如螃蟹爬行,让人看得索然无味,更令维护者烦恼有加。请程序员们学习程序的“书法”,弥补大学计算机教育的漏洞,实在很有必要。

    2.1 类及其排版格式

    • 声明属性依次序是public:、protected:、private:。
    • 关键字public,protected,private不要缩进,声明的函数和变量缩进一个制表符。
    • 类声明前应加上注释,注明该类的主要作用。
    • 不改变对象成员变量的类成员函数都应标记为const,可以预防意外的变动,提高程序的健壮性。
    • 类中成员必须进行初始化,可以通过构造函数的初始化列表初始化成员或者写一个专门初始化成员的函数(如init())。
    • 有继承关系的基类中析构函数一定要声明为虚函数。
    • 为了防止头文件重复包含,应在头文件处加上#ifndef/#define/#endif宏。
    • 函数和成员变量的声明分开。
      类声明的基本格式如下:
      class MyClass : public OtherClass 
      { 
      public:
      MyClass(); 
      MyClass(int var);
      ~MyClass() {} 
      void someFunction(); 
      void someFunctionThatDoesNothing()
      void set_some_var(int var)
      int some_var() const 
      
      private: 
      bool someInternalFunction(); 
      
      private:
      int some_var_;
      int some_other_var_; 
      }; 
      
      

    2.2 函数的声明与定义

    • 返回类型和函数名在同一行,合适的话,参数也放在同一行。

    • 返回值总是和函数名在同一行;参数列表的左圆括号总是和函数名在同一行。

    • 函数名和左圆括号间没有空格;圆括号与参数间没有空格。

    • 左大括号总是新起一行;右大括号总是单独位于函数最后一行。

    • 函数的声明(头文件)和实现处(CPP)的所有形参名称必须保持一致。

    • 函数的内容总与左括号保持一个制表符的缩进。

    • 参数间的逗号总加一个空格。

    • 函数的大小一般不要超过50行,函数越小,代码越容易维护。

    • 函数声明前应加上注释,注明该函数的作用,如果该函数有比较多的参数,还应该加上参数含义和返回值的注释。

    • 如果函数的参数是类对象,应使用对象的指针或引用来传递,以提高效率。

      ReturnType ClassName::FunctionName(Type par_name1, Type par_name2)
      { 
      DoSomething(); 
      ...
      } 
      	如果同行一行文本较多,容不下所有参数时:
      ReturnType ClassName::FunctionName(Type p_name1,
       								   Type p_name2,
                                                                Type p_name3)
      { 
      DoSomething(); 
      ...
      } 
      
    • 如果函数为const的,关键字const应与最后一个参数位于同一行。

      ReturnType  FunctionName(Type par)  const 
      { 	
      ...
      } 
      

    2.3 空行

    空行起着分隔程序段落的作用。空行得体(不过多也不过少)将使程序的布局更加清晰。空行不会浪费内存,虽然打印含有空行的程序是会多消耗一些纸张,但是值得。所以不要舍不得用空行。

    • 在每个类声明之后、每个函数定义结束之后都要加空行。
    // 空行
    void Function1(…)
    {
      …
    }
    // 空行
    void Function2(…)
    {
      …
    }
    
    • 在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。
    // 空行
    while (condition)
    {
    	statement1;
    	// 空行
    	if (condition) 
    	{
    		statement2;
    	}
    	else
    	{
    		statement3;
    	}
    // 空行
    	statement4;
    }
    
    

    2.4 代码行

    • 一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释。
    • if、for、while、do等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加{}。这样可以防止书写失误。

    示例2-4(a)为风格良好的代码行,示例2-4(b)为风格不良的代码行。

    int width = 0;	// 宽度
    int height = 0;	// 高度
    int depth = 0;	// 深度	
    
    2-4(a)
    
    int width, height, depth; // 宽度高度深度
    
    2-4(b)
    
    
    x = a + b;
    y = c + d;
    z = e + f;
    
    2-4(a)
    
    X = a + b;   y = c + d;  z = e + f;
    2-4(b)
    
    
    if (width < height) 
    {
      dosomething();
    }	
    for (initialization; condition; update)
    {
       dosomething();
    }
    // 空行
    other();
    
    2-4(a)
    
    if (width < height) dosomething();
    for (initialization; condition; update)
         dosomething();
    other();
     2-4(b) 
     
    示例2-4(a) 风格良好的代码行                 示例2-4(b) 风格不良的代码行
    
    • 在定义变量的同时必须初始化该变量。
      如果变量的引用处和其定义处相隔比较远,变量的初始化很容易被忘记。如果引用了未被初始化的变量,可能会导致程序错误。例如
    int width = 10; 	// 定义并初绐化width 
    int height = 10;	// 定义并初绐化height 
    int depth = 10; 	// 定义并初绐化depth 
    

    2.5 代码行内的空格

    • ‘,’之后要留空格,如Function(x, y, z)。如果‘;’不是一行的结束符号,其后要留空格,如for (initialization; condition; update)。
    • 赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=” “>=”、“<=”、“+”、“*”、“%”、“&&”、“||”、“<<”,“^”等二元操作符的前后应当加空格。
    • 一元操作符如“!”、“~”、“++”、“–”、“&”(地址运算符)等前后不加空格。
    • 像“[]”、“.”、“->”这类操作符前后不加空格。
    void Func1(int x, int y, int z);          // 良好的风格
    void Func1 (int x,int y,int z);           // 不良的风格
    
    if(year >= 2000)                     // 良好的风格
    if(year>=2000)                      // 不良的风格
    
    if ((a>=b) && (c<=d))                // 良好的风格
    if(a>=b&&c<=d)                    // 不良的风格
    
    for (i=0; i<10; i++)                   // 良好的风格
    for(i=0;i<10;i++)                     // 不良的风格
    for (i = 0; i < 10; i ++)                 // 过多的空格
    
    x = a < b ? a : b;                      // 良好的风格
    x=a<b?a:b;                          // 不好的风格
    
    int *x = &y;                         // 良好的风格  
    int * x = & y;                        // 不良的风格  
    
    array[5] = 0;                         // 不要写成 array [ 5 ] = 0;
    a.Function();                         // 不要写成 a . Function();
    b->Function();                        // 不要写成 b -> Function();
    
    示例2-5 代码行内的空格
    

    2.6 对齐

    • 程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。
    • { }之内的代码块在‘{’右边一个制表符左对齐。

    示例2-6(a)为风格良好的对齐,示例2-6(b)为风格不良的对齐。

    void Function(int x)
    {
    … // program code
    }	
    2-6(a) 
    
    void Function(int x){
    … // program code
    }
    2-6(b)
    
    
    if (condition)
    {
    … // program code
    }
    else
    {
    … // program code
    }
    2-6(a) 
    
    if (condition){
    … // program code
    }
    else {
    … // program code
    }
    2-6(b)
    
    for (initialization; condition; update)
    {
    … // program code
    }
    2-6(a) 
    
    for (initialization; condition; update){
    … // program code
    }
    2-6(b)
    
    While (condition)
    {
    … // program code
    }
    2-6(a) 
    
    while (condition){
    … // program code
    }
    2-6(b)
    
    如果出现嵌套的{},则使用缩进对齐,如:
    	{
    	   …
    		 {
    		   …
    		 }
    	  …
        }	
    示例2-6(a) 风格良好的对齐                       示例2-6(b) 风格不良的对齐
    

    2.7 长行拆分

    • 代码行最大长度宜控制在70至80个字符以内。代码行不要过长,否则眼睛看不过来,也不便于打印。
    • 长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。
    if ((very_longer_variable1 >= very_longer_variable12)
    && (very_longer_variable3 <= very_longer_variable14)
    && (very_longer_variable5 <= very_longer_variable16))
    {
        dosomething();
    }
    
    virtual CMatrix CMultiplyMatrix (CMatrix leftMatrix,
                                     CMatrix rightMatrix);
    
    for (very_longer_initialization;
    	 very_longer_condition;
    	 very_longer_update)
    {
    	dosomething();
    }
    示例2-7 长行的拆分
    

    2.8 修饰符的位置

    修饰符 * 和 & 应该靠近数据类型还是该靠近变量名,是个有争议的活题。
    若将修饰符 * 靠近数据类型,例如:int* x; 从语义上讲此写法比较直观,即x是int 类型的指针。
    上述写法的弊端是容易引起误解,例如:int* x, y; 此处y容易被误解为指针变量。虽然将x和y分行定义可以避免误解,但并不是人人都愿意这样做。

    • 应当将修饰符 * 和 & 紧靠变量名
      例如:
    char  *name;
    int   *x, y;	// 此处y不会被误解为指针
    

    2.9 代码段中的预处理格式

    • 预处理指令不要缩进,从行首开始。即使预处理指令位于缩进代码块中,指令也应从行首开始。
      例如:
    if(lopsided_score)
    { 
    #if DISASTER_PENDING 	// 正确 – 预处理从行首开始
    dropEverything(); 
    #endif 
    BackToNormal(); 
    } 
    
    

    2.10 被注释的代码

    • 在代码中经常残留一下被注释的代码,如果这段代码还有价值,必须对该段代码加上被注释的原因,或者不需要有的就直接删除。

    2.11 注释

    注释虽然写起来很痛苦,但对保证代码可读性至为重要。当然,注释的确很重要,但最好的代码本身就是文档,类名和变量名意义明确要比通过注释解释模糊的命名要好的多。注释是为别人(下一个需要理解你代码的人)而写的,认真点吧,下一个人可能就是你!如何写注释请详见《合约编程》

    • 注释是对代码的“提示”,而不是文档。程序中的注释不可喧宾夺主,注释太多了会让人眼花缭乱。注释的花样要少。
    • 如果代码本来就是清楚的,则不必加注释。否则多此一举,令人厌烦。单行注释用//,多行注释用/* */。
      例如 i++; // i 加 1,多余的注释
    • 边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。
    • 注释应当准确、易懂,防止注释有二义性。错误的注释不但无益反而有害。
    • 尽量避免在注释中使用缩写,特别是不常用缩写。
    • 注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。

    3.命名规则

    命名规则是软件编程中重要的规则之一,规范命名风格会使代码风格保持一致,更容易被团队中其他伙伴理解。
    总体原则是所有命名必须做到见名知意。

    • 标识符应当直观且可以拼读,可见名知意,不必进行“解码”。
      标识符最好采用英文单词或其组合,便于记忆和阅读。切忌使用汉语拼音来命名。程序中的英文单词一般不会太复杂,用词应当准确。例如不要把currentValue写成nowValue。

    • 命名规则要求符合匈牙利命名法。

    • 所有的变量,函数,类的命名,若需要多个单词时,每个单词直接连写,不要用下划线(“_”)或横线(“-”)分开。如:DeviceInfo,RemoteCamera。

    • 类的名字应当使用“名词”。能准确表示被抽象的事物。首字母以大写开头。
      例如:要重新一个摄像机,可以定义一个Camera类。

    • 函数的名字应当使用“动词”或者“动词+名词”(动宾词组)。类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。
      例如:
      DrawBox(); // 全局函数
      box->Draw(); // 类的成员函数

    • 变量的名字应当使用“名词”或者“形容词+名词”。首字母以小写开头。
      例如:
      float value;
      float oldValue;
      float newValue;

    • 对于变量命名,禁止取单个字符(如i、j、k…),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i、j、k作局部循环变量是允许的。

    • 变量名字需要加上作用域的前缀,类的成员变量加上“m_”前缀,局部变量不加作用域前缀,全局变量加上“g_”前缀。
      变量型前缀见下表:
      |前缀 | 类型说明 |
      | ------ | ------ |
      |n |整型变量(int/short/long)|
      |c |字符型变量(char)|
      |psz| 字符型变量指针char*|
      |b |布尔型变量(bool)|
      |w |整型变量word|
      |dw |整型变量DWORD|
      |bt |字节变量byte|
      |e |枚举型变量(enum)|
      |d |浮点型变量(double)|
      |sz |字符型变量(char[n])|
      |str | 字符型变量(string)|
      |obj | 类实例变量|
      |pobj | 类实例变量指针|
      |iter | STL迭代器变量(iterator)|
      |m_ |类成员变量|
      |p_ |函数参数|
      |g_ |全局变量|
      |h |句柄|

    • 常量命名,枚举命名,宏命名都用大写,每个单词直接用下划线(“_”)分开。如:ENCODE_TYPE_H264,ENCODE_TYPE_MPEG2。

    • 项目的名字都使用“名词”,首字母以大写开头。

    • 用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。
      例如:

    int	minValue;
    int	maxValue;
    
    int	setValue(…);
    int	getValue(…);
    
    • 避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。

    • 程序中不要出现仅靠大小写区分的相似的标识符。
      例如:

    int  x,  X;		// 变量x 与 X 容易混淆
    void foo(int x);	// 函数foo 与FOO容易混淆
    void FOO(float x);
    
    • 程序中不要出现标识符完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解。

    • 命名风格保持一致,自己特有的命名风格,要自始至终保持一致,不可来回变化。项目组或产品组对命名有统一的规定,个人服从团队。说明:个人的命名风格,在符合所在项目组或产品组的命名规则的前提下,才可使用。(即命名规则中没有规定到的地方才可有个人命名风格)。

    • 命名中若使用特殊约定或缩写,则要有注释说明。
      说明:应该在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写进行必要的注释说明。

    • 避免命名空间与类名冲突,命名空间的定义以NS_为前缀。

    4.表达式和基本语句

    4.1 运算符的优先级

    C++中的运算符有很多,并且有严格的优先级和结合律,记忆起来比较困难。

    • 如果代码行中的运算符比较多,使用用括号明确表达式的操作顺序,避免使用默认优先级。
      示例:下列语句中的表达式
     word = (high << 8) | low    (1)
     if ((a | b) && (a & c))      	(2)
     if ((a | b) < (c & d))         (3)
     如果书写为
     high << 8 | low
     a | b && a & c
     a | b < c & d
     由于
     high << 8 | low = ( high << 8) | low,
     a | b && a & c = (a | b) && (a & c),
     (1)(2)不会出错,但语句不易理解;
     a | b < c & d = a | (b < c) & d,(3)造成了判断条件出错   
    

    4.2 复合表达式

    如 a = b = c = 0这样的表达式称为复合表达式。允许复合表达式存在的理由是:(1)书写简洁;(2)可以提高编译效率。但要防止滥用复合表达式。

    • 不要编写太复杂的复合表达式。
      例如:
      i = a >= b && c < d && c + f <= g + h ; // 复合表达式过于复杂

    • 不要有多用途的复合表达式。
      例如:
      d = (a = b + c) + r ;
      该表达式既求a值又求d值。应该拆分为两个独立的语句:
      a = b + c;
      d = a + r;

    • 不要把程序中的复合表达式与“真正的数学表达式”混淆。
      例如:

    if (a < b < c)			// a < b < c是数学表达式而不是程序表达式
    并不表示	
    if ((a<b) && (b<c))
    而是成了令人费解的if ( (a<b)<c )
    

    4.3 避免直接使用数字作为标识符

    • 避免使用不易理解的数字,用有意义的标识来替代。涉及物理状态或者含有物理意义的常量,不应直接使用数字,必须用有意义的枚举或常量来代替。
    示例:如下的程序可读性差。
    if (Trunk[index].trunk_state == 0)
    {
        Trunk[index].trunk_state = 1;
        ...  // program code
    }
    
    应改为如下形式。
    const int TRUNK_IDLE = 0;
    const int TRUNK_BUSY = 1;
    
    if (Trunk[index].trunk_state == TRUNK_IDLE)
    {
        Trunk[index].trunk_state = TRUNK_BUSY;
        ...  // program code
    }
    

    4.4 if 语句

    if语句是C++/C语言中最简单、最常用的语句,然而很多程序员用隐含错误的方式写if语句。本节以“与零值比较”为例,展开讨论。

    • 不可将布尔变量直接与TRUE、FALSE或者1、0进行比较。
      根据布尔类型的语义,零值为“假”(记为FALSE),任何非零值都是“真”(记为TRUE)。TRUE的值究竟是什么并没有统一的标准。例如Visual C++ 将TRUE定义为1,而Visual Basic则将TRUE定义为-1。
      假设布尔变量名字为flag,它与零值比较的标准if语句如下:
      if (flag) // 表示flag为真
      if (!flag) // 表示flag为假
      其它的用法都属于不良风格,例如:
      if (flag == TRUE)
      if (flag == 1 )
      if (flag == FALSE)
      if (flag == 0)

    • 应当将整型变量用“==”或“!=”直接与0比较。
      假设整型变量的名字为value,它与零值比较的标准if语句如下:
      if (value == 0)
      if (value != 0)
      不可模仿布尔变量的风格而写成
      if (value) // 会让人误解 value是布尔变量
      if (!value)

    • 不可将浮点变量用“” 或 “!=”与任何数字比较。
      千万要留意,无论是float还是double类型的变量,都有精度限制。所以一定要避免将浮点变量用“
      ”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。
      假设浮点变量的名字为x,应当将
      if (x == 0.0) // 隐含错误的比较
      转化为
      if ((x>=-EPSINON) && (x<=EPSINON))
      其中EPSINON是允许的误差(即精度)。

    • 应当将指针变量用“==”或“!=”与NULL比较。
      指针变量的零值是“空”(记为NULL)。尽管NULL的值与0相同,但是两者意义不同。假设指针变量的名字为p,它与零值比较的标准if语句如下:
      if (p == NULL) // p与NULL显式比较,强调p是指针变量
      if (p != NULL)
      不要写成
      if (p == 0) // 容易让人误解p是整型变量
      if (p != 0)
      或者
      if § // 容易让人误解p是布尔变量
      if (!p)

    • 有时候我们可能会看到 if (NULL == p) 这样古怪的格式。不是程序写错了,是程序员为了防止将 if (p == NULL) 误写成 if (p = NULL),而有意把p和NULL颠倒。编译器认为 if (p = NULL) 是合法的,但是会指出 if (NULL = p)是错误的,因为NULL不能被赋值。

    4.5 循环语句的效率

    C++/C循环语句中,for语句使用频率最高,while语句其次,do语句很少用。本节重点论述循环体的效率。提高循环体效率的基本办法是降低循环体的复杂性。

    • 在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循环层的次数。例如示例4-5(b)的效率比示例4-5(a)的高。
    for (row=0; row<100; row++)
    {
        for ( col=0; col<5; col++ )
        {
          sum = sum + a[row][col];
        }
    }
    4-5(a)
    
    for (col=0; col<5; col++ )
    {
        for (row=0; row<100; row++)
        {
            sum = sum + a[row][col];
        }
    }
    4-5(b)
    
    示例4-5(a) 低效率:长循环在最外层           示例4-5(b) 高效率:长循环在最内层
    
    • 如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体的外面。示例4-4©的程序比示例4-4(d)多执行了N-1次逻辑判断。并且由于前者老要进行逻辑判断,打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。如果N非常大,最好采用示例4-4(d)的写法,可以提高效率。如果N非常小,两者效率差别并不明显,采用示例4-4©的写法比较好,因为程序更加简洁。
    for (i=0; i<N; i++)
    {
    if (condition)
        DoSomething();
    else
        DoOtherthing();
    }	
    4-4(c)
    
    if (condition)
    {
    for (i=0; i<N; i++)
        DoSomething();
    }
    else
    {
      for (i=0; i<N; i++)
        DoOtherthing();
    }
    4-4(d)
    
    表4-4(c) 效率低但程序简洁                表4-4(d) 效率高但程序不简洁
    

    4.6 new的使用

    • new后的指针在使用前也需要进行非空判断,delete指针后应将指针置为空。

    5.常量

    5.1 为什么需要常量

    如果不使用常量,直接在程序中填写数字或字符串,将会有什么麻烦?

    1. 程序的可读性(可理解性)变差。程序员自己会忘记那些数字或字符串是什么意思,用户则更加不知它们从何处来、表示什么。
    2. 在程序的很多地方输入同样的数字或字符串,难保不发生书写错误。
    3. 如果要修改数字或字符串,则会在很多地方改动,既麻烦又容易出错。
    • 尽量使用含义直观的常量来表示那些将在程序中多次出现的数字或字符串。
      例如:
    #define    		MAX   100		/*  C语言的宏常量  */ 
    const  int  MAX = 100;		//  C++ 语言的const常量
    const  float PI = 3.14159;		//  C++ 语言的const常量
    

    5.2 const 与 #define的比较

    C++ 语言可以用const来定义常量,也可以用 #define来定义常量。但是前者比后者有更多的优点:

    1. const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。
    2. 有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。
    • 在C++ 程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。

    5.3 常量定义规则

    • 需要对外公开的常量放在头文件中,不需要对外公开的常量放在定义文件的头部。为便于管理,可以把不同模块的常量集中存放在一个公共的头文件中。
    • 如果某一常量与其它常量密切相关,应在定义中包含这种关系,而不应给出一些孤立的值。
      例如:
    const  float   RADIUS = 100;
    const  float   DIAMETER = RADIUS * 2;
    

    6.函数

    根据《合约编程》中对函数的定义:一个正确的方法应该“不多不少”正好完成要求它完成的功能。该部分的基础理论是《TDD与单元测试》、《合约编程》。

    6.1 参数的规则

    • 参数的书写要完整,不要贪图省事只写参数的类型而省略参数名字。如果函数没有参数,则用void填充。
      例如:

      void setValue(int p_nWidth, int p_nHeight);	// 良好的风格
      
      void setValue(int, int);					// 不良的风格
      
    • 参数命名要恰当,顺序要合理。

      例如编写字符串拷贝函数StringCopy,它有两个参数。如果把参数名字起为str1和str2,例如void stringCopy(char * p_str1, char * p_str2);那么我们很难搞清楚究竟是把str1拷贝到str2中,
      还是刚好倒过来。可以把参数名字起得更有意义,如叫strSource和strDestination。这样从名字上就可以看出应该把strSource拷贝到strDestination。还有一个问题,这两个参数那一个该在前那一个该在后?
      参数的顺序要遵循程序员的习惯。一般地,应将目的参数放在前面,源参数放在后面。
      如果将函数声明为:
      void stringCopy(char * p_strSource, char * p_strDestination);
      别人在使用时可能会不假思索地写成如下形式:
      char str[20];
      stringCopy(str, “Hello World”); // 参数顺序颠倒

    • 如果参数是指针,且仅作输入用,则应在类型前加const,以防止该指针在函数体内被意外修改。
      例如:
      void stringCopy(char * p_strDestination,const char * p_strSource);
      函数中的指针入参必须进行非空判断

    • 如果输入参数以值传递的方式传递对象,则宜改用“const &”方式来传递,
      这样可以省去临时对象的构造和析构过程,从而提高效率。

    • 避免函数有太多的参数,参数个数尽量控制在5个以内。如果参数太多,在使用时容易将参数类型或顺序搞错。

    • 尽量不要使用类型和数目不确定的参数。

      C标准库函数printf是采用不确定参数的典型代表,其原型为:int printf(const chat *format[, argument]…); 这种风格的函数在编译时丧失了严格的类型安全检查。

    6.2 返回值的规则

    • 不要省略返回值的类型。

      C语言中,凡不加类型说明的函数,一律自动按整型处理。这样做不会有什么好处,却容易被误解为void类型。
      C++语言有很严格的类型安全检查,不允许上述情况发生。由于C++程序可以调用C函数,为了避免混乱,规定任何C++/ C函数都必须有类型。如果函数没有返回值,那么应声明为void类型。

    • 函数名字与返回值类型在语义上不可冲突。

      违反这条规则的典型代表是C标准库函数getchar。
      例如:
      char c;
      c = getchar();
      if (c == EOF)

      按照getchar名字的意思,将变量c声明为char类型是很自然的事情。但不幸的是getchar的确不是char类型,而是int类型,其原型如下:
      int getchar(void);
      由于c是char类型,取值范围是[-128,127],如果宏EOF的值在char的取值范围之外,那么if语句将总是失败,这种“危险”人们一般哪里料得到!导致本例错误的责任并不在用户,是函数getchar误导了使用者。

    • 不要将正常值和错误标志混在一起返回。正常值用输出参数获得,而错误标志用return语句返回。

      回顾上例,C标准库函数的设计者为什么要将getchar声明为令人迷糊的int类型呢?他会那么傻吗?
      在正常情况下,getchar的确返回单个字符。但如果getchar碰到文件结束标志或发生读错误,它必须返回一个标志EOF。为了区别于正常的字符,只好将EOF定义为负数(通常为负1)。因此函数getchar就成了int类型。
      我们在实际工作中,经常会碰到上述令人为难的问题。为了避免出现误解,我们应该将正常值和错误标志分开。即:正常值用输出参数获得,而错误标志用return语句返回。
      函数getchar可以改写成 BOOL GetChar(char *c);
      虽然gechar比GetChar灵活,例如 putchar(getchar()); 但是如果getchar用错了,它的灵活性又有什么用呢?

    • 如果函数的返回值是一个对象,有些场合用“引用传递”替换“值传递”可以提高效率。而有些场合只能用“值传递”而不能用“引用传递”,否则会出错。
      例如:

      class String
      {…
      	// 赋值函数
      	String & operate=(const String &other);	
      // 相加函数,如果没有friend修饰则只许有一个右侧参数
      friend	String   operate+( const String &s1, const String &s2); 
      private:
      	char *m_data; 
      }
      
      	String的赋值函数operate = 的实现如下:
      String & String::operate=(const String &other)
      {
      	if (this == &other)
      		return *this;
      	delete m_data;
      	m_data = new char[strlen(other.data)+1];
      	strcpy(m_data, other.data);
      	return *this;	// 返回的是 *this的引用,无需拷贝过程
      }
      

      对于赋值函数,应当用“引用传递”的方式返回String对象。如果用“值传递”的方式,虽然功能仍然正确,但由于return语句要把 *this拷贝到保存返回值的外部存储单元之中,增加了不必要的开销,降低了赋值函数的效率。例如:

          	String a,b,c;
          	…
          	a = b; 		// 如果用“值传递”,将产生一次 *this 拷贝
          	a = b = c; 	// 如果用“值传递”,将产生两次 *this 拷贝
      
      	String的相加函数operate + 的实现如下:
      	
             String  operate+(const String &s1, const String &s2)  
          {
          	String temp;
          	delete temp.data;	// temp.data是仅含‘\0’的字符串
          	temp.data = new char[strlen(s1.data) + strlen(s2.data) +1];
          	strcpy(temp.data, s1.data);
          	strcat(temp.data, s2.data);
          	return temp;
          }
      

      对于相加函数,应当用“值传递”的方式返回String对象。如果改用“引用传递”,那么函数返回值是一个指向局部对象temp的“引用”。由于temp在函数结束时被自动销毁,将导致返回的“引用”无效。例如:
      c = a + b;
      此时 a + b 并不返回期望值,c什么也得不到,留下了隐患。

    • 对所调用函数的错误返回值要仔细、全面地处理。

    7.建议

    7.1 使用const

    看到const关键字,C++程序员首先想到的可能是const常量。这可不是良好的条件反射。如果只知道用const定义常量,那么相当于把火药仅用于制作鞭炮。const更大的魅力是它可以修饰函数的参数、返回值,甚至函数的定义体。const是constant的缩写,“恒定不变”的意思。被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。所以很多C++程序设计书籍建议:“Use const whenever you need”。

    • 用const修饰函数的参数
      如果参数作输出用,不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加const修饰,否则该参数将失去输出功能。
      const修饰输入参数:如果输入参数采用“指针传递”,那么加const修饰可以防止意外地改动该指针,起到保护作用。例如stringCopy函数:void stringCopy(char * p_strDestination, const char * p_strSource); 其中p_strSource是输入参数,p_strDestination是输出参数。给p_strSource加上const修饰后,如果函数体内的语句试图改动p_strSource的内容,编译器将指出错误。
      如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const修饰。用法总结一下

      1.对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const引用传递”,目的是提高效率。
      
      例如将void Func(A a) 改为void Func(const A &a)。
      
      因为函数体内将产生A类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。为了提高效率,可以将函数声明改为void Func(A &a),因为“引用传递”仅借用一下参数的别名而已,
      不需要产生临时对象。但是函数void Func(A &a)存在一个缺点:“引用传递”有可能改变参数a,
      这是我们不期望的。解决这个问题很容易,加const修饰即可,因此函数最终成为void Func(const A &a)。
      
      2.对于内部数据类型的输入参数,不要将“值传递”的方式改为“const引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。
      
      例如void Func(int x) 不应该改为void Func(const int &x)。
      
      以上此类推,是否应将void Func(int x) 改写为void Func(const int&x),以便提高效率?
      完全没有必要,因为内部数据类型的参数不存在构造、析构的过程,而复制也非常快,
      “值传递”和“引用传递”的效率几乎相当
      
      
    • 用const修饰函数的返回值
      如果给以“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const修饰的同类型指针。
      例如 函数 const char * getString();
      如下语句将出现编译错误:
      char *str = getString();
      正确的用法是
      const char *str = getString();
      如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const修饰没有任何价值。
      例如不要把函数int getInt() 写成const int getInt(void)。
      同理不要把函数A getA() 写成const A getA(),其中A为用户自定义的数据类型。
      如果返回值不是内部数据类型,将函数A getA() 改写为const A & getA()的确能提高效率。但此时千万千万要小心,一定要搞清楚函数究竟是想返回一个对象的“拷贝”还是仅返回“别名”就可以了,否则程序会出错。见6.2节“返回值的规则”。

    • const成员函数
      任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提高程序的健壮性。以下程序中,类stack的成员函数getCount仅用于计数,从逻辑上讲getCount应当为const函数。编译器将指出getCount函数中的错误。

      	class Stack
      {
      	  public:
      		void 	push(int elem);
      		int 	pop();
      		int		getCount()  const;	// const成员函数
      	  private:
      		int		m_num;
      		int		m_data[100];
      };
      
      	int Stack::getCount() const
      {
      		++ m_num;	// 编译错误,企图修改数据成员m_num
      	pop();		// 编译错误,企图调用非const函数
      	return m_num;
      	}
      	
      

      const成员函数的声明看起来怪怪的:const关键字只能放在函数声明的尾部,大概是因为其它地方都已经被占用了。

    7.2 其他建议

    • 当心那些视觉上不易分辨的操作符发生书写错误。
    我们经常会把“==”误写成“=”,象“||”、“&&”、“<=”、“>=”这类符号也很容易发生“丢1”失误。然而编译器却不一定能自动指出这类错误。
    
    • 变量(指针、数组)被创建之后应当及时把它们初始化,以防止把未被初始化的变量当成右值使用。

    • 当心变量的初值、缺省值错误,或者精度不够。

    • 当心数据类型转换发生错误。尽量使用显式的数据类型转换(让人们知道发生了什么事),避免让编译器轻悄悄地进行隐式的数据类型转换。

    • 当心变量发生上溢或下溢,数组的下标越界。

    • 当心忘记编写错误处理程序,当心错误处理程序本身有误。

    • 当心文件I/O有错误。

    • 避免编写技巧性很高代码。

    • 不要设计面面俱到、非常灵活的数据结构。

    • 如果原有的代码质量比较好,尽量复用它。但是不要修补很差劲的代码,应当重新编写。

    • 尽量使用标准库函数,不要“发明”已经存在的库函数。

    • 尽量不要使用与具体硬件或软件环境关系密切的变量。

    • 把编译器的选择项设置为最严格状态。

    • 如果可能的话,使用PC-Lint、LogiScope等工具进行代码审查。

    • 业务逻辑等容易出错的地方建议加上错误处理,并写入日志,以便快速定位出错位置。

    • 条件语句中变量与常量比较时尽量将常量放在前面,出错时编译器会直接报错。例如,不小心写成if(true = bRet),编译时会直接报错,但是如果写成if(bRet = true),那么相对没那么容易找出错误了。

    • 在QT中,由于更多用来设计界面,为了更好地区分控件类型,成员变量的命名需要突出控件类型,建议在变量名的后面加上控件的标识,如QLineEdit* m_pIPLineEdit,QComboBox* m_pTimeIntervalComboBox,QPushButton* m_pQueryPushButton。

    • 在QT中,为了区分信号和槽函数,信号函数名建议用前缀signal_,如signal_currentTaskInfo;槽函数名建议用前缀slot_,如slot_queryIpInfo。

    • 在QT中,有继承关系的类若存在信号和槽函数,必须要在类体中加入Q_OBJECT宏,否则加入的信号和槽将会没有响应。

    • 在QT中,需要注意槽函数的参数与信号参数的匹配问题,信号的参数必须要大于等于槽函数的参数;自定义信号和槽函数若存在自定义参数,必须要用qRegisterMetaType("")进行注册,否则信号和槽将没有响应。例如

      #include <QMetaType>
      //注册自定义数据类型DeviceTime
      qRegisterMetaType<DeviceTime>("DeviceTime");
      
    • 在QT中,new时没有指定parent的指针用完后必须要释放,释放后应该置为空;而new时指定parent的指针由系统自动回收,不需要程序员释放。

    展开全文
  • HTML特效代码大全(完整)

    万次阅读 多人点赞 2018-09-17 13:19:16
    1.贴图:&lt;img src="图片地址"&gt; 2.加入连接:&lt;a href="所要连接的相关地址"&gt;写上你想写的字&lt;/a&gt; 3.在新窗口打开连接:&...a h
  • 常见HTTP错误代码大全

    万次阅读 多人点赞 2011-06-24 15:10:00
    一些常见的状态码为:200 - 服务器成功返回网页404 - 请求的网页不存在503 - 服务不可用详细分解:1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态代码代码 说明100 (继续) 请求者应当继续提出请求...
  • 即使是一段普通的代码,在保持思维清晰、功能友好的前提下怎样编写才能结构清晰、整洁美观呢? 在多年以前,人们注重功能是如何实现的。现如今,随着Web及互联网技术的不断发展,功能仅成了最基本的要求,...
  • ©的代码实现

    千次阅读 2017-03-16 14:15:14
  • HTML网页特殊符号代码大全 ...下面做了整理,以备速查(注意:代码对大小写敏感)。 1、特色类 字符 实体名称 实体数字 描述 © &copy; &#169; 版权标志 | 竖线,常用作菜单或导航中的分隔符
  • cmd版贪吃蛇

    万次阅读 2018-03-28 00:23:20
    import java.awt.*; import java.util.LinkedList; import java.util.Scanner; /** * @author aachen0 * @date 2018/3/27 13:56 * IDE:IntelliJ IDEA ...public class SnakeGame { static final int WIDTH = ...
  • 如何在CSDN博客中的所贴的代码进行【代码块】显示

    万次阅读 多人点赞 2012-03-06 10:12:32
     笔者最近很喜欢在csdn发一些技术博客,可是看了别人的博客,有代码的地方总是可以显示出代码块,而自己贴上去的代码总是没有。刚开始还以为CSDN博客里面的编辑功能有,可是找来找去都没有找到。后来才发现原来需要...
  • Android在java代码中设置margin

    万次阅读 2013-09-05 17:52:14
    但是有些情况下,需要在java代码里来写,可是View本身没有setMargin方法,怎么办呢?   通过查阅android api,我们发现android.view.ViewGroup.MarginLayoutParams有个方法setMargins(left, top, right, ...
  • netbeans代码提示功能设置

    万次阅读 2014-12-22 09:13:24
    一、依次点击:菜单===>工具===>选项===>编辑器===>代码完成  语音选择Java。在“Java自动弹出式触发器A”中... 设置后,当在netbeans中按下任何字母或点时,都会弹出代码提示。   二、代码提示快捷键设置  
  • EA代码工程就是将已经画好的类图,使用EA来生成相应的代码结构。之所以说是代码结构,是因为生成的代码中,仅有初始的类结构和一些预设的值,类方法内部的代码还是需要手动去写的。另外,如果你在类的设置里,或者是...
  • 程序员像妹子表白专用代码

    万次阅读 2014-07-04 19:23:45
    程序员表白专用代码
  • 1:尽量让一个人来写相关功能模块,不要把一个独立的模块分给多个人写代码。(不用你提醒,改多了他自己就知道优化代码,减少代码的冗余) 2:业务要清晰,业务不清晰不可避免的写冗余代码,(所以需要一个好的产品...
  • 给code标签加上如下css样式即可 article code { white-space: normal; word-break: break-all; }
1 2 3 4 5 ... 20
收藏数 11,647,030
精华内容 4,658,812
关键字:

代码