如何将负整数连接成字符c语言

时间:2014-11-30 17:01:52

标签: c concatenation subtraction negative-number

我创建了一个脚本来收集秒和microsec的时间戳。然后我试图计算这些值的差异。只要整数是正数,结果就像预期的那样。

作为下一步,我将整数转换为字符串,并将它们连接在一起。用户可以更容易地阅读人类可读的格式。

当整数为负时,会出现问题。首先,当我将负int转换为字符串时,我无法弄清楚如何打印负号。 (例如3sec。-3microsec)

其次,如果两个整数都是负数并且我有两个负号,那么它可能会变得更糟。 (例如-3sec。-3microsec)

所以我的问题是,因为我试图减去两个整数,实际上是浮点数是否有任何其他替代方法,我可以将它们连接成浮点数然后应用减法? (例如int 3sec int 3microsec concatenation to float 3.3sec)

我是C语言的初学者所以我不确定这是否可能,这就是我在所有这个过程中完成的原因(将int转换为字符串然后连接)。

可执行代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <sys/timeb.h>
#include <inttypes.h>
#include <assert.h>

#define TIME_CHAR 22
#define PROCESS_CHARACTERS 32

typedef struct rec {
  char time_1[TIME_CHAR];
  char time_2[TIME_CHAR];
  char time_3[TIME_CHAR];
  char process[PROCESS_CHARACTERS];
}RECORD;

char *u2s(long unsigned int number) {

  RECORD *ptr_record = malloc (sizeof(RECORD));

  if (ptr_record == NULL) {
    printf("Out of memory!\nExit!\n");
    exit(0);
  }

  const int n = snprintf(NULL, 0, "%lu", number);
  assert(n > 0);
  char buf[n+1];
  snprintf(buf, n+1, "%lu", number);
  assert(buf[n] == '\0');
  memcpy(ptr_record->process, buf , sizeof buf);

  return ptr_record->process;

}

uint32_t ClockGetTime() {
  struct timespec ts;
  clock_gettime(CLOCK_REALTIME, &ts);
  return (int32_t)ts.tv_sec * 1000000LL + (int32_t)ts.tv_nsec / 1000LL;
}

void cleanup(RECORD** ptr_record) {
  free(*ptr_record);
  *ptr_record = NULL;
}

int main(int argc, char *argv[]) {

  char *dot = ".";
  RECORD *ptr_record;

  ptr_record = malloc (sizeof(RECORD));

  if (ptr_record == NULL) {
    printf("Out of memory!\nExit!\n");
    exit(0);
  }

  /* Originate Time Stamps for time_1 */
  time_t time_1_sec = time(NULL);
  uint32_t client_1_sec = time_1_sec;
  uint32_t client_1_microsec = ClockGetTime();

  char *client_1_sec_string = u2s(client_1_sec);
  char *client_1_microsec_string = u2s(client_1_microsec);

  memset( ptr_record->time_1 , '\0' , sizeof ptr_record->time_1 );
  strncat( ptr_record->time_1 , client_1_sec_string , strlen(client_1_sec_string) );
  strncat( ptr_record->time_1 , dot , strlen(dot) );
  strncat( ptr_record->time_1 , client_1_microsec_string ,     strlen(client_1_microsec_string) );

  /* Originate Time Stamps for time_2 */
  time_t time_2_sec = time(NULL);
  uint32_t client_2_sec = time_2_sec;
  uint32_t client_2_microsec = ClockGetTime();

  char *client_2_sec_string = u2s(client_2_sec);
  char *client_2_microsec_string = u2s(client_2_microsec);

  memset( ptr_record->time_2 , '\0' , sizeof ptr_record->time_2 );
  strncat( ptr_record->time_2 , client_2_sec_string , strlen(client_2_sec_string) );
  strncat( ptr_record->time_2 , dot , strlen(dot) );
  strncat( ptr_record->time_2 , client_2_microsec_string , strlen(client_2_microsec_string) );

  printf("This is buffer time_2: %s\n",ptr_record->time_2);

  int32_t d_positive_sec = client_2_sec - client_1_sec;
  int32_t d_positive_microsec = client_2_microsec - client_1_microsec;

  printf("This is the positive difference in sec: %"PRId32"\n",d_positive_sec);
  printf("This is the positive difference in microsec: %"PRId32"\n",d_possitive_microsec);

  int32_t d_negative_sec = client_1_sec - client_2_sec;
  int32_t d_negative_microsec = client_1_microsec - client_2_microsec;

  printf("This is the negative difference in sec: %"PRId32"\n",d_negative_sec);
  printf("This is the negative difference in microsec: %"PRId32"\n",d_negative_microsec);

  char *n_sec_string = u2s(d_negative_sec);
  char *n_microsec_string = u2s(d_negative_microsec);

  memset( ptr_record->time_3 , '\0' , sizeof ptr_record->time_3 );
  strncat( ptr_record->time_3 , n_sec_string , strlen(n_sec_string) );
  strncat( ptr_record->time_3 , dot , strlen(dot) );
  strncat( ptr_record->time_3 , n_microsec_string , strlen(n_microsec_string) );

  printf("This is negative concatenated %s\n",ptr_record->time_3);

  cleanup(&ptr_record);

  return 0;

} /* End of main(){} */

