标签 cpp 下的文章

C / C++

先定义 Java native 接口:

package jni;

/**
 * @author syf
 * @date 2024/2/6
 **/
public class JniMath {

    static {
        System.load("/tmp/libzichecpp.so");
        System.load("/tmp/libzichego.so");
    }

    public static native long multiply(long x, long y);

    public static native long multiplygo(long x, long y);

    public static void main(String[] args) {
        System.out.println(JniMath.multiply(12345, 67890));
        System.out.println(JniMath.multiplygo(12345, 67890));
    }
}

javah生成关联的头文件

javah jni.JniMath

生成的jni_JniMath.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jni_JniMath */

#ifndef _Included_jni_JniMath
#define _Included_jni_JniMath
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jni_JniMath
 * Method:    multiply
 * Signature: (JJ)J
 */
JNIEXPORT jlong JNICALL Java_jni_JniMath_multiply
  (JNIEnv *, jclass, jlong, jlong);

#ifdef __cplusplus
}
#endif
#endif

编写代码实现头文件中定义的函数:

#include "jni_JniMath.h"

JNIEXPORT jlong JNICALL Java_jni_JniMath_multiply
  (JNIEnv * env, jclass clazz, jlong argX, jlong argY) {

  return argX * argY;
}

编译 cpp,这里 JAVA_HOME 的头文件目录换成你的系统环境对应的

gcc -shared -fPIC -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin src/jni/jni_JniMath.c -o /tmp/libzichecpp.so

调用见 Java 部分的代码,不重复了

Golang

golang 从 1.5 版本开始支持 c-shared 模式编译,可以作为动态链接库调用

同样这里注释中cgo引入的CFLAG,头文件目录换成你的系统环境对应目录

package main

// #cgo CFLAGS: -I/Users/syf/opt/zulu-jdk-8/include
// #cgo CFLAGS: -I/Users/syf/opt/zulu-jdk-8/include/darwin
// #include <jni.h>
import "C"

//export Java_jni_JniMath_multiplygo
func Java_jni_JniMath_multiplygo(env *C.JNIEnv, clazz C.jclass, x C.jlong, y C.jlong) C.jlong {
    return x * y
}

// main function is required, don't know why!
func main() {} // a dummy function

编译:

go build -buildmode=c-shared -o /tmp/libzichego.so src/jni/jni_math.go

调用见 Java 部分的代码,不重复了

杭电多校后标程里经常看见大神的代码里有断言函数,像这样:assert(a[1] == 1),便了解了一下断言函数。

形式:void assert (int expression);

头文件:assert.h

当括号内表达式为真时继续运行程序,为假时向系统的错误设备抛出一个错误,并退出程序。

例程:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    freopen("input.txt","r",stdin);
    char a = 'N';
    assert(a != 'N');
    cout << a << endl;
    cout << __FUNCTION__ << ", " << __LINE__ << endl;
    return 0;
}

断言括号内的表达式为假,所以运行结果:

Assertion failed!

Program: C:\Users\syf\src\ACM\test.exe
File: C:\Users\syf\src\ACM\test.cpp, Line 8

Expression: a != 'N'

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

此时没有执行9、10行的语句。

大量断言函数会减缓程序运行速度,且断言函数仅在debug时有作用。

取消代码中所有断言时在#include <assert.h>语句前加上宏定义#define NDEBUG即可。

事情起源于一次比赛中大佬的标程无法用sublime直接编译,错误提示如下:

唔,原来是sublime自带的c++编译系统没有-std=c++11的选项。

先看看自带的c++编译系统是怎么配置的。

- 阅读剩余部分 -

碰到一个题目

题目描述

玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2=<N<=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1。

输入

第一行输入N,第二行输入N个数字,只包含0,1,2

输出

样例输入

5
02120

样例输出

1

虽然知道是bfs,但实现起来总觉得哪里不对,参考大佬们的博客后解决了几个难点:

  • 存储类型 虽然题目说是输入n个数,但是使用字符串存储会使后续的处理更方便,题目出处九度OJ_1482输入写的也是长度为n的字符串

- 阅读剩余部分 -