2018.10.17
1. 打印100~200 之间的素数
//打印100-200之间的素数(prime number)
//素数:只有1和它本身两个因数
//也就是从2到他(本身-1)的数,没有可以整除他,则就是素数
//打印100-200之间的素数(prime number)
//素数:只有1和它本身两个因数
//也就是从2到他本身-1的数,没有可以整除他,则就是素数
#include <stdio.h>
#include <windows.h>
void print_prime_num()
{
int i;
int j;
for (i = 100; i <= 200; i++){
for (j = 2; j < i; j++){
if (i%j == 0)
break;//如果在2到i本省之间取余为0,则不是素数
}
//break跳出来的和正常走完跳出来的
if (j == i) //正常走完跳出来的 (一定注意不要把 == 写成 = !!!)
printf("%d ", i);//说明i就是素数
}
//最后换行输出到显示屏(控制台)
printf("\n");
}
int main()
{
print_prime_num();
system("pause");
return 0;
}
经过思考之后,我觉得还有更高效率的做法,请看图:
看过图之后应该一目了然,每次遍历只需要遍历到n开方的因数就可以了,因为n开方的因数之后,与每一个因数对应的另一个因数都是之前我们已经遍历过的,因此就没有必要在进行遍历了,因此循环条件我们就可以把范围调到 sqrt(i) 处了。
代码如下:
//求素数的改进方案
#include <stdio.h>
#include <windows.h>
#include <math.h>
void print_prime_num()
{
int i;
int j;
for (i = 100; i <= 200; i++){
for (j = 2; j <= sqrt(i); j++){
if (i%j == 0)
break;
}
if (j > sqrt(i))
printf("%d ", i);
}
printf("\n");
}
int main()
{
print_prime_num();
system("pause");
return 0;
}
2. 输出乘法口诀表
//输出乘法口诀表(The Multiplication table)
//1 * 1 = 1
//2 * 1 = 2 2 * 2 = 4
//3 * 1 = 3 3 * 2 = 6 3 * 3 = 9
#include <stdio.h>
#include <windows.h>
#define MAX 9
void print_Mul_table()
{
int i;
int j;
for (i = 1; i <= MAX; i++){
for (j = 1; j <= i; j++){
printf("%d*%d=%2d ", i, j, i*j);
}
printf("\n");
}
printf("\n");
}
int main()
{
print_Mul_table();
system("pause");
return 0;
}
3. 判断1000年---2000年之间的闰年
记住一个口诀:逢4年一润,逢百(100)年不润,逢400年再润。
//判断1000-2000年之间的闰年
//闰年:(A leap year)
//普通闰年 能被4但不能被100整除的年份
//世纪年 能被400整除的年份
#include <stdio.h>
#include <windows.h>
void print_leap_year()
{
int i;
for (i = 1000; i <= 2000; i++){
if ((i%4 == 0) && (i%100 != 0)){
printf("%d ", i);
}
else if (i%400 == 0){
printf("%d ", i);
}
else
continue;
}
printf("\n");
}
int main()
{
print_leap_year();
system("pause");
return 0;
}
2018.10.20
1. 给定两个整形变量的值,将两个值的内容进行交换。
常规算法:创建一个变量,作为过渡变量
//1. 给定两个整形变量的值,将两个值的内容进行交换。
//需要定义第三个变量
#include <stdio.h>
#include <windows.h>
void swap(int *x, int *y)
{
int ret = 0;
ret = *x;
*x = *y;
*y = ret;
}
int main()
{
int a = 10;
int b = 20;
printf("a-> %d b-> %d\n", a, b);
swap(&a, &b);
printf("a-> %d b-> %d\n", a, b);
system("pause");
return 0;
}
2. 不允许创建临时变量,交换两个数的内容(附加题)
常规做法:利用加法交换,但是这样做有一个弊端,一旦两个加数都特别大,那么两个数加起来之后,就会发生溢出,则数据会发生截断,最终就会出错!那么要像一个办法,避免这种错误,于是就有了下面这种 异或 的方法。代码如下:
//2. 不允许创建临时变量,交换两个数的内容(附加题)
#include <stdio.h>
#include <windows.h>
void swap(int *x, int *y)
{
*x = (*x) ^ (*y);
*y = (*x) ^ (*y);
*x = (*x) ^ (*y);
//*x ^= *y;
//*y ^= *x;
//*x ^= *y;
}
int main()
{
int a = 10;
int b = 20;
printf("a-> %d b-> %d\n", a, b);
swap(&a, &b);
printf("a-> %d b-> %d\n", a, b);
system("pause");
return 0;
}
3.求10 个整数中最大值。
//3.求10 个整数中最大值。
#include <stdio.h>
#include <windows.h>
int MAX(int arr[], int num)
{
int max = arr[0];
int i = 1;
int index = 0;
for (; i<num; i++)
{
if (arr[i] >= max)
{
max = arr[i];
index = i;//记录最大值下标
}
else
{
continue;
}
}
return index;
}
int main()
{
int arr[] = {5, 1, 3, 4, 8, 6, 9, 10, 9, 13};
int num = sizeof(arr)/sizeof(arr[0]);
int ret = MAX(arr, num);
printf("MAX-> arr[%d] -> %d\n", ret, arr[ret]);
system("pause");
return 0;
}
4.将三个数按从大到小输出。
//4.将三个数按从大到小输出。
//首先保证a是最大的,其次剩下b和c进行比较,最终就得到了a>b>c
#include <stdio.h>
#include <windows.h>
void swap(int *x, int *y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int main()
{
int a = 1;
int b = 2;
int c = 3;
if (a < b)
{
swap(&a, &b);
}
if (a < c)
{
swap(&a, &c);
}
if (b < c)
{
swap(&b, &c);
}
printf("%d > %d > %d\n", a, b, c);
system("pause");
return 0;
}
5.求两个数的最大公约数
//5.求两个数的最大公约数。
//能同时被两个数整除,且最大值不超过两个数中的较小值4
//最大公约数:max common divisor
//10 5 -> 5
//9 6 -> 3
//3 1 -> 1
//8 4 -> 4
//36 34 -> 2
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
void swap(int *x, int *y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int MaxComDiv(int a, int b)
{
int i = 1;
int max = 0;
if (a < b)
{
swap(&a, &b);
}
for (; i <= b; i++)
{
if ((0==a%i) && (0==b%i))
{
max = i;
}
}
return max;
}
int main()
{
int a, b;
int ret = 0;
printf("please Enter two number> ");
scanf("%d%d", &a, &b);
ret = MaxComDiv(a, b);
printf("%d\n", ret);
system("pause");
return 0;
}
法二辗转相除法
//法二 辗转相除法
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
int main()
{
int a, b, t;
printf("please Enter two numbers> ");
scanf("%d%d", &a, &b);
if (a < b)
{
t = a;
a = b;
b = t;
}
while (b != 0)
{
t = a % b;
a = b;
b = t;
}
printf("%d\n", a);
system("pause");
return 0;
}
法三:辗转相减法
//辗转相减法
//6 4
//5 10
#include <stdio.h>
#include <windows.h>
int main()
{
int a, b;
scanf("%d%d", &a, &b);
while (a != b)
{
if (a > b)
{
a -= b;
}
else
{
b -= a;
}
}
printf("MAX = %d\n", a);
system("pause");
return 0;
}
2018.10.21
1.将数组A中的内容和数组B中的内容进行交换。(数组一样大)
//1.将数组A中的内容和数组B中的内容进行交换。(数组一样大)
//将数组内容逐个依次交换
#include <stdio.h>
#include <windows.h>
void swap(char A[], char B[])
{
char tmp = *A;
*A = *B;
*B = tmp;
}
int main()
{
char A[] = "hello bit!";
char B[] = "thank you!";
int size = sizeof(A)/sizeof(A[0]);
int i = 0;
printf("%s\n", A);
printf("%s\n", B);
for (; i < size; i++)
{
swap(A+i, B+i);
}
printf("%s\n", A);
printf("%s\n", B);
system("pause");
return 0;
}
2. 计算1/1-1/2+1/3-1/4+1/5 ⋯⋯ + 1/99 - 1/100 的值。
//2. 计算1/1-1/2+1/3-1/4+1/5 ⋯⋯ + 1/99 - 1/100 的值。
//分母是奇数为+ 偶数为-
#include <stdio.h>
#include <windows.h>
//#pragma warning(disable:4996)
int main()
{
int i = 0;
double sum = 0;
for (i = 1; i < 101; i++)
{
if (i % 2 != 0)//奇数
{
sum += (1.0/i);
}
else//偶数
{
sum -= (1.0/i);
}
}
printf("sum = %lf\n", sum);
system("pause");
return 0;
}
3. 编写程序数一下 1到 100 的所有整数中出现多少次数字9。
这里有一个坑:90-98 有9个9, 99有两个9
//3. 编写程序数一下 1到 100 的所有整数中出现多少次数字9。
//这里有一个坑:90 - 98 有9个 99 有两个,不能忘了!!!
#include <stdio.h>
#include <windows.h>
#define NUM 9
//#pragma warning(disable:4996)
int main()
{
int count = 0;
int i = 1;
for (; i < 101; i++)
{
if ((NUM == i%10) || (NUM == i/10))
{
count++;
if ((NUM == i%10) && (NUM == i/10))
{
count++;
}
}
}
printf("count of [%d] = %d times\n", NUM, count);
system("pause");
return 0;
}
我们数数结果是20个,现在看看输出结果: 很明显,我们是对的!!!
2018.10.21
#include <stdio.h>
#include <windows.h>
int main()
{
int j;
int i;
int k;
int count = 1;
for (j=12; j>5; j--)
{
for (i=0; i<j; i++)
{
printf(" ");
}
for (k=0; k<count; k++)
{
printf("*");
}
printf("\n");
count+=2;
}
count = 11;
for (j=7; j<13; j++)
{
for (i=0; i<j; i++)
{
printf(" ");
}
for (k=0; k<count; k++)
{
printf("*");
}
printf("\n");
count-=2;
}
system("pause");
return 0;
}
//2.求出0〜999之间的所有“水仙花数”并输出。“水仙花数”是指一个三位数,其各位数字的立方和确好等于该数本身,如;153=1+5+3?,则153是一个“水仙花数”。
//在数论中,水仙花数(Narcissistic number)也称为自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数(Armstrong number),是指一N位数,其各个数之N次方和等于该数。
//例如153、370、371及407就是三位数的水仙花数,其各个数之立方和等于该数:
//153 = 1^3 + 5^3 + 3^3。
//370 = 3^3 + 7^3 + 0^3。
//371 = 3^3 + 7^3 + 1^3。
//407 = 4^3 + 0^3 + 7^3。
#include <stdio.h>
#include <windows.h>
int main()
{
int i;
for (i=100; i<1000; i++)
{
int a = i/100;
int b = i/10%10;
int c = i%10;
if (i == (a*a*a) + (b*b*b) + (c*c*c))
{
printf("%d\n", i);
}
}
system("pause");
return 0;
}
//3.求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,例如:2+22+222+2222+22222
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
#define MAX 4
int main()
{
int num = 2;
int Sn = 0;
int ret = 0;
int i = 0;
ret = num;
Sn = num;
printf("%d", num);
for (i=0; i<MAX; i++)
{
num = num*10+ret;
printf(" + %d", num);
Sn += num;
}
printf(" = %d\n", Sn);
system("pause");
return 0;
}
//4.编写一个程序,它从标准输入读取C源代码,并验证所有的花括号都正确的成对出现。
//正确的配对: { } {{{ }}}
//错误的配对: } {
// { { }
// { { } } }
//需要注意的是此题思想是:遇到 '{' count++ '}' count-- (只使用一个计数变量,不易出错!!!)
#include <stdio.h>
#include <windows.h>
int main()
{
char c = 0;
int count = 0;
//int num = 0;
while ((c = getchar()) != EOF)
{
if ((count == 0) && (c == '}'))
{
printf("不匹配!!!");
system("pause");
return 0;
}
else if (c == '{')
{
count++;
}
else if ((count != 0) && (c == '}'))
{
count--;
}
else
{
;
}
}
if (count == 0)
{
printf("匹配!!!");
}
else
{
printf("不匹配!!!");
}
system("pause");
return 0;
}
2018.10.23
1 完成猜数字游戏
#define _CRT_SECURE_NO_WARNINGS
//1.完成猜数字游戏。
#include <stdio.h>
#include <windows.h>
#include <time.h>
void menu()
{
printf("*********************\n");
printf("***1.play 2.exit ***\n");
printf("*********************\n");
printf("please Enter your select> ");
}
void game()
{
int i;
int ret = rand()%100;//随机生成1-99的数字
printf("please Guess> ");
while (1){
scanf("%d", &i);
if (i > ret)
{
printf("猜大了\n");
}
else if (i < ret)
{
printf("猜小了\n");
}
else
{
printf("猜对了\n");
break;
}
}
}
int main()
{
int select = 0;
srand((unsigned long)time(NULL));//种了一个时间种子
while (1){
menu();
scanf("%d", &select);
switch (select)
{
case 1:
game();
break;
case 2:
exit(0);
break;
default:
printf("\nEnter Error, try again\n\n");
break;
}
}
system("pause");
return 0;
}
2. 写代码可以在整型有序数组中查找想要的数字,找到了返回下标,找不到返回 - 1.(折半查找)
//题目要看清楚:整形,有序(升序排列)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
int GetNumber(int arr[], int left, int right)
{
int i = 0;
scanf("%d", &i);
while (left <= right)
{
int mid = left + (right - left) / 2;//防止数据溢出
if (i > arr[mid])
{
left = mid + 1;
}
else if (i < arr[mid])
{
right = mid - 1;
}
else
{
return left;
}
}
return -1;
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};//一定要 ‘有序’
int size = sizeof(arr) / sizeof(arr[0]);
int left = 0;//左下标
int right = size - 1;//右下标
int ret = GetNumber(arr, left, right);
if (ret != -1)
{
printf("find success: arr[%d]\n", ret);
}
else
{
printf("find failed\n");
}
system("pause");
return 0;
}
//3.编写代码模拟三次密码输入的场景。
//最多能输入三次密码,密码正确,提示“登录成功”, 密码错误,可以重新输入,最多输入三次。三次均错,则提示退出程序。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#include <string.h>
int main()
{
int count = 3;
char name[10] = {0};//'\0' = 0
char password[10] = {0};
printf("please Enter your yourname> ");
scanf("%s", name);
if (0 == strcmp(name, "bitekeji"))
{
printf("please Enter your password> ");
while (count)
{
scanf("%s", password);
count--;
if (0 == strcmp(password, "123456"))
{
printf("Download success, please Enter!\n");
break;
}
else
{
if (0 == count)
{
printf("so sorry, Download failed!\n");
break;
}
printf("password Error, try again\n");
printf("you have %d times> ", count);
}
}
}
else
{
printf("yourname Error\n");
}
system("pause");
return 0;
}
//4.编写一个程序,可以一直接收键盘字符,如果是小写字符就输出对应的大写字符,如果接收的是大写字符,就输出对应的小写字符,如果是数字不输出。
#include <stdio.h>
#include <windows.h>
int main()
{
char c = 0;
while ((c = getchar()) != EOF)
{
if ((c >= 'a') && (c <= 'z'))
{
putchar(c-('a'-'A'));
}
else if ((c >= 'A') && (c <= 'Z'))
{
putchar(c + ('a' - 'A'));
}
else
{
;
}
}
system("pause");
return 0;
}
2018.10.25
//1.写一个函数返回参数二进制中 1 的个数
//比如: 15 (0000 1111) 4 个 1
//程序原型:
//int count_one_bits(unsigned int value)
//{
// 返回 1的位数
//}
//方法一(节省时间,效率高,有几个1,就执行几次)
//让一个数和该数减一进行按位与运算,判断得到的结果是否==0,若不等于0则让上次运算结果继续重复相同的运算,
//一直到得到的结果是0才停止运算,则重复运算的次数就是二进制中1的位数。
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996) //不能放在外面,要放在这里!!!
int count_one_bits(unsigned int value)
{
int count = 0;
while (value)//值为0退出循环 ,值>0继续循环
{
value &= (value - 1); //value = value & (value-1);
count++;
}
return count;//1 的个数
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
unsigned int ret = count_one_bits(num);
printf("%d\n", ret);
system("pause");
return 0;
}
//方法二
//让一个数与1进行按位与运算,该数最低位要是1则结果为1,否则为0,然后让该数每次>>一位,一共判断32次。
//缺点:如果是判断负数的二进制1的位数,会发生死循环,因为负数在计算机中存储的是补码,
//最高位是符号位,每次右移一位,最高位填充的永远是1。但传的是无符号整数就不存在这个事了。
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996) //不能放在外面,要放在这里!!!
int count_one_bits(unsigned int value)
{
int count = 0;
while (value)
{
if (1 == (value & 1))
{
count++;
}
value >>= 1;//value = value >> 1;//不能只写 >>
}
return count;
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
unsigned int ret = count_one_bits(num);
printf("%d\n", ret);
system("pause");
return 0;
}
//方法三
//让一个数和1进行按位与运算,然后让1依次左移1位,每次与运算结果为0或不为0,依次判断统计1的位数,
//缺点:二进制中无论有多少个1,都要判断32次,效率比较低(但是不怕求负数的二进制中1的位数)
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996) //不能放在外面,要放在这里!!!
int count_one_bits(unsigned int value)
{
int i = 1;
int count = 0;
int n = 1;
for (; i <= 32; i++)//需要判断32次
{
if (value & n)
{
count++;
}
n <<= 1;//每次在当前位置左移1位
}
return count;//1 的个数
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
unsigned int ret = count_one_bits(num);
printf("%d\n", ret);
system("pause");
return 0;
}
2.获取一个数二进制序列中所有的偶数位和奇数位,分别输出二进制序列。
//(10) 000...1010
//依次把x的32位二进制数位的数放到数组里面,
//存放完毕后,arr_bits[0]放的是最低位(偶数位even bit)
//此时我们可以倒着打印出来,即显示了数在内存中的小端存储方式
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
void get_bin_bits(unsigned int x)//负数拿到cpu中就会从补码变到源码,在寄存器可能会溢出
{
int i = 0;
int arr_bits[32] = {0};
for (; i < 32; i++)
{
arr_bits[i] = x % 2;//依次把x的32位二进制数位的数放到数组里面
x /= 2;
}
//存放完毕后,arr_bits[0]放的是最低位(偶数位even bit)
//此时我们可以倒着打印出来,即显示了数在内存中的小端存储方式
printf("正常数位<normal>:");
for (i = 31; i >= 0; i--)
{
printf("%d ", arr_bits[i]);
}
printf("\n");
printf("偶数位序列<even>:");
for (i = 30; i >= 0; i-=2)
{
printf("%d ", arr_bits[i]);
}
printf("\n");
printf("奇数位序列 <odd>:");
for (i = 31; i >= 1; i-=2)
{
printf("%d ", arr_bits[i]);
}
printf("\n");
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
get_bin_bits(num);
system("pause");
return 0;
}
//3. 输出一个整数的每一位。(大问题分解为子问题解决)
//156 : 1 5 6
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
//顺序打印:156 -> 1 5 6
void print_bit(int x)
{
if (x < 9)//停止条件
{
printf("%d ", x);
return;
}
else
{
print_bit(x / 10);//细化子问题
printf("%d ", x % 10);
}
}
//倒着打印: 156 -> 6 5 1
//void print_bit(int x)
//{
// while (x > 9)
// {
// printf("%d ", (x % 10));
// x /= 10;
// }
// printf("%d\n", x);
//}
int main()
{
int num = 0;
scanf("%d", &num);
print_bit(num);
system("pause");
return 0;
}
//4.编程实现:
//两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
//输入例子 :
//1999 2299
//输出例子 : 7
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
int count_one_bits(int value)
{
int count = 0;
while (value)//值为0退出循环 ,值>0继续循环
{
value &= (value - 1); //value = value & (value-1);
count++;
}
return count;//1 的个数
}
int main()
{
int x, y;
scanf("%d%d", &x, &y);
int ret = count_one_bits(x^y);
printf("整数[%d]和[%d]的二进制表达中,有[%d]个位(bit)不同\n", x, y, ret);
system("pause");
return 0;
}
2018.10.26
//1.实现一个函数,打印乘法口诀表,口诀表的行数和列数自己指定,
//输入9,输出9 * 9口诀表,输入12,输出12 * 12的乘法口诀表。
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
void print_mul(int x)
{
int i = 1;
for (; i <= x; i++)
{
int j = 1;//不能写在外面!!!
for (; j <= i; j++)
{
printf("%d*%d=%2d ", i, j, i*j);
}
printf("\n");
}
}
int main()
{
int x = 0;
scanf("%d", &x);
print_mul(x);
system("pause");
return 0;
}
//2.使用函数实现两个数的交换。
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
void Exchange(int *x, int *y)
{
*x ^= *y;//*x = *x ^ *y;
*y ^= *x;//*y = *x ^ *y;
*x ^= *y;//*x = *x ^ *y;
}
int main()
{
int x, y;
scanf("%d%d", &x, &y);
printf("before Exchange: %d %d\n\n", x, y);
Exchange(&x, &y);
printf("after Exchange: %d %d\n\n", x, y);
system("pause");
return 0;
}
//3.实现一个函数判断year是不是润年。
//逢4年一润 && 逢100年不润, 逢400年再润
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
int IsLeap(int x)
{
if (((x % 4 == 0) && (x % 100 != 0)) || (x % 400 == 0)){
return 1;
}
else{
return 0;
}
}
int main()
{
int year = 0;
scanf("%d", &year);
int ret = IsLeap(year);
if (1 == ret){
printf("%d is leap year!\n", year);
}
else{
printf("%d is not leap year!\n", year);
}
system("pause");
return 0;
}
//4.创建一个数组,
//实现函数init()初始化数组、给其中的数组元素赋值
//实现empty()清空数组、
//实现reverse()函数完成数组元素的逆置。
//要求:自己设计函数的参数,返回值
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#pragma warning(disable:4996)
#define SIZE 10
//初始化数就是给其中的数组元素赋初值
void init(int arr[])
{
assert(arr != NULL);
int i = 0;
for (; i < SIZE; i++)
{
*(arr+i) = (i+1);
}
}
void empty(int arr[])
{
assert(arr != NULL);
int i = 0;
for (; i < SIZE; i++)
{
*(arr + i) = 0;
}
}
void reverse(int arr[])
{
assert(arr != NULL);
int left = 0;
int ret = SIZE;
int right = ret - 1;
while (left <= right)
{
int tmp = *(arr + left);
*(arr + left) = *(arr + right);
*(arr + right) = tmp;
left++;
right--;
}
}
int main()
{
int arr[SIZE];
init(arr);
//empty(arr);
//reverse(arr);
int i = 0;
for (; i < SIZE; i++){
printf("%d ", arr[i]);
}
printf("\n");
system("pause");
return 0;
}
//5.实现一个函数,判断一个数是不是素数。
#include <stdio.h>
#include <windows.h>
#include <math.h>
#include <assert.h>
#pragma warning(disable:4996)
void IsPrimeNumber(int x)
{
assert(x > 1);//素数必须大于1
int i = 2;
while (i <= sqrt(x))
{
if (0 == x % i)
{
printf("%d is not prime number!\n", x);
break;
}
i++;
}
if (i > sqrt(x))
{
printf("%d is prime number!\n", x);
}
}
int main()
{
int x = 0;
scanf("%d", &x);
IsPrimeNumber(x);
system("pause");
return 0;
}
2018.10.27
//1.
//5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果
//A选手说:B第二,我第三;
//B选手说:我第二,E第四;
//C选手说:我第一,D第二;
//D选手说:C最后,我第三;
//E选手说:我第四,A第一;
//比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。
//看到这道题,我首先是蒙的,一下子不知道怎么办了,思考了好久,终于,还是无从下笔,此时心态就有点崩了,但是
//这个时候一定不要放弃,也不要觉得自己不行,谁要是所有题一看就会,那还来练习干啥呢?练习就是自己先思考。实在不懂
//就去参考一下别人的思路,让自己获得相应的做题经验!!!
//这道题参考别人的思路之后,有了想法。题中让确定比赛名次,那么仔细想想:既然是比赛,肯定有名次
//有名次当然就是有人是第一,有人是老末,这里我们忽略掉名次并列的情况。则一场比赛下来,五个人肯定就有
//12345的名次排名,那么我们比赛前知道谁赢谁输吗?当然是不知道的,既然不知道,那就当然要把所有的可能情况列出来
//然后再在这些情况里面寻找符合题目条件的名次,最后输出就好了啊!!!
//现在就开始让我们进入代码吧~
#include <stdio.h>
#include <windows.h>
int main()
{
int a, b, c, d, e;
for (a = 1; a <= 5; a++){
for (b = 1; b <= 5; b++){
for (c = 1; c <= 5; c++){
for (d = 1; d <= 5; d++){
for (e = 1; e <= 5; e++){
if ((a != b)&&(a != c)&&(a != d)&&(a != e)&&\
(b != c)&&(b != d)&&(b != e)&&\
(c != d)&&(c != e)&&\
(d != e)&& //排除并列的情况
((b == 2) + (a == 3) == 1) &&\
((b == 2) + (e == 3) == 1) &&\
((c == 1) + (d == 2) == 1) &&\
((c == 5) + (d == 3) == 1) &&\
((e == 4) + (a == 1) == 1)) //依照题目的判断条件
{
printf("result: a=%d, b=%d, c=%d, d=%d, e=%d\n", a, b, c, d, e);
}
}
}
}
}
}
system("pause");
return 0;
}
//法二(下面代码没有排除并列的情况)
//显然上面代码的if()判断条件比较繁琐,那么现在就针对此问题对代码进行一个优化:
//利用一个整形的二进制序列的前五位来分别记录名次,最低位存放第一名,第五位存放最后一名(用这种方法排除名次有间断的情况)
//代码如下:
#include <stdio.h>
#include <windows.h>
int main()
{
int a, b, c, d, e;
for (a = 1; a <= 5; a++)
{
for (b = 1; b <= 5; b++)
{
for (c = 1; c <= 5; c++)
{
for (d = 1; d <= 5; d++)
{
for (e = 1; e <= 5; e++)
{
if (((b == 2) + (a == 3) == 1) &&\
((b == 2) + (e == 3) == 1) &&\
((c == 1) + (d == 2) == 1) &&\
((c == 5) + (d == 3) == 1) &&\
((e == 4) + (a == 1) == 1)) //依照题目的判断条件
{
int flag = 0;//0000....0000 0000
flag |= (1 << (a - 1));
flag |= (1 << (b - 1));
flag |= (1 << (c - 1));
flag |= (1 << (d - 1));
flag |= (1 << (e - 1));//都是减1,,,别弄错了
//if (flag == 31){//0001 1111 == 31 排除名次并列情况
while (flag)
{
if (flag % 2 == 0)//排除掉其中名次有间断的情况、但是没有排除名次并列情况
break;
flag /= 2;
}
if (flag == 0)
{
printf("result: a=%d, b=%d, c=%d, d=%d, e=%d\n", a, b, c, d, e);
}
//}
}
}
}
}
}
}
system("pause");
return 0;
}
//2.
//日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。以下为4个嫌疑犯的供词。
//A说:不是我。
//B说:是C。
//C说:是D。
//D说:C在胡说
//已知3个人说了真话,1个人说的是假话。
//现在请根据这些信息,写一个程序来确定到底谁是凶手。(murderer 凶手)
//思路:四个人中,三个人说真话,一个人说假话,则4个条件加起来是3,因为有一个假(0)
//要充分利用条件,而不是自己在那里想谁是凶手
#include <stdio.h>
#include <windows.h>
int main()
{
char murderer;//定义此变量放凶手
for (murderer = 'A'; murderer <= 'D'; murderer++)//依次假设A,B,C,D为凶手
{
if ((murderer != 'A') + (murderer == 'C') + (murderer == 'D') + (murderer != 'D') == 3)//题目给的四个条件
{
printf(" %c is murderer!!!\n", murderer);//只要是符合四个条件且三真一假,那么次用手就是我们假设的那一个人
break;
}
}
system("pause");
return 0;
}
//3.在屏幕上打印杨辉三角。
//1
//1 1
//1 2 1
//1 3 3 1
//1 4 6 4 1
//感觉利用数组,输出比较方便
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
int main()
{
int i,j;
int arr[20][20] = {0};//数组[]中不能用变量表示
int n = 30;
while (n > 20)
{
printf("please Enter> ");
scanf("%d", &n);
}
for (i = 0; i < n; i++)
{
arr[i][0] = 1;//先把每一行第一个元素置1
}
for (i = 1; i < n; i++)
{
for (j = 1; j <= i; j++)
{
arr[i][j] = arr[i-1][j-1] + arr[i-1][j];
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j <= i; j++)
{
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n");
system("pause");
return 0;
}
2018.10.31
//1.编写函数:
//unsigned int reverse_bit(unsigned int value);
//这个函数的返回值value的二进制位模式从左到右翻转后的值。
//如:
//在32位机器上25这个值包含下列各位:
//00000000000000000000000000011001
//翻转后:(2550136832)
//10011000000000000000000000000000
//程序结果返回:
//2550136832
方法一:有点投机取巧的意思,而且中间有点有问题,详细见下面代码
#include <stdio.h>
#include <windows.h>
#include <math.h>
#pragma warning(disable:4996)
unsigned int reverse_bit(unsigned int value)
{
int m = 0;
int num = 0;
int i = 31;
while (value)
{
m = value % 2;//取余
num = num + m * pow(2,i);//pow是求2的i次方函数(这个地方会有类型不匹配警告!)
i--;
value /= 2;//相当于value右移一位,前面补0
}
return num;//上述方法相当于一个投机取巧的方法,并不是真的把value的值前后反转,
//而是二进制位前后反转相当于:把低位1移到高位,整个数值增加了2的高位次方
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
unsigned int ret = reverse_bit(num);
printf("%u\n", ret);
system("pause");
return 0;
}
法二(比较难想,常常回顾)
#include <stdio.h>
#include <windows.h>
#include <math.h>
#pragma warning(disable:4996)
unsigned int reverse_bit(unsigned int value)
{
int i;
int sum = 0;
int bit;
for (i = 0; i < 32; i++)
{
sum = sum << 1;//这里左移1位必须有,因为最低位是1时,已经循环一次了,此时1应该在倒数第二位
bit = value & 1;//取余
sum = sum | bit;
value = value >> 1;
}
return sum;
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
unsigned int ret = reverse_bit(num);
printf("%u\n", ret);
system("pause");
return 0;
}
2018.11.1
//2.不使用(a + b) / 2这种方式,求两个数的平均值。
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
int ave_val(int x, int y)
{
int t = 0;
return t = (x + y) >> 1;
}
int main()
{
int a, b;
scanf("%d%d", &a, &b);
int ret = ave_val(a, b);
printf("%d\n", ret);
system("pause");
return 0;
}
//3.编程实现:
//一组数据中只有一个数字出现了一次。其他所有数字都是成对出现的。
//请找出这个数字。(使用位运算)
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
int once_val(int arr[], int size)
{
int i = 0;
int tmp = arr[0];
for (; i < size - 1; i++)
{
tmp ^= arr[i + 1];//按位异或是相异为1
}
return tmp;
}
int main()
{
int arr[] = { 2, 10, 2, 10, -3, 5, 5, -3, 9};
int size = sizeof(arr) / sizeof(arr[0]);
int ret = once_val(arr, size);
printf("%d\n", ret);
system("pause");
return 0;
}
//4.
//有一个字符数组的内容为:"student a am i",
// 请你将数组的内容改为"i am a student".
// 要求:
// 不能使用库函数。
// 只能开辟有限个空间(空间个数和字符串的长度无关)。
//
// student a am i
// i ma a tneduts
// i am a student
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <assert.h>
void Reverse(char *begin, char *end)//把倒序排列函数单独列出来
{
assert(begin);
assert(end);
while (begin < end)
{
*begin ^= *end;
*end ^= *begin;
*begin ^= *end;
begin++;
end--;
}
}
void str_rev(char arr[], int size)
{
assert(arr);
char *str1 = arr;
char *begin = arr;
char *end = arr + size - 1;
Reverse(begin, end);//先倒序排列整个字符串
//接下来再把每个单词倒序排列
while (*begin)
{
str1 = begin;
while ((*begin != ' ') && (*begin != '\0'))//为了找到一个单词,遇到空格或\0就停下来,其之前的就是一个单词
{
begin++;
}
Reverse(str1, begin - 1);//倒序一个单词序列
if (*begin != '\0')//防止到最后一个单词之后,begin继续++,就会越界访问,就有可能循环无法终止!
{
begin++;
}
}
}
int main()
{
char arr[] = "student a am i";//空格并不是'\0'
int size = strlen(arr);
str_rev(arr, size);//指针操作,不用返回值,直接就修改了数组的内容
printf("%s\n", arr);
system("pause");
return 0;
}
2018.11.2
//1.调整数组使奇数全部都位于偶数前面。
//题目:
//输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。
#include <stdio.h>
#include <windows.h>
#include <assert.h>
void put_Odd_Even(int arr[], int sz)
{
assert(arr);
int *pleft = arr;
int *pright = arr + sz - 1;
while (pleft < pright)
{
while ((pleft < pright) && (*pleft % 2 != 0))//小心数组越界(万一数组全是奇数)
{
pleft++;
}
while ((pleft < pright) && (*pright % 2 == 0))//小心数组越界(万一数组全是偶数)
{
pright--;
}
if (pleft < pright)//不要忘记了这个判断条件
{
*pleft ^= *pright;
*pright ^= *pleft;
*pleft ^= *pright;
}
pleft++;
pright--;
}
}
int main()
{
int i = 0;
int arr[] = { 1, 5, 2, 3, 8, 6, 9, 4, 7, 1, 5 };
int size = sizeof(arr) / sizeof(arr[0]);
put_Odd_Even(arr, size);
for (; i < size; i++)
{
printf(" %d", arr[i]);
}
printf("\n");
system("pause");
return 0;
}
//2.
//杨氏矩阵
//有一个二维数组.
//数组的每行从左到右是递增的,每列从上到下是递增的.
//在这样的数组中查找一个数字是否存在。
//时间复杂度小于O(N);
//数组:
//1 2 3
//3 4 5
//4 5 6
//该题以arr[0][2]为基准
//外层循环是arr[0][2] arr[1][2] arr[2][2]
//内层只需要判断每一行的大小即可
//时间复杂度小于O(N)
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
int search(int arr[][3], int num)
{
int i = 0;
for (; i < 3; i++)
{
int j = 2;
while (j >= 0)
{
if (num == arr[i][j])
{
return 1;
}
else if (num < arr[i][j])
{
j--;
}
else
{
break;
}
}
}
return 0;
}
int main()
{
int i, j;
int arr[][3] = { { 1, 2, 3 }, { 2, 3, 4 }, { 3, 4, 5 } };
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf(" %d", arr[i][j]);
}
printf("\n");
}
printf("\n\n");//上面是打印二维数组
int num = 0;
scanf("%d", &num);
int ret = search(arr, num);//这里检查数字是否存在
if (ret == 1)
{
printf("该数存在\n");
}
else
{
printf("该数不存在\n");
}
system("pause");
return 0;
}
//1.实现一个函数,可以左旋字符串中的k个字符。
//ABCD左旋一个字符得到BCDA
//ABCD左旋两个字符得到CDAB
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <assert.h>
#pragma warning(disable:4996)
char * turn_left(char str[], int n)
{
assert(str);
int t = n;
while (n)
{
char * pstr1 = str;
char * pend = str + t - 2;
char ret = *str;
while (pstr1 <= pend)
{
*pstr1 = *(pstr1 + 1);
pstr1++;
}
*pstr1 = ret;
n--;
}
return str;
}
int main()
{
int n = 0;
char str[5] = "ABCD";
printf("%s\n", str);
printf("左旋<?>次: ");
scanf("%d", &n);
char *pstr = turn_left(str, n);
printf("%s\n", pstr);
system("pause");
return 0;
}
//2.判断一个字符串是否为另外一个字符串旋转之后的字符串。
//例如:给定s1 = AABCD和s2 = BCDAA,返回1,给定s1 = abcd和s2 = ACBD,返回0.
//AABCD左旋一个字符得到ABCDA
//AABCD左旋两个字符得到BCDAA
//AABCD右旋一个字符得到DAABC
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include <string.h>
int str_turn_equal(char s1[], char s2[], int n)
{
assert(s1);
assert(s2);
int t = n;
while (n)
{
char * pstr1 = s2;
char * pend = s2 + t - 2;//这个地方需要注意
char ret = *s2;
while (pstr1 <= pend)
{
*pstr1 = *(pstr1 + 1);
pstr1++;
}
*pstr1 = ret;
if (0 == strcmp(s1, s2))
{
return 1;
}
n--;
}
return 0;
}
int main()
{
char s1[10] = "AABCD";
char s2[10] = "CDAAB";
int n = strlen(s2);
int ret = str_turn_equal(s1, s2, n);
if (1 == ret)
{
printf("s1【是】s2字符串旋转之后的字符串\n");
}
else
{
printf("s1【不是】s2字符串旋转之后的字符串\n");
}
system("pause");
return 0;
}
//1.一个数组中只有两个数字是出现一次,
//其他所有数字都出现了两次。
//找出这两个数字,编程实现。
#include <stdio.h>
#include <windows.h>
#include <assert.h>
void search_once_num(int arr[], int n)
{
assert(arr);
int t = n;
int *first = arr;
int *end = arr + t - 2;
while (first <= end)
{
int *second = arr;
while (second <= (end+1))
{
if ((first != second) && (*second == *first))
{
break;
}
second++;
}
if (second > (end+1))
{
printf("【%d】出现一次!\n", *first);
}
first++;
}
}
int main()
{
int arr[] = { 1, 2, 3, 4, 1, 2, 5, 5 };
int sz = sizeof(arr) / sizeof(arr[0]);
search_once_num(arr, sz);
system("pause");
return 0;
}
2018.11.3
//2.喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,
//给20元,可以多少汽水。
//编程实现。
#include <stdio.h>
#include <windows.h>
#pragma warning(disable:4996)
int main()
{
int sum = 0;
int SoadPop = 0;
printf("please Enter your money> ");
scanf("%d", &SoadPop);
sum = SoadPop;
while (SoadPop > 0)
{
SoadPop /= 2;
sum += SoadPop;
}
printf("%d\n", sum);
system("pause");
return 0;
}
//3.模拟实现strcpy
//有数组的时候,一定要记得是否越界的问题!!!!!
assert(dest);
assert(src);
//assert是一个宏,在debug版中有定义,但是在release版本没有此宏,所以尽量使用if判断语句实现空指针判定!!!
#include <stdio.h>
#include <windows.h>
#include <assert.h>
//方法一
char * my_strcpy(char *dest, const char *src)
{
assert(dest);
assert(src);
char *str = dest;
while (*src)
{
*str = *src;
str++;
src++;
}
*str = *src;//把'\0'拷贝过去
return dest;
}
//高级版
char * my_strcpy(char *dest, const char *src)
{
assert(dest);//assert是一个宏,在debug版中有定义,但是在release版本没有此宏
assert(src);//所以尽量使用if判断语句实现空指针判定!!!
char *str = dest;
while (*str++ = *src++)
{
;
}
return dest;
}
int main()
{
const char *str1 = "abcdefg";
char str2[10] = {0};//'\0'
char *str = my_strcpy(str2, str1);
printf("%s\n", str);
system("pause");
return 0;
}
//4.模拟实现strcat
//有数组的时候,一定要记得是否越界的问题!!!!!
assert(dest);
assert(src);
//assert是一个宏,在debug版中有定义,但是在release版本没有此宏,所以尽量使用if判断语句实现空指针判定!!!
char * my_strcat(char *dest, const char *src)
{
assert(dest);//assert是一个宏,在debug版中有定义,但是在release版本没有此宏
assert(src);//所以尽量使用if判断语句实现空指针判定!!!
char *str = dest;
while (*str)
{
str++;
}
while (*str++ = *src++)
{
;
}
return dest;
}
int main()
{
char str1[20] = "abcdefg";//有数组的时候,一定要考虑否越界的问题!!!
char str2[10] = "hijklmn";//'\0'
char *str = my_strcat(str1, str2);
printf("%s\n", str);
system("pause");
return 0;
}
2018.11.6
//1.实现strcpy
Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。 目标空间必须可变。
#include <stdio.h>
#include <windows.h>
#include <assert.h>
char *my_strcpy(char *dest, const char *src)
{
assert(dest);
assert(src);
char *pstr = dest;
while (*pstr++ = *src++)
{
;
}
return dest;
}
int main()
{
char str1[] = "abcdefg";
char str2[10] = {0};
char *str = my_strcpy(str2, str1);
printf("%s\n", str);
system("pause");
return 0;
}
//2.实现strcat
#include <stdio.h>
#include <windows.h>
#include <assert.h>
char *my_strcat(char *dest, const char *src)
{
assert(dest);
assert(src);
char *pstr = dest;
while (*pstr)
{
pstr++;
}
while (*pstr++ = *src++)
{
;
}
return dest;
}
int main()
{
char str1[20] = "abcdefg";
char str2[] = "abcdefg";
char *str = my_strcat(str1, str2);
printf("%s\n", str);
system("pause");
return 0;
}
//3.实现strstr
#include <stdio.h>
#include <windows.h>
#include <assert.h>
const char *my_strstr(const char *dest, const char *src)
{
assert(dest);
assert(src);
const char *pstr = dest;
const char *pdest = pstr;
while (*pstr)
{
pdest = pstr;
while (*pstr == *src && *src)
{
pstr++;
src++;
}
if (*src == '\0')
{
return pdest;
}
pstr++;
}
return NULL;
}
int main()
{
char str1[20] = "abcdefg1234defg";
const char *str = my_strstr(str1, "defg");
printf("%s\n", str);
system("pause");
return 0;
}
//4.实现strchr
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#pragma warning(disable:4996)
const char *my_strchr(const char* str, char ch)
{
assert(str);
const char *pdest = str;
while (*pdest != ch && *pdest)
{
pdest++;
}
if (*pdest == ch)
{
return pdest;
}
else
{
return NULL;
}
}
int main()
{
char str[] = "abcdefg1234";
char ch = 0;
scanf("%c", &ch);
const char *pstr = my_strchr(str, ch);
if (pstr == NULL)
{
printf("<NULL>\n");
}
else
{
int result = pstr - str + 1;
printf("%d\n", result);
}
system("pause");
return 0;
}
//5.实现strcmp
//这个很特殊,一定要多看!!!!
//这个很特殊,一定要多看!!!!
//这个很特殊,一定要多看!!!!
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#pragma warning(disable:4996)
int my_strcmp(const char* str1, const char* str2)
{
assert(str1);
assert(str2);
int sub;
while (!(sub = (*str1 - *str2)) && *str1)//两个字符相等且都不为'\0'就继续循环
{
str1++;
str2++;
}
if (sub > 0)
{
return 1;
}
else if (sub < 0)
{
return -1;
}
else
{
return 0;
}
}
int main()
{
char str1[] = "abcdEfg123";
char str2[] = "abcdEfg123";
int ret = my_strcmp(str1, str2);
printf("%d\n", ret);
system("pause");
return 0;
}
//6.实现memcpy
//此函数对于内存覆盖的问题没有定义,所以对于内存覆盖问题的拷贝,要用memmove函数来处理
//memcpy是内存拷贝函数,以字节为单位进行拷贝,所以不管什么类型都能进行拷贝
//遇到'\0'不会停止
#include <stdio.h>
#include <windows.h>
#include <assert.h>
//#include <string.h>
#pragma warning(disable:4996)
void *my_memcpy(void* dest, const void* src, int num)//mem系列以字节为单位进行操作
{
assert(dest);
assert(src);
assert(num > 0);
char *pdest = (char *)dest;
const char *psrc = (char *)src;
while (num--)
{
*pdest++ = *psrc++;
}
return dest;
}
int main()
{
char str1[] = "abcdefg123";
char str2[20];
my_memcpy(str2, str1, sizeof(str1));
printf("%s\n", str2);
system("pause");
return 0;
}
//7.实现memmove
//内存出现覆盖的时候调用此函数,此函数与memcpy不同之处就是当出现 dest > src 且 dest < src + strlen时,从后往前拷贝就好
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include <string.h>
#pragma warning(disable:4996)
void *my_memmove(void* dest, const void* src, int num)//mem系列以字节为单位进行操作
{
assert(dest);
assert(src);
assert(num > 0);
char *pdest = (char *)dest;
const char *psrc = (char *)src;
if (pdest > psrc && pdest < psrc + num)
{
while (num--)//num == 1时,判断可以进入循环,随后立即num-- 变为0,进入循环进行操作
{
*(pdest + num) = *(psrc + num);
//num--; 如果把--放在这里,那么num等于0就不会进入循环操作,那么*(pdest + 0) = *(psrc + 0)就不会进行,结果会出错!
}
return dest;
}
else
{
while (num--)
{
*pdest++ = *psrc++;
}
return dest;
}
}
int main()
{
char str[20] = "abcdefg123";
my_memmove(str + 1, str, 10);
printf("%s\n", str);
system("pause");
return 0;
}