OCN光で最大124,800円おトク!

教えて下さい。

C言語を用いてプログラミングをしています。
時刻をマイコン内部で1分毎にカウントしていますが、
外部入力があった際は、時刻を外部入力値に更新します。

時刻は以下の構造体で構成しています。

[年] 0x00~0x63 未設定:0x00
[月] 0x01~0x0c 未設定:0x00
[日] 0x01~0x1f 未設定:0x00
[時] 0x00~0x17 未設定:0xff
[分] 0x00~0x3b 未設定:0xff
[曜] 0x01~0x07 未設定:0x00

-----------------------------------------------------
typedef struct {
 unsigned char year_dt;
 unsigned char month_dt;
 unsigned char day_dt;
 unsigned char hour_dt;
 unsigned char min_dt;
 unsigned char week_dt;
}CALENDER_INFO;

CALENDER_INFO Calender_Before;
CALENDER_INFO Calender_After;

void Calender_Update(void){

 /* 処理前の時刻取得 */
 Calender_Before= Calender_Data;

 if(FLG_ON == F_SOUSA_A){
  Calender_Data = Calender_a;   /* 外部操作[a]データ反映 */
 }else{
  if(FLG_ON == F_SOUSA_B){
   Calender_Data = Calender_b;   /* 外部操作[b]データ反映 */
  }else{
   Add_1min_Calender();     /* 操作無ければ1分進める */
  }
 }

 /* 処理後の時刻取得 */
 Calender_After = Calender_Data;

 /* 差分算出 */
 ???????

return;
}
-----------------------------------------------------

時刻は[正]又は[負]のどちらの方向にも変更される可能性があります。

処理前の時刻情報と処理後の時刻情報をメンバ毎に演算するしかないのでしょうか?
演算の際に時刻の繰り上がりや繰り下がりを考慮しますと、
膨大なif文だらけになりバグが多発していまうのではないかと懸念しております。

初歩的な質問で申し訳ありませんが、
時刻計算にお詳しい方がいらっしゃいましたらご教示宜しくお願い致します。

A 回答 (2件)

日付時刻の構造体は自作のものでなきゃいけない理由はあるのでしょうか?


tm構造体を使えば二つの時間の差も簡単に出せます

time関数を使えるならtm構造体を使わず差を算出できます

文章で書くとややこしくなりそうなので参考サイトを貼ります
http://www.c-tipsref.com/tips/time/time.html
http://www1.cts.ne.jp/~clab/hsample/Time/Time5.h …
    • good
    • 0
この回答へのお礼

恥ずかしながらtm構造体の存在を知りませんでした。
ご教示頂いた参考サイトのmktime関数とlocaltime関数で
問題は解決できそうです。

ご丁寧にありがとうございました。

お礼日時:2017/09/22 07:58

時刻関係の関数を使えば済むことですが、基本的な考え方では年月日時分秒を最小単位である『秒』単位の値に換算してから差分計算をします。


1時2分3秒なら3723秒にします。
もちろんうるう年も考慮しなければなりません。
    • good
    • 0
この回答へのお礼

ありがとうございました。

お礼日時:2017/09/22 07:58

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aと関連する良く見られている質問

Q最も高い身長を表示するプログラム

5人分の身長から最も高い身長を表示するプログラムをつくったのですが、エラーがでて実行できません。改善すべきところを教えてください。お願いします。
int main(void)
{
double a[5], max = 0;
int i;

for (i = 1; i <= 5; i++)
{
a[i] = 0;
}
printf("数値を5つ入力してください。\n");

for (i = 1; i <= 5; i++)
{
scanf("%lf", &a[i]);
}

for (i = 1; i <= 5; i++)
{
if (a[i] > max)
max = a[i];
}

printf("最も高い身長は%fです\n", max);

return 0;
}

Aベストアンサー

double a[5] ;
と宣言したら、安全に使えるのは a[0] 〜 a[4] です。

なので、このプログラムを安全なものにするなら
・double a[5]はそのまま、 i=0;i<5;i++ にして、 i=0〜4 の範囲で使う
・「i = 1; i <= 5; i++は変えない」 のなら
 ・ i=1〜5を、 0〜4 に対応させて使う
   単純明快なのは、 a[i-1] とすること
 ・double a[5+1] と宣言して、a[5] を安全に使えるようにする。
   a[0] が無駄になるけど気にしない

