若干C的练习题 (不定期更新)

整数转二进制

用递归,思想就是找下这个整数和2的几次方最接近,而且这个2的几次方还不能大于整数,找到后,减去再重复,知道剩下1或者0为止。看代码吧

char *zhuanerjinzhi(int n, char *a, int ci){
	 //要是n被减的到负数了,那就此为止吧
    if(n <= 0) return a;
    //记一下这个是2的第几次方
    int j = 0;
    //这个就是2
    int z = 2;
    //如果n-z大于等于0,那么n里面还有东西,还得加大z的值
    while ((n-z) >= 0) {
    	 //z往大一走就是两倍的走
        z*=2;
        //顺便记下这个z,现在是j+1次方
        j++;
    }
    //OK出来了,说明已经碰见比n还要大的z了,那就说明n应该就在2的j次方
    //赋值
    a[j] = '1';
    //要是第一次的话那就紧接着在后面家上结束符,要不输出不好看
    if(ci == 0){
        a[++j] = '\0';
    }
    //如果减去之后得到剩下的数等于一的话,那就是2的0次方赋值为一
    if(n-z/2 == 1){
        a[0] = '1';
    }else{
   	 //不是的话就进入递归就好了
        zhuanerjinzhi(n - z/2, a, ++ci);
    }
    //最后返回a
    return a;
}
//逆转
char nizhi(char* a){
    int Strlen = strlen(a);
    char temp;
    for (int i = 0; i < Strlen/2; i++) {
        temp = *(a + Strlen - i - 1);
        *(a + Strlen - i - 1) = *(a+i);
        *(a+i) = temp;
    }
}
void main (){
	//最大到2的20次方,肯定超不过就行	
	 char b[20] = {'0','0','0','0','0','0','0','0','0','0','0','0','0',
	 '0','0','0','0','0','0','0'};
    char *a = b;
    //给个10
    a = zhuanerjinzhi(10, a, 0);
    nizhi(a);
    printf("%s\n" ,a);
}

用筛选法求100之内的素数

	int a[100] = {};
    int b = 2;
    for (int i = 0; i < 100; ++i) {
        a[i] = i;
    }
    a[1] = 0;
    //到此为止有了一个初步的数组
    //下面开始除以除数,除数最大就是sqrt(100)
    while (b < sqrt(100)){
    	//遍历数组中的有效值
        for (int i = 0; i < 100; ++i) {
        	//数组中的数字不为零,而且可以整除除数且不等于除数
            if(a[i] != 0 && a[i] % b ==0 && a[i] != b)
            {
            	//置零
                a[i] = 0;
            }
        }
        //除数累加
        b++;
    }
	//输出
    for (int i = 0; i < 100; ++i) {
        if(a[i] != 0)
        {
            printf("%5d", a[i]);
        }
    }
    2    3    5    7   11   13   17   19   23   29   31   37   
    41   43   47   53   59   61   67   71   73   79   83   89   
    97

判断素数

#define OK 1
#define ERR 0

typedef int Status;

Status isSu(int n){
    int i;
    for (i = 2; i < n; i++) {
        if(n%i == 0){
            return ERR;
        }
    }
    return OK;
}

水仙花数

//1-20000的水仙花数
void outputShuixianhua(int s, int e){
    int i;
    int shuixianhua(int);
    for (i = s; i <= e; i++) {
        if(i == shuixianhua(i)){
            printf("%6d", i);
        }
    }
}
//求出水仙花数
int shuixianhua(int n){
    int weishu(int);
    int w = weishu(n);
    int i, k, j, sum = 0;
    for (i = 0; i < w; i++) {
        k = 1;
        for (j = 0; j < w; j++) {
            k *= n%10;
        }
        n = n/10;
        sum += k;
    }
    return sum;
}
//求该数有几位
int weishu(int n){
    int i = 0;
    while (n) {
        n = n/10;
        i++;
    }
    return i;
}

输出完数

