金金金金金金金金金

男人至死是少年


  • 首页

  • 归档
金金金金金金金金金

SHELL字符分割的IFS变量

发表于 2017-11-30

shell命令解析输入字符串的默认分割符是水平制表符(tab),空格(space)和换行(newline)
要改变当前shell的默认分割符,用IFS的环境变量。

  • 默认的分割符
    1
    2
    3
    [root@centos01 tmp]# echo -n "$IFS" | hexdump
    0000000 0920 000a
    0000003

十六进制值0x20, 0x09和0x0a分别对应于空格(space), 水平制表符(tab)和换行符(newline)的值。

  • 下面两个方法的运行结果直接说明问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/sh

#default IFS are tab,space,and newline

not_change_IFS() {

echo "===========not change IFS=================="
for i in `df -h | head -n 2`;
do
echo $i
done

}

change_IFS() {

echo "===========change IFS=================="

#only use \n as delimeter
oldIFS=$IFS
IFS=$'\n'
for i in `df -h | head -n 2`;
do
echo $i
done
IFS=$oldIFS

}

not_change_IFS
change_IFS

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@centos01 tmp]# ./test.sh
===========not change IFS==================
Filesystem
Size
Used
Avail
Use%
Mounted
on
/dev/mapper/rhel-root
6.7G
5.7G
1.1G
85%
/
===========change IFS==================
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 6.7G 5.7G 1.1G 85% /
金金金金金金金金金

用C语言模拟进度条

发表于 2017-10-01

用C语言搞了一个模拟的进度条
首先要知道三个事情:

  • 1 \r 和 \n 的不同

\r 是输出位置回到行首
\n 是输出位置到下一行

  • 2 printf() 默认是行输出,所以没有完成一行的时候想要保证输出,每次要fflush(stdout);

  • 3 在不断打印进度条的过程中,为了屏蔽来自键盘输入回车,用了tcsetattr。通过这个可以改键。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

int progress()
{
int i = 0;
char progress[40] = "----------------------------------------";
struct termios term_orig;
struct termios term_modify;

//shield return from keybord when printing
tcgetattr(STDIN_FILENO, &term_orig);
term_modify = term_orig;
term_modify.c_iflag = term_orig.c_iflag | IGNCR;
tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_modify);

for(i = 1; i <= 100; i++){
write(STDOUT_FILENO, "\r", 1);
write(STDOUT_FILENO, progress, i / 10 * 4);
printf(" %%%d", i);
fflush(stdout);
usleep(50000);
}

printf("\n");
tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_orig);

return 0;
}
金金金金金金金金金

Shell生成随机数

发表于 2017-08-14

由C语言做随机数想到的,shell里做随机数的方式怎么办?

1 用$RANDOM环境变量
这个是bash自带的, 简单

1
2
3
4
[root@localhost tmp]# echo $RANDOM
15485
[root@localhost tmp]# echo $RANDOM
28251

2 用date命令
date +%s是到Epoch的秒数,同一秒内执行就出现重复值了,差了点意思
date +%N是纳秒,这个可以。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@localhost tmp]# for((i=0;i<10;i++)) do date +%s;done
1563268127
1563268127
1563268127
1563268127
1563268127
1563268127
1563268127
1563268127
1563268127
1563268127
[root@localhost tmp]# for((i=0;i<10;i++)) do date +%N;done
073253018
074129069
075084042
076401830
077565403
078989196
080028619
080871567
081590442
082393070

3 用系统目录下提供的random
也就是/dev/urandom,是持续输出,所以用head -n限制一下。还要配合cksum才能生成数字。

