一些啰嗦的话:其实在学C语言之前,我最早接触的是Java语言,因为Java前期的一些知识比C语言简单,所以在Java学业考试的时候勉强达到理想分数。后面断断续续学了将近3个月的C语言,只停留在初识层面,知识对于我来说难,加上期末周没时间学习整理知识,让我感觉已经忘光了。这段时间的感悟除了"先学难的语言再入门比较简单的语言能学的更通透些"之外,还有就是"学计算机的人怎么那么NB,思路怎么那么灵活,不像我对一道编程题能解一整天"。不过我还是会继续加油,努力学好一门语言。希望屏幕前的你,共勉。
目录
[3.1 数据类型](#3.1 数据类型)
[3.2 变量](#3.2 变量)
一、主程序入口(主函数)的不同
C语言
int main(void) { // 主函数返回类型为 int,参数可为 void(无参数)
// 代码逻辑
return 0; // 必须返回整数值
}
Java
java
public class Main { // 主函数必须位于类内
public static void main(String[] args) { // 固定签名:public static void
// 代码逻辑
}
}
// public:修饰符,此外还有3种
// class:类
// Main:类名(不写死,与.java文件同名)
// static:静态
// String[] :字符串数组类型
// args:数组名
// String[] args字符串数组
刚接触Java的不需要深入理解每个单词代表什么,只要牢记:一个文件中只有一个程序主入口,即只能写一遍 public static void main(String[] args){}
这里我想多说一嘴:
class类,可以理解为类型、种类,比如这世界上有不同种类(class也有种类的意思)的人,黄人、黑人、白人,甚至还有沃尔玛购物袋(bushi);
String[] args 字符串数组,其实和C语言的类似。只不过C语言中没有 字符串 String 类型,且中括号 [ ] 是放在数组名后面的,如 int arr[]; 这么看来Java设计的数组形式似乎更合理些,因为数据类型后面直接跟着中括号就是数组类型了,但是C语言中间却夹着数组名。
二、注释
回忆C语言(包括C99之后)中的注释:
// 两条斜杆后面就是注释,只在该行有效
/* 这是多行注释
回车之后依旧有效
*/
Java注释方法和C语言一样,并且多行注释也是不能嵌套的。但Java比C语言多了一种 文档注释:
/**
文档注释:比多行注释多了一颗*
@version v1.0.0
@author 409
作用:可以声明一些信息,如上面的版本、作者,还可以写上编写时间、文件用途等信息
*/
而在集成开发环境(可以理解为软件)中,注释的快捷键是:
一般用IntelliJ IDEA编写Java文件,其注释的快捷键是 Ctrl + Shift + /,取消注释也是此法
一般用VS编写C语言脚本,其注释的快捷键是 Ctrl + K + C,取消则是Ctrl + K + U
三、数据类型与变量
3.1 数据类型
C语言
区分无符号和有符号类型,char 是 1个字节。
【Java也有字符型 char,但Java的字符占2个字节,可以写入中文,因为一个汉字占2个字节。】


Java
基本数据类型:四类八种(一定要记得是 8 种基本数据类型)
引用数据类型: 前期先将 String 是引用类型与基本数据类型区分开来就行
不注重区分有符号和无符号,可以存储负数、零、整数

基本数据类型的取值范围只要熟记字节型 byte 的取值范围是-128~127即可,与C语言的字符 char 取值范围一致。
3.2 变量
C语言有两种变量,一种是局部变量、一种是全局变量
cpp
int global_var = 42; // 定义全局变量
int main() {
int i = 10; // 局部变量
printf("%d %d", global_var, i);
return 0;
}
Java中除了有全局变量、局部变量还有成员变量
全局变量通常是静态变量(即用 static 修饰),与成员变量(实例变量)一样都是定义在主函数外面的。前期还无法明确全局变量和成员变量的具体区别就先放一放。
但在定义变量时Java有几处注意事项:
如果一个变量没有 初始化 (即赋值),那么在使用的时候就会编译报错
如果进行变量赋值的时候,字面值超过了可存储数值类型的范围,那么编译也会报错
长整型
long
在初始化时在值的后面要加上大写的L
,eg:long a = 10L;
浮点型会被默认为是
double
类型,因此在初始化float
类型变量时,在其值后加上f
/F
四、常量
C语言
1、#define 定义的标识符常量:无类型,纯文本替代,eg: #define PI 3.1415926
2、const 关键字修饰的常变量,定义只读变量(有类型,但本质仍是变量,注意的是const修饰的常变量不能直接被修改)eg: const float PI = 3.14159;
3、用 enum 关键字定义的枚举常量
Java
final 关键字定义的不可变变量(必须显式初始化)eg: final double PI = 3.14159;
五、类型转换
Java与C语言一样,都存在隐式/自动类型转换和强制类型转换,因为C语言的较麻烦,此处只想解释Java的类型转换。
隐式/自动转换规则
- 遵循"小范围→大范围"的自动提升原则:byte→short→int→long→float→double
- 编译器严格检查,不符合规则会直接报错
强制类型转换
就是将"大范围"放到"小范围"内,如将 长整型 long 赋值给 整型 int ,想要将 long 强制类型转换成 int ,再进行赋值。
强制类型转换得到的数值会损失精度,可以理解为想要将 4L 的水放进容量为 50ml 的水杯中,水会溢出,所以得到的水肯定没有4L那么多。
java
public class Test{
public static void main(String[] args){
int a = 10;
long b = 128L;
b = a; // 正常通过编译
a = b; // 报错,在赋值时会损失精度
a = (int)b; // 强制类型转换
System.out.println(a); // 输出-128(127-1得到的值,回顾C语言中的整数存储方式,一个循环)
}
}
输出为-128的原因:

注意事项:
不同数字类型的变量之间赋值, 表示范围更小的类型能隐式转换成范围较大的类型
如果需要把范围大的类型赋值给范围小的, 需要强制类型转换, 但是可能精度丢失
将一个字面值常量进行赋值的时候, Java 会自动针对数字范围进行检查(如将128赋值给byte 类型的常量)
强制类型转换不一定能成功,不相干的类型不能互相转换(如 boolean 类型转换成 int 类型)
还有一项隐式类型转换在运算当中需要注意的:
int
与long
之间运算,int
会被提升为long
byte
与byte
之间运算,最终转换成4个字节的int
类型(整型提升)
整型提升:由于计算机的 CPU 通常是按照 4 个字节为单位从内存中读写数据。为了硬件上实现方便, 诸如 byte 和 short 这种低于 4 个字节的类型, 会先提升成 int,再参与计算。
java
public class Test{
public static void main(String[] args){
byte a = 10;
byte b = 20;
byte c = a + b; // 错误
int c = a + b; // 正确写法1
byte c = (byte)(a + b); // 正确写法2,a+b需要加括号
}
}
六、输入输出
C语言
输出:printf = print + format,格式化输出,需要使用占位符
cpp
#include <stdio.h> // 需要包含头文件
int main(){
printf("%5d\n", 123); // 输出为" 123",默认右对齐,123前面有2个空格
printf("%-5d\n", 123); // 输出"123 ",加一个"-"使其左对齐,后面2个空格
printf("Number is %.2f\n", 0.5); // 输出"Number is 0.50",保留两个小数点
printf("%6.2f\n", 0.5); // 输出为" 0.50"。 %6.2f 表示输出字符串最⼩宽度为6,小数位数为2。所以,输出字符串的头部有两个空格。
printf("%*.*f\n", 6, 2, 0.5); // 等同于printf("%6.2f\n", 0.5);
printf("%s\n", "Hello World"); // 输出字符串默认全部输出
printf("%.8s\n", "Hello World"); // 限定输出8个字符,输出"Hello wo"
}
链式访问 --> printf() 输出的返回值:
猜一下以下代码输出什么
cpp
#include <stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
return 0;
}
输出结果 :4321
因为 printf() 返回的是 打印在屏幕上的字符的个数,43是两个字符,因此 printf("%d", printf("%d", 43)) 输出2,2又是一个字符,因此 printf("%d", printf("%d", printf("%d", 43))); 输出1;并且因为占位符后面没有空格,因此输出每个数字是黏在一起的。
cpp
int main()
{
printf("%d ", printf("%d ", printf("%d ", 43)));
return 0;
}
注意看两个代码的区别,猜一下上面的代码将输出什么?
答案是:43 3 2
因为空格也是字符,也要算在里面。
输入:scanf,格式化输入,与取地址符号 & 搭配使用
cpp
#include <stdio.h>
int main(){
int x = 0;
float y = 0.0;
// 用户输⼊ " -13.45e12# 0"
scanf("%d%f", &x, &y);
}
scanf 读取到的数据是:-13 和 449999994880.000000(即0.45*10^12 // 浮点数输出会有误差)原因是:
scanf() 处理用户输入的原理是,用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。 解读用户输入时,会从上一次解读遗留的第一个字符开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。
对于字符串:
scanf 会忽略输入中的空白字符(空格、制表符、换行符等),解读时从当前第一个非空白字符开始读起,直到遇到空白字符为止。
scanf() 不适合读取可能包含空格的字符串,若要读取多个字符,则使用多个 %s。另外,scanf() 遇到 %s 占位符,会在字符串变量末尾存储一个空字符 \0。
用 %s 能够读到空格的写法:
cpp
#include <stdio.h>
int main()
{
char arr5[20];
scanf("%[^\n]s", arr5); // "%[^\n]s"的意思是读取一个字符串,直到遇到\n停止
printf("%s\n", arr5);
return 0;
}
指定读入字符串的最长度的写法:
cpp
#include <stdio.h>
int main()
{
char arr3[5];
scanf("%4s", arr3); // 4s表示最多读取4个字符,剩一个位置给\0
printf("%s\n", arr3);
return 0;
}
为避免 scanf() 解析带有格式的数据失败的情况,scanf() 提供了一个赋值忽略符 * 。只要把 * 加在任何占位符的百分号后面,该占位符就不会返回值,解析后将被丢弃
cpp
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
scanf("%d%*c%d%*c%d", &year, &month, &day); // %*c 能够读取字符串,但该占位符不会返回值,在解析的时候会将其抛弃
printf("%d %d %d\n", year, month, day);
return 0;
}
无论输入"2025-7-8",还是"2025/7/8",抑或是"2025*7/8"结果都能输出"2025 7 8"
scanf() 返回值是⼀个整数,表示成功读取的变量个数。如果没有读取任何项,或者匹配失败,则返回 0 。
如果在成功读取任何数据之前,发生了读取错误或者遇到读取到文件结尾,则返回常量EOF
(-1)。EOF
- end of file 文件结束标志,通常用于多组输入中。
cpp
#include <stdio.h>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF) { // 注意 while 处理多个 case
printf("%d\n", a + b);
}
return 0;
}
Java
对于Java语言,并没有C语言中 "0为假,非0为真" 的概念,而是用布尔值表示真假,返回值为true 表示真,返回 false 则为假。
Java中的输入输出不需要包含头文件,Java中也没有 #include 的指令
输出:
System.out.print(); 不会对数据进行换行处理;
System.out.println(); 自动换行,不需要占位符 \n ;
System.out.printf(); 与C语言格式化输出使用方法几乎一致,采用占位符
输入:使用 Scanner 类创建引用(如 Scanner scanner = new Scanner(System.in);),通过 scanner.nextXxx() 读取键盘上输入的数据,使用时需要导入相应的包java.util.Scanner。
读取整数是 nextInt(); 读取浮点数是 nextFloat(); ......
读取字符串有两种方式:next(); nextLine();
区别:
next()
遇到空格停止输出;
nextline()
遇到空格不会结束输出,推荐使用
同时读取整型、字符串和浮点数:
java
import java.util.Scanner;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("输入一个整型:");
int i = scan.nextInt();
System.out.println(i); // 如果输入12,再按回车,输出整型时正常输出12,但输出字符串时显示空的,因为"回车"即使是空字符也被当成字符
System.out.println("输入一串字符:");
String str = scan.nextLine();
System.out.println(str);
System.out.println("输入一个浮点型:");
float f = scan.nextFloat();
System.out.println(f);
}
java
输入一个整型:
12
12
输入一串字符:
输入一个浮点型:
4.5
4.5
输出结果显示 还没等我们输入字符串,就显示"输入一个浮点数"的提示,说明 Scanner 读取了"回车"作为我们输入的字符。
若要调整代码,只需要单独写一行来读取输入整数之后的"回车":
java
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("输入一个整型:");
int i = scan.nextInt();
System.out.println(i);
scan.nextLine(); // 读取输入整型之后的"回车"
System.out.println("输入一串字符:");
String str = scan.nextLine();
System.out.println(str);
System.out.println("输入一个浮点型:");
float f = scan.nextFloat();
System.out.println(f);
}
java
输入一个整型:
66
66
输入一串字符:
oha na
oha na
输入一个浮点型:
6.6
6.6