一、单选题共16题,合计80分

1(5分)
手机号正则表达式正确的是( 不会 ) [单选题] *

A. /^[1]([3-9])[0-9]{9}$/

B. /^[1]([3-9])[0-9]?$/

C. / [1]([3-9])[0-9]+/

D. /^[1] [0-9]{10}$/
2(5分)
列出当前目录下所有.h的文件,含子目录( c ) [单选题] *

A. ls *.h

B. find . -name *.h

C. find . -name *.h$

D. find . |grep h
3(5分)
以下最宽松的开源许可证是 ( A ) [单选题] *

A. GPL

B. BSD

C. Apache

D. MIT
4(5分)
假定一个类的构造函数为“A(int i=4, int j=0) {a=i;b=j;}”, 则执行“A x (1);”语 句后,x.a和x.b的值分别为( D )

A. 4和1

B. 4和0

C. 1和4

D. 1和0
5(5分)
对数组名作函数的参数,下面描述正确的是( B )。

A. 数组名作函数的参数,调用时将实参数组复制给形参数组

B. 数组名作函数的参数,主调函数和被调函数共用一段存储单元

C. 数组名作参数时,形参定义的数组长度不能省略

D. 数组名作参数,不能改变主调函数中的数据
6(5分)
进程在从磁盘读取数据时会进入:B

A. 就绪态

B. 阻塞态

C. 运行态

D. 终止态

# 相关知识
# https://www.cnblogs.com/still-smile/p/12052067.html
7(5分)
列出当前目录下所有.h的文件,不含子目录 [单选题] * A

A. ls *.h

B. find . -name *.h

C. find . -name *.h$

D. find . |grep h
8(5分)
执行以下程序段后,m的值为 ( A )。
    int a[2][3]={{1,2,3},{4,5,6}};
    int m,*p=&a[0][0];
    m=(*p)*(*(p+2))*(*(p+4));

A. 15

B. 14

C. 13

D. 12

# 等价于m[2]*m[1],注意数组下角标从0开始,p+4相当于移动到了5
9(5分)
下面哪一个不是一种临界区保护机制:C

A. 互斥锁

B. 信号量

C. 条件变量

D. 读写锁
10(5分)
所谓多态性是指 ( B )。

A. 不同的对象调用不同名称的函数

B. 不同的对象调用相同名称的函数

C. 一个对象调用不同名称的函数

D. 一个对象调用不同名称的对象
11(5分)
2以下程序运行后,循环体运行的次数为( B ) [单选题] *
   int i = 10, x;
   for( ; i < 10; i++){x = x + i;}

A. 10

B. 0

C. 1

D. 无限

# i = 10 不小于10,循环不执行
12(5分)
下面正则表达式不能匹配的是:a*bc?d+  A

A. aaabdd

B. bcdd

C. bcd

D. abc
13(5分)
以下不是开源许可证的有( C ) [单选题] *

A. MIT

B. GPL

C. CC

D. BSD
14(5分)
以下不是C语言提供的合法关键字为( B ) [单选题] *

A. switch

B. printf

C. case

D. default
# printf 是函数
15(5分)
一个类的友元函数可以访问类的( D )成员。

A. 私有成员

B. 保护

C. 公有

D. 以上都正确
16(5分)
C语言中定义符号常量正确的是( D ) [单选题] *

A. #define PI=3.14

B. define PI 3.14

C. #define PI 3.14;

D. #define PI 3.14

二、多选题共4题,合计20分

1(5分)
unsigned long ul1 = 3,ul2 = 7;下列表达式结果正确的是( B D )  [多选题]

A. ul1 & ul2 = 3;

B. ul1 | ul2 = 7;

C. ul1 && ul2 = 0;

D. ul1 || ul2 = 1;
2(5分)
对比for循环和while循环,下面说法正确的是?( A C )[多选题]

A. 在循环已知的情况下,for循环的形式更加简洁

B. 在循环已知的情况下,while循环的形式更加简洁

C. 在循环次数无法预知时,用while循环实现更加合适

