大神养成之路上的经验教训,持续不定期更新ing

1、scanf和gets在读入字符串到char数组变量后会在变量中字符串后自动加'\0',当不用这两个输入函数时注意在变量中字符串后自己补上'\0',否则用输出函数printf和puts时就会出现错误。
#include<stdio.h>

int main()
{
	char s[10];
	scanf("%s", s);
	int i = 0;
	while (s[i] != '\0')
	{
		i++;
	}
	s[i] = 's';
	printf("%s\n",s);
	return 0;
}

上图是刚输入s时。


上图是将s中字符串末尾的'\0'改为's'字符后。


上图是打印的结果。

2、除指定"%c"格式外的scanf和gets都以空白符('\0'、空格、换行符等)作为输入结束标志。由于输入时总以换行来表示输入结束,那么在scanf一行数据后需要用getchar函数将'\n'吸收掉,然后才能用gets函数,因为gets函数是以换行符作为结束标志,它的作用就是把一行吸收掉但不包括末尾的'\n'。

#include<stdio.h>

int main()
{
	int s;
	scanf("%d", &s);
	int i = 0;
	char s1[10];
	//getchar();
	gets_s(s1);
	return 0;
}
/*
123
456
*/
将123'\n'456直接复制到cmd中发现第二行根本读不出来,但将getchar的注释去掉就可以了。(由于编译器的问题,gets_s是gets的安全版)

3、putchar和getchar分别是用于单个字符输出和输入的,也就是说0~127内任何一个字符都能进行处理,包括'\0'(NULL字符)、空白符以及换行符'\n'等。这里再说一下指定格式为"%s"的scanf与gets的区别,前者以空白符作为输入结束标志。而后者以换行符作为结束标志。相应的printf与puts的区别类比即可。

#include<stdio.h>

int main()
{
	char s1[100],s2[100];	
	gets_s(s1);
	scanf("%s", s2);
	printf(s1);
	printf("\n");
	printf(s2);
	printf("\n");
	return 0;
}
/*
123  56 165 1
123  56 165 1
*/

结果如上图所示。


4、进行循环输入时,不推荐用while(n--)这种形式,往往很多算法题需要再次用到n,那么你就得声明一个新的变量来保存n。还有一点就是,在有循环结构的代码中,循环变量必须得放好位置和进行改变,否则循环结构无法推进。再就是scanf中取址运算符一定要加到非数组变量名前面(数组变量名本身就可以表示地址所以不需要取址)。然后就是在刷题时应注意到题目所给定的各个变量的取值范围以及格式的控制,不要一开始就想着用暴力算法来解决问题,像输入的值累加依次保存到数组变量中然后变量相减算差值(Dijkstra题)、二分查找(大数据查询题)、大整数模除截取部分(日期差值)等都可以降低时间的复杂度。有很多涉及大整数的问题能不用字符串处理尽量不用,因为字符串的比较与整数的比较在某些例子上可能不一致,直接对大整数进行模除跟对字符串进行截断是一样的效果,而且模除还省了字符串转整型的麻烦。下面附上日期差值的两段代码,未注释的能AC,注释的不能AC,这就体现大整数模除的优越性。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
int main()
{
	int n1, n2, temp;
	while (scanf("%d%d", &n1, &n2) != EOF)
	{
		if (n1 > n2)
		{
			temp = n1;
			n1 = n2;
			n2 = temp;
		}
		int y1, y2, m1, m2, d1, d2;
		y1 = n1 / 10000; y2 = n2 / 10000;
		m1 = n1 % 10000 / 100; m2 = n2 % 10000 / 100;
		d1 = n1 % 100; d2 = n2 % 100;

		int month[13] = { 29,31,28,31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		int cnt = 1;
		while (n1 != n2)
		{
			cnt++;
			d1++;
			if (m1 == 2)
			{
				if (y1 % 400 == 0 || (y1 % 100 != 0 && y1 % 4 == 0)) //run nian
																	 //可以用这条件返回值来离散化,建立一个二维数组month[13][2]
				{
					if (d1>29)
					{
						d1 = 1; m1++;
					}
				}
				else  //ping nian
					if (d1>28) { d1 = 1; m1++; }
			}
			else
			{
				if (d1>month[m1])
				{
					d1 = 1; m1++;
				}
			}
			if (m1 == 13) { m1 = 1; y1++; }
			n1 = y1 * 10000 + m1 * 100 + d1;
		}
		printf("%d\n", cnt);
	}

	return 0;
}
/*
#include<stdio.h>
#include<string.h>
#include<math.h>
char*subString(char*c, int i, int j)
{
	char s[10];
	int a = 0;
	for (int k = i; k <= j; k++)
	{
		s[a++] = c[k];
	}
	s[a] = '\0';
	return s;
}//截断子串
int StringToInt(char*c)
{
	int i = 0;
	int len = strlen(c);
	int sum = 0;
	while (c[i] != '\0')
	{
		sum += (c[i] - '0')*pow(10, len - 1 - i);
		i++;
	}
	return sum;
}//字符串转为整型
bool checkCommonYear(int y)
{
	if (y % 4 == 0 && y % 400 != 0 || y % 400 == 0)
		return false;
	else
		return true;
}//判断是否是平年
int main()
{
	char date1[10], date2[10];
	while (scanf("%s%s", date1, date2) != EOF)
	{
		char date11[10], date22[10];
		//	if (!(strcmp(date1, date2)))
		//{
		//printf("0\n");
		//continue;
		//}
		strcpy(date11, (strcmp(date1, date2) < 0 ? date1 : date2));
		strcpy(date22, (strcmp(date1, date2) > 0 ? date1 : date2));
		char year1[10], year2[10], month1[10], month2[10], day1[10], day2[10];
		strcpy(year1, subString(date11, 0, 3));
		strcpy(year2, subString(date22, 0, 3));
		strcpy(month1, subString(date11, 4, 5));
		strcpy(month2, subString(date22, 4, 5));
		strcpy(day1, subString(date11, 6, 7));
		strcpy(day2, subString(date22, 6, 7));
		//printf("%s %s %s\n%s %s %s\n", year1, month1, day1, year2, month2, day2);
		int year11 = StringToInt(year1), year22 = StringToInt(year2);
		int sum = 0;
		for (int i = year11; i <year22; i++)
		{
			if (checkCommonYear(i))
			{
				sum += 365;
			}
			else
				sum += 366;
		}
		int month11 = StringToInt(month1), month22 = StringToInt(month2);
		int day11 = StringToInt(day1), day22 = StringToInt(day2);
		int sum1 = 0, sum2 = 0;
		for (int i = 1; i < month11; i++)
		{
			if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12)
			{
				sum1 += 31;
			}
			else if (checkCommonYear(year11) && i == 2)
			{
				sum1 += 28;
			}
			else if (!checkCommonYear(year11) && i == 2)
			{
				sum1 += 29;
			}
			else
				sum1 += 30;
		}
		sum1 += day11;
		for (int i = 1; i < month22; i++)
		{
			if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12)
			{
				sum2 += 31;
			}
			else if (checkCommonYear(year22) && i == 2)
			{
				sum2 += 28;
			}
			else if (!checkCommonYear(year22) && i == 2)
			{
				sum2 += 29;
			}
			else
				sum2 += 30;
		}
		sum2 += day22;
		sum += sum2 - sum1 + 1;
		printf("%d\n", sum);

	}
	return 0;
}
*/




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值