1
2
3
4
5
6
[root@localhost tmp]# head -n 1 /dev/urandom
▒8▒d{▒▒uzlx▒▒▒
[root@localhost tmp]# head -n 1 /dev/urandom | cksum
3580720445 276
[root@localhost tmp]# head -n 1 /dev/urandom | cksum | awk '{print $1}'
1937857628

4 用系统提供的uuid
这个和上一种情况类似,目录的位置是/proc/sys/kernel/random/uuid, 每次产生一条所以可以用cat

1
2
3
4
5
6
7
8
[root@localhost tmp]# cat /proc/sys/kernel/random/uuid
9b40c368-000c-4fd8-b2a3-1205e965222b
[root@localhost tmp]# cat /proc/sys/kernel/random/uuid | cksum
3272696125 37
[root@localhost tmp]# cat /proc/sys/kernel/random/uuid | cksum | cut -f1
1621319366 37
[root@localhost tmp]# cat /proc/sys/kernel/random/uuid | cksum | cut -d' ' -f1
1174319192
金金金金金金金金金

带权重的随机

发表于 2017-07-22

今天想写一个where_to_eat_lunch的小程序,帮助选择中午吃饭的地方,其实是练习随机选择的问题。(让我想到了Knuth大神的n个中均匀抽样m个数并且有序的方法,这个还是自行再去看看编程珠玑的抽样问题吧)

本来以为是一个很容易搞定的问题,结果遇到了各种坑。

坑一:
time() 函数的问题。 开始的时候没有#include <time.h> 竟然编译通过了,但是这个函数有问题,至今没有搞懂奇怪的行为。描述一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@localhost ~]# cat 1.c
#include <stdio.h>

//#include <time.h>


int main(int argc, char ** argv)
{
unsigned long my_seed = 0;
//my_seed = (unsigned long)time(NULL);
my_seed = (unsigned long)time();
int i = 0;

srand(my_seed);
for(i = 0; i < 100; ++i){
printf("%d\n", rand());
}


return 0;
}

[root@localhost ~]# gcc 1.c
[root@localhost ~]# ldd a.out
linux-vdso.so.1 => (0x00007fff5a5fe000)
libc.so.6 => /lib64/libc.so.6 (0x00007f8719dbc000)
/lib64/ld-linux-x86-64.so.2 (0x00007f871a184000)
[root@localhost ~]# nm a.out | grep time
U time@@GLIBC_2.2.5

看似就是普通glibc里的函数。但是竟然不要参数!!! 在<time.h>里的time是需要参数的!而且这个a.out运行会coredump

1
2
3
4
5
6
7
8
[root@localhost ~]# ./a.out
Segmentation fault (core dumped)
[New LWP 7844]
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x00007fff5b9fefe1 in time ()
Missing separate debuginfos, use: debuginfo-install glibc-2.17-55.el7.x86_64
(gdb) q

能不能不coredump呢,能!改一下code, 非常神奇。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@localhost ~]# cat 1.c
#include <stdio.h>

//#include <time.h>


int main(int argc, char ** argv)
{
int array[100] = {}; //加一行这里

unsigned long my_seed = 0;
//my_seed = (unsigned long)time(NULL);
my_seed = (unsigned long)time();
int i = 0;

srand(my_seed);
for(i = 0; i < 100; ++i){
printf("%d\n", rand());
}

return 0;
}

好吧,这里暂且不管这个神奇的time()。这里主要记住的就是库函数time()是要有参数的!要include<time.h>. 参数可以是NULL但是一定要有。

坑二:
也不算是一个坑。突然想起来看过一篇文章说,谈到人的认知错觉,当人在听歌的时候选择在列表里随机播放,当听到一首歌,下一次再听到,就总觉得听到这一首歌的概率很大,感觉概率是不均匀的。苹果的播放器开始就是随机的播放,但是由于人的这个错觉,乔布斯只好改进了一下,将刚听过的歌曲再次出现的概率降低。也就是降低再次出现的权重。
这里我也想引入权重,每次被选择后权重降低。听起来不错。实现起来发现并没有太好的时间空间复杂度的算法(也许有好的算法,但没想出来~~!)。

先写一个放在这里吧。思路是:
1 每个饭馆有一个对应的rate
2 将rate值累加得到另外一个数组cumulative,像这样

