【c语言】五道经典练习题④

 

目录

①、年月日经过n天后的日期

 ②、坐标排序

③、统计文件中出现某个单词的次数

④、输出含for的行

⑤、比较两个文本是否相等


①、年月日经过n天后的日期

题述:定义包含年月日表示的日期的结构体,写程序实现计算某年某月某日过n天后的日期是哪年哪月哪日

思路:

1、这种题因为关于年了,那就应该判断是闰年还是平年,因为会导致2月的天数不同,闰年2月29天。

2、越界问题,无非是月越界或者年越界,因为过n天,这个n你没有指定范围,那他可以无限大也可以无限小,当天数超过本月应有的天数时,月份应该++,并且n应该减掉本月天数。如果月份>12了,年份应该++,并且再判断,上述过程全放在while循环中,直到n是一个正常的月份天数为止。

#include<stdio.h>

typedef struct date
{
	int year, month, day;
}date;
int main()
{	//闰年二月有29天
	int day[2][13] = { {0,31,28,31,30,31,30,31,31,30,31,30,31},{0,31,29,31,30,31,30,31,31,30,31,30,31} };
	date a = { 0 };
	printf("请输入年月日:>\n");
	scanf("%d %d %d", &a.year, &a.month, &a.day);
	int leap = (a.year % 400 == 0) || ((a.year % 4 == 0) && (a.year % 100 == 0));
	int n = 0;
	printf("请输入过多少天:>\n");
	scanf("%d", &n);
	a.day += n;
	while (a.day > day[leap][a.month])
	{//为什么是while循环,因为你输入的天数没有限制范围,他可能很大也可能很小
		a.day -= day[leap][a.month];
		a.month++;
		if (a.month > 12)
		{
			a.month %= 12;
			a.year++;
			//那么年数变了,还要再次判断是否是闰年
			leap = (a.year % 400 == 0) || ((a.year % 4 == 0) && (a.year % 100 == 0));
		}
	}
	printf("经过%d天后为%d年%d月%d日\n",n, a.year, a.month, a.day);
	system("pause");
	return 0;
}

 ②、坐标排序

题述:输入n个点,对这些点的x轴坐标排序并输出

思路:关键就是冒泡排序的应用罢了

#include<stdio.h>
typedef struct
{
	int x, y;
}coord;
int main()
{
	int n = 0;
	printf("你想输入几个坐标:>\n");
	scanf("%d", &n);
	coord s[20];
	for (int i = 0; i < n; i++)
	{
		scanf("%d %d", &s[i].x, &s[i].y);
	}
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = 0; j < n - 1 - i; j++)
		{
			if (s[j].x > s[j+1].x)
			{
				int temp = s[j].x;
				s[j].x = s[j+1].x;
				s[j+1].x = temp;
			}
		}
	}
	for (int i = 0; i < n; i++)
	{
		printf("第%d个坐标:(%d,%d)\n", i + 1, s[i].x, s[i].y);
	}
	return 0;
}

③、统计文件中出现某个单词的次数

题述:文件in.txt存放了一篇文章,从键盘输入某个单词,请统计文章中这个单词出现的次数并输出

思路:打开读取文章的文件,然后每次从文件中读取一行文本,fgets每次读取一行,并且遇到失败或者读到文件结尾返回NULL,因此不能直接用过fgets的返回值来判断函数是否出错而终止,应借助feof函数或者ferror函数来判断)如果已经读到文件末尾则退出循环。在每一行文本中查找单词出现的位置,如果查找到则统计次数并指向单词后面一个字符的位置继续查找,直到这行文本中不存在单词为止。

#include <stdio.h>
#include <string.h>
#define MAX_LEN 1000 // 假设文章最大长度不超过1000

int main() {
    char word[MAX_LEN]; // 用户输入的单词
    char filename[] = "in.txt"; // 文章文件路径
    char line[MAX_LEN]; // 保存读入的一行文本
    int count = 0; // 统计单词出现次数的变量
    FILE* file = fopen(filename, "r"); // 以只读方式打开文件
    if (file == NULL) {
        printf("Failed to open file '%s'.\n", filename);
        return 1;
    }
    printf("Please input a word: ");
    scanf("%s", word); // 读入一个单词
    while (!feof(file)) { // 循环读取一行文本
        fgets(line, MAX_LEN, file);
        char* p = line;
        while ((p = strstr(p, word)) != NULL) { // 查找单词出现的位置
            count++;
            p += strlen(word); // 指向单词后一个字符的位置
        }
    }
    printf("The word '%s' appears %d time(s) in the article.\n", word, count);
    fclose(file);
    return 0;
}

