第三章 数组和字符串

来源:互联网 发布:python 去除列表重复 编辑:程序博客网 时间:2024/06/09 22:38

3.1 数组
3.2 字符数组

3-1 逆序输出
读入一些数据,逆序输出在一行(整数不超过100个)

#include<stdio.h>#define N 105 // 注意点①int num[N]; // 存储量较大的建议定义在外面int main(){    int x, i=0;    while(~scanf("%d", &x)){        num[i++] = x;    }    int j = i-1; // 注意点②    for(; j>=0; j--){        printf("%d", num[j]);        if(j){            printf(" ");        } else {            printf("\n");        }    }    return 0;}

memcpy():
①头文件:string.h
②数组a复制k个元素到数组b:

memcpy(b, a, sizeof(int)*k)

③将数组a全部复制到数组b:

memcpy(b, a, sizeof(a))

3-2 开灯问题
有n盏灯,编号为1-n,第一个人把灯全打开,第二个人把编号为2的倍数的灯关掉,第三个人把编号为3的倍数的灯(关掉的打开,打开的关掉)·····一共k个人(k<=n<=1000),输出最后开着的灯的编号

#include<stdio.h>#include<string.h>#define N 1010int light[N];int main(){    int n, k;    scanf("%d%d", &n, &k);    memset(light, 0, sizeof(light)); // 初始状态设置为关灯(0)     int i, j;    for(i=1; i<=k; i++){        for(j=1; j<=n; j++){            if(j%i == 0){                light[j] = !light[j]; // 入手点             }        }    }    int first = 1; // 设置输出格式     for(i=1; i<=n; i++){        if(light[i]){            if(first){                first = 0;            } else {                printf(" ");            }            printf("%d", i);        }     }    return 0;}

用到:

memset(str, num, sizeof(str)) // str:数组, num:初始化的数

3-3 蛇形填数
这里写图片描述

#include<stdio.h>#include<string.h>#define N 20int n[N][N];int main(){    memset(n, 0, sizeof(n));    int num;    scanf("%d", &num);    int max = 1;    n[0][num-1] = max;    int x = 0, y = num-1;    while(max < num*num){        while(x+1<num && !n[x+1][y]){            n[++x][y] = ++max;        } // 下        while(y-1>=0 && !n[x][y-1]){            n[x][--y] = ++max;        } // 左        while(x-1>=0 && !n[x-1][y]){            n[--x][y] = ++max;        } // 上        while(y+1<num && !n[x][y+1]){            n[x][++y] = ++max;        } // 右    }    for(x=0; x<num; x++){        for(y=0; y<num; y++){            printf("%3d", n[x][y]);        }        printf("\n");    }    return 0;}

这里:

(1)通过寻找填数规律:顺时针一圈一圈
(2)先全部初始化为0,让右上角数为1,往下递增,左转是当它越界前(再一次往下递增时,通过判断下一位数是否已经被初始化为非零数),依次····
(3)%3d很好的找出了输出的规律

3-4 竖式问题
给出一个数字集合,找出满足abc*de的情况,也就是说,三位数乘以两位数,手动计算,计算过程除了进位,数字应该在数字集合中

#include<stdio.h>#include<string.h>int main(){    int count = 0; // 记录满足情况的种类    char s[20], buf[99]; // buf缓冲数组    scanf("%s", s);    int abc, de;    for(abc=111; abc<=999; abc++){        for(de=11; de<=99; de++){            int x = abc * (de%10);            int y = abc * (de/10);            int z = abc * de;            sprintf(buf, "%d%d%d%d%d", abc, de, x, y, z);            int own = 1;            for(int i = 0; i<strlen(buf); i++){                if(strchr(s, buf[i]) == NULL){                    own = 0;                }            }            if(own){                printf("<%d>\n", ++count);                printf("..%d\nX..%d\n-----\n.%d\n%d.\n-----\n%5d\n", abc, de, x, y, z);            }        }    }    return 0;}

这里写图片描述

(1)字符类型char:存储的是ASCII码
(2)scanf读入不含空格、tab、回车符的字符串
(3)strchr的作用:一个字符串中查找1单个字符串
(4)printf:输出到屏幕,fprintf:输出到文件,fprintf:输出到字符串
(5)字符串的本质是:数组,赋值:strcpy(a, b),比较:strcmp(a,b),连接:strcat(a, b)

3-5 TeX中的引号
输出一段文章的Tex的格式(区分左右引号)

#include<stdio.h>int main(){    int character, q=1;    while((character = getchar()) !=EOF){        if(character == '"'){            printf("%s", q? "“" : "“");            q = !q;        } else {            printf("%c", character);        }    }    return 0;}

(1)fgetc
(2)fgets(buf, maxn, fin) :存储限定maxn-1,maxn用来存储\0,gets(s)没有限制,存在缓存区溢出漏洞

3-6 WERTYU
键入一组字符串,每一位都是在输入时,输入了该位在键盘的下一个字符,输出真正想要键入的字符串

#include<stdio.h>int main(){    char s[] = "`1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./"; // 常量数组    char c;    while((c=getchar())!=EOF){        for(int i=1;s[i] && s[i]!=c; i++){            if(s[i]){                putchar(s[i-1]);            } else {                putchar(c);            }        }    }    return 0;}

