C语言博客05--指针

1.1 思惟导图

1.2 本章学习体会及代码量学习体会

1.2.1 学习体会

1.之前我一直都只把指针看成一个固定的地址来使用,没有想过对指针进行运算,通过这周的学习使我对指针有了更深入的认识。
2.在对指针进行初始化的时候能够同时进行赋值,以下c++

int a[10];
int *p=a;

3.使用指针进行大数据的传递能够明显地提升效率,由于传递指针传递的是地址,相对于大数据来讲每次传递的字节更少。
4.将数组存储在局部变量里的时候,局部变量的累积大小有限,不能超过某一限制,而将数组存储在全局变量的时候,大小比在局部变量大得多,也可使用new函数,或者malloc函数对指针进行动态内存分配,均可以得到较大的数组。算法

1.2.2 代码累计

2.PTA总分

2.1截图 PTA中的排名得分

2.2 个人总分

PTA总分:125 分

3.PTA实验做业

3.1 PTA题目1

给定一句英语,要求你编写程序,将句中全部单词的顺序颠倒输出。数组

输入格式:函数

测试输入包含一个测试用例,在一行内给出总长度不超过500 000的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用若干个空格分开。学习

输出格式:测试

每一个测试用例的输出占一行,输出倒序后的句子,而且保证单词间只有1个空格。大数据

输入样例3d

Hello World Here I Come指针

输出样例code

Come I Here World Hello

3.1.1算法分析

算法一:

定义字符型数组 a[511111]
计数 count = 0
flag数组 static int flag[511111]                //用来表示该位置的字母是否为单词的首字母
int startIndex = 0                              //用来标记第一个单词的第一个字母的位置
int stopIndex = strlen(a) - 1                   //用来标记最后一个单词的最后一个字母的位置
输入字符串 a

接下来先将头尾的空格滤去:

|while a[startIndex] == ' '  do
|   startIndex++                            //将前面的空格滤去
|end while

|while a[stopIndex] == ' '  do
|   stopIndex--                             //将后面的空格滤去
| end while

末尾补零,不然过会用地址直接输出字符串会连空格也输出

a[stopIndex + 1] = '\0'                     //末尾补'\0'  使他成为完整的字符串

接下来开始判断找出每一个单词的首字母,判断条件为空格后面是不是字母

flag[startIndex] = 1                        //第一个单词状况比较特殊,直接手动断定
| for int i = startIndex to  stopIndex - 1  do
|
|   |if  a[i+1]是单词的第一个字母   do   
|   |   将 flag[i + 1] 标记赋值为 1
|   |   count++
|   |end if
|
|   |if  a[i]是空格  do                     
|   |   a[i] = '\0'                          //后面输出时遇到'\0'就会中止
|   |end if
|
|end for

最后进行输出

| for  int i = stopIndex  to  startIndex
|
|   |if  flag[i] 等于 1  do                    
|   |
|   |   对该 a+i 的地址以 %s 字符串形式输出
|   |   count--                             
|   |   |if a+i 不是最后一个单词 do                 
|   |   |
|   |   |   printf(" ")
|   |   |
|   |   |end if
|   |
|   |end if
|
|end for

算法二:

存储字符串 a[500010]
输入字符串 a
用函数记录字符串长度 len
起始地址 start = 0

对空格掐头去尾

    |while  a[len - 1] 是空格  do
    |   len--
    |end while
    |len--

    |while  a[start] 是空格 do 
    |   start++
    |end while 

令 stopIndex = len
判断是否要输出的 flag = 1

    for int i = len to start  do
    |
    |   if a[i] 是单词首字母  do
    |   |
    |   |   用 flag 判断法判断是否输出空格
    |   |   for  int j = i  to  stopIndex  do  putchar(a[j])//将单词字母一个个输出
    |   |
    |   if 若是a[i]是单词末尾的空格  do  stopIndex = i - 1  //用stopIndex指向单词末尾
    |end for

3.1.2 代码截图