void outputFineDig(int s, int e){
    int i;
    int gongyinshuSum(int);
    for (i = s; i <= e; i++) {
        if(i == gongyinshuSum(i)){
            printf("%6d", i);
        }
    }
}
//公因数之和
int gongyinshuSum(int n){
    int sum = 0, i;
    for (i = 1; i < n; i++) {
        if(n%i==0){
            sum+=i;
        }
    }
    return sum;
}

两数最大公约数以及最小公倍数

//最大公约数
int zuidagongyue(int n, int m){
    int k = 0;
    //初始顺序
    if(n > m){
        k = n;
        n = m;
        m = k;
    }
    //辗转横跳逼出结果
    while (m%n != 0) {
        k = m;
        m = n;
        n = k%n;
    }
    return n;
}
//最小公倍数
int zuixiaoGongbei(int n, int m){
    return m*n/zuidagongyue(n, m);
}

斐波那契数列

//递归
int feibolaqie(int n){
    if(n == 1){
        return 1;
    }
    if(n == 2){
        return 1;
    }
    return feibolaqie(n-1)+feibolaqie(n-2);
}

小球10m落下,每次回弹高度一半,静止后的距离

//也就是求极限
float ziyouxialuo(float n){
    float sum = 0,temp = n;
    n = 2 * n;
    while (n != 0) {
        sum += n;
        n = n/2;
    }
    return sum - temp;
}

两队比赛,求名单 a不和d, c不和d , f

    char A[3] = {'a', 'b', 'c'};
    char B[3] = {'d', 'e', 'f'};
    
    int i, j;
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            if((*(A+i) == 'a' && *(B+j)=='d') ||( A[i] == 'c' && (B[j] == 'd' || B[j] == 'f')))
                continue;
            printf("%c vs %c\n", A[i], B[j]);
        }
    }

三字符求最大

//三字符求最大
char * zuidazifu(char *a, char *b, char *c, char *t){
    //strcmp
    //如果返回值 < 0,则表示 str1 小于 str2。
    //如果返回值 > 0,则表示 str2 小于 str1。
    //如果返回值 = 0,则表示 str1 等于 str2。
    strcpy(t, a);
    if (strcmp(b, t) > 0) {
        strcpy(t, b);
    }
    if(strcmp(c, t) > 0)
    {
        strcpy(t, c);
    }
    return t;
}

统计字符

 //三行,分别统计每行大小写空格数字空格及其他
    char sum[100] = "aS #1w\nasdas\n234Sx\n";
    int up,low,dig,spac,other,hang,index;
    hang = 1;
    up = low = dig = spac = other = index = 0;
    while (*(sum+index) != '\0') {
        printf("%c", *(sum+index));
        if (*(sum+index) != '\n') {
            if(*(sum+index) == ' ')
                spac++;
            else if(*(sum+index) >= 'A' && *(sum+index) <= 'Z')
                up++;
            else if (*(sum+index) >= 'a' && *(sum+index) <= 'z')
                low++;
            else if (*(sum+index) >= '0' && *(sum+index) <= '9')
                dig++;
            else
                other++;
        }else{
            printf("第%d行 数字:%d 大写:%d 小写:%d 空格:%d 其他:%d", hang, dig, up, low, spac, other);
            printf("\n");
            up = low = dig = spac = other = 0;
            hang++;
        }
        index++;
    }

鞍点,行最大,列最小

//二维数组鞍点 行最大列最小
int andian(int p[][3]){
    int i, j;
    int mincol,maxrow,row = 0,col = 0,biaoji = 0;
    maxrow = 0;
    mincol = INT32_MAX;
    
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            printf("%3d ", p[i][j]);
        }
        printf("\n");
    }
    
    for (i = 0; i < 3; i++) {
        //找到每行最大的坐标出来
        for (j = 0; j < 3; j++) {
            //在具体的一行找到此行最大值
            //并记录最大值的两个下标
            if(p[i][j] > maxrow){
                maxrow = p[i][j];
                col = j;
                biaoji = i;
            }
        }
        //在找到行最大值的的列中,看看它是不是列里面最小的值
        for (j = 0; j < 3; j++) {
            //列下标不动,只需要动前面行下标即可
            //找到最小的也记录下它的坐标
            if(p[j][col] <= mincol){
                mincol = p[j][col];
                row = j;
            }
        }
        //要是行的坐标一样大,看来是同一个值,就意味着找到了
        if(biaoji == row){
            printf("%d\n", p[row][col]);
            return p[row][col];
        }
        //每次找完都要重置最大最小值
        mincol = INT32_MAX;
        maxrow = 0;
    }
    
    //-1啥也没找到,当然返回值待议
    return -1;
}

