天天看点

printf,scanf,字符串,数组(C语言基础学习一)第一题 位数输出第二题 读入一行字符串第三题 数组递归第四题 倍数问题第五题 打印输出浮点型数据小数点后n位

学习笔记总结一

  • 第一题 位数输出
  • 第二题 读入一行字符串
  • 第三题 数组递归
  • 第四题 倍数问题
  • 第五题 打印输出浮点型数据小数点后n位

学习极客时间的人人都能学会的编程入门课的知识点总结

第一题 位数输出

1. 要求:

  • 极客时间:人人都能学会的编程入门课,第二讲,思考题:位数输出
  • 计算一个输入整数的十进制表示的位数?
  • 条件1:允许有多余输出的情况下,怎么实现?
  • 条件2:只允许输出数字位数的时候,怎么实现

    2. 代码实现

//代码来自极客空间课程
#include <stdio.h>
int main() {
    long long int n;
    scanf("%I64d", &n);
    printf(" has %I64d digits\n", printf("%I64d", n)); // 有多余输出
    char output[50];
    int ret = sprintf(output, "%I64d", n);
    printf("%I64d\n", ret); // 无多余输出
    printf("%s", output);
    return 0;
}
           

3. 总结与收获

  1. 对于sprintf()和sscanf()函数的几点新的理解
    1. 善用返回值

      printf()函数的返回值为输出字符的数量,表达错误时为负数

      sprintf() 返回值含义 与printf的类似

      scanf() 返回成功赋值的数据项数,读到文件末尾出错时则返回EOF

      eg:scanf("%d,%d", &a,&b)

      如果ab都成功读入,那么scanf的返回值就是2

      如果只有a成功,返回值为1

      如果都未成功,返回0

      如果遇到错误,或遇到end of file 返回EOF

      sscanf() 返回值与scanf类似

    2. sscanf和sprintf函数的作用:通过与scanf和printf函数比较来记忆区分
      1. printf是将格式数据打印在屏幕上,sprintf是将格式数据打印在字符串中。for example:
        printf(“%s, %c, %d”, x,y,z); //将xyz的值以逗号隔开的形式打印在屏幕上
        sprintf(str, “%s, %c, %d”, x,y,z); //将xyz以逗号隔开的形式写入到数组str中。
                   
      2. testcode(printf , sprintf)
        #include <stdio.h>
        int main()
        {
           char array[100];
           int num = 100;
           char testChar = 'B';
           char charArray[12] = "thank you!";
           printf("%s%c%d\n", charArray, testChar, num);
           sprintf(array, "%s%c%d", charArray, testChar, num);
           printf("%s", array);
           return 0;
        }
                   
      3. sscanf()函数与scanf()函数类似,都是用于输入的,前者以固定字符串为输入源,后者以屏幕为输入源。
      scanf("%d", &x);
      		char s[] = "hello, my friend";
      		sscanf(s, "%[a-z]", string);//string = hello
                 
      1. testcode(scanf sscanf)
  2. 打印printf或者输入scanf长整型(long long int )时,用格式控制符%I64d来表示

第二题 读入一行字符串

1. 要求:

  • 实现一个读入一行字符串,并且输出相关内容的程序,思考如下:
  • 条件1:如果字符串中没有空格,怎么实现?
  • 条件2: 如果字符串中没有空格,又该怎么实现?考虑纯scanf实现

2. 代码实现:

//from  极客时间 胡光
#include <stdio.h>
char str[100];
int main()
 {
    scanf("%[^\n]s", str);
    printf("%s\n", str);
    return 0;
}
           

3. 总结与收获

  1. 代码很简单,重点在于"%[^\n]s"的使用上,其中[]表示一个集合,即输入的字符串中只要不是换行符,都正常输出。
  2. strlen表示字符串的长度,不包括\0
  3. sizeof表示求取字符串所占内存的大小,包含\0占据的内存。

第三题 数组递归

1. 要求:

序读入一个整数n,假设n不会大于1000,请输出1到n的每一个数字二进制表示中的1的个数

2. 代码实现

#include <stdio.h>

int main(void){
	int array[1001];
	int number,i;
	
	scanf("%d", &number);
	array[0] = 0;
	for(i=1; i<=number; i++){
		array[i] = array[i & (i - 1)] + 1; 
	}
	for(i = 1; i<=number; i++){
		if(i!=1) printf(" ");
		printf("%d", array[i]);
	}
	printf("\n");
	return 0;
}
           