算法一:

算法二:

3.1.3 PTA提交列表及说明

苦难是人生的老师,经过苦难,走向欢乐。 ——贝多芬

若是给个人时间趋近于无穷,我就能修复任何bug。 ——谢晓淞

Q:以是否为大写字母来判断是否为首字母,最后一个点老是过不去??
A:可能测试数据或者个人理解有问题,换用空格判断法就能过了

4.大做业

4.1 改造函数介绍

1.void ExpCreator(char exp, char gameClass)

  • 算法分析
初始化exp全为'\0' 
    当等级为1时numAmount为2,其余全为3//记录有多少个数 
    int circuTimes = *gameClass - '0'//circuTimes表示循环次数,也表示数的位数 
    loc = 0 //数组的起始位置 
    for  i = 0 to numAmount - 1 do
    |   //对exp数组的数字位进行赋值 
    |   for  j = 0 to circuTimes - 1 do
    |   |
    |   |   exp[loc++] = rand() % 10 + '0';
    |   |
    |   |end for
    |   //表达式末尾加上等号 
    |   if i == numAmount - 1 do 
    |   |   exp[loc++] = '='
    |   |//不然就是换成运算符 
    |   else
    |   |
    |   |   exp[loc] = rand() % 4;
    |   |   if (exp[loc] == 0) exp[loc++] = '+';
    |   |   else if (exp[loc] == 1) exp[loc++] = '-';
    |   |   else if (exp[loc] == 2) exp[loc++] = '*';
    |   |   else exp[loc++] = '/';
    |   |
    |   |end if
    |
    |end for 
    //补尾巴 
    exp[loc] = '\0';
    使用IsExp判断是否合法
  • 代码截图

2.int ComputeExp(char *exp)

  • 算法分析
//提取数字和运算符
    定义 numIndex = 0, OpeIndex = 0 来记位
    初始化整型数字组 number[4]
    初始化运算符组 Operator[3]
    numberTemp = 0 用来暂时存储数值结果
    for  i = 0 to exp[i]不为空 do
    |
    |   //遇到数字
    |   if exp[i]是数字 do numberTemp = numberTemp * 10 + exp[i] - '0'
    |   else do//遇到运算符
    |   |
    |   |   number[numIndex++] = numberTemp  //切换下一个数
    |   |   Operator[OpeIndex++] = exp[i]    //切换下一个运算符
    |   |   numberTemp = 0   //初始化
    |   |
    |   |end if
    |
    |end for
    //计算
    //先判断第二个运算符优先级
    if Operator[1] == '*' || Operator[1] == '/' do
    |
    |   if Operator[1] == '*'do number[1] = number[1] * number[2]
    |   else         do         number[1] = number[1] / number[2]
    |   switch (Operator[0])
    |   |
    |   |case '+': number[0] = number[0] + number[1]
    |   |case '-': number[0] = number[0] - number[1]
    |   |case '*': number[0] = number[0] * number[1]
    |   |case '/': number[0] = number[0] / number[1]
    |   |
    |   |end switch
    |
    else//第二个运算符不是高级,直接顺序运算
    |
    |   switch (Operator[0])
    |   |
    |   |case '+': number[0] = number[0] + number[1]
    |   |case '-': number[0] = number[0] - number[1]
    |   |case '*': number[0] = number[0] * number[1]
    |   |case '/': number[0] = number[0] / number[1]
    |   |
    |   |end switch
    |
    |   switch (Operator[1])
    |   |
    |   |case '+': number[0] = number[0] + number[2]
    |   |case '-': number[0] = number[0] - number[2]
    |   |case '*': number[0] = number[0] * number[2]
    |   |case '/': number[0] = number[0] / number[2]
    |   |
    |   |end switch
    |
    |end for
    return number[0];
  • 代码截图

3.void IsExp(char exp, char gameClass)

  • 算法分析
