从零开始的c++学习 4:[数组array 与 字符串string]
Published:
记录一下c++学习的步骤 : base on Course ‘CS205 C/C++ Program Design’ in 2021 Fall at Southern University of Science and Technology. | 视频
lecture04 notes
4.1 Arrays 数组
- 定义: 连续分配的内存,拥有固定长度(长度不可变),元素类型可以任意类型
int num_array1[5]; //uninitialized array, random values
int num_array2[5] = {0, 1, 2, 3, 4}; //initialization
1 Variable-length arrays
- 如果长度不是整数常量表达式,则数组将是可变长度
2 Arrays of unknown size
- 初始化时不指定长度
int num_array[ ] = {1, 2, 3, 4}; // the type of num_array is "array of 4 int"`
//The arguments of a function
float array_sum(float values[], size_t length);
float array_sum(float *values, size_t length);
3 Element accessing
- No bounds-checking in C/C++. C/C++没有边界检查, 所以要知道数据的长度避免越界
- Arrays are not objects in C/C++ (different with Java);
- Arrays can be regarded as addresses
int array1[4] = {9,8,7,6};
int array2[4];
array2 = array1; //error! //取地址
array2[0] = array1[0]; //okay
array2[1] = array1[1]; //okay
array2[2] = array1[2]; //okay
array2[3] = array1[3]; //okay
4 Multidimensional arrays
- 在内存中, 多维数组也是顺序存储的,会将多维数组拆成1维数组存放
... - [0][0] - [0][1] - [0][2] - [1][0] - [1][1] - [1][2]-...
... - p+0 - p+1 - p+2 - p+3 - p+4 - p+5 - ...`
int mat[2][3] = \{\{11,12,13\}, \{14,15,16\}\};
for (int r = 0; r < rows; r++){
for(int c = 0; c < cols; c++)
cout << mat[r][c] << ",";
cout << endl;}
// Arrays of unknown bound
void init_2d_array(float mat[][], //error,必须指定维度
size_t rows, size_t cols)
void init_2d_array(float mat[][3],
size_t rows, size_t cols)
5 const Arrays
- 常量数组
- 初始化后不可更改,可以参与运算
const float PI = 3.1415926f;
PI += 1.f; // error
const float values[4] = {1.1f, 2.2f, 3.3f, 4.4f};
values[0] = 1.0f; // error
4.2 string
- Array-style strings
- strings class
1 Array-style strings
- 数组类型的字符串要多一个字节放 ‘\0’, 避免越界,出现错误结果.
char rabbit[10] = {'p', 'e', 'p', '\0'}
size_t strlen( const char *str );
//返回 字符串长度 ,会在第一个NULL ('\0')停止
2 String literals
- 可以使用字符串文本更快的操作
- 这个数据类型也不会越界检查
char name1[] = "Southern University of Science and Technology";
char name2[] = "Southern University of " "Science and Technology";
char name3[] = "ABCD"; //how many bytes for the array?
// 四个字节的字符串,数组的长度是五个字节,还包括多一位的 '\0'
- 更多长度/类型的定义
const wchar_t[] s5 = L"ABCD";
const char16_t[] s9 = u”ABCD"; //since C++11
const char32_t[] s6 = U”ABCD"; //since C++11
3 String manipulation and examination
- Copy
- Concatenate
- Compare
// 1.Copy
char* strcpy( char* dest, const char* src );
//Safer one:
char *strncpy(char *dest, const char *src, size_t count);
//2. Concatenate: appends a copy of src to dest
char *strcat( char *dest, const char *src );
//3.Compare
int strcmp( const char *lhs, const char *rhs );
4 string class
- 不以
null ('\0')
结尾的字符串很容易越界,并导致问题 - 更多字符串类型:
- Different types of strings
std::string std::wstring std::u8string //(C++20) std::u16string //(C++11) std::u32string //(C++11)
- Different types of strings
4.3 结构体,联合体和枚举类型 structures, Unions and Enumerations
1 structures
- 结构是由一系列成员组成的类型。
成员按顺序分配
- padding: 为了对齐内存
- In order to align the data in memory, some empty bytes will be padded
- 数据的io为了方便存取,会让数据存在一个区内,将不够的字节用0补齐(8位之类的)
2 Unions
- 定义 - 一份地址,多个名字
- 共享同一内存
3 Enumerations
4.4 typedef
- 创建类型的别名 create an alias for a type
- 可以控制代码中数据类型的长度,即指定我们需要的数据类型的长度,方便使用
Lab4
Makefile
Makefile is a tool to simplify and organize compilation. Makefile is a set of commands with variable names and targets . You can compile your project(program) or only compile the update files in the project by using Makefile.
- The name of makefile must be either makefile or Makefile without extension
- A rule of makefile including three elements: targets, prerequisites and commands.
- The target is an object file, which is generated by a program. Typically, there is only one per rule.
- The prerequisites are file names, separated by spaces, as input to create the target.
- The commands are a series of steps that make carries out. These need to start with a tab character, not spaces.
下面是五个版本的makefile, 层层递进,方便理解
- version 1: 相当于手动连接各个文件
hello: main.cpp printhello.cpp factorial.cpp g++ -o hello main.cpp printhello.cpp factorial.cpp
- VERSION 2: ```makefile CXX = g++ TARGET = hello OBJ = main.o printhello.o factorial.o
$(TARGET): $(OBJ) $(CXX) -o $(TARGET) $(OBJ)
将版本1中的g++命令全部用变量形式替换, $()
对应每个文件的编译, 只修改了其中一个文件,就可以不用编译全部文件
如果main文件被修改, 就可以使用make编译
main.o: main.cpp $(CXX) -c main.cpp
printhello.o: printhello.cpp $(CXX) -c printhello.cpp
factorial.o: factorial.cpp $(CXX) -c factorial.cpp
3. VERSION 3
```makefile
CXX = g++
TARGET = hello
OBJ = main.o printhello.o factorial.o
# Flag控制 编译器的选项
# -c 生成目标文件 .o
# -Wall 显示编译警告
CXXFLAGS = -c -Wall
$(TARGET): $(OBJ)
$(CXX) -o $@ $^
# $@: Object Files
# $^: all the prerequisites files
# This is a model rule, which indicates that all
# the .o objects depend on the .cpp files
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $@
# $<: the first prerequisite file
# Adding .PHONY to a target will prevent making
# from confusing the phony target with a file name.
## Because clean is a label not a
## target, the command make clean
## can execute the clean part. Only
## make command can not execute
## clean part.
.PHONY: clean
clean:
rm -f *.o $(TARGET)
## 使用`make clean`命令后,删除所有目标文件和可执行文件
- VERSION 4 ```makefile CXX = g++ TARGET = hello SRC = $(wildcard *.cpp) OBJ = $(patsubst %.cpp, %.o, $(SRC))
wildcard: search file
SRC = … 寻找所有.cpp文件
patsubst(pattern substitution): replace file
$(patsubst original pattern, target pattern, file list)
将原来的cpp文件,替换成.o文件,(保持cpp编译时候的相同文件list)
CXXFLAGS = -c -Wall
$(TARGET): $(OBJ) $(CXX) -o $@ $^
%.o: %.cpp $(CXX) $(CXXFLAGS) $< -o $@
.PHONY: clean clean: rm -f *.o $(TARGET)
5. version 5
```makefile
## 进阶操作,在特定文件夹下搜索文件
## 例如 你的文件排列如下
# --work-dir
# --inc : All .h files are in inc
# --src : All .cpp files are in src
# makefile
SRC_DIR = ./src
SOURCE = $(wildcard $(SRC_DIR)/*.cpp)
OBJS = $(patsubst %.cpp, %.o, $(SOURCE))
TARGET = hell
INCLUDE = -I./inc
# -I 在特定文件夹下搜索文件
CXX = g++
CFLAGS = -c -Wall
$(TARGET): $(OBJS)
$(CXX) -o $@ $(OBJS)
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $@ $(INCLUDE)
.PHONY: clean
clean:
rm -f $(SRC_DIR)/*.o $(TARGET)