ABAP基础知识 访问外部数据库-开发篇-程序员宅基地

技术标签: python  java  编程语言  mysql  数据库  

点击蓝字 关注我们

前言

前文讲解了怎么配置连接外部数据库

详见链接

无峰,公众号:ABAP 技巧与实战ABAP基础知识 访问外部数据库-配置篇

本文主要介绍通过ABAP语言访问外部数据库的几种方式

外部数据库配置

本文示例中的代码访问了两个外部数据库

MTD : 外部oracle数据库,其中示例表 ZTTEMP 字段( ZZTNO,WERKS)

S4Q : 外部HANA数据库(开发系统访问测试系统的数据库), 使用表USR02,ZTTEMP

ABAP访问外部数据库

通过ABAP访问外部数据库有四种方式.根据不同的情况,可以选择不同的方法.

  • OPEN SQL访问

  • NATIVE SQL 访问

  • ADBC(ABAP Database Connectivity)

  • AMDP ABAP Managed Database Procedures ? (未验证通过)

OPEN SQL直接访问

OPEN SQL 访问的限制条件:必须在ABAP数据字典中存在该表名,并且最好同目标系统表结构一致, 一般情况下,用来访问另外一个同版本的ECC数据库.当然,也可以把ECC的表定义语句在目标系统中创建一个同名同结构的表,然后用该方式访问.

直接访问时,在FROM TABLE 后面添加 CONNECTION s4q .

s4q是DBCO中建立的和另外一个S/4系统的连接

01

报错及处理一

可能的报错及处理方式

下图报错的原因是访问ORACLE数据库必须指定一个SCHEMA. 这个可以配置在连接参数中.

01

报错及处理二

出现下面的报错,表示系统尝试使用MANDT限制数据, 此时需要给OPEN SQL 语句添加CLIENT SPECIFIED 强制OPEN SQL 不要补充MANDT限制

NATIVE SQL访问

通过NATIVE SQL 访问外部数据库步骤

  • 打开连接

  • 执行SQL命令

  • 关闭连接

示例代码见文末

01

读取多条记录的方式

  • 游标方式     图一

  • 非游标方式 图二

非游标方式其实隐式使用了游标.性能比游标方式要差.数据量小的时候看不出来. 大量数据读取就能看出二者的性能差异了. 

图三是标准帮助中提示的优劣比较.

图一

图二

图三

ADBC访问

ADBC(ABAP Database Connectivity) 是SAP提供的原生SQL(Native SQL)接口API.可以通过ADBC执行任何数据库的原生SQL语句.

ABAP中有个标准的DEMO程序: ADBC_DEMO 演示了各种SQL语句的调用方式.图四的代码示例给出了SELECT语句的常用写法.

大概需要如下的过程

  • 创建默认数据库的链接对象

  • 创建一个查询对象

  • 基于sql语句创建一个结果对象

  • 定义传递结果集一个数据对象-内表

  • 获取数据内容

  • 关闭连接

  • 赋值数据到内表

示例代码详见文末

通过AMDP 访问?

AMDP ABAP Managed Database Procedures

标准ABAP帮助体系中提到访问外部数据库的方法中还有一种AMDP方式.为了完善本文,补充了一个AMDP访问外部数据库表的示例.(验证未通过)

尝试中发现AMDP只适用与HANA数据库. 并且尝试通过DEMO程序 DEMO_AMDP_CONNECTION 连接外部数据库S4Q. 尝试失败. (报错见图四)

感觉AMDP 并不支持连接外部数据库. 

图五中示例代码的连接 是 R/3*开头. 帮助中说S/3*是SERVICE CONNECT. 但是不理解有什么用处.

图四

图五

图六

总结

ABAP访问外部数据库的几种方式中. OPEN SQL 最简单,但是有很大局限性. NATIVE方式最简单易懂. 性能也最好. 但是不利于代码动态化. ADBC 可以动态的实现数据的读取及内表的赋值.

