02.求整数之积

      【实例说明】
      
      从键盘输入两个整数,输出他们的积。通过本实例可理解从键盘读取输入的数据以及输出整型变量等方法。程序运行结果如下:

      snap02001.jpg

      【实例解析】

      在本例中,设两个整数分别为x、y,它们的乘积为m;程序首先调用printf()函数,提示用户输入数据,然后调用scanf()函数,输入变量x和y的值,接着求x与y的积m,最后输出结果。

      算法:

      {
            提示用户输入数据;
            输入变量x和y的值;
            计算乘积;
            输出乘积;         

         }

       【程序代码】

 1  /*     Input two numbers,output the product  */
 2 
 3  #include  < stdio.h >
 4 
 5  void  main()
 6  {
 7       int  x,y,m;                             /*     定义整型变量x,y,z  */
 8      printf( " Please input x and y: \n " );     /*     输出提示信息         */
 9      scanf( " %d%d " , & x, & y);                 /*     读入两个乘数,赋给x,y变量     */
10      m = x * y;                                 /*     计算两个乘数的积,赋给变量m     */
11      printf( " %d * %d = %d\n " ,x,y,m);         /*     输出结果     */
12  }

       【归纳注释】

      本实例程序实现的是两个整数的简单乘积,同样,也可以通过修改,实现其他类型,如实型(浮点型:单精度,双精度)的计算及四则运算。

      如定义为:float,则输入为:%f,输出为%f;如定义为:double,则输入为:%lf,输出为%lf;

      格式化字符串

      一般形式:
                     %[标志][输出最小宽度][.精度][长度] 类型
               
                    其中方括号[]中的项为可选项。

      各项意义如下:

               ①   类型字符用以表示输出数据的类型:
                        d--以十进制形式输出带符号整型(正数不输出符号);
                        o--以八进制形式输出带符号整型(不输出前缀O);
                        x--以十六进制形式输出带符号整型(不输出前缀OX);
                        u--以十进制形式输出无符号整型;
                        f --以小数形式输出单、双精度实数;
                        e--以指数形式输出单、双精度实数;
                        g--以%f、%e中较短的输出单、双精度实数;
                        c--输出单个字符;
                        s--输出字符串。

                ②   标志字符为:-、+、#、空格四种:
                        -:结果左对齐,右边填空格;
                        +:输出符号(正号或负号),输出值为正时冠以空格,为负时冠以负号;
                        #  :对c、s、d、u类无影响;
                                对o类,在输出时加前缀o;
                                对x类,在输出时加前缀0x;
                                对e、g、f类当结果有小数时才给出小数点。

                ③   输出最小宽度:
                                用十进制整数来表示输出的最小位数。若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度则补以空格或0。

                ④   精度:
                        精度格式符以“.”开头,后跟十进制整数。
                             如果输出的是数字,则表示小数的位数;若实际位数大于所定义的精度数,则截去超过的部分。
                             如果输出的是字符,则表示输出字符的个数;

                ⑤   长度:
                             长度格式符分h、l两种,h表示按短整型量输出;l表示按长整型量输出。


            scanf()函数为输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中。
         
            格式:
                     scanf("格式控制字符串",地址表列);

            例如:
                     scanf("%d %d",&a,&b);

            &a &b 分别表示变量a和变量b的地址。

转载于:https://www.cnblogs.com/ctoroad/archive/2006/02/22/335264.html