初始化int型 number[4] = { 0,0,0,0 }
    初始化字符型 Operator[3] = { '\0','\0','\0' }
    int m = 0, n = 0 //用于切换数与字符 
    int i;
    //对内容提取
    for i = 0 to exp[i]=='\0'
    |
    |   if exp[i]是数字字符 do 
    |   |   number[m] = number[m] * 10 + exp[i] - '0'
    |   | 
    |   else
    |   |{
    |   |   Operator[n] = exp[i];
    |   |   n++//切换下一个字符 
    |   |   m++//切换下一个数字 
    |   |
    |   |end if 
    |   | 
    |end for
    //判断非法状况 
    for i = 0 to n - 1 do
    |
    |   if Operator[i] == '/' do
    |   |
    |   |   while number[i+1] 非法 do 
    |   |   |
    |   |   |   对gameClass的不一样状况从新生成number[i+1] 
    |   |   |
    |   |   |end while
    |   |
    |   |end if
    |
    |end for
    初始化exp数组 
    char temp[4] = { '\0','\0','\0','\0' }
    char opeTemp[2] = { '\0','\0' }
    for  i = 0  to m - 1  do
    |
    |   将数字和字符分别存在temp和opeTemp中 
    |   strcat(exp, temp)//接上数字 
    |   strcat(exp, opeTemp)//接上字符 
    |
    |end for
  • 代码截图

4.3 与原有函数代码比较

  • 关于第一个函数的改造

    改造前:本来的函数是使用随机函数直接获取一个数存到数组里面,在此以前还得使用条件语句进行判断要生存的是几位数,所以令代码看起来很繁琐,很头秃。一开始也很天真,曾想过用pow函数加上循环来从高位到地位获取结果存到数组,彻底不知道itoa这种函数的存在。并且生成的表达式的计算结果很不友好,用户体验太差了。

改造后:由于对表达式的存储改为了字符串,所以能够对每一位包括运算符进行处理,因此我采用了一个个输入的办法,一个是可使用for循环加while嵌套进行处理,还有就是简化代码样式,更加简洁,看着不会那么头秃。而且在最后会使用IsExp函数判断是否非法又或者有小数结果,保护用户幼小的心灵。

  • 关于第二个函数的改造

    改造前:原来的计算函数是以全局变量传递的,能够直接对数据调用,可是不利于函数的移植,分享性不是很强,而且对于计算的结果拿出去后还得用差值的办法判断用户给的答案是否正确。

改造后:得益于矫正函数,新一代的计算函数能够直接计算整型变量,不须要用double类型的变量来传递结果,且现在的新一代计算函数采用指针传递,一方面传递的时候只须要传递一个地址,在传递效率上有有不错的改进,另外一方面因为少了全局变量,使得这个函数能够移植到别的程序上使用,也使得程序容易维护。

  • 关于第三个函数的改造

    第三个函数是新增的函数,由于比较差值判断答案的方法实在不官方,且程序中存在的除数为0的bug也没有获得解决,所以独立出一个IsExp函数,对于传入的数据进行拆分分析,看的到数据是否非法,若是是的话,就对数据修正。一开始想着若是数据不合法直接打回ExpCreator重造,但通过不断实验发现,这样改造的话,获得除法算式的几率会大大下降,所以后面改成找到非法数据,只对数进行修改,运算符则保持不变,以此保证四种运算符出现的几率。

4.4 改进大做业总结

1.将全部的全局变量都改成了指针,深入学习了指针的用法,体会到全局变量的危害,也感觉到指针的灵魂之处所在。
2.深入吸收上次大做业的教训,熟悉了fflush的用法,对函数进行了输入上的改造,借此大大加强了代码的健壮性,减小了不少输入致使的bug的产生。
3.在此次的大做业中,我还在结束时加入了排名统计系统,虽然从代码上看对文件函数应用仍是过于青涩,用的方法也是有些旁门左道,可是功能仍是有实现的呀,不过实现归实现,下次正式进行文件大做业时将对这一部分进行正式化修改。。

相关文章
相关标签/搜索