前文DB02 SQL编辑器SQL语句自动生成报表 就采用了ADBC访问数据库的方法: 根据语句动态定义选择屏幕,动态定义内表, 读取的数据写入内表呈现.

详见链接

无峰,公众号:ABAP开发技巧SAP工具箱之一键生成报表

该工具在付费文章中可以获取.

文中通过AMDP方式连接外部数据库的验证失败. 不推荐使用. 其它三种方式根据实际情况选择使用就好.

示例代码详见文末.

THE

END

约定

如果你对这篇文章感兴趣,请帮忙点赞,在看,分享.       

    (如果你真的喜欢这篇文章,请记得回来打个赏,作为支持我继续下去的动力,这是一个正反馈过程. 越多的人打赏,作者越有动力分享,读者就能享受更多的福利.毕竟打赏的金额富不了我,穷不了你,却能支持这个公众号长久发文.)

公众号 : syjf1976_abap

          ABAP开发技巧

微信号 : 392077

请微信联系管理员: 

syjf1976 

sharry_xlp  

Yannick_Duan 申请进入公众号讨论群

示例代码,OPEN SQL:

*&---------------------------------------------------------------------*
*& Report ZTS_SQL_DBCO
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zts_dbco_opensql.


PARAMETERS: p_s4  RADIOBUTTON GROUP ra1,
            p_ora RADIOBUTTON GROUP ra1.


START-OF-SELECTION.
  CASE 'X'.
    WHEN p_s4.
*访问另一个S4系统的同名表
*需要注意的是,目标系统CLIENT和当前CLIENT 很可能不一样, 所以需要加上CLIENT SPECIFIED 避免CLIENT不同干扰数据获取
      SELECT * FROM usr02  CLIENT SPECIFIED  INTO  TABLE @DATA(lt_usr02)  BYPASSING BUFFER CONNECTION R/3*S4Q
        WHERE bname = '00177'.
      ."可以获取数据
      DATA(lv_subrc) = sy-subrc .
      cl_demo_output=>write( lv_subrc ).
      cl_demo_output=>write( lt_usr02 ).
      cl_demo_output=>display(  ).
    WHEN p_ora.
*访问另一个其它系统的同名表
*如果ABAP表有MANDT , 目标表没有, 则需要添加CLIENT SPECIFIED 避免系统自动添加MANDT 的限制条件,导致报错:字段MANDT不存在
      DATA: BEGIN OF ls_temp,
              zztno(30),
              werks(4),
            END OF ls_temp.
      DATA: lt_temp LIKE TABLE OF ls_temp.


      SELECT zztno,werks FROM zttemp CLIENT SPECIFIED CONNECTION mtd
         INTO TABLE @lt_temp.


      cl_demo_output=>display( lt_temp ).
  ENDCASE.
*  COMMIT CONNECTION s4q. "在连接中提交.

示例代码 NATIVESQL

*&---------------------------------------------------------------------*
*& Report ZTS_SQL_DBCO
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zts_dbco_nativesql.


PARAMETERS:
  p_1 RADIOBUTTON GROUP ra1,
  p_2 RADIOBUTTON GROUP ra1,
  p_3 RADIOBUTTON GROUP ra1,
  p_4 RADIOBUTTON GROUP ra1.


DATA: BEGIN OF gs_temp,
        zztno(30),
        werks(4),
      END OF gs_temp.
DATA: gt_temp LIKE TABLE OF gs_temp.
DATA conn TYPE dbcon-con_name.


INITIALIZATION.
  %_p_1_%_app_%-text = 'SELECT方式一:DO循环读取游标,添加内表'.
  %_p_2_%_app_%-text = 'SELECT方式二:通过例程添加内表'.
  %_p_3_%_app_%-text = 'UPDATE:更新表内容'.
  %_p_4_%_app_%-text = 'INSERT:写入表内容'.


START-OF-SELECTION.
  conn = 'MTD'.
  "检查连接是否已经打开
  EXEC SQL.
    SET CONNECTION :conn
  ENDEXEC.
  IF sy-subrc <> 0. "如果连接没有打开, 打开连接
    EXEC SQL.
      CONNECT TO :conn
    ENDEXEC.
  ENDIF.