输出样本:

This is the positive difference in sec: 0
This is the positive difference in microsec: 37
This is the negative difference in sec: 0
This is the negative difference in microsec: -37
This is negative concatenated 0.18446744073709551579

很容易判断,在连接后我们应该看到(0.-37),最好的结果是(-0.37)。

2 个答案:

答案 0 :(得分:0)

You can/should read all about printf format conversions at:

<http://en.wikipedia.org/wiki/Printf_format_string#Format_placeholders>

which states:

the full syntax of a conversion parameter is:
**%[parameter][flags][width][.precision][length]type**
where [parameter] is a posix extension ... (see linked page for details)

标志可以是零或更多(以任何顺序):

Character   Description
**+     always denote the sign '+' or '-' of a number (the default is to omit the sign for positive numbers). Only applicable to numeric types.**
space   prefixes non-negative signed numbers with a space
-   left-align the output of this placeholder (the default is to right-align the output).
#   Alternate form. For 'g' and 'G', trailing zeros are not removed. For 'f', 'F', 'e', 'E', 'g', 'G', the output always contains a decimal point. For 'o', 'x', and 'X', a 0, 0x, and 0X, respectively, is prepended to non-zero numbers.
0   use 0 instead of spaces to pad a field when the width option is specified. For example, printf("%2d", 3) results in " 3", while printf("%02d", 3) results in "03".

Width指定要输出的最小字符数,通常用于填充表格化输出中的固定宽度字段,否则字段会更小,尽管它不会导致超大字段的截断。宽度值中的前导零被解释为上面提到的零填充标记,并且负值被视为与左对齐相关的正值&#34; - &#34;国旗也在上面提到。

Precision通常指定输出的最大限制,具体取决于特定的格式类型。对于浮点数字类型,它指定输出应舍入的小数点右侧的位数。对于字符串类型,它限制了应输出的字符数,之后字符串将被截断。

长度可以省略,也可以是以下任何一种:

Character   Description
hh  For integer types, causes printf to expect an int-sized integer argument which was promoted from a char.
h   For integer types, causes printf to expect an int-sized integer argument which was promoted from a short.
l   For integer types, causes printf to expect a long-sized integer argument.

For floating point types, causes printf to expect a double argument.
ll  For integer types, causes printf to expect a long long-sized integer argument.
L   For floating point types, causes printf to expect a long double argument.
z   For integer types, causes printf to expect a size_t-sized integer argument.
j   For integer types, causes printf to expect a intmax_t-sized integer argument.

so just include the '+' flag in the format conversion parameter and 
if the value is negative, then a '-' will be printed in the output
t   For integer types, causes printf to expect a ptrdiff_t-sized integer argument.

答案 1 :(得分:0)

OP的获取时间的方法存在缺陷。它从2个调用中检索secondmicrosecond,但是在2个调用和秒数之间经过的时间可能会增加。相反,请重新编写ClockGetTime()以同时获取secmicrosec

// time_t time_1_sec = time(NULL);
// uint32_t client_1_sec = time_1_sec;
// uint32_t client_1_microsec = ClockGetTime();

正如@alk所建议的那样,隐藏到一个共同的比例,然后减去

// int32_t d_positive_sec = client_2_sec - client_1_sec;
// int32_t d_positive_microsec = client_2_microsec - client_1_microsec;
// printf("This is the positive difference in sec: %"PRId32"\n",d_positive_sec);
// printf("This is the positive difference in microsec: %"PRId32"\n",     
//     d_possitive_microsec);

int64_t t1 = client_1_sec;
t1 = t1*1000000 /* microseconds per second */ + client_1_microsec;
int64_t t2 = client_2_sec;
t2 = t2*1000000 + client_2_microsec;
int64_t diff = t2 - t1;
int64_t diff_sec = diff/1000000;
int32_t diff_usec = diff%1000000;
if (diff_usec < 0) diff_usec = -diff_usec;

printf("Difference: %" PRId64 ".%06" PRId32 " sec\n", diff_sec, diff_usec);

转换为float通常无法提供足够的精确度。转换为double通常对于32位int和~20位usec来说足够精确。这是另一种方法。

double t1 = client_1_sec;
t1 = t1*1000000 /* microseconds per second */ + client_1_microsec;
double t2 = client_2_sec;
t2 = t2*1000000 + client_2_microsec;
double diff = t2 - t1;

printf("Difference: %0.6f sec\n", diff);

总的来说,建议改为使用int64_t来存储clock_gettime()的秒和纳秒,并在差值计算中使用它。

int64_t ClockGetTime(void) {
  struct timespec ts;
  if (clock_gettime(CLOCK_REALTIME, &ts)) Handle_Error();
  return ts.tv_sec * ((int64_t)1000000000) + ts.tv_nsec;
}

次要说明

u2s在构造数字的字符串表示时经过大量工作,小心不要溢出buf。然而,如果没有检查memcpy(ptr_record->process, buf , sizeof buf),我很高兴sizeof buf <= sizeof ptr_record->process