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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

C

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

コンパイル

コンパイルとは、プログラミング言語のテキストソース(ソースコード)をコンピュータ上で実行可能な形式(オブジェクトコード)に変換することをいいます

Q&A

解決済

2回答

705閲覧

Linux環境では動いていたプログラムがWindows環境では動かない

GLa1192

総合スコア5

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

C

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

コンパイル

コンパイルとは、プログラミング言語のテキストソース(ソースコード)をコンピュータ上で実行可能な形式(オブジェクトコード)に変換することをいいます

0グッド

0クリップ

投稿2020/01/26 02:06

実現したいこと

Linux環境で以下のプログラムを書き、gccでコンパイルからの実行とした時は、正常に動いたのですが、windows環境で同じプログラムをgccでコンパイルからの実行とすると、上手く動いてくれません。何を変えればWindowsでも正常に動いてくれますか?

以下のプログラムはコンパイラー的なのをc言語で書いてみようというもので、構文解析をするものです。

windows環境だと、”<>”が”<”部分だけ読み込まれされ、その後、なにも読み込まなくなり、"Syntax Error"と表示されます。なので、おそらくcheck_word関数がおかしいのですが、なにぶんLinux環境では最後の”.”まで読み取れ”Complete”できるので、なにがおかしいのか分からずにいます。

c

