2019春第十一周作业Compile Summarize

这个作业属于那个课程 C语言程序设计II
这个作业要求在哪里 这里
我在这个课程的目标是 能按自己的想法解出题目
这个作业在那个具体方面帮助我实现目标 能朝着软件工程师方向发展
参考文献与网址 C语言程序设计II(第三版) C语言的教学

题目:汉诺塔问题

汉诺塔是一个源于印度古老传说的益智玩具。据说大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘,大梵天命令僧侣把圆盘移到另一根柱子上,并且规定:在小圆盘上不能放大圆盘,每次只能移动一个圆盘。当所有圆盘都移到另一根柱子上时,世界就会毁灭。

请编写程序,输入汉诺塔圆片的数量,输出移动汉诺塔的步骤。

输入格式

圆盘数 起始柱 目的柱 过度柱

输出格式

移动汉诺塔的步骤
每行显示一步操作,具体格式为:
盘片号: 起始柱 -> 目的柱
其中盘片号从 1 开始由小到大顺序编号。

输入样例

3
a c b

输出样例

1: a -> c
2: a -> b
1: c -> b
3: a -> c
1: b -> a
2: b -> c
1: a -> c

我的代码

#include<stdio.h>
 
void move(int n,char a,char b,char c)
{
    if(n==1)
        printf("\t%c->%c\n",a,c);  
    else
    {
        move(n-1,a,c,b);        
      
        printf("\t%c->%c\n",a,c);  
        move(n-1,b,a,c);           
    }
}
 
main()
{
    int n;
    printf("请输入数字n(要移动的块数)以解决n阶汉诺塔问题:");
    scanf("%d",&n);
  move(n,'a','b','c');
    while(1);
}

解题流程图

本题遇见的问题与解决办法

到处都是问题,达到了无法用言语表达的地步

运行结果截图

题目:估值一亿的AI核心代码

上图来自网络

本题要求你实现一个稍微更值钱一点的 AI 英文问答程序,规则是:

无论用户说什么,首先把对方说的话在一行中原样打印出来;
消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
把原文中所有大写英文字母变成小写,除了 I;
把原文中所有独立的 can you、could you 对应地换成 I can、I could—— 这里“独立”是指被空格或标点符号分隔开的单词;
把原文中所有独立的 I 和 me 换成 you;
把原文中所有的问号 ? 换成惊叹号 !;
在一行中输出替换后的句子作为 AI 的回答。
输入格式:
输入首先在第一行给出不超过 10 的正整数 N,随后 N 行,每行给出一句不超过 1000 个字符的、以回车结尾的用户的对话,对话为非空字符串,仅包括字母、数字、空格、可见的半角标点符号。

输出格式:

按题面要求输出,每个 AI 的回答前要加上 AI: 和一个空格。

输入样例:

6
Hello ?
 Good to chat   with you
can   you speak Chinese?
Really?
Could you show me 5
What Is this prime? I,don 't know

输出样例:

Hello ?
AI: hello!
 Good to chat   with you
AI: good to chat with you
can   you speak Chinese?
AI: I can speak chinese!
Really?
AI: really!
Could you show me 5
AI: I could show you 5
What Is this prime? I,don 't know
AI: what Is this prime! you,don't know

我的代码

#include<iostream>
#include<ctype.h>
#include<vector>
#include<string>
 
using namespace std;
 
vector<string>v;
 
int main()
{
    int n;
    string s;
    cin>>n;
    getchar();
    while(n--)
    {
        getline(cin,s);
        cout<<s<<endl<<"AI: ";
        int len=s.length();
        
        for(int i=0;i<len;i++)
        {
        	if(s[i]=='?')
        	  s[i]='!';
        	else if(isupper(s[i])&&s[i]!='I')
        	  s[i]=tolower(s[i]);
		 }
		
		v.clear();
		
        for(int i=0;i<len;)
        {
        	string tmp="";
        	if(isalpha(s[i]))
        	{
        		while(i<len&&isalpha(s[i])) tmp+=s[i++];
			}
			else if(isdigit(s[i]))
			{
				while(i<len&&isdigit(s[i])) tmp+=s[i++];
			}
			else if(s[i]==' ')
			{
				tmp=" ";
				while(i<len&&s[i]==' ') i++;
			}
			else
			{
				tmp+=s[i];
				i++;
				
				if(v.size()>0&&v.back()==" ") v.pop_back(); 
			}
			if(tmp==" "&&(v.empty()||i==len)) continue;
			v.push_back(tmp);
		}
		for(int i=0;i<v.size();i++)
		  if(v[i]=="I"||v[i]=="me")
		    v[i]="you";
		  else if(v[i]=="you")
		  {
		  	
		  	if(i<2||!(v[i-1].length()==1&&(!isalnum(v[i-1][0])))) continue;
		  	if(v[i-2]=="can")
		  	  v[i-2]="I",v[i]="can";
		  	else if(v[i-2]=="could")
		  	  v[i-2]="I",v[i]="could";
		  }
		 
		for(int i=0;i<v.size();i++)
		  cout<<v[i];
		cout<<endl;
    }
    return 0;
}