D. 在循环次数无法预知时,用for循环实现更加合适
3(5分)
假设iter的类型是vector::iterator,下面的表达式中合法的有哪些( C D )  [多选题]

A. *iter++; 

B. (*iter)++;

C. Iter->empty();

D. Iter++->empty();
# * 优先级高于++, 以string为例,字符串没有++运算
4(5分)
下面哪个定义是不合法的( B D )[多选题]

A. int ival=1.01;

B. int &rvall = 1.01;

C. int &rval2 = ival;

D. int &rval3
 第1题:
/***
 * -------------------------------------------------------------------------------------------------------------------
 * 题目
 * -------------------------------------------------------------------------------------------------------------------
 * 无重复字符串的排列组合。编写一种方法,计算某字符串的所有排列组合,字符串每个字符均不相同。并将结果按字符串从小到大排序
 * 
 * 示例1:
 * - 输入:S = "qwe"
 * - 输出:["eqw", "ewq", "qew", "qwe", "weq", "wqe"]
 * 
 * 示例2:
 * - 输入:S = "ab"
 * - 输出:["ab", "ba"]
 * 
 * 要求:
 * 1. 使用纯C语言修改exam.h文件,通过所有单元测试。
 * 2. 代码逻辑符合题目要求,判卷评分有更多单元测试项。
 * 3. 输出结果按照字典顺序排序。
 * 4. exam.h以外的文件不得修改,修改会被覆盖。
 */
#ifndef EXAM_H
#define EXAM_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char** permute_string(const char* input);
void sort(char* S,int len);
void DFS(char *S, int *visited,  char *buf, char **res, int *index, int idx);

// main用于自己测试用,考试请勿写入。
int main()
{
    const char* input = "ab";
    char **s = permute_string(input);
    int n = 1;
    /* 计算输出长度 */
    for (int i = 1; i <= strlen(input); i++) {
        n *= i;
    }
    for(int i = 0; i < n; i++)
    {
        puts(s[i]);
    }
    return 0;
}

/* 返回一个以空字符串结尾的char*数组 */
char** permute_string(const char* input)
{

    // 获取字符串长度。
    int len = strlen(input);
    int n = 1;
    int i;
    /* 计算输出长度 */
    for (i = 1; i <= len; i++) {
        n *= i;
    }
    
    /* 因为题目中给的是const char,这里将const char* 改为char*,方便排序 */
    char *S = (char*)malloc(sizeof(char) * (len + 1) );
    /* 复制字符串并且排序  */
    strcpy(S, input);
    // 冒泡排序
    sort(S, len);
    
    int N = 7; // 应题目要求
    // 返回数组
    char **res   = (char**)malloc(sizeof(char*) * N);
    res[N-1] = 0; // 应题目要求。
     // 定义一个数组,用来来标识S[i]是否已经选取
    int *visited = (int*)malloc(sizeof(int) * len);
    memset(visited, 0, sizeof(int) * len);
    // 用于临时存储结果
    char *buf    = (char*)malloc(sizeof(char) * (len + 1));
    buf[len] = '\0';
    // res的下角标
    int *index = (int*)malloc(sizeof(int));
    *index = 0;
    
    DFS(S, visited, buf, res, index, 0);
    return res;
}

/* 冒泡排序  */
void sort(char* S,int len){
    int i =0, j = 0;
    char temp = '\0';
    for(i = 0 ; i < len-1; i++)
    {
        for(j = i+1 ; j < len; j++)
        {
            if(S[i] > S[j])
            {
                temp = S[i];
                S[i] = S[j];
                S[j] = temp;
            }
        }
    }
}

