您的位置:首页 > 理论基础

2016级计算机C++助教工作(8)第二次上课内容

2016-10-27 16:30 323 查看

第四章内容:

1.错误函数订正

p100页 4.2.2  sprt(x)改为sqrt(x)  开根号函数

2.codeblock 和 dev 下运行结果的不同

查看以下代码,实现的是字符串反转功能。
#include <iostream>
#include <string>
#include <cstdio>
#include<cstring>
using namespace std;

void WordReversal( const char olist[],char newList[], int listSize){

for(int k=0,n=listSize - 1;k < listSize;k++,n--){
newList
= olist[k];
}
}
int main(){
const int SIZE = 3;
char  list1[SIZE];
cin >> list1;
char newList[SIZE];
WordReversal(list1, newList, 3);
cout << newList;
return 0;
}


codeblocks下的运行结果



dev下的运行结果



改变main函数中的代码
int main(){
const int SIZE = 3;
char newList[SIZE];  把newList的声明放到list1前面,
char  list1[SIZE];
cin >> list1;
WordReversal(list1, newList, 3);
cout << newList;
return 0;
}
codeblocks下再次运行得到的结果。



分析,三次运行得到的结果都不一样。原因是什么?先分析代码:
1.对于C串,需要一个终结字符'\0'作为结束标志,定义长度为3的char数组,并且输入长度为3的字符串,会导致保存'\0'的位置恰好已经越界。因此如果一个char数组长度为n,想要保存c串的话,最多只能保存n-1长度的c串,因为至少要留一个位置保存'\0'
2.WordReversal函数中实现了字符串的反转,但是并未把终止符'\0'复制到对应位置,导致输出时在输出123后依然会继续输出其它字符。
其它分析:
1. 首先肯定是编译器不同导致产生的不同结果,如果逻辑正确的话,应该结果是一样的,因此大家再次遇到这种问题,先检查代码逻辑问题。
2.为什么codeblocks下会输出321123. 可以猜测在分配内存是newList刚好在list1前,在newList没有终止符的情况下,cout继续输出了lsit1中的内容,直到遇到输入123时在list1后写入的终止符才停止。而修改了main函数中的代码,输出一个桃心是因为newList的内存地址在List1后面,然后紧接着一个内存地址保存的东西就未知了。

3.再次提提ASCII编码

参考资料百度百科:点击打开链接  http://baike.baidu.com/link?url=G-MNClonJye7qworrj168QZI9QkZNmbhyqOtOfYcrbXYcMYQULrhioz_0aAKadpAHRnbaAIxhDeBKafdowF9BK
编码:把一个字符映射到它的二进制码叫做编码
在ASCII中0~31及127(共33个)是控制字符或通信专用字符(其余为可显示字符),能够表示128个字符,第八位是奇偶校验位。

4.学习一下freopen函数可以方便debug

参考资料百度百科:点击打开链接 http://baike.baidu.com/link?url=inkB8kSRkuYBZED49Vhe7R0G-CfYCcLMAMQbvas85UtbEYPxiOiOvmC_I1NVRbRLaJ0Qb5-UslUojiVyzeXLqfgFYVvEi_8_IB0-232PI0G
百科中解释为用于重定向输入输出流,我们看看如何使用

#include<iostream>
#include<cstdio>   //引用头文件
using namespace std;

int main(){
freopen("data.txt","r",stdin);    //指定输入的文件,这种写法(没有写完整路径)是默认程序和文件在一个目录下
freopen("anser.txt","w",stdout);  //指定输出文件,默认程序和文件在一个目录下
int n;
char word[10];
cin>>n;
for(int i = 0;i < n; i++){
cin>>word;
cout<<word<<endl;
}
}

未运行前目录下文件,以及data.txt中数据



运行后目录下文件,以及anser.txt中数据。anser.txt是自动生成的(如果不存在该文件),否则会随程序运行覆盖原文件。



在看看运行程序后,黑框子里都有啥。



啥都没有,因为输入输出都重定向了。
如果把以下代码注释掉呢,看看黑框子里的情况
freopen("anser.txt","w",stdout);




