2014-11-30 4 views
1

타임 스탬프를 초 단위로 수집하는 스크립트를 만들었습니다. 그런 다음이 값의 차이를 계산하려고합니다. 정수가 양수이면 결과는 예상대로입니다.음수를 문자로 연결하는 방법 C 언어

다음 단계로 정수를 문자열로 변환하고 사이에 점으로 연결합니다. 사람이 읽을 수있는 형식으로 읽는 것이 훨씬 쉽습니다.

정수가 음수 일 때 문제가 나타납니다. 무엇보다 먼저 음수 int를 문자열로 변환 할 때 음수 부호를 출력하는 방법을 알아낼 수 없습니다. (예 : 3 초 -3 마이크로 초)

둘째 정수가 모두 음수이고 두 개의 음수 부호가있는 경우 두 번째로 악화 될 수 있습니다. (예 : -3 초 -3 마이크로 초)

내 질문은 현실에서 두 개의 정수를 빼기 위해 부동 소수점으로 연결 한 다음 뺄셈을 적용 할 수있는 다른 대안이 있습니까? (예 : int 3sec int 3 마이크로 초 연결하여 3.3 초 부동)

나는 이것이 가능하면 잘 모르겠다. 그래서이 모든 과정을 거쳤다. (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)입니다.

+0

0s + 37us는 0.37s가 아니라 0.000037을 제공합니다! – alk

+0

이것은 사실입니다.이 문제를 해결하려면 어떻게해야합니까? 어떤 제안? – Thanos

+1

caclulation을 수행 할 때 더 작은 해상도로 전환하십시오. 작업이 끝나면 필요한 장치로 다시 확장하십시오. – alk

답변

0

영업 이익의 방법은 결함이있다. 두 번 호출에서 secondmicrosecond을 검색하지만 두 번 호출 사이의 시간 경과 및 초 수가 증가 할 수 있습니다. 대신 ClockGetTime()을 다시 작성하여 secmicrosec을 모두 얻으십시오.

공통의 규모에 비밀 @alk에 의해 제안 된 것과 같은
// time_t time_1_sec = time(NULL); 
// uint32_t client_1_sec = time_1_sec; 
// uint32_t client_1_microsec = ClockGetTime(); 

, 다음 일반적으로 충분한 정밀도를 제공하지 않습니다 float로 변환

// 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); 

뺍니다. 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); 

전체적으로 대신 clock_gettime()에서 초 나노초 저장 차분 계산에서 그 사용 int64_t 사용을 권장합니다. 숫자의 문자열 표현을 구성 할 때 많은 작업이 조심스럽게 buf 오버 플로우하지 불구하고

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 간다. 그래도 행복하게 memcpy(ptr_record->process, buf , sizeof buf)을 확인하지 않고 sizeof buf <= sizeof ptr_record->process을 확인합니다.

+0

완벽 함, 절대적인 의미를 갖습니다. 64 비트 (8 바이트)로 마이크로 초 단위로 초를 추가하여 두 개의 32 비트 값을 맞출 수 있어야합니다. 계산을위한 두 번째 단계. 감사합니다. 시간과 노력에 감사드립니다. – Thanos

+0

답변에 대한 작은 업데이트. 내 코드에 대한 대답을 조정하는 동안 나는 작은 세부 사항을 알아 차렸다. if ((diff_sec <0) || (diff_usec <0)) diff_sec = -diff_sec;'와 같이해야한다. 그 이유는 마이크로 초가 음수 값을 갖거나 초가 음수 값을 가지면 테스트하기를 원하기 때문입니다. 그 두 가지 경우에 우리는 초가 앞쪽에 음수를 표시하기를 원합니다. 다시 한번 감사 드리며 시간과 노력에 감사드립니다. – Thanos

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". 

폭 출력 문자의 최소 개수를 지정하고, 통상적 표로 출력 패드 고정 폭 필드를 사용 여기서 필드는 그렇지 않은 경우 큰 필드의 절단을 초래하지 않지만 필드는 더 작습니다. 너비 값의 앞에 오는 0은 위에서 언급 한 제로 패딩 플래그로 해석되며 음수 값은 위에서 언급 한 왼쪽 맞춤 "-"플래그와 함께 양수 값으로 처리됩니다.

정밀도는 일반적으로 특정 형식 유형에 따라 출력물의 최대 한도를 지정합니다. 부동 소수점 숫자 유형의 경우 소수점 오른쪽에 출력을 반올림 할 자릿수를 지정합니다. 문자열 유형의 경우, 출력해야하는 문자 수를 제한하고 그 이후에는 문자열이 잘립니다.

길이는 생략 또는 중 하나 일 수 있습니다 시간이 점점

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. 
+0

완벽 함,이 모든 세부 사항을 알지 못했습니다. 내가 제공 한 링크를 읽고 스크립트에서 조정 해 보겠습니다. 시간과 노력에 감사드립니다. – Thanos