第i个字母变成第(26-i+1)个字母

//电文加密,第i个变成第(26-i+1)个
    char sum[100] = "abcdefghijklmnopqistuvwxyz\nABCDEFGHIJKLMNOPQISTUVWXYZ";
    char *p = sum;
    int index = 0;
    //循环的时候也可以用 p++; 代替index
    while (*(p+index) != '\0') {
        printf("%c", *(p+index));
        //小写字母
        //先看看该字母是第几位与第一位‘a’做差加一
        //第2位的话那就对应倒数第2个也就是第25个
        //从‘a’开始算那就是后面的25-1个
        if(*(p+index) <= 'z' && *(p+index) >= 'a'){
            *(p+index) = 'a'+26 - (*(p+index)-'a' + 1);
        }
        //大写字母
        if(*(p+index) <= 'Z' && *(p+index) >= 'A'){
            *(p+index) = 'A'+26 - (*(p+index)-'A' + 1);
        }
        index++;
    }
    printf("\n");
    index = 0;
    while (*(p+index) != '\0') {
        printf("%c", *(p+index));
        index++;
    }
    printf("\n");

两字符串生接在一起

    char a[40] = "asdasd";
    char b[20] = "iuiwer";
    
    char *p1 = a;
    char *p2 = b;
    //把p1指向a的末尾的'\0'
    while (*p1 != '\0') {
        p1++;
    }
    //把p2的最开始的字符送给p1末尾的'\0'
    while (*p2 != '\0') {
        *p1++ = *p2++;
    }
    //最后p1指向了整个结尾,就是缺了个'\0',补上
    *p1 = '\0';
    
    printf("%s", a);

两字符串复制起来

 //字符串复制
    char a[100];
    char b[100];
    char *p1 = a;
    char *p2 = b;
    gets(a);
    while ((*p2++ = *p1++) != '\0');
    printf("%s", b);

将数组里的负数排在最靠前

//将负数排在最前面
    int a[10] = {2,3,123,232,1,-3,-1,-02,-10,0};
    int i = 0;
    int j = 9;
    int temp;
    //两个没有见面就一直找下去
    while (j > i) {
        //此时从当前位置往后找到第一个大于零的数字
        while (a[i] < 0 && i <= 9) {
            i++;
        }
        //从当前位置往前找第一个小于零的数字
        while (a[j] > 0 && j >= 0) {
            j--;
        }
        //然后两者互换位置
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }
    for (temp = 0; temp < 10; temp++) {
        printf("%d ", a[temp]);
    }

两数组比较,统计对应元素比大小的个数

    //两数组比较,统计对应元素比大小的个数
    int a[10] = {1,23,3,33,34,9,2,34,54,4};
    int b[10] = {12,45,23,75,34,23,46,34,1,56};
    int i, comp1 = 0,comp2 = 0;
    for (i = 0; i < 10; i++) {
        if(a[i]>b[i])
        {
            comp1++;
        }
        else if (a[i]<b[i])
        {
            comp2++;
        }
        printf("%d,%d\n",a[i],b[i]);
    }
    printf("%d %d", comp1, comp2);

输入字符串,并反序

//输入字符串,并反序
void reverseStr(char * a){

    int i, Strlen = (int)strlen(a);
    char temp = ' ';
    
    for (i = 0; i < Strlen/2; i++) {
        temp = *(a + Strlen - i - 1);
        *(a + Strlen - i - 1) = *(a+i);
        *(a+i) = temp;
    }   
    
}