/* DFS  */
void DFS(char *S, int *visited,  char *buf, char **res, int *index, int idx){
    // 1. 截止条件
    if(strlen(S) == idx){
           res[*index] = (char*)malloc(sizeof(char) * (strlen(S) + 1));
        strcpy(res[*index], buf);
        (*index)++;
        return;
    }
    // 2. 遍历候选节点
    for(int i = 0; i < strlen(S); i++){
        // 2.1 筛选
        if(!visited[i]){
            buf[idx] = S[i];
            visited[i] = 1;
            DFS(S, visited, buf, res, index, idx+1);
            visited[i] = 0;
        }
    }
}
#endif // EXAM_H
第二题:
 /**
 * 
 * -------------------------------------------------------------------------------------------------------------------
 * 题目
 * -------------------------------------------------------------------------------------------------------------------
 * 
 * 遵循 https://specifications.freedesktop.org/desktop-entry-spec/latest/ 标准实现一个desktop文件解析工具
 * 
 * 功能要求
 * - desktop文件格式无错误时进程退出码为0
 * - 实现对desktop文件Name(程序名称)、Exec(可执行文件)、Icon(图标文件)三个字段的解析
 * - 需要检测文件的格式,遇到错误时以退出码 1 退出进程
 * - 输入接收一个desktop文件的绝对路径,能够输出程序名称、图标文件(图标文件不考虑从系统图标主题中查找)
 * - 能够在指定一个desktop文件后启动进程,且允许为其指定参数
 * 
 * 其它要求
 * - 使用cmake构建工程
 * - 可执行文件位置和名称为:./src/freedesktop
 * - testHelper.sh有很少的测试用例,可以帮助做初步验证
 * 
 * 示例
 * - a.desktop文件内容为:
 *     [Desktop Entry]
 *     Name=A;
 *     Name[zh_CN]="我是A";
 *     Exec=cat %f
 *     Icon=/tmp/a.png
 * 
 * - 输入参数(-d指定desktop文件的绝对路径,-n表示要获取应用程序名称):
 *     freedesktop -d /home/a/a.desktop -n
 * - 输出结果:
 *     A或我是A(中文环境下,注意应该去掉引号)
 * 
 * - 输入参数(-i表示要获取应用程序的图标)
 *     freedesktop -d /home/a/a.desktop -i
 * - 输出结果(如图标数据不是一个文件路径,则先将图标文件保存为文件后再返回此文件的绝对路径):
 *     /tmp/a.png
 * 
 * - 输入参数(-e表示要启动此应用程序,其后可根一个或多个传入参数)
 *     freedesktop -d /home/a/a.desktop -e /home/a/test.txt
 * - 输出结果:
 *     输出结果为 /home/a/test.txt 文件的内容,也就是Exec命令执行时对标准输出通道所写入的全部数据
 * 
 */
#include<iostream>
#include<unistd.h>
#include<cstring>
#include<string>

/* 定义了一个字符串拷贝函数。将str2从beg开始到end赋值给str1; beg和end为下角标 */
void strcopy(char* str1, char*str2, int beg, int end);