3. 总结与收获

  1. 看似毫无规律可言,可能最开始想到的办法就是把每一个数字进行统计一遍,换句话说就是判断该数字末尾的二进制码是否为1,然后进行移位操作,统计1的个数,虽然可行,但是效率不高,我刚开始就是想这么做。
  2. 慢慢发现,类似的问题其本质就是找数学规律,就好像小学时候碰到的算术题,计算0-100的数字的和,有的人就一个一个的加,有的人先看规律,然后很快就算出来了,两者之间的效率千差万别。这是一种能力,是可以锻炼出来的!
  3. 找规律
1 2 3 4 5 6 7 8 9
0001 0010 0011 0100 0101 0110 0111 1000 1001

想用递归,就得找出相邻两数字之间的练习,可以用前一个数字表示出后一个数字,那现在观察n和n-1之间的二进制数之间的关系,有两种情况:

  1. )如果n的二进制末尾为1(即奇数),则,n-1就是使n的最后一位变为0
  2. )如果n的二进制末尾为0(即偶数),则,n-1就是使n的最后一位1变为0,之后各位均为1.
  3. )通过上面的观察分析,明白了一个共同特点就是n-1让n最后一位1变成了0,然后将最后一位1之后的0全部变成1,这个时候对比n和n-1就很容易能够观察到:n的最后一位1及其后的各位,和n-1对应的位均不相同,这时候引出按位与&的概念并不突兀,也就是n&(n-1)实际上表示的是比n的二进制中1的个数少一个;
  4. )到这里,递归就派上用场了,假如arry[n]中存储的是数字n的二进制中1的个数,那么想知道2的,就得知道2&1的,3的就得先知道3&2的,以此类推,初始条件是知道的,即0的二进制中1的个数是0,那么递归就形成了。

第四题 倍数问题

1. 要求:

题目要求:设计一个去掉倍数的程序

具体内容:

  1. 读入两个整数n和m,其中n的大小不会超过10,m的大小不会超过10000;
  2. 然后再读入n个各不相同的正整数,输出无法被这n个正整数中的任意一个整除的所有数字(范围:1 - m);

2. 代码实现

#include<stdio.h>
int main(void){
	int array[10001];
	int i, j, k;
	int valueA,valueB, num;
	scanf("%d%d", &valueA, &valueB);
	printf("Please enter the number: ");
	for(i=0; i<valueA; i++){
		scanf("%d", &num);
		if(num == 1){
			printf("there is no number!\n");
			return 0;
		}
		for(j = num; j <= valueB; j += num){
			array[j] = 1;
		}
	}
	for(k=1; k<=valueB; k ++){
		if(array[k] != 1)
			printf("%d ", k);
	}
	printf("\n");
	return 0;
} 
           

3. 总结与收获

  1. 将问题想的复杂了,总是考虑一些最小公倍数,最大公约数之类的东西,可能存在一些好的办法,但是本末倒置了,首先是按照自己的思路实现出来,再优化也可以。
  2. 对我来说,问题的最大的难点在于代码在没有输入之前并不知道会有几个被整除的数字,导致在所有输入完成以后,没办法准确输出结果,很大可能会重复输出。
  3. 利用数组在输入每一个整数之后,就对其倍数进行标注,然后最后在输入完成以后统一进行输出。
  4. 所以最后请重视数组的使用。

第五题 打印输出浮点型数据小数点后n位

1. 要求:要求

题目:打印输出浮点型数据小数点后n位的程序

要求:

2. 代码实现

#include<stdio.h>

int main(void){
	char string[100];
	int num = 0;
	double value = 0;
	
	scanf("%lf%d", &value, &num);
	sprintf(string, "%%.%dlf\n", num);
	printf(string, value);
	return 0;
} 
           

3. 总结与收获

  1. 理解课程中最后总结的两点,只有在自己尝试动手编程,然后遇到问题的时候,才会深刻理解到别人说的话的含义,否则那就只是一段话而已,永远也不可能有自己的理解。—来自小白的感悟。
  2. 理解字符串信息可以存储在字符数组中,字符数组就是“变量”,字符串就是“值”;
  3. sscanf 和 sprintf 函数,本质上在做的是以字符串为中间值,做各种数据类型之间的转换。

继续阅读