0号饭馆 1号饭馆 2号饭馆 3号饭馆
rate 1 2.2 3.0 4.5
cumulative 1 3.2 6.2 10.7

总的rate是1 + 2.2 + 3.0 + 4.5 = 10.7
3 每次随机选择一个100以内的数,算一个百分比,比如随机选择了32,那么百分比就是0.32
4 总的rate 乘以这个百分比,这个例子中就是10.7 * 0.32(我说不好这叫什么化,反正就是把100的尺度按比例尺拉成了总的rate这个尺度)
5 那么第4步的这个乘积落在哪个rate的区间上,就取那个rate的index位置,也就是对应的那个饭馆的index位置。

6 用float不好理解,用整型就好理解了

0号饭馆 1号饭馆 2号饭馆 3号饭馆
rate 1 3 3 3
cumulative 1 4 7 10

也就是说,0号饭馆的权重是1, 1号饭馆的权重是3,2号饭馆的权重是3,3号饭馆的权重是3。一共是10份,0号占1份,1,2和3号各占3份。随机的时候,100个数随机到了10以内,就是0号,随机到了10-40,就是1号。随机到了40-70就是2号,贼好理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
[root@localhost ~]# cat where_to_eat.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define NUM 6

void show(float *rate){
int i = 0;

for(i = 0; i < NUM ; ++i) {
printf("%f\n", rate[i]);
}

return;
}

void rise_all_rate(float *rate){
int i = 0;

for(i = 0; i < NUM; ++i){
rate[i] *= 100;
}

return;
}

int get_random_via_weight(float *rate) {
unsigned long my_seed = (unsigned long)time(NULL);
int random_value = 0;
int i = 0;
float cumulative[NUM] = {0.0};
float random_value_percent = 0.0;
float sum_by_percent = 0.0;

srand(my_seed);
random_value = rand() % 100;
random_value_percent = random_value / 100.0;

for(cumulative[0] = rate[0],i = 1; i < NUM; ++i){
cumulative[i] = rate[i] + cumulative[i-1];
}
sum_by_percent = cumulative[NUM-1] * random_value_percent;

for(i = 0; i < NUM; ++i) {
if(sum_by_percent - cumulative[i] < 0) break;
}

rate[i] = rate[i] / 2;
if(rate[i] < 0.1) {
rise_all_rate(rate);
}
printf("random value is %d, percent is %f, choose %d\n", random_value, random_value_percent, i);
show(rate);

return i;
}

int main(int argc, char ** argv)
{
char *restaurant[NUM] = {"tian", "he", "la",
"kfc", "mc", "subway"};
float rate[NUM] = {0.0};
float *p = rate;
int i = 0;
unsigned char c = '\0';

for(i = 0; i < NUM; ++i) {
rate[i] = 10.0;
}

while(1){
c = getchar();
if('y' == c) break;
i = get_random_via_weight(p);
printf("Ok, Let's go to %s for lunch.\n", restaurant[i]);
}

return 0;
}

这里是有坑的。
1 time(NULL)这玩意返回的和Epoch(1970.1.1)之间的秒数,同一秒内得到的结果一样,也就是seed一样
2 因为机器是伪随机的,每次调用get_random_via_weight的时候,重新开始随机,seed如果一样随机的结果是一样一样的。如果在同一秒内,rand()的返回值是一样的。

所以调整一下,全局的事情全局做,my_seed 弄成了全局的,只srand一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
[root@localhost ~]# cat where_to_eat.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define NUM 6

unsigned long my_seed;
void show(float *rate){
int i = 0;

for(i = 0; i < NUM ; ++i) {
printf("%f\n", rate[i]);
}

return;
}

void rise_all_rate(float *rate){
int i = 0;

for(i = 0; i < NUM; ++i){
rate[i] *= 100;
}

return;
}