巧妙的运用了:常量数组
(1)简化代码
(2)无需计算大小,编译器会计算

3-7 回文词
(1)回文串(abba)
(2)镜像串 (2S)
这里写图片描述

A-A E-3 H-H I-I L-J M-M O-O S-2 T-T U-U V-V W-W X-X Y-Y Z-5 1-1 2-S 8-8

一般没有空白字符,所以选择scanf

#include<stdio.h>#include<string.h>#include<ctype.h>// 常量数组存储const char *rev = "A   3  HIL JM O   2TUVWXY51SE Z  8 ";const char *msg[] = {"not a palidrome", "a regular palindrome", "a mirrored string", "a mirrored palindrome"};char r(char ch){    if(isalpha(ch)){        return rev[ch - 'A'];    }    return rev[ch-'0'+25];} int main(){    char s[30];    while(scanf("%s", s) == 1){        int len = strlen(s);        int p = 1, m =1;        for(int i = 0; i<(len+1)/2; i++){            if(s[i] != s[len-1-i]){ // 非回文串                 p = 0;            }            if(r(s[i]) != s[len-1-i]){ // 非镜像串                 m = 0;            }        }        printf("%s -- is %s.\n\n", s, msg[m*2+p]);    }    return 0;}

头文件ctype.h定义的
(1)isalpha、isdigit、isprint可以用来判断字符的属性
(2)toupper、tolower用来转换大小

3-8 猜数字游戏的提示
输入每个测试项的个数,然后再输入测试项及对比项,统计对比项有多少项与测试项相同,统计在两个项都出现过的但位置对不上的数字数
两次统计有点重复存在,就是说,统计一下在两个项中都出现的数字的个数

#include<stdio.h>#define N 1010int main(){    int n, kcase = 0;    while(scanf("%d", &n) == 1 && n){        int a[N], i=0;        for(; i<n; i++){            scanf("%d", &a[i]);        }        int b[N];        for( ; ; ){            int kseatSame = 0, kb = 0;             for(i=0; i<n; i++){                scanf("%d", &b[i]);                if(a[i] == b[i]){                    kseatSame++;                }            }            if(b[0] = 0){ // 由题意得:正常情况下,测试项不含0 (个人刚开始没有考虑到这个,感觉题目也没有说明)                break;            }            int d;            for(d=1; d<=9; d++){                int c1 = 0, c2 = 0;                for(i=0; i<n; i++){                    if(a[i] == d){                        c1++;                    }                    if(b[i] == d){                        c2++;                    }                }                if(c1 < c2){                    kb += c1;                } else {                    kb += c2;                }            }             printf("Game %d:\n", ++kcase);            printf("    (%d,%d)\n", kseatSame, kb - kseatSame);        }    } } 

3-9 生成元

对于生成元,解释是:当y满足:y = x + x各个数位上的数 时,x称作y的生成元
下面这个题目要求对于输入的整数,输出它的最小生成元,无解时输出0

#include<stdio.h>#include<string.h>#define N 100000int num[N];int main(){    memset(num, 0, sizeof(num));    int i = 1;    // 将每个数当作 生成元,存储到对应的位置,制作成一张表     for(; i<N; i++){        int key = i, digit = i; // digit:生成元, key:生成元对应的数值         while(digit){            key += digit%10;            digit /= 10;        }        // 为了保证存储的是最小生成元, 得判断要存储的位置是否已经有生成元了 或是 生成元是否比较大         if(num[key] || num[key]>i){            num[key] = i;        }     }    int testTime, n;    scanf("%d", &testTime);    while(testTime--){ // 利用上面已经存储好的数         scanf("%d", &n);        printf("%d\n", num[n]);    }    return 0;}

这是一个挺好的方法,先制表,再查表

3-10 环状序列

输入一个长度为n的环状DNA串(只含ACGT四个字母),对于这样的字符串,有多种表示方式(任意从一个端点顺时针得到),现在求输入的字符串(环状)的最小表示
【最小表示】:字典序最小的表示法
【字典序】:字符串在字典中的序列
①对于两个字符串,从第一个字符开始比较,当某个位置的字符不同,该处字符较小的字符串的字典序较小(abc<bcd)
②没有不同的字符时,较短的字符串的字典序较小(hi<his)
③1,2,4,7 <1,2,5

#include<stdio.h>#include<string.h>#define N 105int less(const char *s, int p, int q){ // 环状串s的p表示法是否比q表示法的字典小     int n = strlen(s);    int i = 0;    for(; i<n; i++){        if(s[(p+i)%n] != s[(q+i)%n]){            return s[(p+i)%n] < s[(q+i)%n];        }       }    return 0;}int main(){    int T;    char s[N];    scanf("%d", &T);    while(T--){        scanf("%s", s);        int num = 0;        int n = strlen(s);        int i;        for(i=1; i<n; i++){            if(less(s, i, num)){                num = i;            }        }        for(i=0; i<n; i++){            putchar(s[(i+num)%n]);        }        putchar('\n');    }    return 0;   } 

3-10
1.用ASCII码表示字符
2.进制转换和移位运算符

(1<<8)-1 // 等价于2^8-1,这里的括号不能缺少,(优先级)

3.补码表示法
在大多数计算机内部,整数采用补码表示法

-n == 2^32-n

-1:4294967295

0 0
原创粉丝点击