1#include<stdio.h> 2#include<stdlib.h> 3#include<string.h> 4 5char outtoken[200][10]; //トークン出力用配列 6int tnum; 7 8char token[20]; 9char res[13][20]={"begin","end","if","then","while","do", 10 "return","function","var","const","odd", 11 "write","writeln"}; 12char sign[17][10]={"+","-","*","/","(",")","=","<",">", 13 "<>","<=",">=",",",".",";",":="}; 14FILE *fi; 15int a=0; 16//関数宣言 17void nexttoken(int); //次のトークンを読み込む関数 18int ch(char[]); //引数の文字列との比較 同じ:1 違う:0 19int ttype(); //トークンのタイプを返す 1:予約語 2:記号 20 // 3:名前 4:整数 21void exit_func(); //構文解析エラー 強制終了 22void backtoken(); //現在のトークンの番号を1つ前に戻す 23void block(), varDecl(), constDecl(), funcDecl(), 24 statement(), condition(), expression(), term(), 25 factor(); //構文規則を指定 26void get_token(); 27 28int check_word(char c){ 29 if(c>='0' && c<='9') // 数字なら 30 return 0; 31 else if(c>='a' && c<='z') //アルファベット 32 return 1; 33 else if(c=='\n' || c==' ' || c=='\t') //改行,スペース,タブ 34 return 2; 35 else if(c=='+' || c=='-' || c=='*' || c=='/' || c=='(' || c==')' || c=='=' || c==',' || c=='.' || c==';') //1文字のみの記号 36 return 3; 37 else if(c==':') //コロンは'='と必ず一緒になる 38 return 4; 39 else if(c=='<' || c=='>'){ //この場合は次の文字を見る必要がある 40 c=fgetc(fi); 41 fseek(fi,-1,1); //ファイルポインタを1つ戻す 42 if(c=='=' || c=='>'){ 43 return 4; 44 }else{ 45 return 3; 46 } 47 } 48} 49 50int main(int argc, char **argv) 51{ 52 get_token(); //トークン分割プログラム 53 tnum=0; 54 block(); 55 nexttoken(1); 56 if(ch(".")) printf("Complete\n"); 57 else printf("Syntax Error\n"); 58 59 return 0; 60} 61 62void block() 63{ 64 int c=0; 65 nexttoken(0); 66 while(ch("const")||ch("var")||ch("function")){ 67 c++; 68 if(ch("const")) constDecl(); 69 else if(ch("var")) varDecl(); 70 else if(ch("function")) funcDecl(); 71 } 72 if(!c) backtoken(); 73 statement(); 74} 75 76void varDecl() 77{ 78 nexttoken(1); 79 if(ttype()!=3) exit_func("verdecl"); 80 nexttoken(1); 81 while(ch(",")){ 82 nexttoken(1); 83 if(ttype()!=3) nexttoken(1); 84 else exit_func("verdecl"); 85 } 86 if(ch(";")){} 87 else exit_func("verdecl"); 88} 89 90void funcDecl() 91{ 92 nexttoken(3); 93 if(ttype()!=3) exit_func("funcdecl"); 94 nexttoken(3); 95 if(!ch("("))exit_func("funcdecl"); 96 nexttoken(3); 97 if(ttype()!=3) 98 exit_func("funcdecl"); 99 nexttoken(3); 100 while(ch(",")){ 101 nexttoken(3); 102 if(ttype()==3) nexttoken(3); 103 else exit_func("funcdecl"); 104 } 105 if(ch(")")) block(); 106 else exit_func("funcdec3"); 107 nexttoken(3); 108 if(ch(";")) nexttoken(3); 109 else exit_func("funcdec4"); 110} 111 112void constDecl() 113{ 114 do{ 115 nexttoken(2); 116 if(ttype()!=3) exit_func("constdecl"); 117 nexttoken(2); 118 if(!ch("=")) exit_func("constdecl"); 119 nexttoken(2); 120 if(ttype()!=4) exit_func("constdecl"); 121 nexttoken(2); 122 }while(ch(",")); 123 if(ch(";"))nexttoken(2); 124 else exit_func("constdecl"); 125} 126 127void statement() 128{ 129 int a,b,n; 130 int t_now, t_next; 131 132 nexttoken(4); 133 if(ttype()==3){ 134 nexttoken(4); 135 //if(ch(":=")!=) exit_func("Syntax Error"); 136 if(!ch(":=")) exit_func("Syntax Error"); 137 expression(); 138 } 139 else if(ch("begin")){ 140 statement(); 141 nexttoken(4); 142 while(ch(";")){ 143 statement(); 144 nexttoken(4); 145 } 146 if(!ch("end")) exit_func("Syntax Error"); 147 148 } 149 else if(ch("if")){ 150 condition(); 151 nexttoken(4); 152 if(!ch("then")) exit_func("Syntax Error"); 153 statement(); 154 } 155 else if(ch("while")){ 156 condition(); 157 nexttoken(4); 158 if(!ch("do")) exit_func("Syntax Error"); 159 statement(); 160 } 161 else if(ch("return")){ 162 expression(); 163 }else if(ch("write")){ 164 expression(); 165 }else if(ch("writeln")){ 166 }else{ //何もせずにスルー 167 backtoken(); 168 } 169} 170 171void condition() 172{ 173 nexttoken(5); 174 if(!ch("odd")){ 175 backtoken(); 176 expression(); 177 }else expression(); 178 if(!ch("=")&&!ch("<>")&&!ch("<")&&!ch(">")&&!ch("<=")&&!ch(">=")){ 179 exit_func("Syntax Error"); 180 }else{ 181 nexttoken(5); 182 expression(); 183 } 184} 185 186void expression() 187{ 188 nexttoken(6); 189 if(!ch("+")&&!ch("-")){ 190 backtoken(); 191 term(); 192 }else{ 193 term(); 194 } 195 nexttoken(6); 196 while(ch("+")||ch("-")){ 197 term(); 198 nexttoken(6); 199 } 200 backtoken(); 201} 202 203void term() 204{ 205 factor(); 206 nexttoken(7); 207 while(ch("*")||ch("/")){ 208 factor(); 209 nexttoken(7); 210 } 211 backtoken(); 212} 213 214void factor() 215{ 216 nexttoken(8); 217 if(ttype()==4){ 218 }else if(ttype()==3){ 219 nexttoken(8); 220 if(!ch("(")){ 221 backtoken(); 222 }else{ 223 nexttoken(8); 224 if(ch(")")){ 225 backtoken(); 226 }else{ 227 backtoken(); 228 expression(); 229 nexttoken(8); 230 while(ch(",")){ 231 expression(); 232 nexttoken(8); 233 } 234 } 235 if(ch(")")){ 236 }else{ 237 exit_func("factor1"); 238 } 239 } 240 }else if(ch("(")){ 241 expression(); 242 nexttoken(8); 243 if(ch(")")){ 244 }else{ 245 exit_func("factor2"); 246 } 247 } 248} 249 250void nexttoken(int s) 251{ 252 char state[30]; 253 switch(s){ 254 case 0: sprintf(state,"block"); 255 break; 256 case 1: sprintf(state, "constDecl"); 257 break; 258 case 2: sprintf(state, "verDecl"); 259 break; 260 case 3: sprintf(state, "funcDecl"); 261 break; 262 case 4: sprintf(state, "statement"); 263 break; 264 case 5: sprintf(state, "condition"); 265 break; 266 case 6: sprintf(state, "expression"); 267 break; 268 case 7: sprintf(state, "term"); 269 break; 270 case 8: sprintf(state, "factor"); 271 break; 272 } 273 strcpy(token,outtoken[tnum]); 274 tnum++; 275 printf("%-13s : [%s]\n",state,token); 276} 277 278int ch(char str[20]) //文字列の比較 279{ 280 if(strcmp(token,str)==0) return 1; 281 else return 0; 282} 283 284int ttype() //トークンのタイプを返す 285{ 286 int i,c; 287 for(i=0;i<13;i++){ 288 c=strcmp(token,res[i]); 289 if(c==0){ 290 return 1; 291 break; 292 } 293 } 294 295 for(i=0;i<16;i++){ 296 c=strcmp(token,sign[i]); 297 if(c==0){ 298 return 2; 299 break; 300 } 301 } 302 303 if(token[0] >='0' && token[0]<='9') 304 return 4; 305 else 306 return 3; 307} 308 309void backtoken() //トークン番号を1つ前に戻す 310{ 311 tnum--; 312} 313 314void exit_func(char str[20]) //文法規則に合わないため終了 315{ 316 printf("Syntax Error Near the Word \"%s\"\n",token); 317 printf("%s\n",str); 318 exit(1); //強制終了 319} 320 321 322void get_token() 323{ 324 int i,j,token_num; 325 char c; 326 fi=fopen("2.txt","r"); 327 token_num=0; //トークンの数の初期化 328 j=0; 329 while(1){ 330 c=fgetc(fi); //1文字ずつ入力 331 printf("%c\n",c); 332 if(c==EOF)break; 333 334 if(check_word(c)==0){//数字なら 335 outtoken[token_num][j]=c; 336 j++; 337 a=1; 338 } 339 else if(check_word(c)==1){//文字なら 340 if(a==1){ 341 outtoken[token_num][j]='\0'; 342 j=0; 343 token_num++; 344 a=0; 345 } 346 outtoken[token_num][j]=c; 347 j++; 348 } 349 else if(check_word(c)==2){ //改行,スペース,タブなら 350 if(j!=0){ 351 outtoken[token_num][j]='\0'; 352 j=0; 353 token_num++; 354 } 355 else{ 356 //do nothing!! 357 } 358 }else if(check_word(c)==3){ //記号なら(1文字) 359 if(j!=0){ 360 outtoken[token_num][j]='\0'; 361 j=0; 362 token_num++; 363 } 364 outtoken[token_num][j]=c; 365 j++; 366 outtoken[token_num][j]='\0'; 367 j=0; 368 token_num++; 369 a=0; 370 } else if(check_word(c)==4){ //記号なら(2文字) 371 if(j!=0){ 372 outtoken[token_num][j]='\0'; 373 j=0; 374 token_num++; 375 } 376 outtoken[token_num][j]=c; 377 j++; 378 c=fgetc(fi); 379 printf("%c\n",c); 380 outtoken[token_num][j]=c; 381 j++; 382 outtoken[token_num][j]='\0'; 383 j=0; 384 token_num++; 385 a=0; 386 } 387 } 388 389 for(i=0;i<token_num;i++){ 390 printf("%3d %s ",i,outtoken[i]); 391 if(check_word(outtoken[i][0])==0){ 392 printf("整数\n"); 393 }else if(check_word(outtoken[i][0])==3 || check_word(outtoken[i][0])==4){ 394 printf("記号\n"); 395 }else if(check_word(outtoken[i][0])==1){ 396 if(strcmp(outtoken[i],"begin")==0 || strcmp(outtoken[i],"end")==0 || strcmp(outtoken[i],"if")==0 || strcmp(outtoken[i],"then")==0 || strcmp(outtoken[i],"while")==0 || strcmp(outtoken[i],"do")==0 || strcmp(outtoken[i],"return")==0 || strcmp(outtoken[i],"function")==0 || strcmp(outtoken[i],"var")==0 || strcmp(outtoken[i],"const")==0 || strcmp(outtoken[i],"odd")==0 || strcmp(outtoken[i],"write")==0 || strcmp(outtoken[i],"writeln")==0){ 397 printf("予約語\n"); 398 } 399 else { 400 printf("名前\n"); 401 } 402 } 403 } 404 405} 406