int get_random_via_weight(float *rate) {
static int random_value = 0;
int i = 0;
float cumulative[NUM] = {0.0};
float random_value_percent = 0.0;
float sum_by_percent = 0.0;

random_value = rand() % 100;
random_value_percent = random_value / 100.0;

for(cumulative[0] = rate[0],i = 1; i < NUM; ++i){
cumulative[i] = rate[i] + cumulative[i-1];
}
sum_by_percent = cumulative[NUM-1] * random_value_percent;

for(i = 0; i < NUM; ++i) {
if(sum_by_percent - cumulative[i] < 0) break;
}

rate[i] = rate[i] / 2;
if(rate[i] < 0.1) {
rise_all_rate(rate);
}
printf("random value is %d, percent is %f, choose %d\n", random_value, random_value_percent, i);
show(rate);

return i;
}

int main(int argc, char ** argv)
{
char *restaurant[NUM] = {"tian", "he", "la",
"kfc", "mc", "subway"};
float rate[NUM] = {0.0};
float *p = rate;
int i = 0;
unsigned char c = '\0';

my_seed = (unsigned long)time(NULL);
srand(my_seed);

for(i = 0; i < NUM; ++i) {
rate[i] = 10.0;
}

int test = 100;
while(test--){
#if 0
c = getchar();
if('y' == c) break;
#endif
i = get_random_via_weight(p);
printf("Ok, Let's go to %s for lunch.\n", restaurant[i]);
}

return 0;
}

这个算法在饭馆数组特别大的时候,就不算太好了,累加那么多次。有改进的方案是数组分块,每一块大小可以是sqrt(total_array_size)。 然后每次更新权重只是影响一块,块间的cumulative要重新计算。然后随机落到哪个块里了,在那个块里再细细掰扯。

金金金金金金金金金

那些危险溢出的c函数们

发表于 2017-06-24

防止缓冲区溢出

函数 严重程度 解决方案
gets 最危险 使用fgets(buf,size,stdin)。这几乎总是一个大问题!
strcpy 很危险 改为使用strncpy。
strcat 很危险 改为使用strncat。
sprintf 很危险 改为使用snprintf,或者使用精度说明符。
scanf 很危险 使用精度说明符,或自己进行解析。
sscanf 很危险 使用精度说明符,或自己进行解析。
fscanf 很危险 使用精度说明符,或自己进行解析。
vfscanf 很危险 使用精度说明符,或自己进行解析。
vsprintf 很危险 改为使用vsnprintf,或者使用精度说明符。
vscanf 很危险 使用精度说明符,或自己进行解析。
vsscanf 很危险 使用精度说明符,或自己进行解析。
streadd 很危险 确保分配的目的地参数大小是源参数大小的四倍。
strecpy 很危险 确保分配的目的地参数大小是源参数大小的四倍。
strtrns 危险 手工检查来查看目的地大小是否至少与源字符串相等。
realpath 很危险(或稍小,取决于实现) 分配缓冲区大小为MAXPATHLEN。同样,手工检查参数以确保输入参数不超过MAXPATHLEN。
syslog 很危险(或稍小,取决于实现) 在将字符串输入传递给该函数之前,将所有字符串输入截成合理的大小。
getopt 很危险(或稍小,取决于实现) 在将字符串输入传递给该函数之前,将所有字符串输入截成合理的大小。
getopt_long 很危险(或稍小,取决于实现) 在将字符串输入传递给该函数之前,将所有字符串输入截成合理的大小。
getpass 很危险(或稍小,取决于实现) 在将字符串输入传递给该函数之前,将所有字符串输入截成合理的大小。
getchar 中等危险 如果在循环中使用该函数,确保检查缓冲区边界。
fgetc 中等危险 如果在循环中使用该函数,确保检查缓冲区边界。
getc 中等危险 如果在循环中使用该函数,确保检查缓冲区边界。
read 中等危险 如果在循环中使用该函数,确保检查缓冲区边界。
bcopy 低危险 确保缓冲区大小与它所说的一样大。
fgets 低危险 确保缓冲区大小与它所说的一样大。
memcpy 低危险 确保缓冲区大小与它所说的一样大。
snprintf 低危险 确保缓冲区大小与它所说的一样大。
strccpy 低危险 确保缓冲区大小与它所说的一样大。
strcadd 低危险 确保缓冲区大小与它所说的一样大。
strncpy 低危险 确保缓冲区大小与它所说的一样大。
vsnprintf 低危险 确保缓冲区大小与它所说的一样大。
金金金金金金金金金