QC言語について質問お願いします まだ勉強中なのでご指導よろしくお願いします str1=big str

C言語について質問お願いします

まだ勉強中なのでご指導よろしくお願いします

str1=big
str2=city
str3=bigcity

という結果にしたいのですが下のような結果になり困っております(´;Д;`)

もっといい書き方もあるかもしれませんが、今書いてあるコードを活かして訂正して結果通りになるにはどうすればいいでしょうか?!

その他アドバイスありましたら先輩方よろしくお願いしますm(_ _)m

Aベストアンサー

一つ訂正します
誤) char str1[4]={"big"},str2[4]={"city"}, str3[1]={0};
正) char str1[4]={"big"},str2[5]={"city"}, str3[1]={0};

ベテランでもこういう単純な間違いをすることがあります。
間違えもいいんです。それに気付いて直せれば。

ダメなときは、どこでダメになっているかを調べ、何故ダメになるかを調べ、どうすればダメじゃなくなるかを考えます。
これはベテランでも初心者でも変わりません。



原因は str3[1],str3[2] ...と範囲外に書き込んだことです。
例えるなら、「子供に紙とクレヨン渡したら、調子にのって床にまで絵を描いてしまった」状態です。
よって、対策は
・これらに書きこまないようにする。つまり、配列に収まる大きさの文字列にする
 (例えるなら「紙の外に描かないような小さな絵にする」)
・これらが書き込まれても問題ない状態にする。つまり、配列の大きさを十分に大きくする
 (例えるなら「絵が入るくらいの大きな紙にする」)
のどちらか、となります。

今回の場合、書き込みたい文字列が決まっているので、前者の「収まる文字列にする」という方法は使えません。
よって、後者の「文字列が収まる配列にする」が正解になります。

配列の大きさの指定方法はわかりますね?

一つ訂正します
誤) char str1[4]={"big"},str2[4]={"city"}, str3[1]={0};
正) char str1[4]={"big"},str2[5]={"city"}, str3[1]={0};

ベテランでもこういう単純な間違いをすることがあります。
間違えもいいんです。それに気付いて直せれば。

ダメなときは、どこでダメになっているかを調べ、何故ダメになるかを調べ、どうすればダメじゃなくなるかを考えます。
これはベテランでも初心者でも変わりません。



原因は str3[1],str3[2] ...と範囲外に書き込んだことです。
例えるなら、「子供に紙とクレヨン渡...続きを読む

QCのプログラムに無性にイライラするのはおかしいですか?

CQ出版のインタフェース 2017-5 の記事のプログラム例に
for( i=0; i<256; i++){
 for( y =0; y < Y; y++ ){
  for( x = 0; x < X; x++){
   p[0] = img -> imageData[img->widthStep* y + x*3 ]; //B(青色)
   if(p[0]==i){hn[i]++;}
  }
 }
}
がありました。このリストを見て、無性にイライラするのは私だけでしょうか?

なぜ、i,y,x の3重のループで処理しないといけないのか、y,xの2重ループで十分ではないかと思います。

for( y =0; y < Y; y++ ){
 for( x = 0; x < X; x++){
  p[0] = img -> imageData[img->widthStep* y + x*3 ];  //B(青色)
  hn[ p[0] ]++;
 }
}

3重にするならせめて、y,x,i の順にしてp[0]への代入は1回で済ませればと思います。

for( y =0; y < Y; y++ ){
 for( x = 0; x < X; x++){
  p[0] = img -> imageData[img->widthStep* y + x*3 ];  //B(青色)
  for( i=0; i<256; i++){
     if(p[0]==i){hn[i]++;}
  }
 }
}

最近のコンパイラの最適化では、私の書いたようなコーディング(修正?)は無意味なのでしょうか?

CQ出版のインタフェース 2017-5 の記事のプログラム例に
for( i=0; i<256; i++){
 for( y =0; y < Y; y++ ){
  for( x = 0; x < X; x++){
   p[0] = img -> imageData[img->widthStep* y + x*3 ]; //B(青色)
   if(p[0]==i){hn[i]++;}
  }
 }
}
がありました。このリストを見て、無性にイライラするのは私だけでしょうか?

なぜ、i,y,x の3重のループで処理しないといけないのか、y,xの2重ループで十分ではないかと思います。

for( y =0; y < Y; y++ ){
 for( x = 0; x < X; x++)...続きを読む

Aベストアンサー

利点を考えてみました


これを並列処理したときに
スレッド0: hn[0] に p[0] = 0 をカウント
スレッド1: hn[1] に p[0] = 1 をカウント
...
とすれば、
・img -> imageData は読み出すだけなので衝突しない
・hn[i] でアクセスする領域は、スレッド毎に i が違うので、同じ箇所に書き込まれることはない。
となり、排他処理が不要となります。
(もちろん、x,y,i,p[0]はスレッドでローカルな変数とします)

ただ、並列処理のオーバーヘッドや同時並列処理数等を考えると、こんな並列処理はしない方が効率的です。


あるいは、hn[]がシークに時間がかかる領域の場合、
hn[p[0]) で毎回違う位置を探しに行って、その時間が無視できないほどだったら、
先にhnを決めてしまった方が速くなるでしょう。

こちらも、非現実的です。

QC言語で、べき乗の計算をするプログラムについてです

X^8の計算を、掛け算を使わずに、足し算と引き算を使って計算するプログラムを作成するというものです。
足し算のみを使ってべき乗の計算をするプログラムは以下のソースコードの様にできたのですが、足し算と引き算の両方ともを使って計算するプログラムがわかりません。
べき乗の計算をどのように考えれば、足し算と引き算の両方を使って計算できるのか教えてください。
以下、足し算のみを使って計算するプログラムのソースコードです。
・・・ソースコード・・・
#include<stdio.h>

int main(void) {

int i, j, k;
i = 0; ///①Xの加算回数の値を保持する変数iを0に初期化する。///
j = 0; ///②X^2の加算回数の値を保持する変数jを0に初期化する。///
k = 0; ///③X^4の加算回数の値を保持する変数kを0に初期化する。///
double X, goukei1, goukei2, goukei3;
X = 0;
goukei1 = 0; ///④X^2の計算値を保持する変数goukei1を0に初期化する。///
goukei2 = 0; ///⑤X^4の計算値を保持する変数goukei2を0に初期化する。///
goukei3 = 0; ///⑥X^8の計算値を保持する変数goukei3を0に初期化する。///

printf("X=");
///数値Xを入力///
scanf_s("%lf", &X);

///⑦iがX以下か判定し、真ならば⑧~⑨を繰り返し、偽ならば繰り返しを終了する。///
for (i = 0; i < X; i++) { ///⑨iに1を加算する。///
goukei1 += X; ///⑧goukei1にXを加算する。///
}

///⑩jがgoukei1以下か判定し、真ならば⑪~⑫を繰り返し、偽ならば繰り返しを終了する。///
for (j = 0; j < goukei1; j++) { ///⑫jに1を加算する。///
goukei2 += goukei1; ///⑪goukei2にgoukei1を加算する。///
}

///⑬kがgoukei2以下か判定し、真ならば⑭~⑮を繰り返し、偽ならば繰り返しを終了する。///
for (k = 0; k < goukei2; k++) { ///⑮kに1を加算する。///
goukei3 += goukei2; ///⑭goukei3にgoukei2を加算する。///
}
///最終的な計算結果を出力///
printf("X^8=%f", goukei3);

return 0;
}

X^8の計算を、掛け算を使わずに、足し算と引き算を使って計算するプログラムを作成するというものです。
足し算のみを使ってべき乗の計算をするプログラムは以下のソースコードの様にできたのですが、足し算と引き算の両方ともを使って計算するプログラムがわかりません。
べき乗の計算をどのように考えれば、足し算と引き算の両方を使って計算できるのか教えてください。
以下、足し算のみを使って計算するプログラムのソースコードです。
・・・ソースコード・・・
#include<stdio.h>

int main(void) {
...続きを読む

Aベストアンサー

「引き算を使え」という問題の意図がよくわかりませんが、単純にfor文のカウンタ(質問文ではi, j, k)を加算ではなく減算でカウントするっていう意味だったりしないでしょうか。

ところで、X^8 = ((X^2)^2)^2 というアイデアは数学的には賢いやり方ですが、
足し算縛りのプログラムで作ると実は計算量は大きくなると思います。
X^8 = ((((((X*X)*X)*X)*X)*X)*X)*X の方が、実は計算回数が少なくて済みます。
X=10の場合、前者は10,110回、後者は70回の足し算になります。

QC言語 構造体の中に共用体を定義した変数の初期化に関して

C言語のコンパイルエラーに関する質問です。
以下のような構造体の中に共用体を作成して、constで初期値を入れておきたいと考えています。
機械に適用する初期パラメータのような感じです。
「初期化子が多すぎます。」というコンパイルエラーがでるのですが、どこが多いのかわかりません。
どう修正すれば良のか教えていただけないでしょうか?

// 構造体定義
typedef struct {
Uint16_t time;
Uint8_t mode;
Uint16_t xxxx;
Uint16_t zzzz;
}PrgPatternA_t;

typedef struct {
Uint16_t time;
Uint8_t mode;
Uint16_t yyyy;
}PrgPatternB_t;

typedef struct {
Uint8_t pattern;
union {
PrgPatternA_t param_a[3];
PrgPatternB_t param_b[2];
}param;
} Program_t;

// 変数定義
EsCourseProgram_t ES_COURSE_PROG_DATA = {
PATTERN_A,
{ // Aパターン
// time mode xxxx yyyy
{ 10, MODE_A, 100, 50},
{ 10, MODE_A, 100, 50},
{ 10, MODE_A, 100, 50}
}
}

C言語のコンパイルエラーに関する質問です。
以下のような構造体の中に共用体を作成して、constで初期値を入れておきたいと考えています。
機械に適用する初期パラメータのような感じです。
「初期化子が多すぎます。」というコンパイルエラーがでるのですが、どこが多いのかわかりません。
どう修正すれば良のか教えていただけないでしょうか?

// 構造体定義
typedef struct {
Uint16_t time;
Uint8_t mode;
Uint16_t xxxx;
Uint16_t zzzz;
}PrgPatternA_t;

typedef struct {
Uint16_t ti...続きを読む

Aベストアンサー

どの初期値がどのメンバーに対応するかをじっと見ていくと, {} が 1つ足らない. つまり初期化子は
{
PATTERN_A,
{ // Aパターン
// time mode xxxx yyyy
{
{ 10, MODE_A, 100, 50},
{ 10, MODE_A, 100, 50},
{ 10, MODE_A, 100, 50}
}
}
}
でないといけない.

どこかの {} を忘れていたんだと思う. 共用体を初期化するときの {} かなぁ?

QC言語初心者です。

1~100までの適当な数字をテキストに10個出力し、さらにそのファイルを読み込み、昇順にソートしてテキスト出力する単純なプログラムを教えてください。
※10個の数字は配列で保持するものとします。

Aベストアンサー

単純かどうかわかりません。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 10

int main(void)
{
FILE *fp1;
FILE *fp2;
FILE *fp3;
int i, j, temp=0;
int num[N]={0};
srand((unsigned)time(NULL));

fp1=fopen("sample.txt", "w"); //書き込み
fp2=fopen("sample.txt", "r"); //読み込み
fp3=fopen("sample.txt", "a"); //追加の書き込み

//--------------------------------------エラーチェック
if(fp1==NULL){
printf("file open error\n");
exit(EXIT_FAILURE);
}
if(fp2==NULL){
printf("file open error\n");
exit(EXIT_FAILURE);
}
if(fp3==NULL){
printf("file open error\n");
exit(EXIT_FAILURE);
}
//--------------------------------------乱数を作成
for(i=0; i<N; i++)
{
num[i]=rand()%100+1;

}
//---------------------------------------乱数を書き込み
for(i=0; i<N; i++)
{
fprintf(fp1, "%d ", num[i]);
}
fprintf(fp1, "\n");//-------------------ファイル内で改行

//----------------------------ファイルから乱数を読み込み
for(i=0; i<N; i++)
{
fscanf(fp2, "%d ", &num[i]);
}
//-------------------------読み込んだ数値を昇順に並べ替え
for(j=0; j<N; j++)
{
for(i=j+1; i<N; i++)
{
if(num[i]<num[j]){
temp=num[j];
num[j]=num[i];
num[i]=temp;
}
}
}
//----------------------------昇順に並べ替えたモノを書き込み
for(i=0; i<N; i++)
{
fprintf(fp3, "%d ", num[i]);
}
//-----------------------------書き込まれたファイルを読み込み
for(i=0; i<N; i++)
{
fprintf(fp2, "%d ", num[i]);
}
//------------------------------ファイルポインタをすべて閉じる
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}

出力例
>type sample.txt
38 49 96 8 84 18 14 85 26 58
8 14 18 26 38 49 58 84 85 96

単純かどうかわかりません。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 10

int main(void)
{
FILE *fp1;
FILE *fp2;
FILE *fp3;
int i, j, temp=0;
int num[N]={0};
srand((unsigned)time(NULL));

fp1=fopen("sample.txt", "w"); //書き込み
fp2=fopen("sample.txt", "r"); //読み込み
fp3=fopen("sample.txt", "a"); //追加の書き込み

//--------------------------------------エラーチェック
if(fp1==NULL){
printf("file open error\n");
exit(EXIT_FAILURE);...続きを読む

QC#プログラミング、少数の取り扱い方がわかりません

説明のしかたが下手で申し訳ないのですが

double型の数値で0.999999999999......と続く数値があったとして、この数値が1.0として扱われるのは小数第何位からですか?

また、1.0に近似してほしくないときはどうしたらいいですか?
C#でプログラミングをしています

Aベストアンサー

やろうとしていることは
lim_(x→0) f(x) = 1
で、 xを0に近付けつつ、f(x) を計算する、という感じなのでしょうか。


方法は3つあります。
(1) 計算式を工夫する。
0.999... だと 10^-15程度までしか正しくありませんが
0.000 .... 1 → 1.0 * 10^-n だと、10^-nの桁から15桁程度までの精度があります。
式を工夫して、計算結果が1ではなく、0に向うようにすることで、精度よく計算できるかもしれません
例)
g(x)=1-f(x) を求める。 ※「桁落ち」に注意


(2)十分な精度のある型を使う
https://ja.wikipedia.org/wiki/%E4%BB%BB%E6%84%8F%E7%B2%BE%E5%BA%A6%E6%BC%94%E7%AE%97
自作するか、既存のものを使う


(3)計算自体に意味があるのか、考えてみる。

Qプログラムの改良

人の作ったプログラムを改良することになりました。
Visual C++ は初めてですが、CやC++は一通り勉強しています。

そこで、いろいろ調べているのですが、
例えば
「MFCは使わずに,Win32API SDKを用いた方法」
などという説明があります。

自分が対応しているプログラムが、そのどちらであるか、あるいはほかの方法で作られているか
というのはどうしたら分かるのでしょうか?

Aベストアンサー

No1です
私はC++は全然触ったこと無いので
あまり的確な回答は期待しないでくださいね

Q1.いいんじゃないでしょうか?
MSDNのOnPoint↓
https://msdn.microsoft.com/ja-jp/library/01c9aaty.aspx

OnPointクラス(Cwndクラス)
https://msdn.microsoft.com/ja-jp/library/1xb05f0h.aspx
このページの一番最初に
「Microsoft Foundation Class ライブラリにあるすべてのウィンドウ クラスの基本機能が用意されています。」と書いてありますから
そういうことですね

Q2.なんでもいいと思いますけど
そもそもあなたが対応するプログラムが
きちんとWin32のみで、もしくはMFCのみで書かれているとは限らないですからね
適当に作られて、両方が混在している可能性だってありますし

Q3.そこからですか
そこは調べればすぐ出てくるかと思いますが
MFCというのはWin32をラッピングしたものです

Q4.作った本人に聞く
仕様書とかがあるならそれを見る

No1です
私はC++は全然触ったこと無いので
あまり的確な回答は期待しないでくださいね

Q1.いいんじゃないでしょうか?
MSDNのOnPoint↓
https://msdn.microsoft.com/ja-jp/library/01c9aaty.aspx

OnPointクラス(Cwndクラス)
https://msdn.microsoft.com/ja-jp/library/1xb05f0h.aspx
このページの一番最初に
「Microsoft Foundation Class ライブラリにあるすべてのウィンドウ クラスの基本機能が用意されています。」と書いてありますから
そういうことですね

Q2.なんでもいいと思いますけど
そもそもあなたが...続きを読む

Qc言語での文字列の渡し方

ある関数内で、作成した、文字列をmainプログラムでうけとるにはどのようにすればよいのでしょうか。
普通の変数の場合は解説書に例はありますが、配列の場合の例は見つかりませんでした。
以下は例です。gccを使っています。

int main(){
char str[20]; // sub内で加工した文字列を受け取る配列
...
sub( str );
....
}
void sub( char *ch ){
....
ch="ABCD"; // この値をmainプログラム内でつかいたい
....
}

Aベストアンサー

No2のかたが言われているように、strcpyを使用して、文字列を設定します。
厳密に言えば、strcpyの他にも方法はありますが、現時点では、strcpyと覚えておけばよいでしょう。
但し、strcpyを使用する場合、一点、必ず、守らなければいけないことがあります。
それは、呼び出し元のサイズ(今回は20バイト)を超えるサイズを設定してはいけないということです。
もし、strcpy(ch,"ABCDEFGHIJKLMNOPQRSTUVZWYZ");
を行うと、コンパイルは正常に終了しますが、呼び出し側で確保した20バイトを突き破りメモリの設定を行います。
その結果、異常終了します。(場合によっては、異常終了せずに、正常のようにみえることもあります)
----------------------------------------------------
#include<stdio.h>
#include<string.h>
void sub( char *ch ); //プロトタイプ宣言
int main(){
char str[20]; // sub内で加工した文字列を受け取る配列
sub( str );
printf("%s",str); //受け取った結果を印字
}
void sub( char *ch ){
strcpy(ch,"ABCD"); // この値をmainプログラム内でつかいたい
}
-----------------------------------------------------
実行結果
ABCD

No2のかたが言われているように、strcpyを使用して、文字列を設定します。
厳密に言えば、strcpyの他にも方法はありますが、現時点では、strcpyと覚えておけばよいでしょう。
但し、strcpyを使用する場合、一点、必ず、守らなければいけないことがあります。
それは、呼び出し元のサイズ(今回は20バイト)を超えるサイズを設定してはいけないということです。
もし、strcpy(ch,"ABCDEFGHIJKLMNOPQRSTUVZWYZ");
を行うと、コンパイルは正常に終了しますが、呼び出し側で確保した20バイトを突き破りメモリの設定を...続きを読む

QC言語について(三角形の面積・double型)

現在C言語を勉強中のものです。
以下のプログラムを実行すると、面積の計算結果が0になってしまいます。
doubleを全てintに、%fを全て%dにするとうまく動くのは確認したのですが、
自分が作りたいのは、引数をdoubleにし、実行結果も小数点込みで計算するものです。

以下のプログラムの問題点とその理由、またどのように書き換えることでうまく動くのかを教えていただけたらと思います。
よろしくお願いいたします。

~~以下コード~~
#include <stdio.h>

double tri(double,double);

int main(){
   double takasa,teihen;
   double menseki;
   printf("takasa=");
   scanf("%f",&takasa);
   printf("teihen=");
   scanf("%f",&teihen);
   menseki = tri(takasa,teihen);
   printf("menseki = %f",menseki);
}

double tri(double n1,double n2){
   return n1*n2/2;
}

~~以下実行結果~~
takasa=3
teihen=4
menseki = 0.000000

現在C言語を勉強中のものです。
以下のプログラムを実行すると、面積の計算結果が0になってしまいます。
doubleを全てintに、%fを全て%dにするとうまく動くのは確認したのですが、
自分が作りたいのは、引数をdoubleにし、実行結果も小数点込みで計算するものです。

以下のプログラムの問題点とその理由、またどのように書き換えることでうまく動くのかを教えていただけたらと思います。
よろしくお願いいたします。

~~以下コード~~
#include <stdio.h>

double tri(double,double);

int mai...続きを読む

Aベストアンサー

doubleのフォーマット指定子は%fではなく%lfです
とりあえずそこを変えてみて実行してみてください


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング