参考:C语言运算符优先级
优先级总结:
括号,指向成员类优先级 > 单目运算符 > 算数运算符 (乘除求余 高于 加减)> 移位运算符 > 关系运算符 > 按位运算符 > 逻辑运算符 > 条件运算符 > 赋值运算符 > 逗号运算符
结合性:
只有单目运算符,条件运算符(? :)和赋值运算符是从右向左,其余从左往右。
分析:
题中的for循环如下:
for(i = 0; i < lim - 1 && (c = getchar())!='\n' && c != EOF;++i)
s[i] = c;
要求实现相同的功能但不用逻辑运算符:
int i = 0;
char c;
while(i < lim - 1)
{
c = getchar();
if(c == EOF)
break;
else if (c == '\n')
break;
else
s[i++] = c;
}
分析:
十六进制数 0xa1a2a3a4,对应的十进制数计算为:
a4 + a3 * 16 + a2 * 16 * 16 + a1 * 16 * 16 * 16 =
a4 + 16* (a3 + 16 * (a2 + 16 * a1))
#include
#include
#include
#define LEN 19 //unsigned long有8位,要16个十六进制字符,加上两个字符表示前缀,一个字符串结束符
int s_gets(char *s, int n);
void eatline(void);
int check(char *s);
unsigned long htoi(char *s);
int main(void)
{
char s[LEN];
int ok, good;
unsigned long val;
puts("Please enter a string of hexadecimal digis (optional 0x or 0X):");
while(((good = s_gets(s, LEN)) == 0) || (ok = check(s)) == 0)
{
if(good == 0)
{
printf("Please enter no more than %d hexadecimal characters, "
"enter again:\n",LEN-1);
continue;
}
else if(ok == 0)
{
puts("Not a string of hexadecimal digis, enter again:");
continue;
}
}
val = htoi(s);
printf("%s corresponds to %lu\n",s, val);
return 0;
}
void eatline(void)
{
while(getchar() != '\n')
continue;
}
int s_gets(char *s, int n)
{
char *find;
int ok = 0; //检查输入是否超过,超过则对应整数范围超过,需重新输入,不能直接将后面截断
fgets(s, n, stdin);
if(s)
{
find = strchr(s, '\n');
if(find)
{ *find = '\0';
ok = 1;
}
else
{
if(getchar() == '\n')
ok = 1;
else
eatline();
}
}
return ok;
}
int check(char *s)
{
int i = 0;
int flag = 0;
if(s[i++] == '0')
{
if(s[i] == 'x' || s[i] == 'X')
flag = 1;
}
while(s[++i] != '\0' && flag == 1)
{
if(s[i] < '0' || (s[i] > '9' && s[i] < 'A') || (s[i] > 'F' && s[i] < 'a') || s[i] > 'f')
flag = 0;
}
return flag;
}
unsigned long htoi(char *s)
{
unsigned long n = 0;
int h_d;
for(int i = 2; s[i] != '\0'; i++)
{
if(s[i] >= '0' && s[i] <= '9')
h_d = s[i] - '0';
else if(s[i] >= 'A' && s[i] <= 'F')
h_d = s[i] - 'A' + 10;
else if(s[i] >= 'a' && s[i] <= 'f')
h_d = s[i] - 'a' + 10;
n = 16 * n + h_d;
}
return n;
}
/*
// 进制转换另一种方法
// 加上头文件 ctype.h
unsigned long pow_i(int x, int y)
{
unsigned long sum = 1;
for(int i = 0; i < y; i++)
sum *= x;
return sum;
}
unsigned long htoi(char *s)
{
unsigned long n = 0;
int i, j;
int h_d;
int len = strlen(s);
for(i = len - 1, j = 0; i > 1; i--, j++)
{
s[i] = tolower(s[i]);
if(s[i] >= '0' && s[i] <= '9')
h_d = s[i] - '0';
else
h_d = s[i] - 'a' + 10;
n += s[i] * pow_i(16, j);
}
return n;
}
*/
#include
#include
#define LEN 41
char *s_gets(char *s, int n);
void squeeze(char *s1, char *s2);
int main(void)
{
char s1[LEN], s2[LEN];
printf("Please enter two strings (no more than %d characters:\n",LEN-1);
s_gets(s1, LEN);
s_gets(s2, LEN);
printf("Delete each charater in \"%s\" that matches any character in \"%s\".\n",s1,s2);
printf("\"%s\" becomes ",s1);
squeeze(s1, s2);
printf("\"%s\"\n",s1);
return 0;
}
char *s_gets(char *s, int n)
{
char *ret_val, *find;
ret_val = fgets(s, n, stdin);
if(ret_val)
{
find = strchr(s, '\n');
if(find)
*find = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
void squeeze(char *s1, char *s2)
{
int i, j, k;
for(i = 0; s2[i] != '\0'; i++)
{
for(j = 0, k = 0; s1[j] != '\0'; j++)
if(s1[j] != s2[i])
s1[k++] = s1[j];
s1[k] = '\0';
}
}
#include
#include
#define LEN 41
char *s_gets(char *s, int n);
int mystrpbrk(char *s1, char *s2);
int main(void)
{
char s1[LEN], s2[LEN];
int pos;
printf("Please enter two strings (no more than %d characters):\n",LEN-1);
s_gets(s1, LEN);
s_gets(s2, LEN);
pos = mystrpbrk(s1, s2);
if(pos != -1)
printf("The first character in \"%s\" that also belongs to \"%s\" is %c.\n",s1, s2, s1[pos]);
else
printf("\"%s\" does not have the same characters as \"%s\".\n",s1, s2);
return 0;
}
char *s_gets(char *s, int n)
{
char *ret_val, *find;
ret_val = fgets(s, n, stdin);
if(ret_val)
{
find = strchr(s, '\n');
if(find)
*find = '\0';
else
while(getchar() != '\n')
continue;
}
return ret_val;
}
int mystrpbrk(char *s1, char *s2)
{
int i, j;
for(i = 0; s1[i] != '\0'; i++)
for(j = 0; s2[j] != '\0'; j++)
if(s1[i] == s2[j])
return i;
return -1;
}
setbits(x,p,n,y) 函数返回对x执行下列操作后的结果值: 将x中从第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变。
分析:
mask1 = ~(~(~0 << n) << (p-n+1));
x = x & mask1;
y = y & (~(~0 << n)) << (p-n+1);
x = x | y; // 0 | x = x;
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
unsigned mask1;
mask1 = ~(~(~0 << n) << (p-n+1));
x = x & mask1;
y = y & (~(~0 << n)) << (p-n+1);
x = x | y; // 0 | x = x;
return x;
}
invert(x,p,n) 函数返回对x执行下列操作后的结果值: 将x中从第p位开始的n个(二进制)位取反,x的其余各位保持不变。
分析:
取反考虑异或 ^,有如下关系:
1 ^ 1 == 0; // 1 与 x 异或,使 x 取反
1 ^ 0 == 1;
0 ^ 0 == 0; // 0 与 x 异或, x 不变
0 ^ 1 == 1;
因此,得到:
mask = ~(~0 << n) << (p-n+1); // 将 p 到 p-n+1 置1,其余0;
x = x ^ mask;
函数:
unsigned invert(unsigned x, int p, int n)
{
unsigned mask1;
mask1 = ~(~(~0 << n) << (p-n+1));
x = x ^ mask;
return x;
}
rightrot(x,n) 函数返回将x循环右移(即从最右端移出的位将从最左端移入)n(二进制)
位后所得到的值。
分析:
unsigned y = ~(~0 << n) & x;
int len(void)
{
unsigned i
int len = 0;
for(i = 1; i != 0; i << 1)
++len;
return len;
}
// len 就是unsigned 的位数
y = y << len - n;
x = y | (x >> n);
函数:
int len(void)
{
unsigned i
int len = 0;
for(i = 1; i != 0; i << 1)
++len;
return len;
}
unsigned y = ~(~0 << n) & x;
y = y << len - n;
x = y | (x >> n);
return x;
分析:
int bitcount(unsigned x)
{
int b;
for(b = 0; x != 0; x >>= 1)
if (x & 01)
b++;
return b;
}
改进:
int bitcount(unsigned x)
{
int b = 0;
while(x != 0)
{
b++;
x &= (x - 1);
}
return b;
}
将一个字符串中的大写字符转化为小写字符,ASCLL 码中大些字母范围为 65 ~ 90,小写字母范围为 97 ~ 122,对于大些字母 c,将其转化为对应的小写字母:c + ‘a’ - 'A‘
void * lower(char *s)
{
for(int i = 0; s[i] != '\0'; i++)
s[i] = (s[i] >= 'A' && s[i] <= 'Z') ? (s[i] + 'a' - 'A') : s[i]);
}