KMP字符串匹配算法

发表于 2017-05-13

举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”?
许多算法可以完成这个任务,Knuth-Morris-Pratt算法(简称KMP)是最常用的之一。它以三个发明者命名,起头的那个K就是著名科学家Donald Knuth。

1.
log
首先,字符串”BBC ABCDAB ABCDABCDABDE”的第一个字符与搜索词”ABCDABD”的第一个字符,进行比较。因为B与A不匹配,所以搜索词后移一位。
2.
log
因为B与A不匹配,搜索词再往后移。
3.
log
就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止。
4.
log
接着比较字符串和搜索词的下一个字符,还是相同。
5.
log
直到字符串有一个字符,与搜索词对应的字符不相同为止。
6.
log
这时,最自然的反应是,将搜索词整个后移一位,再从头逐个比较。这样做虽然可行,但是效率很差,因为你要把”搜索位置”移到已经比较过的位置,重比一遍。
7.
log
一个基本事实是,当空格与D不匹配时,你其实知道前面六个字符是”ABCDAB”。KMP算法的想法是,设法利用这个已知信息,不要把”搜索位置”移回已经比较过的位置,继续把它向后移,这样就提高了效率。
8.
log
怎么做到这一点呢?可以针对搜索词,算出一张《部分匹配表》(Partial Match Table)。这张表是如何产生的,后面再介绍,这里只要会用就可以了。
9.
log
已知空格与D不匹配时,前面六个字符”ABCDAB”是匹配的。查表可知,最后一个匹配字符B对应的”部分匹配值”为2,因此按照下面的公式算出向后移动的位数:
  移动位数 = 已匹配的字符数 - 对应的部分匹配值
因为 6 - 2 等于4,所以将搜索词向后移动4位。
10.
log
因为空格与C不匹配,搜索词还要继续往后移。这时,已匹配的字符数为2(”AB”),对应的”部分匹配值”为0。所以,移动位数 = 2 - 0,结果为 2,于是将搜索词向后移2位。
11.
log
因为空格与A不匹配,继续后移一位。
12.
log
逐位比较,直到发现C与D不匹配。于是,移动位数 = 6 - 2,继续将搜索词向后移动4位。
13.
log
逐位比较,直到搜索词的最后一位,发现完全匹配,于是搜索完成。如果还要继续搜索(即找出全部匹配),移动位数 = 7 - 0,再将搜索词向后移动7位,这里就不再重复了。
14.
log
下面介绍《部分匹配表》是如何产生的。
  首先,要了解两个概念:”前缀”和”后缀”。 “前缀”指除了最后一个字符以外,一个字符串的全部头部组合;”后缀”指除了第一个字符以外,一个字符串的全部尾部组合。
15.
log
“部分匹配值”就是”前缀”和”后缀”的最长的共有元素的长度。以”ABCDABD”为例,
- “A”的前缀和后缀都为空集,共有元素的长度为0;
- “AB”的前缀为[A],后缀为[B],共有元素的长度为0;
- “ABC”的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;
- “ABCD”的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;
- “ABCDA”的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为”A”,长度为1;
- “ABCDAB”的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为”AB”,长度为2;
- “ABCDABD”的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。
16.
log
“部分匹配”的实质是,有时候,字符串头部和尾部会有重复。比如,”ABCDAB”之中有两个”AB”,那么它的”部分匹配值”就是2(”AB”的长度)。搜索词移动的时候,第一个”AB”向后移动4位(字符串长度-部分匹配值),就可以来到第二个”AB”的位置。

金金金金金金金金金

git 冲突的解决

发表于 2017-04-10

