C语言练习好题目

1.求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字
例如:2+22+222+2222+22222

int main()
{
    
    
	int a = 0;
	int n = 0;
	scanf("%d%d", &a, &n);
	int sum = 0;
	int i = 0;
	int ret = 0;
	for (i = 0; i < n; i++)
	{
    
    
		ret = ret * 10 + a;
		sum += ret;
	}
	printf("sum = %d", sum);
	return 0;
}

2.求出0~100000之间的所有“水仙花数”并输出。也叫自幂数
"水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如 : 153=1 ^ 3+5 ^ 3+3 ^ 3,则153是一个“水仙花数”

#include<stdio.h>
#include<math.h>
int main()
{
    
    
	int i = 0;
	for (i = 0; i <= 100000; i++)
	{
    
    
		//1.计算i的位数  n
		int n = 1;  //一个数至少是一位数,所以这里初始化为1
		//但是这里你会发现如果使用i,那么就会在while里面改变循环变量i的值,需要重新定义一个临时变量,来暂时保管这个i的数值
		int tmp = i;
		int sum = 0;
		while (tmp /= 10)
		{
    
    
			n++;
		}
		//2.计算每一位的n次方之和  sum
		tmp = i;
		while (tmp)
		{
    
    
			sum += pow(tmp % 10, n); //平方和的函数   pow得到的数是一个double类型,但是你赋给了一个整形的上面,所以为了避免警告可以强制转换类型
			tmp /= 10;
		}
		//比较i和sum的值是否相等
		if (i == sum)
		{
    
    
			printf("%d ", i);
		}
	}
	return 0;
}

3.打印菱形
在这里插入图片描述

int main()
{
    
    
	int line = 0;
	scanf("%d", &line); // 7
	//打印上半部分
	int i = 0;
	for (i = 0; i < line; i++)
	{
    
    
		//打印空格
		int j = 0;
		for (j = 0; j <line-1-i; j++)  // 6 5 4 3 2 1 0 每一行的空格数都是在减少的
		{
    
    
			printf(" ");
		}
		//打印'*'
		for (j = 0; j < 2*i+1; j++)  // '*' 是
		{
    
    
			printf("*");
		}
		printf("\n");
	}
	//打印下半部分
	for (i = 0; i < line - 1; i++)
	{
    
    
		//打印空格
		int j = 0;
		for (j = 0; j <=i; j++)
		{
    
    
			printf(" ");
		}
		//打印'*'
		for (j = 0; j <2*(line-1-i)-1 ; j++)  // 下半部分的第一行是11个,第二行是9个
		{
    
    
			printf("*");
		}
		printf("\n");
	}
	return 0;
}

4.旋转字符串
实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB

首先你的字符串应该满足可以修改这个条件,如果为常量字符串,那就不能修改,是不对的

#include<string.h>
#include<assert.h>
void left_move(char* arr, int k)
{
    
    
	assert(arr != NULL);
	int i = 0;
	int len = strlen(arr);
	for (i = 0; i < k; i++)
	{
    
    
		左旋转一个字符
		1.先把第一个字符拿出来放在一个临时变量里面
		char tmp = *arr;
		2.把后面的元素都向前移动,所以这里需要知道字符串的长度
		int j = 0;
		for (j = 0; j <len-1 ; j++)
		{
    
    
			*(arr + j) = *(arr + j + 1);
		}
		3.
		*(arr + len - 1) = tmp;
	}
}
int main()
{
    
    
	char arr[] = "abcdef";
	left_move(arr, 2);
	printf("%s\n", arr);
	return 0;
}

第二种实现方法三步翻转法

//abcdef
//ba fedc 把这两个字符串分别逆序
//在整体逆序