int main(int argc, char** argv)
{

    char tmp[1024];
    int flag[5] = {0};
    char *name, *exec, *icon;
    int i;
    for(i = 1;i < argc; i++)
    {
        /* -d 文件绝对路径带解析功能 */
        if( strcmp( argv[i], "-d" ) == 0 ) 
        {
            FILE *p_file = fopen(argv[i+1], "r");
            while(fgets(tmp, sizeof(tmp), p_file) != NULL )
            {
                tmp[strlen(tmp)-1] = '\0';
                if( strncmp( tmp, "[Desktop Entry]", 15) == 0 ) flag[0] = 1;
                if( strncmp( tmp, "Name=", 5) == 0)
                {
                    char *Name = (char*)malloc(sizeof(char) * ( strlen(tmp) - 5 ) );
                    strcopy(Name, tmp, 5, strlen(tmp));
                    if( Name[strlen(Name) - 1 ] == ';' || Name[strlen(Name) - 1 ] == '\n' ) Name[strlen(Name) -1] = '\0';
                    name = Name;
                    flag[1] = 1;
                }
                if( strncmp( tmp, "Exec=", 5) == 0)
                {
                    char *Exec = (char*)malloc(sizeof(char) * ( strlen(tmp) - 5 ) );
                    strcopy(Exec, tmp, 5, strlen(tmp));
                    if(Exec[strlen(Exec) - 1 ] == ';' || Exec[strlen(Exec) - 1 ] == '\n') Exec[strlen(Exec) -1] = '\0';
                    exec = Exec;
                    flag[2] = 1;
                }
                if( strncmp( tmp, "Icon=", 5) == 0)
                {
                    char *Icon = (char*)malloc(sizeof(char) * ( strlen(tmp) - 5 ) );
                    strcopy(Icon, tmp, 5, strlen(tmp));
                    if(Icon[strlen(Icon) - 1 ] == ';' || Icon[strlen(Icon) - 1 ] == '\n') Icon[strlen(Icon) - 1] = '\0';
                    flag[3] = 1;
                    icon = Icon;
                }
                if( strncmp( tmp, "Name[zh_CN]=", 5) == 0)
                {
                    flag[4] = 1;
                }
            }

            fclose(p_file);
            // 遇到错误时以退出码 1 
            if( ! ( flag[0] == 1 && flag[2] == 1 && flag[3] == 1 && (flag[4] == 1 || flag[1] == 1) ) )
                exit(1);        
        }
    }

    for(i = 1 ; i < argc; i++)
    {
        
        /* -n 获取名称 */
        if( strcmp( argv[i], "-n" ) == 0 )
        {
            std::cout << name << std::endl;
        }
        /* -i Icon 路径获取  */
        if( strcmp( argv[i], "-i" ) == 0 )
        {
             std::cout << icon << std::endl;
        }   
        /* -e 运行  */
        if( strcmp( argv[i], "-e" ) == 0 )
        {
            std::string s = "cat ";
            std::string temp;
            int j = i + 1;
            while( argv[j] != NULL )
            { 
                temp = argv[j];
                s += temp;
                s += " "; 
                j++;
            }
            char cmdTemp[1024];
            strcpy(cmdTemp,s.c_str());
            FILE *pp = popen(cmdTemp, "r");
            char tmp[1024];
            while(fgets(tmp, sizeof(tmp), pp) != NULL)
            {
                std::cout << tmp ;
            }
            pclose(pp);
        }
    }    
    return 0;
}

void strcopy(char* str1, char*str2, int beg, int end)
{
    int i;
    for( i = 0; i < end - beg + 1 ; i++ )
    {
        str1[i] = str2[ beg + i]; 
    }
}
第三题:
/**
 * 编写一个颜色列表程序,功能及要求如下:
 * 
 * - 实现的功能是:添加、删除颜色项。
 * - 颜色列表继承QListView,不许使用QListWidget。数据Model继承QAbstractItemModel。
 * - 界面上有这几个元素(如何布局不做强制要求):
 *   - 颜色列表控件:按行显示每个颜色条目。每个条目显示添加时指定的颜色。
 *   - 一个QComboBox,可以下拉选择这几种颜色:red, green, blue, cyan, yellow, purple, white, black
 *   - 一个QPushButton实现’添加‘新的颜色项。添加QComboBox当前的颜色到列表中。
 *   - 一个QPushButton实现’删除‘选择的颜色项。如果没有选择一个列表中的项,disabled状态
 */
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QAbstractItemModel>
#include <QStyledItemDelegate>
#include <QListView>

namespace Ui {
class MainWindow;
}

class ItemDelegate : public QStyledItemDelegate
{
public:
    ItemDelegate(QObject *parent = nullptr);
};

class ListModel : public QAbstractItemModel
{

    Q_OBJECT
public:
    explicit ListModel();
    ~ListModel();
    virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
    virtual QModelIndex parent(const QModelIndex &child) const override;
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
};

class ListView : public QListView
{
    Q_OBJECT
public:
    explicit ListView(QWidget *parent = nullptr);
    ~ListView();
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    friend class autoTest;
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    ListModel *m_Model;
    ItemDelegate *m_Delegate;
    ListView *m_ListView;
};

#endif // MAINWINDOW_H




// Mianwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QVBoxLayout"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_Model=new ListModel();
    m_ListView=new ListView();
    m_Delegate=new ItemDelegate();

    m_ListView->setModel(m_Model);
    m_ListView->setItemDelegate(m_Delegate);

    QVBoxLayout * layout = new QVBoxLayout(ui->widget);
    layout->addWidget(m_ListView);
}