*两种方式: 方式一性能好于方式二
  CASE 'X'.
    WHEN p_1.
      PERFORM frm_method_1. "SELECT方式一:DO循环读取游标,添加内表'.
    WHEN p_2.
      PERFORM frm_method_2. "SELECT方式二:通过例程添加内表'.
    when p_3.
      perform frm_update.
    when p_4.
      perform frm_insert.
  ENDCASE.


  "关闭数据库连接
  EXEC SQL.
    DISCONNECT :CONN
  ENDEXEC.


*输出结果
  CASE 'X'.
    WHEN p_1 or p_2.
      cl_demo_output=>display( gt_temp ).
  ENDCASE.
*&---------------------------------------------------------------------*
*& Form FRM_METHOD_1
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_method_1 .
  DATA: ls_temp LIKE gs_temp,
        lt_temp LIKE TABLE OF ls_temp.
  "执行SQL语句:通过open dbcur打开游标
  EXEC SQL.
    OPEN dbcur FOR
    SELECT zztno,werks FROM zttemp
  ENDEXEC.
  "循环通过游标读取记录
  " 两种赋值方式:
  " 1.按字段顺序赋值,select 字段与 INTO 字段顺序必须一致
  "   FETCH NEXT dbcur INTO :ls_TEMP-ZZTNO,:LS_TEMP-WERKS
  " 2.按结构整体赋值:select 字段必须与结构字段顺序一致,且字段长度一致.
  "   FETCH NEXT dbcur INTO :ls_TEMP
  DO.
    EXEC SQL.
      FETCH NEXT dbcur INTO :ls_TEMP-ZZTNO,:LS_TEMP-WERKS
    ENDEXEC.
    IF sy-subrc <> 0.
      EXIT.
    ELSE.
      APPEND ls_temp TO lt_temp.
    ENDIF.
  ENDDO.
  "关闭游标
  EXEC SQL.
    CLOSE dbcur
  ENDEXEC.
  gt_temp[] = lt_temp[].
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_METHOD_2
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_method_2 .
  conn = 'MTD'.
  "检查连接是否已经打开
  EXEC SQL.
    SET CONNECTION :conn
  ENDEXEC.
  IF sy-subrc <> 0. "如果连接没有打开, 打开连接
    EXEC SQL.
      CONNECT TO :conn
    ENDEXEC.
  ENDIF.
*注意:工作区 gs_temp 内表 gt_temp 必须是全局变量
  EXEC SQL PERFORMING FRM_FILL_DATA.
    SELECT zztno,werks FROM zttemp INTO :GS_TEMP
  ENDEXEC.


ENDFORM.
FORM frm_fill_data.
  APPEND gs_temp TO gt_temp.


ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_UPDATE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_update .
  DATA: lv_werks(4).
  lv_werks = '1002'.
  EXEC SQL.
    UPDATE ZTTEMP SET WERKS = :LV_WERKS
     WHERE WERKS = '1003'
  ENDEXEC.
  IF sy-subrc = 0.
*提交数据更新
    EXEC SQL.
      COMMIT WORK
    ENDEXEC.
    DATA: lv_msg(50).
    lv_msg = '更新成功记录数:' && sy-dbcnt .
    cl_demo_output=>display(  lv_msg ).
  ELSE.
    cl_demo_output=>display( '更新失败' ).
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_INSERT
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_insert .
  DATA: lv_werks(4).
  lv_werks = '1002'.
  EXEC SQL.
    INSERT INTO ZTTEMP VALUES ('4502',:LV_WERKS)
  ENDEXEC.
  IF sy-subrc = 0.
*提交数据更新
    EXEC SQL.
      COMMIT WORK
    ENDEXEC.
    DATA: lv_msg(50).
    lv_msg = '写入成功记录数:' && sy-dbcnt .
    cl_demo_output=>display(  lv_msg ).
  ELSE.
    cl_demo_output=>display( '写入失败' ).
  ENDIF.