冲突的类型:

  • 逻辑冲突
    这种比较坑,自动merge的时候没有问题,但是实际内容中有问题了。比如说函数的返回值含义变了,不是git中解决的。需要自己看好,看不好就等测试吧。anyway不在这篇的讨论范围,好吧。

  • 树冲突
    文件名修改造成的冲突,称为树冲突。
    比如,a用户把文件改名为a.c,b用户把同一个文件改名为b.c,那么b将这两个commit合并时,会产生冲突。

    1
    2
    3
    4
    $ git status
    added by us: b.c
    both deleted: origin-name.c
    added by them: a.c

    如果最终确定用b.c,那么解决办法如下:

    1
    2
    3
    4
    git rm a.c
    git rm origin-name.c
    git add b.c
    git commit

    执行前面两个git rm时,会告警“file-name : needs merge”,可以不必理会。
    树冲突也可以用git mergetool来解决,但整个解决过程是在交互式问答中完成的,用d 删除不要的文件,用c保留需要的文件。
    最后执行git commit提交即可。

  • 内容冲突
    merge的时候会显示CONFLICT

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $git fetch origin
    $git merge origin/wombat_master
    Auto-merging src/allocator_server.c
    Auto-merging src/arg_parse.c
    Auto-merging src/cli.c
    CONFLICT (content): Merge conflict in src/cli.c
    Auto-merging src/include/allocator.h
    CONFLICT (content): Merge conflict in src/include/allocator.h
    Auto-merging src/include/arg_parse.h
    Auto-merging src/spawn.c
    Automatic merge failed; fix conflicts and then commit the result.

    编辑src/cli.c和src/include/allocator.h
    冲突产生后,文件系统中冲突了的文件(这里是test.txt)里面的内容会显示为类似下面这样:

    1
    2
    3
    4
    5
    6
    7
    a123
    <<<<<<< HEAD
    b789
    =======
    b45678910
    >>>>>>> 6853e5ff961e684d3a6c02d4d06183b5ff330dcc
    c

    其中:冲突标记<<<<<<< (7个<)与=======之间的内容是我的修改,=======与>>>>>>>之间的内容是别人的修改。

    编辑完,可以git status看一下,
    然后git add -u 注:-u 表示把所有已track的文件的新的修改加入缓存,但不加入新的文件。
    然后git commit
    Git下的冲突解决

金金金金金金金金金

为什么中国人说英语听起来没有礼貌?那些你没注意的小细节