MainWindow::~MainWindow()
{
    delete ui;
}

ListView::ListView(QWidget *parent)
{

}

ListView::~ListView()
{

}

ListModel::ListModel():
    QAbstractItemModel()
{
}

ListModel::~ListModel()
{

}

QVariant ListModel::data(const QModelIndex &index, int role) const
{
//    // 节点内容:左对齐,显示行列号
//   if (role == Qt::TextAlignmentRole)
//       return int(Qt::AlignLeft | Qt::AlignVCenter);
//   else if (role == Qt::DisplayRole)
//       return QString("row=%1,col=%2").arg(index.row()).arg(index.column());
//   else
//       return QVariant();
}

int ListModel::columnCount(const QModelIndex &parent) const
{
    // 每行有量列
//    return 2;
}

int ListModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
    {
            return 0;
    }
    else
    {
        return parent.row();
    }
}

QModelIndex ListModel::parent(const QModelIndex &child) const
{
    // 父节点均为跟节点
    return QModelIndex();
}

QModelIndex ListModel::index(int row, int column, const QModelIndex &parent) const
{
    // 创建普通索引
    return createIndex(row, column);
}

ItemDelegate::ItemDelegate(QObject *parent)
{

}
 第1题:
 * -------------------------------------------------------------------------------------------------------------------
 * 题目
 * -------------------------------------------------------------------------------------------------------------------
 * 输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
 *  
 * 示例 1:
 * 给定二叉树 [3,9,20,null,null,15,7]
 *     3
 *    / \
 *   9  20
 *     /  \
 *    15   7
 * 返回 true 。
 * 
 * 示例 2:
 * 给定二叉树 [1,2,2,3,3,null,null,4,4]
 *        1
 *       / \
 *      2   2
 *     / \
 *    3   3
 *   / \
 *  4   4
 * 返回 false 。
 * 
 * 要求:
 * 1. 使用纯C语言完善exam.h文件,通过所有单元测试
 * 2. 代码逻辑符合题目要求,判卷评分有更多单元测试项
 * 3. 除exam.h以外的文件不得修改,修改会被覆盖
struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
};

int getTreeDepth(struct TreeNode* node)
{
    int rightDepth = 1;
    int leftDepth  = 1;

    if(node == NULL)
    {
        return 0;
    }

    //查找左子树
    if(node->left != NULL)
    {
        leftDepth = rightDepth + getTreeDepth(node->left);
    }

    //查找右子树
    if(node->right != NULL)
    {
        rightDepth = rightDepth + getTreeDepth(node->right) ;
    }

    if(leftDepth >= rightDepth)
    {
        return leftDepth;
    }
    else
    {
        return rightDepth;
    }
}



static int tree_is_balanced(TreeNode* root) {

    if(root == NULL || (root->left == NULL && root->right == NULL))
    {
        //当到达叶子结点时候
        return 1;
    }

    if(abs (getTreeDepth(root->left) - getTreeDepth(root->right)) > 1)
    {
        return 0;
    }

    //检查左子树 和 右子树
    return tree_is_balanced(root->left)  && tree_is_balanced(root->right) ;
}
第二题:
 * -------------------------------------------------------------------------------------------------------------------
 * 题目
 * -------------------------------------------------------------------------------------------------------------------
 * 编写一个程序,从命令行读取一个软件包的名称,调用“dpkg -L”命令获得该软件包的文件列表,并检查所有文件。
 * 要求:
 * 1. 使用cmake和c/c++开发
 * 2. 可执行文件名称和位置是./src/pkgverify
 * 3. 检查该软件包所有文件,确认:
 *   - 路径存在
 *   - 文件存在
 *   - 如果是符号链接,链接的文件也存在
 *   - /usr路径下的文件,确认文件属主都是root
 * 4. 输出所有有问题的文件或路径名
 * 5. 由于qDebug/qInfo等输出方式会添加多余字符,且不在标准输出上,与考试要求不符,请谨慎使用
 * 6. testHelper.sh有很少的测试用例,可以帮助做初步验证
 *  
 * 示例:
 * 如果/etc/cups路径被删除了,则运行结果如下:
 * pkgverify cups
 * /etc/cups
 * /etc/cups/snmp.conf
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <cstring>