求和 a+aa+aaa+aaaa+aaaaa+aaaaaa+…+a…a

//求和
int sum(int a, int n){
    int sum = 0, i = 1;
    //个位相加,十位相加,百位相加
    while (n) {
        sum += a*i*n;
        i *= 10;
        n--;
    } 
    return sum;
}

static用法

//static变量的用法
int process(int a, int b){
	//就跟单例模式一样,初始化只走一次
    static int i = 0;
    //在函数中,i是一个静态的局部变量,但是随着外面对函数的调用,值是不会被抹去的
    i++;
    if(i == 1)
        return a>b?a:b;
    if(i == 2)
        return a<b?a:b;
    if(i == 3)
        return a+b;
    return i;
}

一年中的第几天

//第几天
int Howmanydays(int y, int m, int d){
    int days = 0, i;
    int M[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    //判断闰年加一天
    if( y%400 == 0 || ( y%100 != 0 && y%4 == 0 ) ){
        M[2]+=1;
    }
    //将前面的整月天数算上
    for (i = 0; i < m; i++) {
        days+=M[i];
    }
    //再加上这个月的日子
    days+=d;
    //就酱
    return days;
}

字符串长度

 char s[100];
 gets(s);
 char *p1 = s;
 //循环完毕后p1指向了'\0',最后一个的后一个
 while (*++p1 != '\0');
 //s指向了第一个,他们中间相差恰巧就是char的长度
 printf("%ld",p1-s);

数组往后移动n位,循环移动

//往后排
    int arra[10] = {1,2,3,4,5,6,7,8,9,10};
    int i, j, m, temp;
    scanf("%d", &m);
    //每次移动一位,移动m次
    for (i = 0; i < m; i++) {
        temp = arra[9];
        for (j = 8; j >= 0; j--) {
            arra[j+1] = arra[j];
        }
        arra[0] = temp;
    }
    //输出
    for (i = 0; i < 10; i++) {
        printf("%3d", arra[i]);
    }

截取字符串从m位,包含m位的后面的全部

 //截取字符串从m位以后的全部
    char a[100] = "abcdefjhijklmn";
    char b[100];
    char *p1, *p2;
    p1 = a;
    p2 = b;
    int m, len = (int)strlen(a);
    scanf("%d", &m);
    if(m > len && m < 0){
        printf("Noooo!");
    }else
    {	
    	//直接找到第m位的字符,包含第m个字符,后面全都要
        while (*(p1+m-1) != '\0') {
            *p2++ = *(p1+m-1);
            p1++;
        }
        *p2 = '\0';
    }
    printf("%s", b);

分数列前20项1/2,2/3,3/5,5/8…之和

//分数列前20项1/2,2/3,3/5,5/8.....
    int i;
    float sum = 0, fenzi, fenmu, temp;
    fenzi = 1;
    fenmu = 2;
    //迭代20次
    for (i = 0; i < 20; i++) {
        //加加加加
        sum += fenzi/fenmu;
        //产出下一个分子分母
        temp = fenzi;
        fenzi = fenmu;
        fenmu += temp;
    }
    //输出咯
    printf("%.2f", sum);

十行杨辉三角形

//杨辉三角形,就是个二维数组
    int i, j;
    int yang[10][10] = {{1,},{}};
    for (i = 0; i < 10; i++) {
    	//第i行就输出i个数字
        for (j = 0; j <= i; j++) {
            printf("%d ", yang[i][j]);
            //趁这个机会就可以填存下一个数组的前i个数
            //有点奇怪的是yang[0][-1]我的编译器没报错并且还等于0
            //应该是个野值才对,严格的写的话,这里得判断一下
            if(i != 9)
                yang[i+1][j] = yang[i][j]+yang[i][j-1];
        }
        //下一行比上一行多一个,那就加上
        if(i != 9)
            yang[i+1][j] = yang[i][j]+yang[i][j-1];
        printf("\n");
    }
/*
1 
1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
1 5 10 10 5 1 
1 6 15 20 15 6 1 
1 7 21 35 35 21 7 1 
1 8 28 56 70 56 28 8 1 
1 9 36 84 126 126 84 36 9 1 
*/

递归法求n阶勒让德多项式的值

double duoxiang(int n, double x){
    if(n == 0)
        return 1;
    if(n == 1)
        return x;
    else
        return ((2*(n-1)+1)*x*duoxiang(n-1,x) - (n-1)*duoxiang(n-2, x))/n;
}

字符串中的偶数下标提出来

	char str1[100] = "acacacacacadasasawafasafas";
	char str2[100];
	//初始下表为1
    int index = 1;
    char *p1, *p2;
    p1 = str1;
    p2 = str2;
    //边走边赋值
    while (*(p1+index) != '\0' || *(p1+index-1) != '\0') {
        *p2++ = *(p1 + index);
        index += 2;//一次跳两个
    }
    printf("%s", str2);

5个字符串排排序

 	char str[5][100];
    char temp[100];
    
    printf("输入第1个字符串");
    gets(str[0]);
    printf("输入第2个字符串");
    gets(str[1]);
    printf("输入第3个字符串");
    gets(str[2]);
    printf("输入第4个字符串");
    gets(str[3]);
    printf("输入第5个字符串");
    gets(str[4]);
    //遍历快排
    int i, j, tempindex;
    for (i = 0; i < 5; i++) {
        tempindex = i;
        strcpy(temp, str[i]);
        //从后面的几个元素挑出来最小的
        for (j = i; j < 5; j++) {
            if(strcmp(temp, str[j]) > 0)
            {
                strcpy(temp, str[j]);
                tempindex = j;
            }
        }
        //标记的换一下
        if (tempindex != i) {
            strcpy(temp, str[i]);
            strcpy(str[i], str[tempindex]);
            strcpy(str[tempindex], temp);
        }
    }
    //输出一下
    for (i = 0; i < 5; i++) {
        printf("%s\n", str[i]);
    }

结构体相关操作

//八个同学
    int i, j, temp;
    CoursesScore tempCourseSoure;
    CouersesScoreRecords courseScoreRecors = {{98,90,86,"王小明"},{76,87,90,"刘晓华"},{75,69,86,"张晓霞"},{79,86,90,"李晓玲"},
        {92,78,75,"赵小安"},{87,83,86,"卢小荣"},{76,72,86,"周晓鸥"},{91,84,86,"戴小伟"}
    };
    float average[8];
    int sum[8];
    int classsum[3];
    //输入也行的
    for (i = 0; i < 8; i++) {
//        printf("姓名:");
//        gets(courseScoreRecors[i].StudentName);
//        printf("语文:");
//        scanf("%d", &courseScoreRecors[i].ChineseScore);
//        printf("数学:");
//        scanf("%d", &courseScoreRecors[i].MathScore);
//        printf("英语:");
//        scanf("%d", &courseScoreRecors[i].EnglishScore);
        
        sum[i] = courseScoreRecors[i].ChineseScore + courseScoreRecors[i].MathScore + courseScoreRecors[i].EnglishScore;
        average[i] = sum[i]/3.0;
        
        classsum[0] += courseScoreRecors[i].ChineseScore;
        classsum[1] += courseScoreRecors[i].MathScore;
        classsum[2] += courseScoreRecors[i].EnglishScore;
    }
    for (i = 0; i < 8; i++) {
        printf("姓名:%s,语文:%d,数学:%d,英语:%d,平均分:%.2f,总分:%d\n", courseScoreRecors[i].StudentName, courseScoreRecors[i].ChineseScore, courseScoreRecors[i].MathScore, courseScoreRecors[i].EnglishScore,average[i],sum[i]);
    }
    printf("语文总分,数学总分,英语总分");
    for (i = 0; i < 3; i++) {
        printf(", %d",classsum[i]);
    }
    printf("\n");
    //冒泡泡
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 7 - i; j++) {
            if(sum[j] < sum[j+1]){
                //在总分里排排序
                temp = sum[j];
                sum[j] = sum[j+1];
                sum[j+1] = temp;
                //相应的在结构体里排排序
                tempCourseSoure = courseScoreRecors[j];
                courseScoreRecors[j] = courseScoreRecors[j+1];
                courseScoreRecors[j+1] = tempCourseSoure;
            }
        }
    }
    //输入这个排名呢
    for (i = 0; i < 8; i++) {
        printf("姓名:%s,语文:%d,数学:%d,英语:%d,总分:%d\n", courseScoreRecors[i].StudentName, courseScoreRecors[i].ChineseScore,  courseScoreRecors[i].MathScore, courseScoreRecors[i].EnglishScore,sum[i]);
    }