解题流程图

本题遇见的问题与解决办法

到处都是问题,达到了无法用言语表达的地步

运行结果截图

题目:***八皇后问题

在国际象棋中,皇后是最厉害的棋子,可以横走、直走,还可以斜走。棋手马克斯·贝瑟尔 1848 年提出著名的八皇后问题:即在 8 × 8 的棋盘上摆放八个皇后,使其不能互相攻击 —— 即任意两个皇后都不能处于同一行、同一列或同一条斜线上。

现在我们把棋盘扩展到 n × n 的棋盘上摆放 n 个皇后,请问该怎么摆?请编写程序,输入正整数 n,输出全部摆法(棋盘格子空白处显示句点“.”,皇后处显示字母“Q”,每两格之间空一格)。

输入格式

正整数 n (0 < n ≤ 12)

输出格式

若问题有解,则输出全部摆法(两种摆法之间空一行),否则输出 None。

要求:试探的顺序逐行从左往右的顺序进行,请参看输出样例2。

输入样例1

3

输出样例1

None

输入样例2

6

输出样例2

. Q . . . .
. . . Q . .
. . . . . Q
Q . . . . .
. . Q . . .
. . . . Q .

. . Q . . .
. . . . . Q
. Q . . . .
. . . . Q .
Q . . . . .
. . . Q . .

. . . Q . .
Q . . . . .
. . . . Q .
. Q . . . .
. . . . . Q
. . Q . . .

. . . . Q .
. . Q . . .
Q . . . . .
. . . . . Q
. . . Q . .
. Q . . . .

我的代码

#include <stdio.h>
int Queenes[8]={0},Counts=0;
int Check(int line,int list){
   
    for (int index=0; index<line; index++) {
        
        int data=Queenes[index];
        
        if (list==data) {
            return 0;
        }
       
        if ((index+data)==(line+list)) {
            return 0;
        }
      
            return 0;
        }
    }
    
    return 1;
}

void print()
{
    for (int line = 0; line < 8; line++)
    {
        int list;
        for (list = 0; list < Queenes[line]; list++)
            printf("0");
        printf("#");
        for (list = Queenes[line] + 1; list < 8; list++){
            printf("0");
        }
        printf("\n");
    }
    printf("================\n");
}
void eight_queen(int line){
   
    for (int list=0; list<8; list++) {
        
        if (Check(line, list)) {
            
            Queenes[line]=list;
           
            if (line==7) {
                
                Counts++;
               
                print();
               
                Queenes[line]=0;
                return;
            }
           
            eight_queen(line+1);
            
            Queenes[line]=0;
        }
    }
}
int main() {
    
    eight_queen(0);
    printf("摆放的方式有%d种",Counts);
    return 0;
}

解题流程图

本题遇见的问题与解决办法

到处都是问题,达到了无法用言语表达的地步

运行结果截图

何为数组指针?

数组指针,指的是数组名的指针,即数组首元素地址的指针。即是指向数组的指针。例:int (*p)[10]; p即为指向数组的指针,又称数组指针。

解释来源于百度百科

比如。。。