入力するテキストファイル↓

function gcd(x,y) begin while x <> y do begin if x < y then y:=y-x; if y<x then x:=x-y; end; return x end; const bunsi=32,bunbo=88; var g; begin g:=gcd(bunsi,bunbo); write bunsi/g; write bunbo/g; writeln end.

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

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

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

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

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

y_waiwai

2020/01/26 02:07

エラーが出るならエラーメッセージを提示しましょう。
otn

2020/01/26 02:28

関数ごとの単体テストをやっていないなら、やった方がいいです。
guest

回答2

0

ベストアンサー

全体を見たわけではないですがぱっと目についたところだけ。

テキストモードで開いたストリームに対して fseek で現在位置から -1 するというのは C の言語仕様では保証されない動作です。

マイクロソフトのサイトにある Visual Studio のドキュメントでも保証されないということは明記されています。 Windows 用の GCC でも実行環境としては MSVCRT (Windows 用の C ランタイムライブラリ) を使うコードを生成するのでこの説明が適用されます。

一方で、 Linux ではストリームのテキストモードとバイナリモードの区別がありませんので、 fseek は成功するでしょう。

<> の付近で動作が違うのであれば、これが関係しているのかもしれません。

投稿2020/01/26 03:11

SaitoAtsushi

総合スコア5444

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

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

