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左利きの1文字はBCDAを取得します
ABCD左利きの2文字は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;
}

2番目の実現方法3ステップフリップ法

//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を取得するために1文字左に回転します

BCDAAを取得するためのAABCD左利きの2文字

AABCDは、DAABCを取得するために1文字を右に回転します

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;
}

2番目の方法

//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");
	}
}

Baiduからの筆記試験の質問、実現は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
おすすめ