ENDFORM.

示例代码 ADBC

*&---------------------------------------------------------------------*
*& Report ZTS_DBCO_ADBC
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zts_dbco_adbc.


DATA: BEGIN OF gs_temp,
        zztno(30),
        werks(4),
      END OF gs_temp.
DATA: gt_temp LIKE TABLE OF gs_temp.
DATA conn TYPE dbcon-con_name.
DATA: gv_sql TYPE string.


START-OF-SELECTION.
  gv_sql = 'SELECT zztno,werks FROM zttemp'.
  PERFORM frm_get_data_adbc_simple.
*  PERFORM frm_get_data_adbc.
  cl_demo_output=>display( gt_temp ).
*&---------------------------------------------------------------------*
*& Form FRM_GET_DATA_ADBC
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_data_adbc .
  DATA: r_adbc_conn   TYPE REF TO  cl_sql_connection,
        r_adbc_query  TYPE REF TO  cl_sql_statement,
        r_metadata    TYPE REF TO  data,
        it_metadata   TYPE         adbc_rs_metadata_descr_tab,
        lv_len        TYPE         i,
        lv_off        TYPE         i,
        wa_metadata   LIKE LINE OF it_metadata,
        r_adbc_result TYPE REF TO  cl_sql_result_set,
        r_tabletype   TYPE REF TO  cl_abap_tabledescr,
        r_cxadbc      TYPE REF TO  cx_dba_adbc,
        r_cxsql       TYPE REF TO  cx_sql_exception,
        tabix_n(4)    TYPE n,
        column_names  TYPE HASHED TABLE OF adbc_name WITH UNIQUE KEY table_line.
  DATA:         lv_stmt_type      TYPE string.
  DATA:
    ex_structdescr TYPE REF TO  cl_abap_structdescr,
    ex_result_ref  TYPE REF TO data.
*获取sql语句的类型
  lv_stmt_type = cl_hdb_sql_executor=>get_statement_type( gv_sql ).
*创建默认数据库的链接对象
  r_adbc_conn    = cl_db6_con=>get_connection( 'MTD' ).
*创建一个查询对象
  r_adbc_query   = r_adbc_conn->create_statement( ).
*基于sql语句创建一个结果对象
  r_adbc_result  = r_adbc_query->execute_query( gv_sql  ).
*获取结果集合的字段名
  it_metadata = r_adbc_result->get_metadata( ).
*使用结果集合的字段信息,创建一个数据对象-结构
  r_metadata = r_adbc_result->get_struct_ref( md_tab = it_metadata   p_strict = abap_false ).
*创建一个数据对象-内表
  ex_structdescr ?= cl_abap_typedescr=>describe_by_data_ref( r_metadata ).
  r_tabletype     = cl_abap_tabledescr=>create( p_line_type  = ex_structdescr
                                                p_table_kind = cl_abap_tabledescr=>tablekind_std ).


  CREATE DATA ex_result_ref TYPE HANDLE r_tabletype.
*传递结果集一个数据对象-内表
  r_adbc_result->set_param_table( itab_ref = ex_result_ref ).
*获取数据内容
  r_adbc_result->next_package( EXPORTING upto = 100 ).
*关闭连接
  r_adbc_result->close( ).
*赋值数据到内表
  FIELD-SYMBOLS: <fs_itab> TYPE STANDARD TABLE.
  ASSIGN ex_result_ref->* TO <fs_itab>.
  MOVE-CORRESPONDING <fs_itab> TO gt_temp.
ENDFORM.