void reverse(char* left, char* right)
{
    
    
	assert(left != NULL);
	assert(right != NULL);
	while (left<right)
	{
    
    
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}
void left_move(char* arr, int k)
{
    
    
	assert(arr != NULL);
	int len = strlen(arr);
	assert(k <= len);
	reverse(arr,arr+k-1);//逆转左边
	reverse(arr+k,arr+len-1);//逆转右边
	reverse(arr,arr+len-1);//整体逆转
}
int main()
{
    
    
	char arr[] = "abcdef";
	left_move(arr, 2);
	printf("%s\n", arr);
	return 0;
}

5.字符串旋转结果

作业内容
写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。

例如:给定s1 = AABCD和s2 = BCDAA,返回1

给定s1 = abcd和s2 = ACBD,返回0.

AABCD左旋一个字符得到ABCDA

AABCD左旋两个字符得到BCDAA

AABCD右旋一个字符得到DAABC

void left_move(char* s1, int k)
{
    
    
	assert(s1 != NULL);
	int i = 0;
	int len = strlen(s1);
	for (i = 0; i < k; i++)
	{
    
    
		//左旋转一个字符
		//1.先把第一个字符拿出来放在一个临时变量里面
		char tmp = *s1;
		//2.把后面的元素都向前移动,所以这里需要知道字符串的长度
		int j = 0;
		for (j = 0; j <len - 1; j++)
		{
    
    
			*(s1 + j) = *(s1 + j + 1);
		}
		//3.
		*(s1 + len - 1) = tmp;
	}
}
int is_left_move(char* s1, char* s2)
{
    
    
	assert(s1 != NULL);
	assert(s2 != NULL);
	int len = strlen(s1); 
	int i = 0;
	for (i = 0; i < len; i++)
	{
    
    
		left_move(s1, 1);
		int ret = strcmp(s1, s2);
		if (ret == 0)
			return 1;
	}
	return 0;
}
int main()
{
    
    
	char s1[] = "abcdef";
	char s2[] = "cdefab";
	int ret = is_left_move(s1, s2);
	if (ret == 1)
	{
    
    
		printf("YES\n");
	}
	else
	{
    
    
		printf("NO\n");
	}
	return 0;
}

第二种方法

//arr1:"abcdefabcdef\0"
//arr2:"cdefab\0"
//看一下arr2是否是arr1的子串
//但是你会发现自己给自己追加的时候,会把后面的'\0'给覆盖掉,然后他就找不到挺值得标记了
#include<string.h>
#include<stdio.h>
int is_left_move(char* str1, char* str2)
{
    
    
	assert(str1);
	assert(str2);
	int len1 = strlen(str1);
	int len2 = strlen(str2);
	if (len1 != len2) //当s2和s1的长度都不相等的时候,压根谈不是是不是旋转得来的结果。
		return 0;
	//1.在str1字符串中追加一个str1字符串
	//但是strcat这个函数是不能给自己追加的
	strncat(str1, str1, len1);
	//2.判断str2指向的字符串是否是str1指向的字符串的子串
	char* ret = strstr(str1,str2);
	if (ret == NULL)
	{
    
    
		return 0;
	}
	else
	{
    
    
		return 1;
	}
}
int main()
{
    
    
	char s1[] = "abcdef";
	char s2[] = "cdefab";
	int ret = is_left_move(s1, s2);
	if (ret == 1)
	{
    
    
		printf("YES\n");
	}
	else
	{
    
    
		printf("NO\n");
	}
	return 0;
}

杨氏矩阵

有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。

要求:时间复杂度小于O(N);

//1 2 3
//4 5 6
//7 8 9
//这里面右上角的这个数具有特殊的意义,因为对于一行来说他是最大的值,但是对于一列来说他又是最小的值,所以那这个数去和我们需要查找的那个数
//去比较,就可以很快的去掉一行或者一列
int FindNum(int arr[3][3], int k, int row, int col)
{
    
    
	int x = 0;
	int y = col - 1;//定义右上角那个元素的坐标
	while (x<=row-1 && y>=0)
	{
    
    
		if (arr[x][y] > k)
		{
    
    
			y--;
		}
		else if (arr[x][y]<k)
		{
    
    
			x++;
		}
		else
		{
    
    
			return 1;
		}
	}
	return 0;
}
int main()
{
    
    
	int arr[3][3] = {
    
     {
    
     1, 2, 3 }, {
    
     4, 5, 6 }, {
    
     7, 8, 9 } };
	int k = 7;
	int ret = FindNum(arr, k, 3, 3); 
	if (ret == 1)
	{
    
    
		printf("找到了\n");
	}
	else
	{
    
    
		printf("找不到\n");
	}
}

百度的一道笔试题,实现是个OFFSETOF的宏定义

struct S
{
    
    
	char c1;
	int a;
	char c2;
};
#define OFFSETOF(struct_name,member_name) (int)&(((struct_name*)0)->member_name)
//(int)&((struct S*)0)->c1 
//(struct S*)0相当于把0变成了一个结构体指针然后找到结构体内的成员变量,取其地址,然后和首地址相减就会得到一个指针类型,强制类型转换

int main()
{
    
    
	printf("%d\n",OFFSETOF(struct S,c1));
	printf("%d\n",OFFSETOF(struct S,a));
	printf("%d\n",OFFSETOF(struct S,c2));
	return 0;
}

猜你喜欢

转载自blog.csdn.net/MEANSWER/article/details/109606266