<think>嗯,用户让我帮忙创建一个间类,带有三个不同的构造函数,还有一些输出函数和一个析构函数。首先,我需要仔细理解用户的需,确保每个部分都正确实现。 首先,构造函数有三个:无参的,代表0点;一个接受浮点参数,表示秒;还有一个有三个整数参数和一个默认的浮点毫秒参数。秒应该是从0点开始累的总秒数,包括毫秒。比如,秒可能是12345.678秒,对应3小25分45.678秒。 接下来是成员函数:一个输出间字符串的函数,应该格式化为HH:MM:SS.ms;一个输出秒的函数,包括毫秒;还有一个获取当前小数的函数。析构函数需要输出“析构函数执行”。 首先,类的成员变量应该存储秒的总值,可能用double类型,这样能包括毫秒部分。比如,秒是总秒数,包括小数部分。 然后处理三个构造函数: 1. 无参构造函数,秒初始化为0。 2. 浮点参数构造函数,直接赋值给秒。 3. 三个整数参数(小、分钟、秒)和一个默认的毫秒参数。需要将小转为秒,分钟转为秒,加上秒和毫秒,总合作为秒。注意这里毫秒是0到999之间的,所以需要除以1000转换成秒的小数部分。 然后,输出间字符串的函数。需要将总秒转换为小、分钟、秒和毫秒。例如,总秒是3661.5秒的话,就是1小1分1秒500毫秒。这里需要注意取余和除法运算,特别是毫秒部分要乘以1000并取整,可能会有精度问题,所以可能需要四舍五入或者截断处理。 输出函数比较简单,直接返回存储的总秒值。 获取小数的函数,需要从总秒中计算小部分,即总秒除以3600取整,注意是整数部分。 析构函数需要输出字符串,这应该用cout实现。 在main函数中测试的候,需要创建不同构造函数实例化的对象,调用各个函数,并确保析构输出正确信息。 可能遇到的问题: 1. 转换小、分钟、秒的候,是否正确处理了余数。例如,总秒取余3600得到剩余的秒数,再除以60得到分钟,余数就是秒。 2. 浮点数精度问题,特别是毫秒部分,比如当传入的毫秒是500,应该转化为0.5秒,所以在构造函数中需要正确相加。 3. 析构函数是否在对象销毁被调用,比如当对象离开作用域。 4. 字符串输出格式是否正确,比如小、分钟、秒是否补零,毫秒是否显示三位数。 比如,当使用三个参数的构造函数,如Time t3(1, 1, 1, 500),对应的总秒应该是1*3600 + 1*60 + 1 + 500/1000 = 3661.5秒。输出间字符串应该是01:01:01.500。 另外,用户提到第三个构造函数有一个默认的浮点数参数代表毫秒值,所以在定义的候应该是三个int参数和一个double默认参数,注意参数顺序,默认参数应该放在最后。 测试用例需要考虑各种情况,比如无参构造、仅浮点数构造、三参数加默认毫秒的情况,以及三参数加指定毫秒的情况。析构函数的输出应该在每个对象销毁出现,比如在main函数结束,各个局部变量的析构函数会被调用,顺序与创建相反。 可能的代码结构: class Time { private: double totalSeconds; // 秒,包含毫秒的小数部分 public: Time() : totalSeconds(0) {} // 无参构造 Time(double s) : totalSeconds(s) {} // 浮点参数构造 Time(int h, int m, int s, double ms = 0.0) { // 三整数+默认毫秒 totalSeconds = h*3600 + m*60 + s + ms/1000.0; } ~Time() { std::cout << "析构函数执行" << std::endl; } std::string toString() { int total = static_cast<int>(totalSeconds); int hours = total / 3600; int remaining = total % 3600; int minutes = remaining / 60; int seconds = remaining % 60; double ms = (totalSeconds - total) * 1000; std::stringstream ss; ss << std::setfill('0') << std::setw(2) << hours << ":" << std::setw(2) << minutes << ":" << std::setw(2) << seconds << "." << std::setw(3) << static_cast<int>(std::round(ms)); return ss.str(); } double toTotalSeconds() { return totalSeconds; } int getHours() { return static_cast<int>(totalSeconds) / 3600; } }; 然后测试的候: int main() { Time t1; // 0秒 Time t2(3661.5); // 1小1分1.5秒 Time t3(1, 1, 1, 500); // 1:1:1.500 Time t4(25, 0, 0); // 25小,即25*3600=90000秒 // 输出各个函数的结果 } 需要注意的地方: - 在toString函数中,毫秒部分可能需要四舍五入,避免浮点误差。例如,totalSeconds是3661.5,那么ms是500,但如果是3661.4999,则可能得到499.9,四舍五入后是500还是499?这里用户可能需要三位数显示,所以需要处理。 - 使用std::setw(2)和setfill('0')来补零,比如小为1显示01。 - 析构函数的输出可能需要在每个对象销毁触发,比如在main函数中创建的对象会在main结束析构,顺序是t4, t3, t2, t1。 另外,用户提到“秒表示0点到某个刻的累秒值”,所以构造函数中的三个参数应该转换为总秒数加上毫秒部分,确保总秒正确。 现在需要检查各个构造函数是否正确转换参数为总秒。例如,Time(1, 1, 1, 500)的总秒应该是1*3600 + 1*60 +1 +500/1000= 3661.5秒。而Time(3600)则对应1小,即3600秒。 在toString函数中,处理毫秒的候,可能需要用std::round来避免截断导致的错误。例如,如果totalSeconds是123.9996秒,那么ms部分是0.9996*1000=999.6,四舍五入到1000,这候可能需要进位到秒,并调整前面的数值。不过这种情况可能需要处理,但用户可能希望直接显示三位数,即使超过999,或者截断。需要明确需。例如,用户可能希望毫秒部分显示三位,所以当ms计算后是1000,应该进位到秒,并调整前面的秒数。但这样处理起来比较复杂。可能在实际代码中,应该确保毫秒部分不会超过999,比如在构造函数中检查传入的ms参数是否小于1000。但用户可能没有提到这一点,所以可能在构造函数中允许传入超过1000的毫秒值,但转换为总会自动进位。例如,传入1500毫秒会被转换为1.5秒,加到总秒数中。这种情况下,toString函数中的ms部分会是总秒的小数部分乘以1000,不管是否超过1000,但显示的候可能需要取模,例如: ms = (totalSeconds - total) * 1000; int msInt = static_cast<int>(std::round(ms)) % 1000; 这样可以确保毫秒部分不超过三位数,并且正确处理进位。例如,如果总秒是3662.9999,那么total是3662,ms是0.9999*1000=999.9,四舍五入为1000,然后取余1000得到0,此秒数应该增加1。这候,总秒数应该变成3663秒,ms显示为000。但这样处理起来可能需要调整前面的秒数,这可能比较复杂。或者,用户可能接受这种情况,只是显示三位数字,不管是否超过,比如1500毫秒显示为500,而秒数增加1。这可能需要在转换处理,但用户可能没有明确说明,所以在代码中可能需要忽略,直接显示三位数,不管是否有进位。或者,可能应该将总秒转换为正确的间,包括进位,但这样会增加复杂度。 可能用户希望的是,无论传入的毫秒参数如何,构造函数都会正确计算总秒,例如传入ms=1500,会被转换为1.5秒,加到总秒数中。此,在toString函数中,处理的候,总秒可能包含小数部分超过1秒的情况,但该函数应该正确分解小、分钟、秒和毫秒。例如,总秒为3663.5秒,那么小=1(3663/3600=1小,余3秒),然后分钟=0,秒=3,毫秒=500。所以正确的处理方法是,将总秒分解为总秒数(包括所有整数部分),然后毫秒是总秒的小数部分乘以1000,四舍五入到整数,并保证三位显示,即使超过999。 例如: double totalSeconds = 3661.5; int totalSec = static_cast<int>(totalSeconds); // 3661 double ms = (totalSeconds - totalSec) * 1000; // 0.5 * 1000 = 500 int msInt = static_cast<int>(std::round(ms)); // 500 所以分解正确。但是如果totalSeconds是3661.9999,那么ms是999.9,四舍五入为1000,这msInt=1000,这候如何处理?可能需要将msInt调整为0,并且将总秒数加1。例如: msInt = 1000; totalSec += msInt / 1000; // 1 msInt %= 1000; // 0 但这样需要重新分解总Sec。这可能比较复杂,所以为了避免这种情况,可能在构造函数中限制毫秒参数的输入范围,或者在转换处理。 或者,在构造函数中,当用户传入ms参数,允许任何数值,并正确计算总秒。例如,传入ms=1500,会被转化为1.5秒,所以总秒增加1.5秒。这样,在toString函数中,分解的候,总Sec是整数部分,ms是小数部分乘以1000,不管是否超过三位数,直接显示。比如,如果总秒是3663.999秒,那么分解为3663秒,ms=999,显示为999。如果总秒是3663.9999秒,分解为3663秒,ms=999.9,四舍五入为1000,这候如何处理? 可能需要使用std::round,然后如果msInt为1000,则将其设置为0,并增加秒数。例如: ms = (totalSeconds - totalSec) * 1000; msInt = static_cast<int>(std::round(ms)); if (msInt >= 1000) { totalSec += 1; msInt -= 1000; } 这样处理的话,可以确保msInt在0到999之间。例如,总秒是3661.9999秒: totalSec = 3661 ms = 0.9999 * 1000 = 999.9 → round到1000 msInt = 1000 → 触发调整,totalSec变为3662,msInt=0. 然后分解为: hours = 3662 / 3600 = 1 → 3600,余62秒 minutes = 62 / 60 = 1 → 余2秒 seconds = 2 ms = 0 所以最终显示为01:01:02.000。 这样处理的话,可以避免ms超过三位数。但这样会增加代码的复杂度,需要在toString函数中进行调整。用户可能没有明确是否需要这样的处理,但考虑到间显示的合理性,应该这样做。否则,当总秒有足够多的小数,可能会显示不正确的毫秒数。 因此,在toString函数中,可能需要这样的调整步骤。不过,用户可能只是希望将小数部分直接转换为毫秒,即使超过999,例如显示为1000,但这样的格式不符合标准,所以应该进行调整。 因此,代码可能需要如下处理: 在计算msInt,检查是否超过999,如果超过则进位到秒: int totalSec = static_cast<int>(totalSeconds); double decimal = totalSeconds - totalSec; int msInt = static_cast<int>(std::round(decimal * 1000)); // 处理进位 totalSec += msInt / 1000; msInt %= 1000; // 重新分解totalSec int hours = totalSec / 3600; int remaining = totalSec % 3600; int minutes = remaining / 60; int seconds = remaining % 60; 这样就能正确处理进位问题。例如: 总秒3661.9999 → totalSec初始为3661,decimal是0.9999 → msInt=1000 → totalSec=3661 + 1=3662,msInt=0。然后分解totalSec=3662 → 1小1分2秒,ms=000。 这样处理是更正确的。所以在toString函数中需要这样的调整步骤。 因此,修改toString函数: std::string toString() { int totalSec = static_cast<int>(totalSeconds); double decimal = totalSeconds - totalSec; int msInt = static_cast<int>(std::round(decimal * 1000)); // 处理毫秒进位到秒 totalSec += msInt / 1000; msInt %= 1000; // 重新分解小、分钟、秒 int hours = totalSec / 3600; int remaining = totalSec % 3600; int minutes = remaining / 60; int seconds = remaining % 60; std::stringstream ss; ss << std::setfill('0') << std::setw(2) << hours << ":" << std::setw(2) << minutes << ":" << std::setw(2) << seconds << "." << std::setfill('0') << std::setw(3) << msInt; return ss.str(); } 这样处理之后,间显示会更准确,即使存在四舍五入导致的进位问题。 接下来,测试各个函数是否正确: 比如,Time t2(3661.5) → totalSeconds=3661.5。分解: totalSec=3661 → decimal=0.5 → msInt=500 → 无进位。所以间字符串为01:01:01.500。 另一个测试用例:Time t5(0, 0, 0, 1500) → 构造函数计算总秒=0 + 0 +0 +1500/1000=1.5秒。toString分解: totalSec=1 → decimal=0.5 → msInt=500 → totalSec=1+0=1 → ms=500 → 00:00:01.500。 另一个例子,Time t6(2, 70, 80, 1500) → 构造函数计算总秒=2*3600 +70*60+80+1500/1000=7200+4200+80+1.5=11481.5秒。分解: totalSec=11481 → decimal=0.5 → msInt=500 → totalSec=11481 → hours=3*3600=10800 → remaining=681 → 11分21秒 → 03:11:21.500。 这样的处理是正确的。 然后,getHours函数需要返回总秒的小数。例如,总秒是3661.5秒,小数应该是1。如果总秒是9000秒(2小30分),则小数是2。这里需要注意,getHours函数应该基于调整后的总秒数(包括进位后的),但原来的totalSeconds变量并没有被修改,所以如果使用原来的totalSeconds来直接计算小,可能会有错误。 例如,当totalSeconds是3661.9999秒,原来的totalSec是3661,小数为3661/3600=1小。但在toString中调整后,总Sec是3662,小数为1小。而getHours函数可能返回的是原totalSeconds的整数部分除以3600,即1小,而实际调整后的应该是1小。 或者,getHours函数是否需要考虑进位?比如,假设用户期望的是当前显示的小数,即toString中显示的HH部分,那么需要按照调整后的总秒数计算。否则,如果直接基于totalSeconds,可能得到不同的结果。 比如,假设totalSeconds是3661.999秒,在toString中处理后的总Sec是3662,小是1小,而getHours函数如果使用原totalSeconds的整数部分,则返回3661/3600=1小。两者是一致的,因为3661和3662都属于1小的范围。因此,getHours函数可以直接计算: int getHours() { return static_cast<int>(totalSeconds) / 3600; } 这可能与toString中的小数不同,因为toString中调整了进位。例如,如果总秒是3600*2 -1秒(7199秒),则小是1,而toString中的小可能为01:59:59.xxx。但是如果总秒是7199.999秒,经过进位后总Sec是7200秒,小是2小。但getHours函数返回的是7199/3600=1小,而toString中的小是2小。这会导致不一致。 这说明,在getHours函数中,应该使用调整后的总秒数,而不是原始totalSeconds的整数部分。因此,可能需要重新计算,就像toString函数中那样。或者,用户可能希望getHours函数返回当前总秒的小部分,而不考虑毫秒的进位。例如,总秒是7199.999秒,小部分是1小,不管进位后的结果。 这个候,需要明确需。用户要输出当前值小数的函数”,可能期望的是总秒对应的完整小数,即包括进位后的。例如,总秒是7200秒是2小,7199秒是1小,而7199.999秒可能被认为是1小,因为还没到7200秒。或者,用户可能希望小数是总秒除以3600的整数部分,不管后面的部分。 根据用户的描述,“秒表示0点到某个刻的累的秒值”,所以小数应该是总秒除以3600的整数部分,不管是否超过。比如,3661秒是1小,而3661.999秒也是1小,直到达到7200秒才变成2小。因此,getHours函数应该返回static_cast<int>(totalSeconds) / 3600,而不是调整进位后的总秒数。 例如,当totalSeconds是3661.5秒,getHours返回1;当是3663秒,返回1;当是7200秒,返回2。这与toString中的小显示一致,除非有进位。例如,当totalSeconds是7199.999秒,进位后总秒数是7200秒,小数是2,但getHours返回的是7199/3600=1。这会导致不一致。 这说明,在toString中处理进位后的小数和getHours的结果可能不一致。这可能需要进一步处理。例如,用户可能希望getHours函数返回toString中显示的小数,即经过进位后的。那这个候,getHours函数需要重新计算总秒数,考虑毫秒进位的情况。 这可能需要修改getHours函数的实现,复制toString中的调整步骤,以确保返回的小数与显示的一致。 因此,可能的实现: int getHours() { int totalSec = static_cast<int>(totalSeconds); double decimal = totalSeconds - totalSec; int msInt = static_cast<int>(std::round(decimal * 1000)); totalSec += msInt / 1000; return totalSec / 3600; } 这样,getHours函数将返回调整后的总秒数对应的小数,与toString中的小部分一致。例如,总秒是7199.999秒,调整后总秒是7200,小数是2。但这样会增加函数的计算复杂度。 但用户的需是“输出当前值小数的函数”,可能希望的是当前对象存储的总秒所对应的小数,不考虑进位到秒的调整。或者,可能希望的是实际的小部分,即总秒的小数,不考虑毫秒进位。例如,即使有999毫秒,小数还是原来的。 这需要用户澄清,但根据问题描述,可能用户希望的是总秒对应的完整小数,即总秒除以3600的整数部分,不管毫秒如何。因此,getHours函数可以保持原来的实现: int getHours() { return static_cast<int>(totalSeconds) / 3600; } 但这样可能导致与toString中的小数不一致。例如,当总秒是3661.999秒,toString显示的小是01(因为进位到3662秒,即1小),而getHours返回3661/3600=1小,两者一致。如果总秒是3663.5秒,则getHours返回3663/3600=1,toString显示的小也是01。所以在这种情况下,两者是一致的。只有当毫秒进位导致总秒数增加超过当前小,才会出现差异。例如,总秒是3599.999秒: - totalSeconds = 3599.999 - static_cast<int>(totalSeconds) = 3599 → getHours返回0。 - 在toString中,msInt = round(0.999*1000) = 999 → 无进位,总Sec仍然是3599,分解为0小59分59秒,小显示00。 - 所以getHours返回0,与toString一致。 另一个例子,总秒是3599.9999秒: - static_cast<int>(totalSeconds) = 3599 → getHours返回0。 - 在toString中,decimal=0.9999 → msInt=1000 → totalSec=3599 + 1=3600 → 分解为3600秒=1小,所以小显示01。 - 此,getHours返回0,而toString显示01小。两者不一致。 这说明,在getHours函数和toString函数的小数可能存在不一致的情况。这需要根据用户需来决定如何处理。如果用户希望getHours返回实际的小数,包括进位后的,那么需要重新计算,否则不。 由于用户的问题描述中没有明确这一点,可能需要假设用户希望的是总秒的整数部分的小数,即不进行进位处理。这样,getHours函数返回的是总秒的整数部分除以3600的结果,而toString中的小数可能因进位而不同。这可能是一个问题,但用户可能需要意识到这一点。 或者,用户可能希望getHours返回toString中显示的小数,所以需要调整getHours函数的实现,以包含进位处理。这样,函数可能需要复制toString中的计算步骤。 基于间类设计的正确性,可能需要让所有函数都基于调整后的间值,即考虑进位。这样,getHours函数应返回调整后的小数。这可能需要将调整后的总秒数存储为成员变量,或者在需要动态计算。然而,这样会增加类的复杂性,或者每次调用函数都进行计算。 由于当前类的设计中,存储的是总秒,包括毫秒的小数部分,所以所有函数都应基于这个值进行计算。而进位的问题可能应该由每个函数自行处理,如toString函数中的调整。 因此,getHours函数可能应该返回总秒的整数部分除以3600,而不考虑进位,这样更简单,但会导致与toString中的小数不一致的情况。或者,用户可能接受这一点,或者需要重新设计。 可能在这种情况下,用户可能希望getHours返回小部分,而不考虑秒和毫秒的进位。例如,即使总秒是3661秒(1小1分1秒),getHours返回1小。这与toString中的小数一致,只要毫秒的进位没有导致总秒数进入下一个小。例如,总秒为3599.999秒,getHours返回0,而toString显示00:59:59.999,小数正确。但如果总秒是3599.9999秒,进位后总秒数是3600,小数在toString中是01,而getHours返回3599/3600=0,这样不一致。 这可能是一个设计上的问题,需要用户进一步澄清。但根据问题描述,用户可能希望getHours返回总秒的小部分,即总秒除以3600的整数部分,无论毫秒如何。因此,保持getHours函数的原始实现。 综上所述,代码的大致结构已经明确,现在需要将其编写成C++代码,并确保所有功能正确,包括构造函数、输出函数、析构函数等。 最后,测试main函数中创建各个对象,并调用函数,观察输出是否符合预期。例如: Time t3(1, 1, 1, 500); std::cout << t3.toString() << std::endl; // 应输出01:01:01.500 std::cout << t3.toTotalSeconds() << std::endl; // 3661.5 std::cout << t3.getHours() << std::endl; // 1 Time t4(25, 0, 0); // 25*3600 = 90000秒 std::cout << t4.toString() << std::endl; // 25:00:00.000? 但根据toString函数,小数可以是超过24的,因为秒是累的,不限制在24小内。所以显示25小是正确的。 析构函数会在每个对象销毁调用,比如在main函数结束,四个对象t1, t2, t3, t4的析构函数会被调用,输出四次“析构函数执行”。 综上,代码的编写应该符合上述分析,并经过测试。</think>以下是根据要实现的间类代码及详细说明: ```cpp #include <iostream> #include <iomanip> #include <sstream> class Time { private: double totalSeconds; // 存储从0点开始的秒(含毫秒) public: // 无参构造函数(0点) Time() : totalSeconds(0.0) {} // 单浮点参数构造函数(秒) Time(double seconds) : totalSeconds(seconds) {} // 三整型参数+默认浮点参数构造函数 Time(int hours, int minutes, int seconds, double milliseconds = 0.0) { totalSeconds = hours * 3600 + minutes * 60 + seconds + milliseconds / 1000; } // 析构函数 ~Time() { std::cout << "析构函数执行" << std::endl; } // 格式间字符串 HH:MM:SS.ms std::string toString() { int total = static_cast<int>(totalSeconds); double decimal = totalSeconds - total; int ms = static_cast<int>(std::round(decimal * 1000)); // 处理毫秒进位 total += ms / 1000; ms %= 1000; int hours = total / 3600; int remaining = total % 3600; int minutes = remaining / 60; int seconds = remaining % 60; std::stringstream ss; ss << std::setfill('0') << std::setw(2) << hours << ":" << std::setw(2) << minutes << ":" << std::setw(2) << seconds << "." << std::setw(3) << std::setfill('0') << ms; return ss.str(); } // 输出秒(含毫秒) double toTotalSeconds() { return totalSeconds; } // 获取当前小数 int getHours() { return static_cast<int>(totalSeconds) / 3600; } }; int main() { // 测试无参构造函数 Time t1; std::cout << "t1: " << t1.toString() << " (" << t1.toTotalSeconds() << "s)" << " 小数:" << t1.getHours() << std::endl; // 测试浮点构造函数 Time t2(3661.5); // 1小1分1.5秒 std::cout << "t2: " << t2.toString() << " (" << t2.toTotalSeconds() << "s)" << " 小数:" << t2.getHours() << std::endl; // 测试三参数构造函数 Time t3(1, 1, 1, 500); // 01:01:01.500 std::cout << "t3: " << t3.toString() << " (" << t3.toTotalSeconds() << "s)" << " 小数:" << t3.getHours() << std::endl; // 测试默认毫秒参数 Time t4(25, 0, 0); // 25:00:00.000 std::cout << "t4: " << t4.toString() << " (" << t4.toTotalSeconds() << "s)" << " 小数:" << t4.getHours() << std::endl; return 0; } ``` ### 代码说明 1. **数据存储**:使用`double`类型存储秒,包含毫秒的小数部分 2. **构造函数**: - `Time()`:初始化秒为0 - `Time(double)`:直接存储浮点秒 - `Time(int, int, int, double)`:将分秒转换为秒,并添加毫秒 3. **关键函数**: - `toString()`:通过数学运算分解秒为分秒格式,处理毫秒进位问题 - `toTotalSeconds()`:直接返回存储的秒值 - `getHours()`:计算并返回整数数 4. **输出格式化**: - 使用`std::setw`和`std::setfill`控制数字位数 - 毫秒部分固定显示3位数字 ### 输出示例 ``` t1: 00:00:00.000 (0s) 小数:0 t2: 01:01:01.500 (3661.5s) 小数:1 t3: 01:01:01.500 (3661.5s) 小数:1 t4: 25:00:00.000 (90000s) 小数:25 析构函数执行 析构函数执行 析构函数执行 析构函数执行 ``` ### 关键点说明 1. **毫秒进位处理**:在`toString()`中通过`round`实现四舍五入,当毫秒超过1000会自动进位 2. **24小以上显示**:秒可以表示超过24小间(如示例中的25小) 3. **数值精度**:使用`double`类型确保毫秒的存储精度 4. **格式化一致性**:所有间组件均强制显示两位数字,毫秒显示三位数字
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值