FORM frm_get_data_adbc_simple .
  DATA: r_adbc_conn   TYPE REF TO  cl_sql_connection,
        r_adbc_query  TYPE REF TO  cl_sql_statement,
        r_metadata    TYPE REF TO  data,
        it_metadata   TYPE         adbc_rs_metadata_descr_tab,
        lv_len        TYPE         i,
        lv_off        TYPE         i,
        wa_metadata   LIKE LINE OF it_metadata,
        r_adbc_result TYPE REF TO  cl_sql_result_set,
        r_tabletype   TYPE REF TO  cl_abap_tabledescr,
        r_cxadbc      TYPE REF TO  cx_dba_adbc,
        r_cxsql       TYPE REF TO  cx_sql_exception,
        tabix_n(4)    TYPE n,
        column_names  TYPE HASHED TABLE OF adbc_name WITH UNIQUE KEY table_line.
  DATA:         lv_stmt_type      TYPE string.
  DATA:
    ex_structdescr TYPE REF TO  cl_abap_structdescr,
    ex_result_ref  TYPE REF TO data.


*创建默认数据库的链接对象
  r_adbc_conn    = cl_db6_con=>get_connection( 'MTD' ).
*创建一个查询对象
  r_adbc_query   = r_adbc_conn->create_statement( ).
*基于sql语句创建一个结果对象
  r_adbc_result  = r_adbc_query->execute_query( gv_sql  ).


*定义
  DATA: lr_ref LIKE REF TO gt_temp.
  CREATE DATA lr_ref .
*传递结果集一个数据对象-内表
  r_adbc_result->set_param_table( itab_ref = lr_ref ).
*获取数据内容
  r_adbc_result->next_package( EXPORTING upto = 100 ).
*关闭连接
  r_adbc_result->close( ).
*赋值数据到内表


  gt_temp = lr_ref->*.
ENDFORM.
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/syjf1976/article/details/120320522

智能推荐

Spring Boot 获取 bean 的 3 种方式!还有谁不会?,Java面试官_springboot2.7获取bean-程序员宅基地

文章浏览阅读1.2k次,点赞35次,收藏18次。AutowiredPostConstruct 注释用于在依赖关系注入完成之后需要执行的方法上,以执行任何初始化。此方法必须在将类放入服务之前调用。支持依赖关系注入的所有类都必须支持此注释。即使类没有请求注入任何资源,用 PostConstruct 注释的方法也必须被调用。只有一个方法可以用此注释进行注释。_springboot2.7获取bean

Logistic Regression Java程序_logisticregression java-程序员宅基地

