質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.93%

文字列をBase64に変換するプログラムについて

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,954

szbhdulla

score 15

前提・実現したいこと

プログラミング初心者の大学1年です
入力した文字列をBase64に変換する(表現があっているかわかりませんが)
プログラムをC言語で作ってみました。

発生している問題・エラーメッセージ

このプログラムの改善したほうがいいことがあれば教えてください。
自分としては、
1.下のようなエラー文がコンパイル時に出る

warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
   int *p; p = bin;


これはおそらく2次元配列を一次元の配列に並べたときに出る警告で、
無理にポインタで書いたのですが、警告文が出ないのがベターなので出来るのであれば警告文が出ないように出来ますでしょうか?

2.自分で文字列の長さを求める関数lengthを作って使っているのですが、
あとでstrlen関数があるのを思い出してそれに変えて再度実行してみると、
結果がおかしくなってしまいます。

その他改善点やしたらもっと良くなることがあれば、教えてください

下にソースコードを書いているのですが、少し長いのでこちらに上げておきます
↑のBase64のフォルダにソースコードが書かれています。
それ以外には作成までの考えが書かれているソースコードが書かれています。

該当のソースコード

base64.c

#include <stdio.h>
#include "base64.h"

int main(void){

//inputに文字列を入力する
  char input[MAX];
    fgets(input, sizeof(input), stdin);

//文字列の長さ定義
  int len = length(input);

//文字列をdecに挿入 ascii.c
  int dec[MAX];
  for(i=0; i<=len-1; i++){
    dec[i] = ToDec(input[i]);
  }

//数列を2進数に allDecToBin.c
  int bin[MAX][bitNum];
  for(i=0; i<=len-1; i++){
    for(j=0; j<=bitNum-1; j++){
      bin[i][j] = *(ToBin(dec[i])+j);
    }
  }

//一列に並べる
  int sort[NUMBER];
  int sortLen = len*8;
  int *p; p = bin;
  for(i=0; i<=sortLen-1; i++){
        sort[i] = *(p+i);
    }

//6bitずつに並べる
  int sprit[43][6];
  int quotient = (sortLen-1)/6;    //商  行の大きさ
  p = sort;
  int n = 0;
  for(i=0; i<=quotient; i++){
        for(j=0; j<=5; j++){
            if(n<sortLen){
                sprit[i][j] = *(p+n);
            }else{
                sprit[i][j] = 0;
            }
            n++;
        }
    }

//とりあえずBase64に変換
  int line[6];
  char output[quotient+1];
  for(i=0; i<=quotient; i++){
    for(j=0; j<=5; j++){
      line[j] = sprit[i][j];
    }
    int dec = Dec6(line);
    output[i] = library(dec);
  }

//=をつけて並べて出力
  int remain = 4-((quotient+1)%4);
  int resultLen = quotient+1+(remain);
  int i;
  for(i=0; i<=resultLen-1; i++){
    if(i<=quotient){
      printf("%c", output[i]);
    }else{
      printf("=");
    }
  }printf("\n");

  return 0;
}


base64.h

//入力できる文字列の最大文字数
#define MAX 32

//decを2進数に変換しbin[][]に挿入
#define bitNum 8

//一列ソート後の文字数
#define NUMBER 256

//繰り返し処理用
int i, j;

//文字列を10進数へ
int ToDec(char pre){
    int dec = (int)pre;
  return dec;
}

//文字数定義
int length(char array[]){
  int len = 0;
  while(array[len] != '\0'){
    len++;
  }len--;
  return len;
}

//binの先頭ポインタを返す
int *ToBin(int pre){
    int dec[bitNum];
    int *p;
    for(int i=bitNum-1; i>=0; i--){
        if(pre != 0){
            dec[i] = pre%2;
            pre /= 2;
        }else{
            dec[i] = 0;
        }
    }
    p = dec;
    return p;
}

//数字を文字(Base64)に
char library(int dec){
  char after[62] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    char *p; p = after;
  char word = *(p+dec);
    return word;
}

//6bitのbinを一つずつdecに
int Dec6(int bin[6]){
  int i;
  int dec = 0;
  int weight = 1;
    for(i=6-1; i>=0; i--){
    dec += bin[i]*weight;
    weight *= 2;
  }
    return dec;
}