GLa1192

2020/01/26 04:30

fseekがあやしいと思って調べても、-方向にも進められるという記述があったりで、困っていたところだったので助かりました!ありがとうございます!どうやらご指摘の内容が原因だったようです。 さらに質問したいのですが、ファイルポインタを1つ戻すという動作をwindows環境で行う場合、何か別の手段があるのでしょうか? 先頭から何文字目という方法で実質的に戻すしかないのでしょうか?
tatsu99

2020/01/26 04:42 編集

1.fp=fopen("2.txt","r");を fp=fopen("2.txt","rb");にかえてください。 そうするとバイナリーモードになるのでwindowsでもfseekで-1が使用可能です。 linuxの場合は、デフォルトでバイナリーモードなので、問題ありませんでした。 尚、linuxでfp=fopen("2.txt","rb");としても問題ありません。(同じ結果になります) 2.windowsの改行コードはCR(0x0d)LF(0x0a)なので check_wordの改行判定に'\r'を追加してください。 '\n'=0x0a '\r'=0x0dです。
SaitoAtsushi

2020/01/26 04:46 編集

ストリームがパイプなどのキャラクターデバイスに接続されているときはシークできませんし、質問中の事例では先読みが必要なのは一文字だけですからシーク可能であることを要求するのは強すぎる制限に感じます。 ungetc を使うのが一般的です。
GLa1192

2020/01/26 05:23

tatsu99様の方法で、無事に想定通りの動きをさせることができました。ありがとうございます! テキストモード、バイナリモードについての理解不足が身に染みて分かりました。環境差による影響も勉強になりました。 SaitoAtsushi様の回答にあるungetcは存在自体知らなかったので、これもまた勉強になりました。同様のことをする時があれば使っていこうと思います。 回答者の皆様、本当にありがとうございました!
otn

2020/01/26 08:20

> fseekがあやしいと思って調べても、 そもそも、返り値をチェックしていないというのもまずかったですね。
guest

0

GCCであるなら、Windows環境でもEcripseでデバッグできます
ブレークポイントを設定すれば、ソースコードの任意の行で実行を止め、変数のナカミを見ることが出来ます。
また、ワンステップ実行で1行づつ実行させ、変数のナカミの変化を見ることが出来ます。
そうやって動作のおかしいところを特定していきましょう。

そうすれば、なにもわからないのでどーにかしろ、という質問をしなくて済むようになります

投稿2020/01/26 02:27

y_waiwai

総合スコア87749

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

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

GLa1192

2020/01/26 04:34

そのようなデバック方法があったのですね!不勉強でした。今後使っていこうと思います。 加えて、曖昧な質問をしてしまいすみませんでした。
SaitoAtsushi

2020/01/26 05:47

漠然としすぎた質問というのは結局のところかわりにやってくれというのと同じなのであまりよい気はしませんが、わからないなりの質問の仕方としては良くできていると思います。 自分なりに絞り込んだつもりでその範囲の情報しか挙げずに、しかし実は質問文にない箇所が原因だったというのはかなり頻繁にあることなので、再現可能なソースコードと具体的な現象を提示できているのは良い質問です。 ただ、 fseek について調べてみても記述が色々あったというのがググってみたという意味だとしたらあまりよい方法とは言えません。 C の規格は ISO や JIS になっているのでまずはそれを見る、各環境ごとのドキュメントにあたるといった一次情報を見るべきです。 規格で決まっていることは規格を見るのが確実です。 ピンポイントで関数の仕様を見るだけならそれほど難解なものではありませんので。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問