输出还在黑框子中。
因此如果在debug的时候,可以考虑写一个数据文件,然后用freopen读入,输出还在黑框子中,这样就不用每次手动复制黏贴了。



第五章内容:

1.循环

循环主要的三种方式:
while( ... ){
...
}

do{
...
}while(...);

for(... ; ... ; ...){
...
}
两个相关语句:
break 跳出循环
continue 直接进入下一个循环

我们讨论一下再多重循环中,如何在用深层的循环得到的结果控制外层的循环。
例子: 当i + j + k = 100 的时候 结束当前循环以及第二层循环, i + j + k = 200 的时候结束所有循环
#include<iostream>
#include<cstdio>   
using namespace std;

int main(){
    for(int i = 0;i < 200; i++){
        int flag1 = 0;//标记1 用于判断i + j + k是否等于200了
        for(int j = 0;j < 200; j++){
            int flag2 = 0; //标记2 用于判断i + j + k 是否等于100了
            for(int k = 0;k < 200; k++){
                if(i + j + k == 100){
                    flag2 = 1;
                    break;
                }
                
                if(i + j + k == 200){
                    flag1 = 1;
                    break; 
                }
            }
            if(flag2) //条件成立结束循环
                break;
            if(flag1)
                break;
        }
        if(flag1)  //条件成立结束循环
            break;
    }
}


从上面代码可以看出,两个标记的值会在条件成立时赋值为1 即 true。
然后会分别触发两次或三次break语句。
写起来比较繁琐但是是可以实现的。

下面展示一下goto的用法,不做介绍,写起来方便,但是不符合当前的要求。有兴趣的自己查找信息。
#include<iostream>
#include<cstdio>
using namespace std;

int main(){
for(int i = 0;i < 200; i++){
for(int j = 0;j < 200; j++){
for(int k = 0;k < 200; k++){
if(i + j + k == 100){
cout<<i + j + k <<endl;
goto flag2;
}

if(i + j + k == 200){
cout<<i + j + k <<endl;
goto flag1;
}
}
}
flag2:;
}
flag1:;
}



第六章内容:

1.函数结构 

P177 6.2 函数由函数名、参数、返回值类型和主体构成

2.函数调用

P178  6.3 相当于执行函数中的代码
返回值是函数执行结束后返回的结果,该结果可以在调用方被保存或者忽略掉。
int max(int a,int b){
if(a > b)
return a;
else
return b;
}

int main(){
int a = max(1,2);
int b = a>b?a:b;

max(1,2);
a>b?a:b;
}
看上面的代码,求最大值,函数如果有返回值,那么返回的结果保存和不保存都是可以的,就像一个表达式得到的结果我们可以保存或者忽略掉。
注意以下问题
#include<iostream>
#include<windows.h>
using namespace std;
void f(){

}

int f2(int n){
if(n % 2== 0)   //这事一个有返回值的函数,
return 1;    //但是在 n%2==0的时候,没有返回任何值

}

int main(){
int x = f();  //这是一个无返回值函数,却用采用函数返回值方式复制
int y = f2(1);
cout<<y<<endl;
}


P179中间部分说明了,main函数也是一种函数,只是main函数是操作系统用来识别一个程序的入口的函数。我们甚至也可以调用main函数。
int ans = 10;
int main(){
if(ans == 0) return 0;
cout<<ans<<endl;
ans--;
main();
}
任一函数也可以调用其他函数,函数自己调用自己的行为称之为递归调用。写过DFS(深度优先搜索的)就非常熟悉了。

3.函数重载

P186 函数名可以相同,函数的签名不同即可。

4.函数原型声明

P189 声明一个函数,而没有实体

5.内联函数

  P191 提升函数性能,减少CPU寄存器压栈,关键字inline

6.局部、全局和静态局部变量

参考资料: http://www.cnblogs.com/DannyShi/p/4584750.html  变量
http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html  内存堆和栈区别

P192 6.1.1  
修正一下:全局变量不在堆中分配内存,在静态内存区中(然而我并不是很清楚如何分配的)

7引用

P197
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++助教