一 . 函 数
1 . c h a r
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout << (str1 == str2) << endl;
cout << (str3 == str4) << endl;
cout << (str5 == str6) << endl;
cout << (str7 == str8) << endl;
char str1[] = "abc":
这里的"abc"是一个常量,首先会在常量存储区里存储"abc"这个常量,然后会因为"abc"被赋值给str1[],所以在栈中开辟一段内存,内存大小为4个节点(char数组后会自动加一个'\0'),然后又有一个"abc"被保存在栈中。 同理,str2[]中的"abc"也是保存在栈中,地址不同。到此,有三个"abc"被保存起来,一个在常量存储区,另外两个在栈中。此外,插一句,c++内存被分为5个区,分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
const char str3[] = "abc":
对于这种被const修饰起来的变量,一般也是被保存在常量存储区,但是,但是对于const数组来讲,系统不确定符号表是否有足够的空间来存放const数组,所以还是为const数组分配内存的。所以str3指向的是栈上的"abc"。同理,str4[]也是保存在栈中,地址不同。
const char *str5 = "abc":
因为"abc"在常量存储区中保存有一份(即使没保存,这样的操作也会新建一份),这里str5定义的时候,嘿,我见过这个,str5就可以开心的直接指向"abc"所在的常量区的地址。
同理str6,str7,str8。与const没有半毛钱关系,const只是使得str5和str6无法指向新的字符串常量(也就是新的地址)。
2 . 左 移 符 “<<”
3 . p u s h _ b a c k 的 用 法
C++中vector头文件中有push_back这一函数,作用是在vector尾部加入一个数据。string中也有这个函数,作用是在字符串结尾插入一个字符。
#include <bits/stdc++.h>
using namespace std;
int main(){
vector<int> vi;
vi.push_back(1);
cout << vi.back() << endl;
vi.push_back(2);
cout << vi.back() << endl;
return 0;
}
4 . a s s e r t 函 数
assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
请看下面的程序清单badptr.c:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
int main( void )
{
FILE *fp;
fp = fopen( "test.txt", "w" );//以可写的方式打开一个文件,如果不存在就创建一个同名文件
assert( fp ); //所以这里不会出错
fclose( fp );
fp = fopen( "noexitfile.txt", "r" );//以只读的方式打开一个文件,如果不存在就打开文件失败
assert( fp ); //所以这里出错
fclose( fp ); //程序永远都执行不到这里来
return 0;
}
[root@localhost error_process]# gcc badptr.c
[root@localhost error_process]# ./a.out
a.out: badptr.c:14: main: Assertion `fp' failed.
使用assert()的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。在调试结束后,可以通过在包含#include <assert.h>的语句之前插入 #define NDEBUG 来禁用assert调用,
示例代码如下:
#include <stdio.h>
#define NDEBUG
#include <assert.h>
用法总结与注意事项:
1)在函数开始处检验传入参数的合法性如
int resetBufferSize(int nNewSize)
{
//功能:改变缓冲区大小,
//参数:nNewSize 缓冲区新长度
//返回值:缓冲区当前长度
//说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);
...
}
2)每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败,如:
不好:
assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);
好
assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);
3)不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题,如:
错误:
assert(i++ < 100);
这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i++这条命令就没有执行。
正确
assert(i < 100);
i++;
4)assert和后面的语句应空一行,以形成逻辑和视觉上的一致感。
5)有的地方,assert不能代替条件过滤。
以下是使用断言的几个原则:
(1)使用断言捕捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的。
(2)使用断言对函数的参数进行确认。
(3)在编写函数时,要进行反复的考查,并且自问:“我打算做哪些假定?”一旦确定了的假定,就要使用断言对假定进行检查。
(4)一般教科书都鼓励程序员们进行防错性的程序设计,但要记住这种编程风格会隐瞒错误。当进行防错性编程时,如果“不可能发生”的事情的确发生了,则要使用断言进行报警。
ASSERT ()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。
ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。
比较好的在程序中使用assert的地方:
(1)空指针检查。例如,针对一个函数的参数进行空指针检查。你可以这样使用:assert (pointer != NULL);,产生的错误会像这样:Assertion ‘pointer != ((void *)0)' failed。这样,当出现空指针时,你的程序就会退出,并很好的给出错误信息。
(2)检查函数参数的值。例如,如果一个函数只能在它的一个参数foo为正值的时候被调用,你可以在函数开始时这样写:assert (foo > 0);,这将帮助你检测函数的错误使用,这也给源代码阅读者很清晰的印象,那就是在这里对函数的参数值有限制。
二 . 题 目
1 . 1 8 B
Problem - 81B - Codeforces
思路:
首先先删除所有的空格
然后在合适的位置添加
代码:
//81-B
#include<bits/stdc++.h>
using namespace std;
#define y1 fndjifhwdn
#define y2 vfsdkofsjd
#define fs first
#define sc second
#define pb push_back
#define mp make_pair
typedef long long 11;
typedef long double ld;
typedef pair<int,int>pi;
int n,tk,ff;
int main()
{
#ifdef home
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
gets(s);
n=strlen(s);
int tk=0;
for(int i=0;i<n;i++)
{
if(s[i]==' ')
{
continue;
}
if(s[i]==',')
{
if(tk>0 && a[tk-1]!=" ")
{
a[tk++]=" ";
}
a[tk]="...";
tk++;
i+=2;
continue
}
ff=i;
while(s[ff]>='0'&&s[ff]<='9')
{
ff++;
}
if(ff>i)
{
if(tk>0&&a[tk-1][0]>=0&&a[tk-1][0]<='9')
{
a[tk++]=' ';
}
for(int j=i;j<ff;j++)
{
a[tk]+=s[j];
tk++;
i=ff-1;
continue;
}
a[tk++]=s[i];
a[tk++]=" ";
}
}
if(tk>0&&a[tk-1]==" ")tk--;
for(int i=0;i<tk;i++)
cout<<a[i];
cout<<endl;
return 0;
}