前言
之前一直在个人博客上写作(Hexo + Github Actions)但由于比国内访问比较慢,因此转移到CSDN,这样加载比较快,方便便自己的温习。
曾经待过的平台:掘金,博客园,Github+Hexo,Typecho + Handsome(阿里云) …
这篇博客是大一临近期末考试做的。
正文:
1.平均数
计算输入数字的平均数
#include<stdio.h>
int main()
{
int x;
double sum = 0;
int cnt = 0;
scanf("%d",&x);
while(x!=-1) //输入数字-1时截止
{
sum +=x;
cnt++;
scanf("%d",&x);
}
if(cnt != 0){
printf("%lf",sum/cnt);
}
return 0;
}
2.平均数_plus
计算输入数字的平均数,输出大于平均数的数字
#include<stdio.h>
int main()
{
int x;
double sum = 0;
int cnt = 0;
int number[100]; //定义数组
scanf("%d",&x);
while(x!=-1)
{
number[cnt] = x; //对数组元素赋值
sum +=x;
cnt++;
scanf("%d",&x);
}
if(cnt != 0){
printf("%lf",sum/cnt);
int i;
for(i=0;i<cnt;i++) //遍历数组中元素
{
if(number[i] > sum/cnt) //使用数组中的元素
printf("%d\n",number[i]);
}
}
return 0;
}
知识点:
数组定义:
<类型> 变量名称[元素数量]
eg:
int number[100];
数组特点:
- 数组中元素在内存中是连续依次排列的
- 其中元素具有相同的数据类型
- 一旦创建,不能改变大小
- 数组中放在[]中数字叫做下标或者索引,下标从0开始计数
3.统计数字出现次数
写一个程序,输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数 ,输入-1表示结束
000版
#include<stdio.h>
int main()
{
int x;
scanf("%d",&x);
int count[10]; //数组大小
for(int i=0;i<10;i++)
{
count[i] = 0; //初始化数组
}
while(x!=-1){
if(x>=0&&x<=9){
count[x]++;
}
scanf("%d",&x);
}
for(int i=0;i<10;i++)
{
printf("%d:%d\n",i,count[i]);
}
return 0;
}
001版
#include<stdio.h>
int main()
{
const int number = 10; //数组大小
int x;
scanf("%d",&x);
int count[number]; //定义数组
for(int i=0;i<number;i++)
{
count[i] = 0; //初始化数组
}
while(x!=-1){
if(x>=0&&x<=9){
count[x]++; //数组参与运算
}
scanf("%d",&x);
}
for(int i=0;i<number;i++)
{
printf("%d:%d\n",i,count[i]);
}
return 0;
}
4.求素数的和
000版
#include<stdio.h>
int main()
{
int m,n; //输入素数的取值范围:[m,n]
int sum = 0;
int cnt = 0;
int i;
scanf("%d %d",&m,&n);
// m =10, n =31;
if(m == 1) m=2;
for(i =m;i<=n;i++){
int isPrime = 1;
int k;
for(k=2;k<i-1;k++){
if(i%k == 0){
isPrime = 0;
break;
}
}
if(isPrime){
sum+=i;
cnt++;
}
}
printf("%d %d\n",cnt,sum);
return 0;
}
001版_通过定义isPrime函数判断是否是素数
#include<stdio.h>
int isPrime(int i)
{
int ret = 1;
int k;
for(k=2;k<i-1;k++)
{
if(i%k == 0){
ret = 0;
break;
}
}
return ret;
}
int main()
{
int m,n;
int sum = 0;
int cnt = 0;
int i;
scanf("%d %d",&m,&n);
// m =10, n =31;
if(m = 1) m=2;
for(i =m;i<=n;i++)
{
if(isPrime(i))
{
sum+=i;
cnt++;
}
}
printf("%d %d\n",cnt,sum);
return 0;
}
5.求和函数
000版
//求和
#include<stdio.h>
void sum(int begin,int end)
{
int i;
int sum = 0;
for(i = begin;i <= end;i++ )
{
sum += i;
}
printf("%d到%d的和为%d\n",begin,end,sum);
}
int main()
{
sum(1,10);
sum(20,30);
sum(35,45);
return 0;
}
001版
#include<stdio.h>
void sum(int begin,int end) //函数头
{
//函数体
int i;
int sum = 0;
for(i = begin;i <= end;i++ )
{
sum += i;
}
printf("%d到%d的和为%d\n",begin,end,sum);
}
int main()
{
int begin,end;
while(scanf("%d %d",&begin,&end))
{
sum(begin,end);
}
return 0;
}
知识点:
- 什么是函数?
- 函数是一块代码,接收零个或多个参数,做一件事情,并返回零个或一个值
- 函数定义
- 函数头【
返回类型 函数名(参数表)
<=>void sum(int a)
】 + 函数体
- 函数头【
6.比较大小
#include<stdio.h>
int max(int a,int b)
{
int ret;
if(a > b){
ret = a;
}
else{
ret = b;
}
return ret;
}
int main()
{
int a,b;
while(scanf("%d %d",&a,&b)){
printf("max = %d\n",max(a,b));
}
return 0;
}
知识点:
- C的编译器自上而下顺序的的分析代码,存在函数的先后关
7.数组元素的查找
// 在一组给定的数据中,如何找出某个数据是否存在?
#include<stdio.h>
/*
找出k在数组a中的位置
@param key 要寻找的数字
@param a 要寻找的数组
@param length 数组a的长度
@return 如果找到,返回其在a中的位置;如果找不到,则返回-1
*/
int search(int key,int a[],int length);
int main(void)
{
int a[]={2,4,6,7,1,3,5,9,11,13,23,14,32};
int x;
int loc;
printf("请输入一个数字:");
scanf("%d",&x);
loc = search(x,a,sizeof(a)/sizeof(a[0]));
if(loc != -1){
printf("%d在%d个位置上\n",x,loc);
}else{
printf("%d不存在\n",x);
}
return 0;
}
int search(int key,int a[],int length)
{
int ret = -1;
int i;
for(i=0;i<length;i++)
{
if(a[i] == key)
{
ret = i;
break;
}
}
return ret+1;
}
- 个人理解:
- 先定义查找函数,遍历需要查找的数组,返回查找到的数组的下标,否则,返回-1.
- 知识点
- 返回数组的长度
length = sizeof(a)/sizeof(a[0])
- 数组变量本身不能赋值,eg:
b[] = a
,错误;要把一个数组元素赋给另一个数组,需要遍历一个循环,将每一个元素赋给另一个数组。 - C99中特有的给数组中元素初始化:
int a[] = {[1]=3,4,[5]=7};
- 返回数组的长度
8.素数判断
判断素数 - 01
/*
质数又称素数,是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
*/
#include<stdio.h>
int isPrime(int x)
{
int ret = 1;
int i;
if(x == 1) ret = 0;
for(i = 2 ;i < x;i++)
{
if(x % i == 0)
{
ret = 0;
break;
}
}
return ret;
}
int main()
{
int x;
int loc;
printf("请输入需要判断的数:");
scanf("%d",&x);
loc = isPrime(x);
if(loc != 0)
printf("%d 是素数\n",x);
else
printf("%d 不是素数\n",x);
return 0;
}
判断素数 - 02
#include<stdio.h>
#include<math.h>
int isPrime(int x)
{
int ret = 1;
int i;
if(x == 2 || (x % 2 == 0 && x != 2))
ret = 0;
for(i = 3;i < x; i += 2) // for(i = 3;i < sqrt(i);i += 2)
{
if(x % i == 0){
ret = 0;
break;
}
}
return ret;
}
int main()
{
int x;
int loc;
printf("请输入需要判断的数:");
scanf("%d",&x);
loc = isPrime(x);
if(loc != 0)
printf("%d 是素数\n",x);
else
printf("%d 不是素数\n",x);
return 0;
}
素数 - 03
//判断是否能被已知的,且小于x的素数整除
#include<stdio.h>
int isPrime(int x,int knowPrimes[],int number0fKnownPrimes)
{
int ret = 1;
int i;
for(i = 0;i < number0fKnownPrimes;i++)
{
if(x % knowPrimes[i] == 0){
ret = 0;
break;
}
}
}
int main(void)
{
const int number = 100;
int prime[number] ={2};
int count = 1;
int i = 3;
while(count < number){
if(isPrime(i,prime,count)){
prime[count++] = i;
}
i++;
}
for(i = 0;i <number; i++)
{
printf("%d",prime[i]);
if((i + 1)% 5) printf("\t");
else printf("\n");
}
return 0;
}
构造素数表
- 欲构造n以内(不含)的素数表
- 1.开辟
prime[n]
,初始化其所有元素为1
,prime[x]
为1
表示×是素数 - 2.令
x=2
- 3.如果x是素数,则对于
(i=2;x*i<n;i++)
令prime[i*x]=0
- 4.令
x++
,如果x<n
,重复3,否则结束
- 1.开辟
// 构造素数表
#include<stdio.h>
int main()
{
const int maxNumber = 25;
int isPrime[maxNumber];
int i;
int x;
for(i = 0;i<maxNumber;i++)
{
isPrime[i] = 1;
}
for(x = 2;x < maxNumber;x++)
{
if(isPrime[x])
{
for(i = 2; i*x<maxNumber;i++)
{
isPrime[i*x] = 0;
}
}
}
for(i = 2;i<maxNumber;i++)
{
if(isPrime[i])
{
printf("%d\t",i);
}
}
printf("\n");
return 0;
}
9.搜索的例子(线性)
01版
#include<stdio.h>
int amount[] = {1,5,10,15,25,50};
const char *name[] = {"penny","nickel","dime","quarter","half-dollar"};
int search(int key,int a[],int len)
{
int ret = -1;
int i;
for(i = 0;i < len;i++)
{
if(key == a[i])
{
ret = i;
break;
}
}
return ret;
}
int main()
{
int k = 10;
int r = search(k,amount,sizeof(amount)/sizeof(amount[0]));
if(r > -1)
{
printf("%s\n",name[r]);
}
return 0;
}
02版
- 优点:效率,搜索次数
log2n,以二为底
eg:100个数-7次,1000个数-10次 - 缺点: 数组内数据有序
#include<stdio.h>
int amount[] = {1,2,3,4,5,6,7,8,9,11,22,44,56,88,99};
int search(int key,int a[],int len)
{
int ret = -1;
int left = 0;
int right = len - 1;
while(left < right)
{
int mid = (left + right)/2;
if(a[mid] == key)
{
ret = mid;
break;
}
else if(a[mid] < key)
{
left = mid +1;
}
else
{
right = mid - 1;
}
}
return ret;
}
int main()
{
int i;
int k = 2;
int r;
r = search(k,amount,sizeof(amount)/sizeof(amount[0]));
if(r>-1)
{
printf("%d\n",r+1);
}
return 0;
}
10.指针
-
*
是一个单目运算符,用来访问指针的值所表示的变量
可以做右值,也可以做左值
int k = *p;
*p = k+1;
-
代码:
#include<stdio.h>
void f(int *p);
void g(int k);
int main()
{
int i = 99;
printf("&i = %p\n",&i);
f(&i);
g(i);
return 0;
}
void f(int *p)
{
printf("p = %p\n*p = %d\n",p,*p); // p访问的是变量的地址,*p访问的是变量的值
*p = 26; // 通过*p访问i来改变i的值
}
void g(int k)
{
printf("k = %d\n",k);
}
-
如何在调用函数内部改变全局变量的值(c++描述)
- 一、使用return
#include <iostream.h> char* foo() { char* p = "after foo()"; return p; } void main() { char* p = "before foo()"; p = foo(); cout<<p<<endl; }
- 二、使用指针引用
#include <iostream> void foo(char *& q) { q = "after foo()"; } void main() { char *p = "before foo()"; foo(p); cout <<p <<endl; }
该程序将p的地址传给foo,则p=&q,而p是字符串变量的内存地址,那么&q也是字符串变量的内存地址,则q也是指向该字符串变量所在内存的指针。 简单的说foo中的q这时是p的引用(别名),q和p共享同一个内存空间。这时在foo中修改q指向的内存空间的字符串内容,main中p的值当然也随之变化。
- 三、使用指向指针的指针
#include <iostream.h> void foo(char ** p) { *p = "after foo()"; } void main() { char **p = "before foo()"; foo(p); cout <<*p<<endl; }
main中p是指向指针的指针,即它的值的值是指向字符串变量内存的指针的地址,在foo中*p就表示该指针,即字符串变量内存的地址。所以修改*p的值自然可以修改该内存的内容。
-
数组变量本身表示的就是地址
int a[10];int *p = a; // 无需用&取地址
p[0] == a[0]
- 但是数组单元表达的变量需要用取地址符
a == &a[0]
- 数组变量是
const
的指针,所以不能被赋值
11.指针与字符串
#include<stdio.h> int main() { int i = 0; char *s = "Hello World"; // s是一个指针,初始化指向一个字符串常量 // s[0] = 'B'; 不能修改 char *s2 = "Hello World"; char s3[] = "Hello World"; printf("&i = %p\n",&i); printf("s = %p\n",s); printf("s2 = %p\n",s2); printf("s3 = %p\n",s3); s3[0] = 'B'; printf("Here!s3[0] = %c\n",s3[0]); return 0; }
char *s = 'Hello World';
s
是一个指针,初始化指向字符串常量。- 由于这个常量所在的地方,所以
s
实际上是const char* s
。由于历史原因,编译器接受不带const
的写法。 - 但试图对
s
所指的字符串做写入操作,会导致严重后果!
- 如果需要修改字符串,应该用数组:
char s3[] = 'Hello World!';
- 但是数组单元表达的变量需要用取地址符
知识点:
-
一.
-
char *str = 'Hello!';
-
char word[] = 'Hello!';
-
数组:这个字符串在这里
- 作为本地变量空间自动被回收。
-
指针:这个字符串不知道在哪里
- 处理参数
- 动态分配空间
-
二.
-
char*
是字符串?- 字符串可以表达为
char*
的形式 char*
不一定是字符串- 本意是指向字符的指针,可能指向的是字符的数组(就像
int*
一样) - 只有它所指的字符数组有结尾的
0
才能说他所指的是字符串
- 本意是指向字符的指针,可能指向的是字符的数组(就像
- 字符串可以表达为
-
三.
-
字符串输入:
-
scanf
读入一个单词(到空格、tab或回车为止)-
char string[8]; scanf("%7s",string);
- 在%和s之间的数字表示最多允许读入的字符的数量,这个数字应该比数组的大小小一
-
-
-
12.字符串的计算(#include<string.h>
)
1.strlen,sizeof
#include<stdio.h>
#include<string.h>
int main(int argc,char const *argv[])
{
char line[]= "Hello";
printf("strlen = %lu\n",strlen(line)); // strlen返回字符数,%lu - 32位无符号整数
printf("sizeof = %lu\n",sizeof(line)); // sizeof返回需要的空间
return 0;
}
2.strcmp
int strcmp(const char *s1,const cahr *s2);
- 比较两个字符串,返回:
0
:s1 ==s2
1
:s1 > s2
-1
:s1 < s2
3.strcpy
char *strcpy(char *restrict dst,const char *restrict stc);
- 把
str
字符串拷贝到dst
restrict
表示src
和dst
不重叠(C99)
- 返回
dst
- 为了能链起代码来
4.strcat
char *strcat(char *restrict s1,const char *restrict s2);
- 把
s2
拷到s1
后面,形成一个长的字符串 - 返回
s1
s1
必须具有足够的空间