n个人围成圈,1 2 3循环数,数到3就出局,下面的人继续,直到最后一个

//n个人,3个3个走,可以用循环列表做,那样会特别简单,我用了数组试了一下
    int n, i, k = 1, temp, flag = 1;
    scanf("%d", &n);
    temp = n;
    int arra[n];
    //赋值,给它弄成自然数
    for (i = 0; i < n; i++) {
        arra[i] = i+1;
    }
    //打印一下
    for (i = 0; i < n; i++) {
        printf("%3d", arra[i]);
    }
    printf("\n");
    //处理开始,从第一号人开始
    i = 0; 
    //理论上循环所以永远为真,
    while (flag) {
    	//这里判断数组里面是不是0,是0就说面已经出去了,不是的话则还是游戏中呢
        if(arra[i] != 0){
        	//是不是输了三次,特别注意,第一个人应该数的数字是1,k的初始值就为1
            while (k == 3) {
            	//第i个人喊出了他的编号
                printf("%3d",arra[i]);
                //这个值记录当前还剩多少人,剩到一个人时,那就出来吧
                 if(temp == 1){
                 	printf("\n******** ");
                    printf("%d",arra[i]);
                    printf(" ********");
                    flag = 0;
                }
                //数完之后总人数减一,并在他的位置上给标记的0,而且还要重新数数
                temp--;           
                arra[i] = 0;
                //k应该为1,但是下面会执行k++,所以这里为了统一就给0
                k = 0;
            }
            //k的发动机开始启动,每次报数的人都算一次
            k++;
        }
        //这里就是循环走,下一个下一个,到最后的时候,再排到前面
        i++;
        if(i == n){
            i = 0;
        }
    }
