

自分はC言語が得意じゃないため、皆さんの力貸してください。  
下記のRubyで作成したソースコードをC言語に変換したいです。

[code]

    n = gets.to_i
    
    ans = 0
    i = 1
    n.times {
      a = gets.to_i
      ans += (a-i).abs
      i = a
    }
    
    puts ans
    
[/code]

[code]

    #include <stdio.h>
    
    int main(void){
    
    int n[100];
    int ans,i;
    
        scanf("%d",&n);
    
        if((1<=n)&&(n<=100)){
            for(i=1; i<=n; i++){
                   ans = ans+(n-i);
            }
        }
        return 0;
    }
    
[/code]

宜しくお願い致します。


CC BY-SA 4.0
2019-06-21T05:42:02.593
55965
2019-06-21T12:03:43.897
2019-06-21T07:45:09.537
34810
34810
question
ruby c
RubyからC言語への変換について


まず、Rubyプログラムで使っている関数の仕様を調べます。

[module function Kernel.#gets](https://docs.ruby-
lang.org/ja/latest/method/Kernel/m/gets.html)

> ARGFから一行読み込んで、それを返します。

[object ARGF](https://docs.ruby-lang.org/ja/latest/class/ARGF.html)

> スクリプトに指定した引数 (Object::ARGV を参照) をファイル名とみなして、 それらのファイルを連結した 1
> つの仮想ファイルを表すオブジェクトです。 ARGV が空なら標準入力を対象とします。

[instance method String#to_i](https://docs.ruby-
lang.org/ja/latest/method/String/i/to_i.html)

> 文字列を 10 進数表現された整数であると解釈して、整数に変換します。

[class Integer](https://docs.ruby-lang.org/ja/latest/class/Integer.html)

> 整数クラスです。2.4.0 から Fixnum, Bignum は Integerに統合されました。

[instance method Integer#times](https://docs.ruby-
lang.org/ja/latest/method/Integer/i/times.html)

> self 回だけ繰り返します。 self が正の整数でない場合は何もしません。

[instance method Integer#abs](https://docs.ruby-
lang.org/ja/latest/method/Integer/i/abs.html)

> 自身の絶対値を返します。

[module function Kernel.#puts](https://docs.ruby-
lang.org/ja/latest/method/Kernel/m/puts.html)

> 引数と改行を順番に 標準出力 $stdout に出力します。 引数がなければ改行のみを出力します。  
>  引数が配列の場合、その要素と改行を順に出力します。 配列や文字列以外のオブジェクトが引数として与えられた場合には、 当該オブジェクトを最初に
> to_ary により配列へ、 次に to_s メソッドにより文字列へ変換を試みます。 末尾が改行で終っている引数や配列の要素に対しては puts 自身
> は改行を出力しません。

[instance method Integer#inspect](https://docs.ruby-
lang.org/ja/latest/method/Integer/i/to_s.html)

> 整数を 10 進文字列表現に変換します。

* * *

それらから、Rubyプログラムの内容を推測します。仕様が明記されていれば、それを利用します。  
おそらく以下のようになるでしょう。

  * (標準入力または指定入力ファイルから) 1行分の文字列を読み込んで、それを10進数とみなして整数に変換し、整数変数`n`に格納

  * 整数変数`ans`を0に、`i`を1に初期化

  * `n`回分、以下の処理を繰り返す

    * (標準入力または指定入力ファイルから) 1行分の文字列を読み込んで、それを10進数とみなして整数に変換し、整数変数`a`に格納
    * `a`から`i`を引いた結果を絶対値に変換し、`ans`に追加
    * `a`を`i`に代入
  * 上記処理結果の`ans`を10 進数文字列に変換し、標準出力に出力

* * *

次に C言語で同等な関数を調べます。  
無ければ近い仕様のものや複数の処理の組み合わせで代替します。  
以下はC言語ではなくVC++の記述です。  
Rubyの`Integer`は最大値がVC++では取り扱えないので、`long long`で代替します。

[memset、wmemset](https://docs.microsoft.com/ja-jp/cpp/c-runtime-
library/reference/memset-wmemset?view=vs-2019)  
[gets_s、_getws_s](https://docs.microsoft.com/ja-jp/cpp/c-runtime-
library/reference/gets-s-getws-s?view=vs-2019)  
[データ型の範囲](https://docs.microsoft.com/ja-jp/cpp/cpp/data-type-
ranges?view=vs-2019)  
[atoll、_atoll_l、_wtoll、_wtoll_l](https://docs.microsoft.com/ja-
jp/cpp/c-runtime-library/reference/atoll-atoll-l-wtoll-wtoll-l?view=vs-2019)  
[abs、labs、llabs、_abs64](https://docs.microsoft.com/ja-jp/cpp/c-runtime-
library/reference/abs-labs-llabs-abs64?view=vs-2019)  
[_itoa_s、_ltoa_s、_ultoa_s、_i64toa_s、_ui64toa_s、_itow_s、_ltow_s、_ultow_s、_i64tow_s、_ui64tow_s](https://docs.microsoft.com/ja-
jp/cpp/c-runtime-library/reference/itoa-s-itow-s?view=vs-2019)  
[puts、_putws](https://docs.microsoft.com/ja-jp/cpp/c-runtime-
library/reference/puts-putws?view=vs-2019)

* * *

変換した例が以下になるでしょう。  
(ただしMBCS版ですね。UNICODE版やdefineでの切り替え版はもう少し考慮・対処が必要です)  
完全に同等とはなりませんが、ほぼ近いものと考えられます。

[code]

    #include "pch.h"    // VC++のコンソールアプリケーション用：C言語版には不要
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define WORK_BUFFER_SIZE 24
    #define MAX_INPUT_COLUMN  20
    
    int main()
    {
        char buffer[WORK_BUFFER_SIZE] = { 0 };
        gets_s(buffer, MAX_INPUT_COLUMN);
        long long n = atoll(buffer);
    
        long long ans = 0;
        long long i = 1;
    
        for (long long counter = 0; counter < n; counter++) {
            memset(buffer, 0, WORK_BUFFER_SIZE);
            gets_s(buffer, MAX_INPUT_COLUMN);
            long long a = atoll(buffer);
    
            ans += llabs(a - i);
    
            i = a;
        }
    
        memset(buffer, 0, WORK_BUFFER_SIZE);
        _i64toa_s(ans, buffer, WORK_BUFFER_SIZE, 10);
        puts(buffer);
    
        return 0;
    }
    
[/code]


CC BY-SA 4.0
2019-06-21T11:53:55.577
55980
2019-06-21T12:03:43.897
2019-06-21T12:03:43.897
26370
26370
55965
answer


まず、以下の部分が C 言語のコードとして不自然な部分です。

  * `scanf("%d", &n);` となっているので `n` は `int` 型として宣言されているのが自然だが、実際には `int` の配列になっている。

Ruby のコードを見ても「最初に数をひとつだけ入力から読み取って `n` に代入する」という形になっているので、`n` を配列にするのは不自然そうです。

次に、以下の部分が Ruby のコードと C 言語のコードを比較して不自然な部分です。

  * C 言語側には、Ruby 側にはない「`n` が 1 以上 100 以下か？」という if 文が増えている。
  * Ruby 側では「`n` 回繰り返す」というコードの中で更に入力を読み取って `a` に代入しているが、そのコードが無い。
  * 同様に、ループの中で「`a - i` の絶対値を `ans` に足す」や「`a` を `i` に代入する」というコードが無い。ただし、Ruby 側では変数 `i` は `i = a` という使われ方をしている一方、C 言語側では for 文の繰り返し回数を数えるという使われ方をしているので、そこから直す必要がありそうです。
  * 同様に、「`ans` を出力する」というコードが無い。

以上を元に、C 言語側のプログラムを直してみてください。なお、C 言語における絶対値関数 `abs` は `#include <stdlib.h>`
をすることで `ans += abs(a - i)` という風に使えるようになります。

また、私の方で作ったプログラムを[こちらにリンク](https://wandbox.org/permlink/tAuugTadTWLt6rF0)しておきますので、ご自身で直された後の参考にお使いください。


CC BY-SA 4.0
2019-06-21T12:01:12.733
55981
2019-06-21T12:01:12.733
19110
55965
answer