#include "stdafx.h"
 
 
int main()
{
	//一维数组
	int a[5] = { 1, 2, 3, 4, 5 };
	//步长为5的数组指针,即数组里有5个元素
	int (*p)[5];
	//把数组a的地址赋给p,则p为数组a的地址,则*p表示数组a本身
	p = &a;
 
	//%p输出地址, %d输出十进制
	//\n回车
	//在C中,在几乎所有使用数组的表达式中,数组名的值是个指针常量,也就是数组第一个元素的地址,它的类型取决于数组元素的类型。
	printf("%p\n", a); //输出数组名,一般用数组的首元素地址来标识一个数组,则输出数组首元素地址
	printf("%p\n", p); //根据上面,p为数组a的地址,输出数组a的地址
	printf("%p\n", *p); //*p表示数组a本身,一般用数组的首元素地址来标识一个数组
	printf("%p\n", &a[0]); //a[0]的地址
	printf("%p\n", &a[1]); //a[1]的地址
	printf("%p\n", p[0]); //数组首元素的地址
	printf("%d\n", **p); //*p为数组a本身,即为数组a首元素地址,则*(*p)为值,当*p为数组首元素地址时,**p表示首元素的值1
	printf("%d\n", *p[0]); //根据优先级,p[0] 表示首元素地址,则*p[0]表示首元素本身,即首元素的值1
	printf("%d\n", *p[1]); //为一个绝对值很大的负数,不表示a[1]...表示什么我还不知道
 
	
 
	//将二维数组赋给指针
	int b[3][4];
	int(*pp)[4]; //定义一个数组指针,指向含4个元素的一维数组
	pp = b; //将该二维数组的首地址赋给pp,也就是b[0]或&b[0],二维数组中pp=b和pp=&b[0]是等价的
	pp++; //pp=pp+1,该语句执行过后pp的指向从行b[0][]变为了行b[1][],pp=&b[1]
 
	int k;
	scanf_s("%d", &k);
 
    return 0;
}

何为指针数组?

在C语言和C++语言中,数组元素全为指针的数组称为指针数组。

一维指针数组的定义形式为:“类型名 *数组标识符[数组长度]”。
例如,一个一维指针数组的定义:int *ptr_array[10]。

解释来源于百度百科

例如。。。

#include "stdafx.h"
 
 
int main()
{
	int a = 1;
	int b = 2;
	int *p[2];
	p[0] = &a;
	p[1] = &b;
 
	printf("%p\n", p[0]); //a的地址
	printf("%p\n", &a); //a的地址
	printf("%p\n", p[1]); //b的地址
	printf("%p\n", &b); //b的地址
	printf("%d\n", *p[0]); //p[0]表示a的地址,则*p[0]表示a的值
	printf("%d\n", *p[1]); //p[1]表示b的地址,则*p[1]表示b的值
 
 
	//将二维数组赋给指针数组
	int *pp[3]; //一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2],所以要分别赋值
	int c[3][4];
	for (int i = 0; i<3; i++)
		pp[i] = c[i];
 
	int k;
	scanf_s("%d", &k);
 
    return 0;
}

何为指针函数?

指针函数是一个函数。函数都有返回类型(如果不返回值,则为无值型),只不过指针函数返回类型是某一类型的指针。

解释来源于百度百科

像。。。

typedef struct _Data{
    int a;
    int b;
}Data;

//指针函数
Data* f(int a,int b){
    Data * data = new Data;
    data->a = a;
    data->b = b;
    return data;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //调用指针函数
    Data * myData = f(4,5);
    qDebug() << "f(4,5) = " << myData->a << myData->b;

    return a.exec();
}


何为函数指针?

函数指针是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数。

解释来源于百度百科

那么。。。

int add(int x,int y){
    return x+y;
}
int sub(int x,int y){
    return x-y;
}
//函数指针
int (*fun)(int x,int y);

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //第一种写法
    fun = add;
    qDebug() << "(*fun)(1,2) = " << (*fun)(1,2) ;
	//第二种写法
    fun = &sub;
    qDebug() << "(*fun)(5,2) = " << (*fun)(5,3)  << fun(5,3);

    return a.exec();
}


何为二级指针

A(即B的地址)是指向指针的指针,称为二级指针,用于存放二级指针的变量称为二级指针变量.根据B的不同情况,二级指针又分为指向指针变量的指针和指向数组的指针。

解释来源于百度百科

嗯。。。

#include<stdio.h>
#include<stdlib.h>
 
void mainA()
{
	char *p[4] = { "calc","notepad","write","tasklist&pause" };
	//for (int i = 0; i < 4; i++)
	//{
	//	system(p[i]);//下标的方式访问
	//}
 
	//for (int i = 0; i < 4; i++)
	//{
	//	system(*(p+i));//下标的方式访问
	//}
	//轮询一个数组,需要一个指针,轮询一个指针数组,需要一个二级指针
	for (int **pp = p; pp < p + 4; pp++)
	{
		system(*pp);
	}
}
 