//  给了30个数字的测试结果
//  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
//  3  6  9 12 15 18 21 24 27 30  4  8 13 17 22 26  1  7 14 20 28  5 16 25 10 23 11  2 19 29
//  ******** 29 ********

100 到 999 的数,数里面的数字是互不相同的,而且能开根号

void putout(){
    int i, j, k, temp;
	//寻找数
    for (i = 1; i < 10; i++) {
        for (j = 0; j < 10; j++) {
            for (k = 0; k < 10; k++) {
            	//看条件1是否符合
                if(i == j || j == k || i == k)
                    continue;
                temp = i * 100 + j * 10 + k;
                //条件2是否符合
                if((sqrtf(temp) - (int)sqrt(temp)) == 0){
                    printf("%d, %f\n", temp, sqrt(temp));
                }
            }
        }
    }
}

字符串s中删除字串t,t可能出现多次

void delsubStr(char *s, char *t){
    char *p1 = s, *p2 = t, *temp = s;
    //母串永远有东西就永远不停留
    while (*temp != '\0') {
    	//找一个字串
        while (*p1 == *p2 && *p1) {
            p1++;
            p2++;
        }
        //如果没找到,母串从下一个找,在初始化所有的字串
        if(*p2){
            temp++;
            p1 = temp;
            p2 = t;
        }
        //如果找到了,就删除
        else
        {
        	//p2临时记录母串的位置
            p2 = temp;
            //往后走,就是把p1后面的提前
            while (*p1) {
                *temp++ = *p1++;
            }
            //删除结束善尾工作
            *temp = '\0';
            //整体结束后,再往后走
            temp = p2;
            temp++;
        }
    }
}
posted @ 2018-10-14 16:39  赫凯  阅读(26)  评论(0)    收藏  举报