文章浏览阅读2.1k次。理论介绍 节点定义package logistic;public class Instance { public int label; public double[] x; public Instance(){} public Instance(int label,double[] x){ this.label = label; th_logisticregression java

linux文件误删除该如何恢复?,2024年最新Linux运维开发知识点-程序员宅基地

文章浏览阅读981次,点赞21次,收藏18次。本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。下面我们来进行文件的恢复,执行下文中的lsof命令,在其返回结果中我们可以看到test-recovery.txt (deleted)被删除了,但是其存在一个进程tail使用它,tail进程的进程编号是1535。我们看到文件名为3的文件,就是我们刚刚“误删除”的文件,所以我们使用下面的cp命令把它恢复回去。命令进入该进程的文件目录下,1535是tail进程的进程id,这个文件目录里包含了若干该进程正在打开使用的文件。

流媒体协议之RTMP详解-程序员宅基地

文章浏览阅读10w+次,点赞12次,收藏72次。RTMP(Real Time Messaging Protocol)实时消息传输协议是Adobe公司提出得一种媒体流传输协议,其提供了一个双向得通道消息服务,意图在通信端之间传递带有时间信息得视频、音频和数据消息流,其通过对不同类型得消息分配不同得优先级,进而在网传能力限制下确定各种消息得传输次序。_rtmp

微型计算机2017年12月下,2017年12月计算机一级MSOffice考试习题(二)-程序员宅基地

文章浏览阅读64次。2017年12月的计算机等级考试将要来临!出国留学网为考生们整理了2017年12月计算机一级MSOffice考试习题,希望能帮到大家,想了解更多计算机等级考试消息,请关注我们,我们会第一时间更新。2017年12月计算机一级MSOffice考试习题(二)一、单选题1). 计算机最主要的工作特点是( )。A.存储程序与自动控制B.高速度与高精度C.可靠性与可用性D.有记忆能力正确答案:A答案解析:计算...

20210415web渗透学习之Mysqludf提权(二)(胃肠炎住院期间转)_the provided input file '/usr/share/metasploit-fra-程序员宅基地

文章浏览阅读356次。在学MYSQL的时候刚刚好看到了这个提权,很久之前用过别人现成的,但是一直时间没去细想, 这次就自己复现学习下。 0x00 UDF 什么是UDF? UDF (user defined function),即用户自定义函数。是通过添加新函数,对MySQL的功能进行扩充,就像使..._the provided input file '/usr/share/metasploit-framework/data/exploits/mysql

随便推点

webService详细-程序员宅基地

文章浏览阅读3.1w次,点赞71次,收藏485次。webService一 WebService概述1.1 WebService是什么WebService是一种跨编程语言和跨操作系统平台的远程调用技术。Web service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准...

Retrofit(2.0)入门小错误 -- Could not locate ResponseBody xxx Tried: * retrofit.BuiltInConverters_已添加addconverterfactory 但是 could not locate respons-程序员宅基地

文章浏览阅读1w次。前言照例给出官网:Retrofit官网其实大家学习的时候,完全可以按照官网Introduction,自己写一个例子来运行。但是百密一疏,官网可能忘记添加了一句非常重要的话,导致你可能出现如下错误:Could not locate ResponseBody converter错误信息:Caused by: java.lang.IllegalArgumentException: Could not l_已添加addconverterfactory 但是 could not locate responsebody converter

一套键鼠控制Windows+Linux——Synergy在Windows10和Ubuntu18.04共控的实践_linux 18.04 synergy-程序员宅基地

文章浏览阅读1k次。一套键鼠控制Windows+Linux——Synergy在Windows10和Ubuntu18.04共控的实践Synergy简介准备工作(重要)Windows服务端配置Ubuntu客户端配置配置开机启动Synergy简介Synergy能够通过IP地址实现一套键鼠对多系统、多终端进行控制,免去了对不同终端操作时频繁切换键鼠的麻烦,可跨平台使用,拥有Linux、MacOS、Windows多个版本。Synergy应用分服务端和客户端,服务端即主控端,Synergy会共享连接服务端的键鼠给客户端终端使用。本文_linux 18.04 synergy

nacos集成seata1.4.0注意事项_seata1.4.0 +nacos 集成-程序员宅基地

文章浏览阅读374次。写demo的时候遇到了很多问题,记录一下。安装nacos1.4.0配置mysql数据库,新建nacos_config数据库,并根据初始化脚本新建表,使配置从数据库读取,可单机模式启动也可以集群模式启动,启动时 ./start.sh -m standaloneapplication.properties 主要是db部分配置## Copyright 1999-2018 Alibaba Group Holding Ltd.## Licensed under the Apache License,_seata1.4.0 +nacos 集成

iperf3常用_iperf客户端指定ip地址-程序员宅基地

文章浏览阅读833次。iperf使用方法详解 iperf3是一款带宽测试工具,它支持调节各种参数,比如通信协议,数据包个数,发送持续时间,测试完会报告网络带宽,丢包率和其他参数。 安装 sudo apt-get install iperf3 iPerf3常用的参数: -c :指定客户端模式。例如:iperf3 -c 192.168.1.100。这将使用客户端模式连接到IP地址为192.16..._iperf客户端指定ip地址

浮点性(float)转化为字符串类型 自定义实现和深入探讨C++内部实现方法_c++浮点数 转 字符串 精度损失最小-程序员宅基地

文章浏览阅读7.4k次。 写这个函数目的不是为了和C/C++库中的函数在性能和安全性上一比高低,只是为了给那些喜欢探讨函数内部实现的网友,提供一种从浮点性到字符串转换的一种途径。 浮点数是有精度限制的,所以即使我们在使用C/C++中的sprintf或者cout 限制,当然这个精度限制是可以修改的。比方在C++中,我们可以cout.precision(10),不过这样设置的整个输出字符长度为10,而不是特定的小数点后1_c++浮点数 转 字符串 精度损失最小

推荐文章

热门文章

相关标签