int binsearch(int x , int v[] , int n)
{
int low , high , mid;
low = 0 ;
high = n - 1;
while (low <= high )
{
mid = (low + high) / 2;
if(x < v[mid])
high = mid - 1 ;
else if(x > v[mid])
low = mid + 1 ;
else
return mid ;
}
return -1 ;
}
int binsearch(int x , int v[] , int n)
{
int low , high , mid;
low = 0 ;
high = n - 1;
mid = (low + high) / 2 ;
while (low <= high && x != v[mid] )
{
if(x < v [mid])
high = mid - 1 ;
else
low = mid + 1 ;
mid = (low + high ) / 2 ;
}
if(x == v[mid])
return mid ;
return -1 ;
}
这是重写后的代码,实际上时间复杂度最多都是O(log2N) ,差距是不大。而且重改后阅读起比较烦人,不便于理解
相反功能的函数,在复制过程中将转义字符转换为实际字符
#include
#include
#include
using namespace std;
/*编写一个函数escape(s ,t),将字符串t复制到字符串s中,并在复制过程中将换行符、制表符
等不可见字符分别转换为\n,\t等相应可见的转义字符序列,要求用switch语句。在编写一个具有
相反功能的函数,在复制过程中将转义字符转换为实际字符
*/
void escape(char s[] , char t[]);
int getline(char line []);
int main()
{
char s[100] , t[100];
int length;
while ((length = getline(t)) > 0)
{
escape(s , t);
printf("%s\n" , s);
}
system("pause");
return 0 ;
}
//t --> s
void escape(char s[] , char t[])
{
int i , j ;
for(i = j =0; t[i] != '\0'; i++)
{
switch (t[i])
{
case '\n': //t[i] == '\n'
s[j++] = '\\';
s[j++] = 'n' ;
break;
case '\t': //t[i] == '\t'
s[j++] = '\\';
s[j++] = 't' ;
break;
default :
s[j++] = t[i];
break ;
}
}
s[j] = '\0';
}
//getline函数:获取字符串
int getline(char line[])
{
int c , i ;
for(i = 0; (c = getchar()) != EOF && c != '\n'; i++)
line[i] = c ;
if(c == '\n')
line[i++] = '\n';
line[i] = '\0';
return i ;
}
相反功能函数oppositr_escape(s , t):
void opposite_escape(char s[] , char t[])
{
int i , j ;
for(i = j = 0; t[i] != '\0'; i++)
{
if(t[i] != '\\')
{
s[j++] = t[i] ;
}
else
{
switch (t[++i])
{
case 't':
s[j++] = '\t';
break;
case 'n':
s[j++] = '\n';
break;
default:
s[j++] = '\\';
s[j++] = t[i];
break;
}
}
}
s[j] = '\0' ;
}
上面这个是修改后的,原本的写法如下
//函数的初始版本
void oppositr_escape(char s[] , char t[])
{
int i , j ;
for(i = j = 0; t[i] != '\0'; i++)
{
if(t[i++] == '\\') //i++,即switch里的t[i]是"\"后的字符
{
switch (t[++i])
{
case 't':
s[j++] = '\t';
break;
case 'n':
s[j++] = '\n';
break;
default:
s[j++] = '\\';
s[j++] = t[i] ;
break;
}
}
else
{
s[j++] = t[i] ;
}
}
s[j] = '\0' ;
}
一直出错,缺少许多字符串,后来发现是这句if(t[i++] == '\\')
出了问题,因为在每一次判断的时候i
自增1。
其实在今天在学习控制流的时候就有所启发,K&R一直在强调代码的规范与简洁,即如何在保证阅读顺利的前提下编写最简洁明了的代码
在此例题中,我这个写法看似简洁,实际上存在很大的bug,是我忘记了if
的逻辑:先执行括号里的表达式,若为真,则执行程序块的语句。即判断时,括号里的表达式是一定执行。
而我误解为若括号里表达式为真,才会执行此条表达式。
#include
#include
#include
using namespace std;
/*编写函数expand(s1 , s2),将字符串s1中类似于a-z一类多的速记符号在字符
串s2中扩展为等价的完整列表abc…xyz。该函数可以处理大小写字母和数字,并可
以处理a-b-c、a-z0-9与-a-z等类似的情况。作为前导和尾随的-字符原样排印
*/
void expand(char s1[] , char s2[]);
int getline(char line []);
int main()
{
char s[100] , t[100];
int length;
while ((length = getline(s)) > 0)
{
expand(s , t);
printf("%s\n" , t);
}
system("pause");
return 0 ;
}
void expand(char s1[] , char s2[])
{
char c ;
int i , j ;
i = j = 0 ;
while ((c = s1[i++]) != '\0')
{
if(s1[i] == '-' && s1[i+1] >= c )
{
i++;
while (c < s1[i]) //进行扩展
{
s2[j++] = c++;
}
}
else
{
s2[j++] = c ; //复制字符(最后一个)
}
}
s2[j] = '\0' ;
}
int getline(char line[])
{
int c , i ;
for(i = 0; (c = getchar()) != EOF && c != '\n'; i++)
line[i] = c ;
if(c == '\n')
line[i++] = '\n';
line[i] = '\0';
return i ;
}
答案思路太清晰了,while用的十分nice。
原因:二进制补码表示中,正整数的范围比多1,因为0只要全0就可以表示,便把符号位为1的全0表示为-2^(字长-1);
若n= -n,那么就会爆掉哦
所以思路就是在直接对负数进行取余
void re_itoa(int n , char s[])
{
int i , sign ;
i = 0 ;
sign = n ;
while(n != 0)
{
s[i++] = abs(n % 10) + '0';
n /= 10 ;
}
if(sign < 0)
s[i++] = '-' ;
s[i] = '\0';
reverse(s) ;
}
#include
#include
#include
#include
using namespace std;
/*编写itob(n , s ,b)将整数n转化为以b为进制的数,并将转化结果
以字符串的形式保存到字符串s。例如itob(n, s , b)把整数n化为十六进制
整数保存在s中
*/
void itob(int n , char s[] , int b);//将数字转换字符串
int getline(char line []); //获取字符串
void reverse(char s[]); //将字符串倒置
int main()
{
char s[100] , t[100];
int n , b;
int length;
cout << "请输入整数n、基数b:";
while (cin >> n >> b)
{
itob(n , s , b);
printf("%s\n" , s);
}
system("pause");
return 0 ;
}
void itob(int n , char s[] , int b)//b为基数。
{
int i , sign , a;
i = 0;
sign = n ; //记录符号;
while (n != 0)
{
a = abs(n % b);
s[i++] = ((a < 10) ? a + '0' : a + 'a' - 10) ;
n /= b ;
}
if(sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
int getline(char line[])
{
}
void reverse(char s[])
{
}
s[i++] = ((a < 10) ? a + '0' : a + 'a' - 10) ;
秒啊秒啊,这个表达式我在第一次写的时候应该想不到。learning!
不过十进制转其他进制原来这门简单吗,想之前我可是被困扰很久。。。
#include
#include
#include
#include
using namespace std;
/*改写itoa,可以获得参数lim,使得转换后所得的结果至少具有lim的长度
必要时在左边填充一定的空格(为了便于观察,用 ~ )
*/
void itob(int n , char s[] , int b , int lim);//将数字转换字符串
int getline(char line []); //获取字符串
void reverse(char s[]); //将字符串倒置
int main()
{
char s[100] , t[100];
int n , b , lim ;
int length;
cout << "请输入整数n、基数b、最小宽度:";
while (cin >> n >> b >> lim)
{
itob(n , s , b , lim);
printf("%s\n" , s);
}
system("pause");
return 0 ;
}
void itob(int n , char s[] , int b , int lim)//b为基数。
{
int i , sign , a;
i = 0;
sign = n ; //记录符号;
while (n != 0)
{
a = abs(n % b);
s[i++] = ((a < 10) ? a + '0' : a + 'a' - 10) ;
n /= b ;
}
if(sign < 0)
s[i++] = '-';
while (i < lim )
{
s[i++] = '~' ;//为了便于观察,用~代替空格
}
s[i] = '\0';
reverse(s);
}
int getline(char line[])
{
}
void reverse(char s[])
{
}
总结:第三章难度还行,但是想要强调的思想很nice,如何写简洁明了、不影响阅读的代码?
在什么情况用for , while , do-while ,
"?:"
,可以用来简化一个if-else
语句
还学了进制转换、数字转字符串等blabla的东西。
春季赛决赛开始了,今晚划水摸鱼,明天第四章函数与程序结构咯