发表于 2017-03-16
  • 中国人的英语以Chinglish或Chenglish闻名于世。中国人最大的英语发音问题就是没有连读,但这都不是最主要的语言问题。老外时常议论,很多中国人在说英语时,听起来没有礼貌;并不是这些中国人本身没礼貌,而是他们还没习惯英语的礼貌表达方式…..

    比如,中国人在餐厅或咖啡厅,会说:“我想要一个汉堡包”或者“我想要一杯咖啡”。但是,如果直接把这些话翻译成英语“I want to have a hamburger.”或“I want to have a coffee.”老外们就会觉得这样说话很没有礼貌,当然他们也不会直接告诉你。而在西方国家,老外们一般会说:“Could I have a hamburger, please?”或“Can I have a coffee, please?”在这里又提到一个需要注意的问题,“打工的孩子最容易不注意的是see you.See u应该是客人说的,隐含了他觉得不错他会再来的意思,而店员最好用低调一点的bye,用see u太强势了。另外人家说谢谢,你也不用说you are welcome, 这实在是太正式了,让人觉得有点帮了人家然后把自己很当回事的味道。所以回答cheers或no worries就好,如果仅仅是对方爱说谢而已,你甚至可以不回应他的谢,直接说你要说的事情就好,如果是买了他的东西他谢你,更不能说you r welcome了,最好也谢对方。
    再比如,中国人在拒绝别人邀请的午宴或晚宴时,会说:“抱歉,我不能去,我还有别的安排。”翻译成英文就是“Sorry,I can’t. I have another appointment.”如果这样说,那也许别人第二次不会再邀请你了。老外们一般会这样说:“That is a good idea! I would like to join in but I have another appointment today.”

  • 我们可以从中总结一些“有礼貌”的技巧:

    1、西方人(主要指有一定修养的欧美人)在与他人交流时,比较多地使用情态动词:can、could、may、might、would等等;情态动词(Model Verbs)又称为情态助动词(Model Auxil-iaries),表示说话人的语气,可表达建议、要求、可能和意愿等,使得说话的语气比较有礼貌。
    2、比较多地使用虚拟语气,比如would (had) rather、would (had) sooner、would (just) as soon等等,或者在陈述句中使用过去式表示虚拟语气,或者使用if等引导的从句表示“可能性”。这样说话可以使人感觉表达者是在考虑达到最佳的结果或方式,尽量避免不好的结果或方式,或者推测可能出现的问题,并找出可能解决的办法。
    3、往往在句尾加please,而不是在句首加please。当please用在句首的时候,语气听起来就比较强,像命令。比如请求别人做某事的时候,我们中国人会说“请在周一前给我回复。谢谢。”但是如果你直接用英语说“Please reply to me by Monday. Thank you.”听者会觉得你是在命令他,一点礼貌也没有。而如果这样说:“Could you please reply to me by Monday? Thank you.”就显得有礼貌了。
    4、在陈述句的表达中可能会显得生硬、没礼貌时,尽量使用疑问句、否定句或从句,尽量避免自己的主观判断或武断发生,并以积极的、建议的、比较的、人性的语气,代替消极的、命令的、直接的、武断的语气。
    5、说话要以他人为中心,以肯定他人、赞同他人为前提,让自己显得谦卑、渺小。说完之后,还要附带一句“Thank you”或“Thanks”。其实,这种礼貌的表达方式是来自古老的中国。这是东西方文化的共同点,也是为人处世的基本原则。了解英语中礼貌的表达方式,尽量让自己的英语表达更有礼貌,融入社会。

  • 说到这里,我们索性再八一八英国人那些弱爆了的思维吧。

    当英国人夸你“很不错”时,当英国人说“顺便说一句”时,当英国人说“基本同意”时,他们想表达的实际含义是什么呢?而你又是如何理解的呢?以下是作者总结出来的一些经验,您需要千万不要误会他们的意思,闹出笑话哦!
    When the British say “I hear what you say. ” They mean “I disagree and do not want to discuss it further.” But what others understand is “He accepts my point of view.”
    当英国人说“我听到你所说的了”时,他们的意思是“我不同意也不想就其做进一步讨论”,而其他人却理解成了“他接受了我的观点”。
    When the British say “With the greatest respect… ” They mean “I think you are an idiot.” But what others understand is “He is listening to me.”
    当英国人说“出于最大的尊重…”时,他们的意思是“我觉得你太二了”,而其他人却理解成了“他正听我说话呢”。
    When the British say “That’s not bad. ” They mean “That’s good.” But what others understand is “That’s poor.”
    当英国人说“不算太糟”时,他们的意思是“太好了”,而其他人却理解成了“太差了”。
    When the British say “That is a very brave proposal. ” They mean “You are insane.” But what others understand is “He thinks I have courage.”
    当英国人说“那真是一个非常有勇气的提议”时,他们的意思是“你真是疯了”,而其他人却理解成了“他觉得我很有胆识”。
    When the British say “Quite good. ” They mean “A bit disappointing.” But what others understand is “Quite good.”
    当英国人说“很不错哦”时,他们的意思是“有点小失望”,而其他人却理解成了“真心不错”。
    When the British say “I would suggest… ” They mean “Do it or be prepared to justify yourself.” But what others understand is “Think about the idea, but do what you like.”
    当英国人说“我想建议的是……”时,他们的意思是“去实践或者做好准备来证明你自己”,而其他人却理解成了“考虑一下他的点子,但还是做我想做的”。
    When the British say “Oh, incidentally / by the way… ” They mean “The primary purpose of our discussion is…” But what others understand is “That is not very important.”
    当英国人说“顺便说一句……”时,他们的意思是“我们讨论的最根本目的是……”,而其他人却理解成了“接下来的内容并不是非常重要”。
    When the British say “I was a bit disappointed that… ” They mean “I am annoyed that…” But what others understand is “It doesn’t really matter.”
    当英国人说“我对……有点小失望”时,他们的意思是“我对……很恼火”,而其他人却理解成了“无伤大雅”。
    When the British say “Very interesting. ” They mean “That is clearly nonsense.” But what others understand is “They are impressed.”
    当英国人说“非常有意思啊”时,他们的意思是“那明显是瞎扯淡”,而其他人却理解成了“那真是让人印象深刻”。
    When the British say “I’ll bear it in mind. ” They mean “I’ve forgotten it already.” But what others understand is “They will probably do it.”
    当英国人说“我将刻在脑子里”时,他们的意思是“我已经不记得了”,而其他人却理解成了“他们大概会去做的吧”。
    When the British say “I’m sure it’s my fault. ” They mean “It’s your fault.” But what others understand is “Why do they think it was their fault?”
    当英国人说“我确定是我错了”时,他们的意思是“那其实是你的错”,而其他人却理解成了“为什么他们会觉得是他们的错呢?”
    When the British say “You must come for dinner. ” They mean “It’s not an invitation, I’m just being polite.” But what others understand is “I will get an invitation soon.”
    当英国人说“你一定要来赴宴”时,他们的意思是“那绝不是什么邀请,我只不过想礼貌一些”,而其他人却理解成了“我马上就会收到一个邀请了”。
    When the British say “I almost agree. ” They mean “I don’t agree at all.” But what others understand is “He’s not far from agreement.”
    当英国人说“我基本同意”时,他们的意思是“我一点儿都不同意”,而其他人却理解成了“他真的是非常非常同意啊”。
    When the British say “I only have a few minor comments. ” They mean “Please re-write completely.” But what others understand is “He has found a few typos.”
    当英国人说“我只是有一点儿建议”时,他们的意思是“请从头到尾地重写一份吧”,而其他人却理解成了“他只不过发现了一些言语错误”。
    When the British say “Could we consider some other options?” They mean “I don’t like your idea.” But what others understand is “They have not yet decided.”
    当英国人说“我们可以再考虑一些其他的选择吗?”时,他们的意思是“我着实不喜欢你的点子”,而其他人却理解成了“他们还没有决定下来吧”。
    PS:这些问题不看还真不了解啊,原来东西方的文化差异这么大,学英语的童鞋们可要认真的专研咯,靠以上这么一说还真不够学呢,还是多看点英剧电影吧!那样你能学到更多地道的礼貌英语!

金金金金金金金金金

linux c functions大全

发表于 2017-03-09

linux c function

ispunct(测试字符是否为标点符号或特殊符号)
相关函数
isspace,isdigit,isalpha
表头文件

1
#include<ctype.h>

定义函数

1
int ispunct(int c)

函数说明
检查参数c是否为标点符号或特殊符号。返回TRUE也就是代表参数c为非空格、非数字和非英文字母。
返回值
v若参数c为标点符号或特殊符号,则返回TRUE,否则返回NULL(0)。
附加说明
此为宏定义,非真正函数。
范例
/列出字符串str中的标点符号或特殊符号/

1
2
3
4
5
6
7
8
#include <ctype.h>
main()
{
char str[]="123c@ #FDsP[e?";
int i;
for(i=0;str[i]!=0;i++)
if(ispunct(str[i])) printf("%c\n",str[i]);
}

执行
v
@#[?

金金金金金金金金金

二手房交哪些税

发表于 2017-03-07

log

123
金金金金金金金金金

金金金金金金金金金

郭鑫的小站

25 日志
© 2019 金金金金金金金金金