④、输出含for的行

题述:输出文件中含字符串"for"的行

思路:这道题是第③道题的变形,但是这道题有两种方法。

法一、与③同样的方法,调用strstr

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define N 888
int main()
{
	FILE* fp = fopen("a.txt", "r");
	if (fp == NULL)
	{
		printf("文件打开错误!\n");
		exit(0);
	}
	char s[N];
	while(!feof(fp))
	{
		fgets(s, N, fp);//一次读取一行
		char *p = s;//一个为了保存一个为了遍历
		if (strstr(p, "for") != NULL)
		{
			printf("%s", s);
		}
	}
	return 0;
}

法二、循环遍历一行的方法

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define N 888
int main()
{
	FILE* fp = fopen("a.txt", "r");
	if (fp == NULL)
	{
		printf("文件打开错误!\n");
		exit(0);
	}
	char s[N];
	while(!feof(fp))
	{
		fgets(s, N, fp);//一次读取一行
		if (strlen(s) >= 3)
		{
			for (int i = 0; i < strlen(s) - 2; i++)
			{
				if (s[i] == 'f' && s[i + 1] == 'o' && s[i + 2] == 'r')
				{
					printf("%s", s);
				}
			}
		}
	}
	return 0;
}

⑤、比较两个文本是否相等

题述:比较两个文本是否相等:比较两个文本文件内容是否相等,并输出两个文件中第一次不相同字符内容行号及列值。

思路:

1、我们可以一个一个字符比较,故用fgetc函数,那么循环终止条件应该是两个中有一个文件读到了文件尾

2、如果其中有一个文件读到了'\n',说明要换行,那么对应的列也要发生变化

3、如果读到的字符不相等有两种情况:要么就是有一个文件,或者两个文件都读到了文件尾标志EOF,要么就是字符不相等,并不是因为结束标志,这种情况需要打印行号和列号。

4、因为读到EOF和字符确实不相等的情况都会跳出循环,那我们就要判断,到底是因为读到结束标志了还是因为字符确实不相等。

#include <stdio.h>

int main( ) 
{
	FILE* fp, * fp1;
	int col1 = 1, row1 = 1, col2 = 1, row2 = 1;//两个文件内容行和列肯定都是从1开始的
	char ch1, ch2;
	//test与test1都是与当前程序在同一目录下的文件
	fp = fopen("test.txt", "r");
	fp1 = fopen("test1.txt", "r");
	while (!feof(fp) || !feof(fp1)) 
	{//循环继续的条件一定是两个文件都没读到文件尾
		ch1 = fgetc(fp);
		ch2 = fgetc(fp1);
		if (ch1 == '\n') 
		{
			row1++;//如果读到了换行,说明行数要++
			col1 = 1;//换行后列数还要是1
		}
		if (ch2 == '\n')
		{
			row2++;
			col2 = 1;
		}
		if (ch1 != ch2) 
		{
			if (ch1 == EOF || ch2 == EOF) break;//如果其中一个文件结束了,就跳出循环,因为不相等包括结束的情况
			printf("test\t行号:%d 列号:%d\n", row1, col1);//按要求,如果两个文件都没有结束的,就打印出行和列
			printf("test1\t行号:%d 列号:%d\n", row2, col2);
			break;//不相等就没有必要继续往下比了
		}
		else
		{
			col1++; col2++;//相等就列值++
		}
	}
	if (ch1 == EOF && ch2 != EOF)//能比到EOF说明之前一定有字符是相等的
		printf("test文件内容被包含在test1中");
	if (ch2 == EOF && ch1 != EOF)
		printf("test1文件内容被包含在test中");
	if (ch1 == EOF && ch2 == EOF)
		printf("两个文件完全相同!");
	fclose(fp);
	fclose(fp1);
	fp = fp1 = NULL;
	return 0;
}

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值