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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

6070閲覧

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

szbhdulla

総合スコア15

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/10/31 15:42

編集2016/11/02 16:00

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

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

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

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

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

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

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

###該当のソースコード
base64.c

c

1#include <stdio.h> 2#include "base64.h" 3 4int main(void){ 5 6//inputに文字列を入力する 7 char input[MAX]; 8 fgets(input, sizeof(input), stdin); 9 10//文字列の長さ定義 11 int len = length(input); 12 13//文字列をdecに挿入 ascii.c 14 int dec[MAX]; 15 for(i=0; i<=len-1; i++){ 16 dec[i] = ToDec(input[i]); 17 } 18 19//数列を2進数に allDecToBin.c 20 int bin[MAX][bitNum]; 21 for(i=0; i<=len-1; i++){ 22 for(j=0; j<=bitNum-1; j++){ 23 bin[i][j] = *(ToBin(dec[i])+j); 24 } 25 } 26 27//一列に並べる 28 int sort[NUMBER]; 29 int sortLen = len*8; 30 int *p; p = bin; 31 for(i=0; i<=sortLen-1; i++){ 32 sort[i] = *(p+i); 33 } 34 35//6bitずつに並べる 36 int sprit[43][6]; 37 int quotient = (sortLen-1)/6; //商 行の大きさ 38 p = sort; 39 int n = 0; 40 for(i=0; i<=quotient; i++){ 41 for(j=0; j<=5; j++){ 42 if(n<sortLen){ 43 sprit[i][j] = *(p+n); 44 }else{ 45 sprit[i][j] = 0; 46 } 47 n++; 48 } 49 } 50 51//とりあえずBase64に変換 52 int line[6]; 53 char output[quotient+1]; 54 for(i=0; i<=quotient; i++){ 55 for(j=0; j<=5; j++){ 56 line[j] = sprit[i][j]; 57 } 58 int dec = Dec6(line); 59 output[i] = library(dec); 60 } 61 62//=をつけて並べて出力 63 int remain = 4-((quotient+1)%4); 64 int resultLen = quotient+1+(remain); 65 int i; 66 for(i=0; i<=resultLen-1; i++){ 67 if(i<=quotient){ 68 printf("%c", output[i]); 69 }else{ 70 printf("="); 71 } 72 }printf("\n"); 73 74 return 0; 75}

base64.h

c

1//入力できる文字列の最大文字数 2#define MAX 32 3 4//decを2進数に変換しbin[][]に挿入 5#define bitNum 8 6 7//一列ソート後の文字数 8#define NUMBER 256 9 10//繰り返し処理用 11int i, j; 12 13//文字列を10進数へ 14int ToDec(char pre){ 15 int dec = (int)pre; 16 return dec; 17} 18 19//文字数定義 20int length(char array[]){ 21 int len = 0; 22 while(array[len] != '\0'){ 23 len++; 24 }len--; 25 return len; 26} 27 28//binの先頭ポインタを返す 29int *ToBin(int pre){ 30 int dec[bitNum]; 31 int *p; 32 for(int i=bitNum-1; i>=0; i--){ 33 if(pre != 0){ 34 dec[i] = pre%2; 35 pre /= 2; 36 }else{ 37 dec[i] = 0; 38 } 39 } 40 p = dec; 41 return p; 42} 43 44//数字を文字(Base64)に 45char library(int dec){ 46 char after[62] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 47 char *p; p = after; 48 char word = *(p+dec); 49 return word; 50} 51 52//6bitのbinを一つずつdecに 53int Dec6(int bin[6]){ 54 int i; 55 int dec = 0; 56 int weight = 1; 57 for(i=6-1; i>=0; i--){ 58 dec += bin[i]*weight; 59 weight *= 2; 60 } 61 return dec; 62}

###補足情報(言語/FW/ツール等のバージョンなど)
コンパイラーはgccです。
OSはlinux(archlinux)です。

###追記

sharowさんのアドバイスにより追記します。

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

ikedasさんより追記します

gitHub上にのファイルを追加しました。(/base64/base64_strlen.c)

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikedas

2016/10/31 23:49

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

2016/11/01 00:16

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

2016/11/02 15:41

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

回答3

0

ベストアンサー

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

投稿2016/11/02 07:25

編集2016/11/02 07:42
WoodenHamlet

総合スコア306

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

szbhdulla

2016/11/02 16:11

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

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 01:21

sharow

総合スコア1149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

szbhdulla

2016/11/03 06:52

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

0

C

1int bin[10][10]; 2int* p = bin[0]; 3 4bin[1][2] = 3; 5printf("%d",p[1*10+2]); // 3

C

1printf("%d\n",length("")); // -1 2printf("%d\n",strlen("")); // 0 3 4printf("%d\n",length("ABC")); // 2 5printf("%d\n",strlen("ABC")); // 3

投稿2016/10/31 23:36

ozwk

総合スコア13512

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

szbhdulla

2016/11/02 16:14

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問