C语言经典程序
1、输入一行字符统计单词个数
- 输入一行字符串,统计其中有多少单词,单词之间用空格符号隔开
#include<stdio.h>
int main() {
printf("请输入一行字符串:");
int i = 0, word = 0;
char str[81];
gets_s(str);
while (str[i] != '\0') {
if (str[i] == ' ') {
//跳过所有空白字符
for (i++; str[i] == ' '; i++);
}
else {
word++;
//跳过所有非空格,即一个单词
for (i++; str[i] != ' ' && str[i] != '\0'; i++);
}
}
printf("字符串单词数量:%d", word);
return 0;
}
1、字符串以
'\0'
作为结束标志
2、for循环内的 第一部分的i++ 类似开关,使得下标能指向下一位元素进行判断
2、输出不重复三位数
- 有0、1、2、3、4共5个数字 能组成多少个互不相同且无重复
数字的3位数?并输出这些数
#include<stdio.h>
int main() {
int i, j, k, count = 0;
for (i = 1; i < 5; i++) {
for (j = 0; j < 5; j++) {
for (k = 0; k < 5; k++) {
if (i != j && i != k && j != k) {
printf("%d ", i * 100 + j * 10 + k);
count++;
}
if (count % 5 == 0) {
printf("\n");
}
}
}
}
printf("\n3位数总个数=%d\n", count);
}
1、枚举列出所有情况,再从其中进行筛选
2、无重复数字 =( i != j && i != k && j != k)
3、注意百位不包括数字0
3、水仙花数
3.1 方法一:枚举法
#include<stdio.h>
#include<math.h>//使用三次方函数pow
int main() {
int i, j, k,count=0,number;
for (i = 1; i < 9; i++) {
for (j = 0; j < 9; j++) {
for (k = 0; k < 9; k++) {
number = i * 100 + j * 10 + k;
//153 = 1的三次方 +5的三次方 +3的三次方
if ( number==(pow(i,3) + pow(j,3) + pow(k,3)) ){
printf("%d ",number);
count++;
}
}
}
}
printf("\n水仙花数个数=%d\n",count);
}
3.2 方法二:取出各个位数
#include<stdio.h>
#include<math.h>//使用三次方函数pow
int main() {
int ge, shi, bai,count=0;
for (int i = 100; i < 1000; i++) {
ge = i % 10;
shi = i / 10 % 10;;
bai = i / 100;
if (i == pow(bai, 3) + pow(shi, 3) + pow(ge, 3)) {
printf(" %d", i);
count++;
}
}
printf("\n水仙花数个数: %d", count);
}
1、方法二的使用更加广泛,在应对求更大范围的水仙花数时更加实用
4、完数
方法一:枚举法
#include<stdio.h>
//找出一万以内的完数 完数:6=1+2+3, 28=1+2+4+7+14 本身等于其因子之和
int main() {
int i, j, sum,count=0;
//列出所有数
for (i = 1; i < 10000; i++) {
sum = 0;//注意每次要先清空上一次的因子之和
for (j = 1; j < i; j++) {
//选出其中所有的的因子
if (i % j == 0) {
sum += j;
}
}
//本身等于因子之和
if (sum == i) {
printf("%d ", sum);
count++;
}
}
printf("\n一万以内完数的个数:%d", count);
}
方法二:算法
书本P156 有提升性能的算法 以根号i作为一个分水岭,因子关于其对称,当出现两边因子相同则要减去一个
5、判断整数重复数字
- 输入一个不超过9位数的无符号整数,判断该整数中是否存在重复数字
#include<stdio.h>
//输入一个不超过9位数的无符号整数,判断该整数中是否存在重复数字
int main() {
int num,n,i;
int count[10]={0};//统计数字出现次数
printf("请输入一个正整数:");
scanf("%d", &num);
n = num;
//分类数字的个位,统计每个数字出现的次数
while (n != 0) {
count[n % 10]++;
n = n / 10;
}
//遍历查找数组的记录的值
for (i = 0; i < 10; i++) {
if (count[i] > 1) {
break;
}
}
if (i < 10 ) {
printf("%d存在重复数字", num);
}
else
{
printf("%d不存在重复数字", num);
}
}
用一个数组通过每次截取个位数,实现记录每位数字出现的次数。这种思想要学会
6、插入升序数组,使插入后还是升序
#include<stdio.h>
#define N 10
int main() {
//多预留了一位空位置用于放插入数据
int arr[N] = { 1,2,10,13,20,32,40,67,80 },*p=arr+N-2,in;//使指针指向最后数组最后一位
printf("请输入要插入的数字:");
scanf("%d",&in);
//进行反向扫描
while (p >= arr) {
if (*p > in) {
//将值移动到右边
*(p + 1) = *p;
p--;
}
else{
break;
}
}
//循环结束后指针移动到了比待插入数字要小的数字处 在其右边插入
*(p + 1) = in;
printf("插入后的数组:");
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
}
指针倒序扫描找到待插入位置,在其右侧插入
7、字符串中提取整数
- 假设输入的字符串中有数字和非数字字符(如"a123x456 17960? 302tab799“), 编写程序找出字符串中所有由连续的数字字符组成的整数(如123、456、19960、302、6799),并统计共找到多少个整数
#include<stdio.h>
//假设输入的字符串中有数字和非数字字符(如"a123x456 17960? 302tab799“)
int main() {
char str[81],*p=str;//将数组的首地址给指针p,用于便利每一个字符
int count=0, num, i;//count:记录次数,num:每个数字,i:控制循环
printf("请输入一行字符:");
gets_s(str);
while (*p) { // '\0'的ASCll为0,扫描到末尾则跳出循环
//遇到数字
if (*p > '0' && *p < '9') {
//遇到连续的数字
for (num = 0; *p > '0' && *p < '9' ;p++) {
num = num * 10 + (*p - '0');
}
count++;
printf("NO %d:%d\n", count, num);
}
//遇到非数字,跳过
else {
//跳过所有非数字,这里可有可无
if(*p != '\0' && ( * p > '0' || *p < '9')) {
p++;
}
}
}
}
8、两个升序数组合并成一个
#include<stdio.h>
//数组名本身就是首元素的地址,即指向首元素的指针
void merge_sort(int *x, int lenx,int *y, int leny,int* z) {
int i=0, j=0, k=0;
//只要小于数组长度就继续比较
//比较后较小的数组会消失,留下两数组的差值部分没有比较,直接存入
while (i < lenx && j < leny) {
if (x[i] < y[j]) {
z[k++] = x[i++]; //等价于 z[k[ = x [i]; k++; i++;
}else{
z[k++] = y[j++];
}
}
//如果其中一个数组还有剩余,则按顺序依次存入
while (lenx > i) {
z[k++] = x[i++];
}
while (leny > j) {
z[k++] = y[j++];
}
}
//两个升序数组合并成一个
int main() {
int a[10] = { 0,3,6,9,10,18,23,25,30,35 };
int b[8] = { -5,-1,1,2,5,11,28,40 };
int i, c[18];
printf("原始数组a:");
for (i = 0; i < 10; i++) {
printf("%d ", a[i]);
}
printf("\n原始数组b:");
for (i = 0; i < 8; i++) {
printf("%d ", b[i]);
}
merge_sort(a,10,b,8,c);
printf("\n合并后的新数组c:");
for (i = 0; i < 18; i++) {
printf("%d ", c[i]);
}
}
运用数组下标和本身就是升序的特性将两个旧数组进行比较存储,余下的再按顺序存储
9、字符串匹配
- 设主串数组名为S,子串数组名为T,找出子串T在主串S中第一次出现的位置
#include<stdio.h>
#include<string.h>
//字符串匹配
//设主串数组名为S,子串数组名为T,找出子串T在主串S中第一次出现的位置
int index(char *s,char *t,int start) {
int i = start, j = 0; //i作为母串的起始位置 j为子串的起始位置 都用于便利字符串
int m = strlen(s), n = strlen(t);//m:母串长度,n:子串长度
if (start<0 || n == 0 || start + n>m) {
return -1;
}
while (i < m && j<n ) {
//相同则移动到下一位继续比较
if (s[i] == t[j]) {
i++;
j++;
}
//不同则将子串清空,母串从不相同元素的下一位开始
else {
i = i-j + 1;
j = 0;
}
}
//如果比较出来的子串长度等于原长度,说明母串中存在子串
if (n == j) {
return(i - n);//子串在母串中的起始位置
}
else {
return -1;
}
}
int main() {
char S[] = "abcdegdefg", T[] = "def";
//成功返回子串在主串的起始位置,失败返回-1
int num = index(S, T, 1);
printf("子串在主串的起始位置:%d", num+1);//下标从0开始,返回的位置是6
}
运用下标逐个比较,注意不相符的比较需要将 主串的起始位置移动到主串的下一位 子串从头开始 再次进行逐个比较
10、学生加权平均成绩
- 4个学生,每个学生有3门课程的成绩,每门课程的学分不一样。请计算每一个学生的加权成绩
#include<stdio.h>
//传入每一个学生的成绩和每门课程的学分
float aver(int x[], int y[]) {
int i,sum1=0,sum2=0;//sum1记录成绩*学分,sum2记录总学分
for (i = 0; i < 3; i++) {
sum1 += x[i] * y[i];
sum2 += y[i];
}
return ((float)sum1 / sum2);
}
//4个学生,每个学生有3门课程的成绩,每门课程的学分不一样。请计算每一个学生的加权成绩
int main() {
int scores[4][3] = { {81.92,88},{99,88,98},{95,86,90},{90,90,90} };
int credit[3] = { 3,4,2 };
float p;
for (int i = 0; i < 4; i++) {
//传入每个学生各自的成绩,和成绩对应的学分
p = aver(scores[i], credit);
printf("第%d个学生的加权成绩:%.2f\n", i + 1, p);
}
return 0;
}
11、字符串中找出字符
#include<stdio.h>
char* strch(char* s, char ch) {
//跳过不匹配的字符
while (*s && *s != ch) {
s++;
}
//如果不是读到了末尾,则返回当前匹配的字符指针
if (*s) {
return s;
}
return NULL;
}
//在一串字符串中找出某一个字符
int main() {
char str[81] = "abcdefg", ch = 'h', * p = str,*s;
s= strch(p,ch);
if (s == NULL) {
printf("字符串中不存在该字符!");
}
printf("从字符串中找出的字符:%c", *s);
}
运用指针,对字符串中的每个字符依次比较,相同则将指针移动一位直至比到相同的元素,返回指向其的指针
12、折半查找某数是否在升序数组中
#include<stdio.h>
//p指向一维数组,n是数组长度,key为查找关键字 找到返回元素下标,否则返回-1
int search(int* p, int n, int key) {
int low = 0, high = n-1, mid,result=-1;
while(high > low) {
//折半查找
mid = (low + high) / 2;
if (p[mid] == key) {
result = mid;
break;
}
else if (p[mid] > key) {//待查找数字小于中间数,即在左边,需要缩小最大值
high = mid - 1;
}
else {//在右边,需要放大最小值
low= mid + 1;
}
}
return result;
}
//用折半查找法找某数是否在给定的升序数组中
int main() {
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int result = search(arr, 10, 8);
printf("查找结果位于的下标:%d", result);
}