void run(char*p[4])//数组没有副本机制,传递的是地址:二级指针
{
	printf("run=%d\n", sizeof(p));//4
	for (int **pp = p; pp < p + 4; pp++)
	{
		system(*pp);
	}
}
void main()
{
	char *p[4] = { "calc","notepad","write","tasklist&pause" };
	printf("main=%d\n",sizeof(p));//16
	run(p);//4
	getchar();
}
//因为函数对于数组没有副本机制
//数组作为参数退化为一个指针
//指针作为参数会退化为一个二级指针

何为单向链表?

单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始;链表是使用指针进行构造的列表;又称为结点列表,因为链表是由一个个结点组装起来的;其中每个结点都有指针成员变量指向列表中的下一个结点;

列表是由结点构成,head指针指向第一个成为表头结点,而终止于最后一个指向NULL的指针。

解释来源于百度百科

so。。。

package com.zjn.LinkAndQueue;

/**
 * 自定义链表设计
 * 
 * @author zjn
 *
 */
public class MyLink {
    Node head = null; // 头节点

    /**
     * 链表中的节点,data代表节点的值,next是指向下一个节点的引用
     * 
     * @author zjn
     *
     */
    class Node {
        Node next = null;// 节点的引用,指向下一个节点
        int data;// 节点的对象,即内容

        public Node(int data) {
            this.data = data;
        }
    }

    /**
     * 向链表中插入数据
     * 
     * @param d
     */
    public void addNode(int d) {
        Node newNode = new Node(d);// 实例化一个节点
        if (head == null) {
            head = newNode;
            return;
        }
        Node tmp = head;
        while (tmp.next != null) {
            tmp = tmp.next;
        }
        tmp.next = newNode;
    }

    /**
     * 
     * @param index:删除第index个节点
     * @return
     */
    public boolean deleteNode(int index) {
        if (index < 1 || index > length()) {
            return false;
        }
        if (index == 1) {
            head = head.next;
            return true;
        }
        int i = 1;
        Node preNode = head;
        Node curNode = preNode.next;
        while (curNode != null) {
            if (i == index) {
                preNode.next = curNode.next;
                return true;
            }
            preNode = curNode;
            curNode = curNode.next;
            i++;
        }
        return false;
    }

    /**
     * 
     * @return 返回节点长度
     */
    public int length() {
        int length = 0;
        Node tmp = head;
        while (tmp != null) {
            length++;
            tmp = tmp.next;
        }
        return length;
    }

    /**
     * 在不知道头指针的情况下删除指定节点
     * 
     * @param n
     * @return
     */
    public boolean deleteNode11(Node n) {
        if (n == null || n.next == null)
            return false;
        int tmp = n.data;
        n.data = n.next.data;
        n.next.data = tmp;
        n.next = n.next.next;
        System.out.println("删除成功!");
        return true;
    }

    public void printList() {
        Node tmp = head;
        while (tmp != null) {
            System.out.println(tmp.data);
            tmp = tmp.next;
        }
    }

    public static void main(String[] args) {
        MyLink list = new MyLink();
        list.addNode(5);
        list.addNode(3);
        list.addNode(1);
        list.addNode(2);
        list.addNode(55);
        list.addNode(36);
        System.out.println("linkLength:" + list.length());
        System.out.println("head.data:" + list.head.data);
        list.printList();
        list.deleteNode(4);
        System.out.println("After deleteNode(4):");
        list.printList();
    }
}

时间 代码行数 这周所花的时间 学到的知识点简介 目前比较疑惑的问题
3/2-3/19 35 两天 通过代码读取文件里的数据,并且在屏幕上打印 为什么文件的使用还要进行关闭
3/9-3/19 65 三十分钟 没有学到任何知识点 想知道指针与数组之间的内在联系
3/19-3/22 186 五个小时 二维数组的用法加上二分法找元素 需要多打代码多多练习
3/22-3/28 31 一天 字符串的使用 数组排序的内部原理
3/28-4/5 108 一天 指针初步 行参与实参如何相互影响
4/5-4/11 62 一天 熟练指针 指针实际应用的问题
4/11-4/19 182 两天 会使用struct进行编码 为什么不能用赋值表达式直接对数组赋值
4/19- 4/26 126 三天 对结构体的使用更加得心应手 结构定义形式的具体影响是什么
5/6-5/10 189 三天 宏定义的初步体验 如何使用函数递归解决问题
posted @ 2019-05-08 10:19  404NFD  阅读(218)  评论(0编辑  收藏  举报