int main(int argc, char** argv)
{
    // 调用系统命令,最小化数组,节省空间
    int len = strlen(argv[1]) + 9;
    char str1[len] = "dpkg -L ";
    strcat(str1, argv[1]);
    // 调用系统命令,并取得返回值    
    FILE *pp = popen(str1, "r");
    if (!pp)
        return 1;
    // 返回值数组
    char tmp[1024];
    // 初始化stat结构体buf、返回值(retRes用于判断文件是否存在);
    // buf2 用于链接文件的返回存储。事实上这里仅仅为了调用,并不进行实际上的作用;
    int retRes = 0;
    struct stat buf;
    char buf2[1024];
    
    // 逐行读取所有的dpkg -L返回值
    while(fgets(tmp, sizeof(tmp), pp) != NULL)
    {
        // 末尾包含 "\n",更改为"\0"结束,后面可能会有问题。
        tmp[strlen(tmp)-1] = '\0';
        retRes = lstat(tmp, &buf);
        
        // 判断 文件和文件路径 是否存在;
        if(retRes == 0)  // 存在
        {
            // - 如果是符号链接
            if(  S_ISLNK(buf.st_mode)   )
            {
                // 检测链接文件是否存在,不存在输出
                int retResult = readlink(tmp,buf2,sizeof(buf2));
                if(retResult == -1)
                {
                    std::cout << tmp << std::endl;
                }
            }

            // - /usr路径下的文件,确认文件属主都是root
            if( strncmp("/usr", tmp, 4) == 0 )
            {
                if( buf.st_uid !=0 && buf.st_gid != 0)
                {
                    std::cout << tmp << std::endl;
                } 
            }
 
        }
        else // 文件不存在
        {
            std::cout << tmp << std::endl; // can join each line as string
        }
        
    }    
    pclose(pp);
    return 0;
}
/**
 * 编写一个todo程序,功能及要求如下:
 *
 * - 实现的功能是:添加、删除、修改todo项目。
 * - todo列表继承QListView,不许使用QListWidget。数据Model继承QAbstractItemModel。
 * - 界面上有这几个元素(如何布局不做强制要求):
 *   - todo列表控件:按行显示todo items。单击选中一个todo,双击原地修改todo的内容
 *   - 一个QLineEdit用于输入todo条目的内容
 *   - 一个QPushButton实现’添加‘新的todo,QLineEdit为空,disabled
 *   - 一个QPushButton实现’删除‘选择的todo,没有选择一个todo,disabled
 */
# .H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QStringListModel>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    QStringListModel *theModel;

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_lineEdit_textChanged(const QString &arg1);

    void on_listView_clicked(const QModelIndex &index);

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H


main.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QStringListModel"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    theModel=new QStringListModel(this);
    ui->listView->setModel(theModel);
    ui->listView->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);
    ui->pushButton->setEnabled(false);
    ui->pushButton_2->setEnabled(false);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    theModel->insertRows(theModel->rowCount(),1);
    QModelIndex index=theModel->index(theModel->rowCount()-1,0);
    theModel->setData(index,ui->lineEdit->text(),Qt::DisplayRole);
    ui->listView->setCurrentIndex(index);
}

void MainWindow::on_pushButton_2_clicked()
{
    QModelIndex index=ui->listView->currentIndex();
    theModel->removeRows(index.row(),1);
    if(index.row()<0)
    {
        ui->pushButton_2->setEnabled(false);
    }
}

void MainWindow::on_lineEdit_textChanged(const QString &arg1)
{
    if(arg1=="")
    {
        ui->pushButton->setEnabled(false);
    }
    else {
        ui->pushButton->setEnabled(true);
    }
}

void MainWindow::on_listView_clicked(const QModelIndex &index)
{
    if(index.row()>=0)
    {
        ui->pushButton_2->setEnabled(true);
    }
    else {
        ui->pushButton_2->setEnabled(false);
    }
}

标签: none