数组与字符串
数组:
数组的定义:
就是线性表的实现。
c语言
定义: int array[N] 或者 int *array = malloc();
数组的名不是指针。
#include <stdio.h>
#include <stdio.h>
// 这个地方其实是传入的数组的地址 *array,和大小
int func(int *array,int size){
// array[0] 其实就是指针 array求值得出首地址
return array[0]; // 等价于 *(array+0);
}
int main(int argc,const char * argv[]){
// array是一个数组
int array[100] = {11,22,33,44};
// 指针的形式
int *p = malloc(100 * sizeof(int));
// 在这里是获取到了数组的指针
printf("%d\n",*(array+1));
// 传入的其实是数组首地址的指针
printf("%d\n",func(array,100));
return 0;
}
c++:
数组定义:int array[N] 或 int * array = new int[N];
java
数组定义:int array[] = new int[N];
public class main{
public static void main(String[] args){
int [] array = new int[10];
array[1]=222;
array[2]=333;
System.out.println(array.length);
ArrayList<Integer> list = new ArrayList<>();
list.add(123);
list.add(22);
System.out.println(list);
}
}
python
数组定义: array = [];
数组元素的查找:
c语言实现:
#include <stdio.h>
/**
** 根据值找到下标
*/
int findX(int * array,int size,int x){
int flag=0;
int index=-1;
for(int i=0;i<size;i++){
if(array[i]==x){
flag =1;
index = i;
}
}
return index;
}
/**
** 根据下标找到值,并把原来的地址给返回过来,并返回状态。
*/
int findElement(int * array,int size, int k, int *px){
if(k>=size || k<0) return 0;
else{
*px=array[k];
return 1;
}
}
/**
* 查找最大的。
*/
int findMax(int * array, int size){
// 是将数组中的一个元素初始为max;
int max =array[0];
for(int i=1;i<size;i++){
if(max<array[i]) max = array[i];
}
return max;
}
int main(int argc,const char * argv[]){
int array[10] = {111,112,33,44,55};
int x;
x=12;
int k;
k= findX(array,10,x);
printf("%d\n",k);
int m,flag;
// 传入的是数组引用,长度,和下标,和地址
flag= findElement(array,10,3,&m);
printf("%d,%d\n",flag,m);
// 查找最大值
int max ;
max = findMax(array,10);
printf("%d\n",max);
return 0;
}
求两个100位的十进制的和。
C语言实现
int main(int argc, const char * argv[]){
//
// 思路 用数组 ,数组的底位存0号元素(如果0号元素存在高位,则是不可以进位的)
int a[11] = {0,9,8,7,6,5,4,3,2,1};
int b[11] = {1,2,3,4,5,6,7,8,9,9};
int sum[11] = {0};
int carry=0;//进位操作
// i< 11是为了计算最后一个
for(int i=0;i<11;i++){
int s;
s=a[i]+b[i]+carry;
carry = s/10;
sum[i] = s%10;
}
for(int i=10;i>=0;i--){
printf("%d",sum[i]);
}
putchar('\n');
return 0;
}
java 实现:
public static void main(String[] args){
BigInteger a= new BigInteger("12345678");
BigInteger b= new BigInteger("12345678");
BigInteger c= a.add(b);
System.out.println(c);
}
二维数组
二维数组的实质:数组的数组。数组中的每一个元素仍然是个数组。
逻辑上可看做二维,其实并不是二维的
c语言
int array [][] 与 int **array
int array[3][4];和int **pa 的中的array和pa类型是相同的,但是 pa== array的写法是错误的
int array [ ][ ]
与int * *
array是数组的数组。
int *p ===> 是p 指向一个整形变量。
p[2] <==> *(p+2) 就是 p指向的整形变量再+2的位置就是 p[2]
int * * p 因为*靠p元素最近,所以p是一个指针。所以 * * p是指的是指针的指针。p[1][1]
与 p[0][1]
的位置截然不同,并不是相差一个
int * *p= array是错误的
#include <stdio.h>
int main(void) {
printf("test");
int array[3][5]; // 是由int[5]
//int *p[5];
//p =array; // 这样是错误的。
int (*p)[5];
p = array; // 数组名赋值与指针。 那也就是 array是 一个指针。
int a[10];
int *pa =a // s数组的名求值可获取数组元素的受地址。所以 *pa就是一个指针。
return 0;
}
数组传参:
#include <stdio.h>
vaid func(int (*)[5] , int ){
// int (*)[5] 就是一个指向[5]的指针
}
void func(int array[][5] ,int k){
// int array[][5]==>int (*p) [5];
}
int main(void) {
printf("test");
int array[3][5]; // 是由int[5]
//int *p[5];
//p =array; // 这样是错误的。
int (*p)[5];
p = array; // 数组名赋值与指针。 那也就是 array是 一个指针。
// 这传递的是指针
func(array, 3);
int a[10];
int *pa =a // s数组的名求值可获取数组元素的受地址。所以 *pa就是一个指针。
return 0;
}
java
public void test(){
// 这是个3行的但是列未定义。
int[][] array= new int[3][];
array[0] = new int[5]; // 第0行有5列 ,创建有5个整形变量的数组
arry[1] = new int[4];
array[2]= new int[3];
}
大炮打蚊子案例:
/**
* 蚊子分布在一个M×N格的二维平面上,每只蚊子占据一格。向该平面的任意位置发射炮弹,炮弹的杀伤范围如下示意:
O
OXO
O
其中,X为炮弹落点中心,O为紧靠中心的四个有杀伤力的格子范围。若蚊子被炮弹命中(位于X格),一击毙命,若仅被杀伤(位于O格),则损失一半的生命力。也就是说,一次命中或者两次杀伤均可消灭蚊子。现在给出蚊子的分布情况以及连续k发炮弹的落点,给出每炮消灭的蚊子数。
输入格式:
第一行为两个不超过20的正整数M和N,中间空一格,表示二维平面有M行、N列。
接下来M行,每行有N个0或者#字符,其中#表示所在格子有蚊子。
接下来一行,包含一个不超过400的正整数k,表示发射炮弹的数量。
最后k行,每行包括一发炮弹的整数坐标x和y(0≤x<M,0≤y<N),之间用一个空格间隔。
输出格式:
对应输入的k发炮弹,输出共有k行,第i行即第i发炮弹消灭的蚊子数。
输入样例:
5 6
00#00#
000###
00#000
000000
00#000
2
1 2
1 4
输出样例:
0
2
* */
#include <stdio.h>
int board[20][20];
int M,N;
// 函数处理逻辑 当前坐标 和 杀上力
int bang(int x, int y, int kill){
if((x>=0 && x<M) && (y>=0 && y<N) && board[x][y]>0){
board[x][y] -=kill;
if(board[x][y]<=0){
// 蚊子死了
return 1;
}else{
return 0;
}
}else{
return 0;
}
return 1;
}
int main(int argc, const char * argv[]){
scanf("%d%d",&M,&N);
getchar();// 去除换行符
for(int i=0;i<M;i++){
for(int j=0;j<N;j++){
// 给数组赋值:令蚊子的生命力为2;因为如果为1时炮弹没有击中,而是在
// 炮弹范围内所以让其生命力为2更好计算。
board[i][j] = getchar() == '0' ? 0:2;
}
// 再次读取换行符
getchar();
}
int k;
scanf("%d",&k);
for(int i=0;i<k;i++){
// 用来定义大炮打的一泡的落点
int x,y;
scanf("%d%d",&x,&y);
int count=0;
count += bang(x,y,2);
count += bang(x-1,y,1);
count += bang(x,y-1,1);
count += bang(x,y+1,1);
printf("%d\n",count);
}
return 0;
}
字符串
字符串就是一串字符。
字符串的定义:
c语言:“abcdefeg” 或 字符数组
#include <stdio.h>
int main(void) {
// c 语言运行时内存有四个部分: 栈,堆,常量区,代码块
char *str ="hello world";
printf("%s\n",str);
printf("%p\n",str);
char *str2 ="hello world";
printf("%s\n",str2);
printf("%p\n",str2);
// 这的是s3放到了堆栈里了
char s3[] = "hello";
printf("%s\n",s3);
printf("%p\n",s3);
// s4数组是将常量池中的拿过来
char s4[] = "hello word";
printf("%s\n",s4);
printf("%p\n",s4);
printf("%d\n",sizeof(s3));
return 0;
}
// 输出:
hello world
0x402004
hello world
0x402004
hello
0x7fffc8a4589a
hello word
0x7fffc8a4588f
6
可以看到 *str 与*str 两个字符的指针指向的位置相同。
c++
#include <iostream>
using namespace std;
int main() {
string name;
cout << name <<"\n"; // 什么都没有是空字符串
string name2="llk";
cout << name2 <<"\n";
return 0;
}
java
public void name(){
String name ="张三";
System.out.println(name);
// java一般都是new出来的而这个却可以直接复值;
// String name = "zhang" 这个其实就是在常量池中创建了一个对象,然后name引用指向常量池; 等价于 char data[] = {'z','h','a','n',y};
String namestr= new String(data);
// String name = new String("zhang");
// 这个是在堆栈中创建一个新的对象将“zhang”放到静态区
}
String str="hello";//直接赋值的方式,先在栈中创建一个对String类的对象的引用变量str,然后查找栈中有没有存放“hello”,如果没有就将“hello”存放在栈,并令star指向“hello”,如果已经有“hello”直接令str指向“hello”
通过构造方法创建字符串对象是在堆内存
String str=new String("hello");//实例化的方式
1)直接赋值(String str = "hello"):只开辟一块堆内存空间,并且会自动入池(到常量池中),不会产生垃圾。
2)构造方法(String str= new String("hello");):会开辟两块堆内存空间,其中一块堆内存会变成垃圾被系统回收,而且不能够自动入池(到常量池中),需要通过public String intern();方法进行手工入池(到常量池中)。new的每次都会创建对象,他只会存在堆中,每次调用一次就会创建一个新的对象。 将“hello”放到静态区
在开发的过程中不会采用构造方法进行字符串的实例化。
正则表达式与串的匹配
正则表达式是用于对字符串的匹配。
自动机
- 非确定型有限状态自动机(NFA):
- 确定型有限状态自动机(DFA):
// C++;
#include <iostream>
using namespace std;
#include <regex>
int main() {
string str ="abcd";
regex r("[a-z]+"); // 匹配一个或多个字母
string email = "abc123@123.xm";
regex r1("[a-z0-9]+@[a-z0-9]+\\.[a-z0-9]+");
bool x=regex_match(str,r);
cout << x <<endl;
cout << regex_match(email,r1) << endl;
return 0;
}
// java 使用类 pattern类
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数
public static void main(String args[]){
String content = "I am noob " +
"from runoob.com.";
String pattern = ".*runoob.*";
boolean isMatch = Pattern.matches(pattern, content);
System.out.println("字符串中是否包含了 'runoob' 子字符串? " + isMatch);
}
// python
import re;
re(r"正则表达式","匹配的字符")