補足情報(言語/FW/ツール等のバージョンなど)

コンパイラーはgccです。
OSはlinux(archlinux)です。

追記

>>sharowさんのアドバイスにより追記します。
これは学校の課題ではありません。
初心者なので段階を踏んで行かないとわからなくなってしまうので、メモとしてgnoteに書いてpdfに出力しました。
Base64は「8946」というサイトの序盤に出てきたので興味をもって調べて、C言語でできないかということで作りました。

>>ikedasさんより追記します
gitHub上にのファイルを追加しました。(/base64/base64_strlen.c)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ikedas

    2016/11/01 08:49

    length()をstrlen()に変えたということですが、どういうふうに変えたんでしょう。GitHubのほうには変えたのがあるのかな

    キャンセル

  • sharow

    2016/11/01 09:16

    学校の課題であるか否かを明記したほうがよいと思います。githubに構成を説明したPDFがあるので、学校の課題のように見えてしまいます。

    キャンセル

  • szbhdulla

    2016/11/03 00:41

    学校の課題ではありません、初心者なので段階を踏んで行かないとわからなくなってしまうので、メモとしてgnoteに書いてpdfに出力しました。Base64は「8946」というサイトの序盤に出てきたので興味をもって調べて、C言語でできないかということで作りました。紛らわしくてすいません。

    キャンセル

回答 3

checkベストアンサー

+2

● とりあえずヘッダファイルに関数を書くのはやめよう(第一印象)
● ヘッダで変数を宣言するのはやめよう(extern はもう習われましたか?)
● 大域変数に i, j など局所変数で使われかねない変数名を付けるのはやめよう。
● 古い環境だとブロックの最初以外での変数の宣言は不正となる可能性がある
● 共用体を習っているなら使ってみよう
● ↑が難しければ構造体で挑戦するのもアリ
● 関数内で宣言した配列の賞味期限はいつまで?(ToBin)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/03 01:11

    おっしゃって頂いたことを参考にソースを改良/Cの勉強をしていきたいと思います。

    キャンセル

0

int bin[10][10];
int* p = bin[0];

bin[1][2] = 3;
printf("%d",p[1*10+2]); // 3
printf("%d\n",length("")); // -1
printf("%d\n",strlen("")); // 0

printf("%d\n",length("ABC")); // 2
printf("%d\n",strlen("ABC")); // 3

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/03 01:14

    結果まで記入いただきありがとうございます。
    これを参考に再度挑戦させていただきます。

    キャンセル

0

「Base64とは何か」という点をも少し調べてみてください。これは印字不可能なものを含めすべてを印字可能な64文字の表現にするエンコード方式です。本来なら文字列に限ってはなりません。…が、最初はそれでも良いでしょう。

一見で「あれれ?」と思ったのはここ。

char after[62] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";


これではBase62です。

ソースの構成についても、.h.cに分けれることを知っているようですが、「何のために」分けるのかが抜けているように思います。わからないうちは使わないのも手です。どちらにしろそのうち必要が生じて何のためにあるのかがわかるようになります。

あとご存じかもしれませんが、Linuxのcoreutilsには/usr/bin/base64があります。これの出力を模範とすることで、あなたが正しく問題を理解して正しく実装できているのか検証できます。こういう検証を1コマンド(たとえばmake test)でできるようにするのもプログラミングのうちです。

$ echo -n 'Hello World' | base64
SGVsbG8gV29ybGQ=
$ echo -n 'Hello World' | ./mybase64
# 上と同じものが出力されればOK

$ openssl rand 128 > randomdata
$ cat randomdata | base64
v15xf2a86aU9Kv81fvAdsG8T7TUfmZrkIPoBxoBaAg9mf38oEGDfn3wagyVg2FJoIxUpbHmKGYxC
y1uid8KpvPAV+XClx1ZoLBlhioD3rSnqB90wOrzGdVq/5OqMdzmrE9fSsGhp+YlmDD3zzWf4YEIL
5DejO26KF24spM90GMY=
$ cat randomdata | ./mybase64 | fold -w76
# 上と同じものが出力されればOK

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/03 15:52

    ありがとうございます。Base64の本質的なことを教えていただきありがとうございます。
    Linuxのコマンドでbase64があったのですね、知らなかったです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る