• 締切済み

セグメンテーション違反について教えてください。

2つの文字列s、tを入力して 、sの中からtを検索し、一致したらsからtを削除したものを結果に出すという問題です。たとえば、s = a v a b c a 、t = a b c とすると、sからa b cが削除され、a v aと結果が表示されます。 ちなみに条件として、s、tとも配列の大きさが80となっており、出力用の文字列out[ ]も同様です。 また、文字列の入力は50字に制限されています。 ロジックを何とかつかんだ後、以下のようにコードで書いたのですが、セグメンテーション違反になってしまいます。 (1)まず、2行何か書かなければ「文字列を入力して下さい」が表示されません。 (2)「文字列を入力して下さい」「削除する文字列を入力したください」は表示されますが、その後の「削除後の文字列」とその結果が表示されません。 (3)その代わり、セグメンテーション違反が出ます。 たとえば、こんな感じで表示されてしまいました。 /************************************************/ 12 12 文字列を入力して下さい。(50字) :asd 削除する文字列を入力して下さい。(削除) :a セグメンテーション違反です /************************************************/ このとき、どこを直せばいいのでしょうか? 1 #include <stdio.h> 2 #include <string.h> 3 4 #define NULLB '0' /* 入力制限 */ 5 6 int main(int argc , char *argv[]) 7 { 8 /*********各変数の宣言*********/ 9 char s[80] ; 10 char t[80] ; 11 char out[80] ; 12 int s_len ; 13 int t_len ; 14 int out_len ; 15 int s_index ; 16 int t_index ; 17 int out_index ; 18 19 /******************************/ 20 21 fgets(s , 50 , stdin) ; 22 fgets(t , 80 , stdin) ; 23 24 25 printf("文字列を入力して下さい。(50字) :" ) ; 26 scanf("%s",&s) ; 27 s_len = strlen(s) ; 28 29 30 printf("削除する文字列を入力して下さい。(削除) :") ; 31 scanf(" %s",&t) ; 32 t_len = strlen(t) ; 33 34 35 /********各変数の初期化********/ 36 memset(s , '\0' , sizeof(int) *80) ; 37 memset(t , '\0' , sizeof(int) *80) ; 38 memset(out , '\0' , sizeof(int) *80) ; 39 s_index = 0 ; 40 t_index = 0 ; 41 out_index = 0 ; 42 43 /******************************/ 44 45 if( s_len >= t_len) 46 { 47 48 /********外側のループ********/ 49 while(s_index < s_len) 50 { 51 /********内側のループ********/ 52 while(t_index < t_len) 53 { 54 if( (s_len - s_index) >= t_len) 55 { 56 if( s[s_index + t_index] == t[t_index]) 57 { 58 if(t_len - t_index ==1) 59 { 60 s_index += t_len ; 61 } 62 else 63 { 64 continue ; 65 } 66 t_index ++ ; 67 } 68 else 69 { 70 out[out_index] = s[s_index] ; 71 out_index++ ; 72 s_index++ ; 73 74 break ; 75 } 76 } 77 else 78 { 79 strncpy(out, s , (s_len-s_index + 1 )) ; 80 } 81 } 82 /****************************/ 83 } 84 /****************************/ 85 } 86 else 87 { 88 strcpy( out, s) ; 89 } 90 91 printf("\n削除後の文字列: %s": ); 92 93 return 0 ; 94 }

みんなの回答

  • kb-nike
  • ベストアンサー率36% (72/200)
回答No.3

できるだけ質問者さんの作風に従ってコーディングしてみました。 変更点は質問者さんのほうでチェックしてみてください。 //-------------------------------------------------------------------- #include <stdio.h> #include <string.h> int main( int argc, char *argv[] ) { /*********各変数の宣言*********/ char s[80]; char t[80]; char out[80]; int s_len, t_len, out_len; int s_index, t_index; int k; printf("文字列を入力して下さい。(50字) :"); scanf("%s", s) ; s_len = strlen(s) ; printf("削除する文字列を入力して下さい。(削除) :"); scanf("%s", t) ; t_len = strlen(t) ; if(s_len < t_len){ printf("削除する文字列が長すぎます。\n"); return 0; } s_index = 0; while(s[s_index]){ k = 0; t_index = 0; while(t[t_index]){ if(s[s_index + k] == t[t_index]){ k ++; t_index ++; } else{ break; } } if(k == t_len){ break; } else{ s_index ++; } } strcpy(out, s); out[s_index] = '\0'; strcat(out, &s[s_index + k]); printf("削除後の文字列: %s\n", out); return 0; }

回答No.2

全部は見てないが、 > (1)まず、2行何か書かなければ「文字列を入力して下さい」が表示されません。 21 fgets(s , 50 , stdin) ; 22 fgets(t , 80 , stdin) ; これがあるので、正常な動作です。 36 memset(s , '\0' , sizeof(int) *80) ; 37 memset(t , '\0' , sizeof(int) *80) ; 38 memset(out , '\0' , sizeof(int) *80) ; s,t,outはchar型の配列ですよね。sizeof(char)とsizeof(int)が違えば、問題がありますよね。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

........ プログラムが上の方から順に実行されるってことすら知らない?

関連するQ&A

  • 「セグメンテーション違反」について

    参考書に載っていたプログラムを打ち込みながら勉強していたのですが、次のプログラムを動かしたときに「セグメンテーション違反」と出てきました。 /* 可変書式による印字_簡単な棒グラフ */ #include <stdio.h> main() { char *f, *a; int i; f="%2d = %-20.1s\n"; a="********************"; for(i=1; i<10; i++){ *(f+11)=i+'0'; printf(f,i,a); } } コンパイル後に、 「セグメンテーション違反です」 と、表示されて終わってしまいます。 何処が問題だったのでしょうか???教えて頂ければ幸いです。

  • C++

    文字を入力して、それを1つ右にずらして出力する問題。 例  aret → tare 関数内でポインタを使用するのが条件です。 ズラしているつもりが、入力した文字がそのまま出力されてしまいます。 自分の方針としては、 関数内で入力された文字の長さを確認。 文字列の最後の文字をtmpに保存して ドンドン右にずらして保存していく。 最後にtmpに保存したものを、文字列の最初に入れる。 というものです。 わかるかた、ご指導お願いします。 #include<stdio.h> #include<string.h> void kaiten(char *t) { int len =0; int i; char tmp; while (*t++){ len++; } tmp = *(t+(len-1)); for(i=len-1;i>0;i--) *(t+i)=*(t+i-1); *t = tmp; } int main() { char s[100]; printf("文字列を入力:"); scanf("%s",s); kaiten(s); printf("一文字ずらすと:%s\n",s); }

  • コードのどこが間違っているのかを教えてください。

    ある文字を入力し、それをカンマ区切りして3つに分け、その3つの最大値を表示するプログラムを入力したいです。ただし、条件として、上限の桁数5を越える、文字か数字化の判定を行い、文字が1つでも混ざっている際はエラー表記され再度入力、さらに終了判断を行う際も、あくまで「y」「n」と入力したときのみが正常であり、複数文字を入力する際は、エラー表記され、再度入力という形をとりたいです。 フローを書きながら、サブ関数も使い、LINUXで以下のように書いてみました。 ただ、これだと /*-----------------------------------------*/ /tmp/ccKMOmJN.o: In function `word_judge': kadai6.c:(.text+0x4b2): undefined reference to `isdigits' collect2: ld はステータス 1 で終了しました /*-----------------------------------------*/ となってしまいました。 どのようなコードに直せばいいのでしょうか? すごく長いですが、わかりやすく解説してくださると、とても助かります。 あと、fgets関数やsscanf、getchar関数など、ネット上のサンプルを参照して、使っただけなので、もしかしたら間違ってるかもしれません。 そこについても、教えてくださると、とてもうれしいです。 /* ソースコード */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #define LIMIT (5) #define NULLB '\0' #define ECOUNT (20) #define EWORD (2) int word_judge(char array[]); void digits_judge(int a_len , int b_len , int c_len) ; int main(int argc , char *argv[]) { int number_a ; int number_b ; int number_c ; int input_len ; int a_len ; int b_len ; int c_len ; int end_len ; char input[ECOUNT] ; char a[ECOUNT] ; char b[ECOUNT] ; char c[ECOUNT] ; char array[ECOUNT] ; char end[EWORD] ; end[0] = 'n' ; while( end[0] == 'n' ) { while(1) { number_a = 0 ; number_b = 0 ; number_c = 0 ; input_len = 0 ; a_len = 0 ; b_len = 0 ; c_len = 0 ; end_len = 0 ; memset(input , NULLB , sizeof(char) *ECOUNT) ; memset(a , NULLB , sizeof(char) *ECOUNT) ; memset(b , NULLB , sizeof(char) *ECOUNT) ; memset(c , NULLB , sizeof(char) *ECOUNT) ; memset(end , NULLB , sizeof(char) *EWORD) ; printf("a , b , c ?:") ; fgets(input , ECOUNT , stdin); input_len = strlen(input); if( input_len < ECOUNT-1 ) { sscanf(input , "%[^,] , %[^,], %s" , a , b , c); if(a[0] != NULLB && a[0] != NULLB && c[0] != NULLB) { if(word_judge(a) != 0 && word_judge(b) != 0 && word_judge(c) != 0 ) { a_len = strlen(a) ; b_len = strlen(b) ; c_len = strlen(c) ; if(a_len >= LIMIT || b_len >= LIMIT || c_len >= LIMIT) { digits_judge(a_len , b_len , c_len) ; } else { number_a = strtol(a , NULL , 10) ; number_b = strtol(b , NULL , 10) ; number_c = strtol(c , NULL , 10) ; printf("最大値:") ; if(number_a > number_b && number_a > number_c) { printf("%d\n", a); } else { if(number_b >number_a && number_b > number_c) { printf("%d\n", b) ; } else { printf("%d\n", c) ; } } break ; } } else { printf("文字が混ざっています。\n") ; } } else { printf("正しく入力して下さい。\n") ; } } else { if(input[ECOUNT] == '\n') { } else { while(getchar() != '\n'); } printf("入力数が多いです。\n"); } } while(1) { int end_len ; char end[EWORD] ; end_len = 0 ; memset(end , NULLB , sizeof(char) *EWORD) ; printf("終了しますか? y/n: "); fgets(end , EWORD , stdin); end_len = strlen(end); printf("\n"); if(end_len == EWORD) { if(end[0] != 'y' && end[0] != 'n') { printf("y or nを入力して下さい。\n"); } else { break ; } } else { if(input[ECOUNT] == '\n') { } else { while(getchar() != '\n'); } printf("入力が間違っています。y or n を入力しなおしてください。\n"); } } } return 0 ; } int word_judge(char array[ ]) { int array_len ; int i ; int tmp ; int r_value ; tmp = 0; r_value = 0 ; for(i=0 ; i< array_len ; i++) { tmp = isdigits(array[i]) ; if(tmp != 0) { r_value = 1; } else { r_value = 0; break ; } } return r_value ; } void digits_judge(int a_len , int b_len , int c_len) { int a ; int b ; int c ; a = 0 ; b = 0 ; c = 0 ; a_len = 0 ; b_len = 0 ; c_len = 0 ; if(a_len >= LIMIT) { a = 1 ; } else { } if(b_len >= LIMIT) { b = 10 ; } else { } if(c_len >= LIMIT) { c = 100 ; } else { } switch(a + b + c) { case 111 : printf("aとbとcの桁が多いです。\n"); break; case 11 : printf("aとbの桁が多いです。\n"); break; case 110 : printf("bとcの桁が多いです。\n"); break; case 101 : printf("cとaの桁が多いです。\n"); break; case 1 : printf("aの桁が多いです。\n"); break; case 10 : printf("bの桁が多いです。\n"); break; case 100 : printf("cの桁が多いです。\n"); break; } }

  • 三つの文字を順に並べるプログラム

    三つの文字を入力して、順番に並べて表示させるプログラムが作りたいのですが、どうしたらいいのかわかりません。 二つまではできました。以下に記します import java.io.*; class Sample { public static void main(String args[]) throws IOException { System.out.println("文字列1を入力してください。"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str1=br.readLine(); System.out.println("文字列2を入力してください。"); String str2=br.readLine(); int s = 1,t = 0; if(str1.length()>str2.length()){ int len=str1.length(); StringBuffer sb=new StringBuffer(str1); while(s<len+1){ sb.insert(s,str2.charAt(t)); s=s+2; t++; } System.out.println("文字列は"+sb+"となる。"); }else{ int len=str2.length(); StringBuffer sb=new StringBuffer(str2); while(s<len+1){ sb.insert(s-1,str1.charAt(t)); s=s+2; t++; } System.out.println("文字列は"+sb+"となる。"); } } } str1に123 str2に45といった風に入力すると14253といった風になります。 これにstr3を加え、str3が6789ならば、146257389 となる風にしたいです。

    • ベストアンサー
    • Java
  • c++でセグメンテーション違反

    c++言語を勉強しているものです。 配列を関数の引数として扱うプログラムを作ろうとしているのですが、 コンパイルが通ったかと思えば実行すると 「セグメンテーション違反です」 と表示されて異常終了してしまいます。 原因がさっぱりわかりません。 OSはLinux(RED HAT ENTERPRISE LINUX 5)、コンパイラはg++(バージョン 4.1.2)です。 これがソースコードです。 #include <iostream> using namespace std; #define BUFSIZE 1024 #define MSG "msg" void test(char buf[]) { //bzero(buf,BUFSIZE); LEGACY memset(&buf, 0, BUFSIZE); sprintf(buf, "%s\n", MSG); cout << buf; cout << "(Terminated)" << endl; return; } int main() { char buf[BUFSIZE]; test(buf); return 0; }

  • セグメンテーション違反

    VC++からgccに移行してセグメンテーション違反が出るようになりました。VC++ではちゃんと動くのに、です…。 void enterData() { FILE *file_ptr; flights_record flights_array[25]; char in_string[10]; int index = 1; int repeat = TRUE; char ch; while(repeat) { printf("\nFlight ID => "); gets(flights_array[index].flightID); flights_array[index].recordNumber = index; printf("Enter more data (Y/N) => "); ch = toupper(getc(stdin)); putchar(ch); setbuf(stdin,NULL); index++; if(ch != 'Y') repeat = FALSE; fflush(stdin); } if((file_ptr = fopen("C:FLIGHTS.DTA","w+")) == NULL) { printf("Can't open filights file."); exit(0); } fwrite(flights_array, sizeof(flights_array), index, file_ptr); //←どうもここで止まるようです fclose(file_ptr); } 構造体の内容を"flightID"と"recordNumber"だけにして端折っていますが その他はそのままです。上のindex++;のせいかと思ってfwriteでindex-1にしても変わりません。 ちなみにVC++ではFLIGHTS.DTAが存在してても"w"だけで良かったのですがgccでは"w+"にしないと通りませんでした。 どこが怪しいところがあればご指摘戴けるとありがたいです。どうかよろしくお願いします。

  • fclose()でセグメンテーション違反

    C言語でのファイル読み込みで、ファイルを開いてデータを読み込んで表示することはできたのですが、最後のfclose(fp)でセグメンテーション違反になります。一番最後のwhileループをコメントアウトしたところセグメンテーション違反にはならなかったので、ここに何か問題があると思うのですが、どこが悪いのかが分かりません... #include<stdio.h> #include<stdlib.h> main(void){ FILE *fp; int i=0 , j=0 ,cnt = 0 , c=0; char *name="data.txt"; float *buf1,*buf2; if((fp = fopen(name,"r")) == NULL){ printf("error\n"); return 0; } else{ while((c = getc(fp)) != EOF) { if(c == '\n') cnt++; } printf(">>%d<<\n",cnt+1); rewind(fp); buf1 = (float *)malloc( (int)(cnt/2) +1); buf2 = (float *)malloc( (int)(cnt/2) +1); /*ここからがおかしい?*/ while(1){ if( fscanf( fp ,"%f %f",&buf1[i],&buf2[i])==EOF )break; printf("%f %f\n",buf1[i],buf2[i]); i++; } fclose(fp); } return 0; } なぜセグメンテーション違反になっているのでしょうか?

  • 下のコードの修正をお願いします。

    終了処理、バッファのクリアなど、ほとんどの処理は出来たのですが、唯一a,b,cの入力数が上限の桁数LIMITをオーバーしてしまった場合に本来エラーが表示されなければならないのにそのまま正常処理で最大値が出力されてしまいます。つまり、サブ関数void disp_errorでの処理がmain関数で実行されません。 どこを直せばいいのでしょうか? #include <stdio.h> #include <string.h> #include <stdlib.h> #include <limits.h> #define LIMIT (5) #define NULLB '\0' #define ECOUNT (3*LIMIT + 4) #define EWORD (3) #define NORMAL (0) #define ABNORMAL (-1) #define LF '\n' int word_judge(char array[]); void disp_error(int x_len , int y_len , int z_len) ; int main(int argc , char *argv[]) { int number_a ; int number_b ; int number_c ; int input_len ; int a_len ; int b_len ; int c_len ; int end_len ; int max ; char input[ECOUNT+1] ; char a[ECOUNT+1] ; char b[ECOUNT+1] ; char c[ECOUNT+1] ; char array[ECOUNT+1] ; char end[EWORD+1] ; end[0] = 'n' ; while(end[0] == 'n' ) { while(1) { number_a = 0 ; number_b = 0 ; number_c = 0 ; input_len = 0 ; a_len = 0 ; b_len = 0 ; c_len = 0 ; end_len = 0 ; max = 0; memset(input , NULLB , sizeof(char) *ECOUNT+1) ; memset(a , NULLB , sizeof(char) *ECOUNT+1) ; memset(b , NULLB , sizeof(char) *ECOUNT+1) ; memset(c , NULLB , sizeof(char) *ECOUNT+1) ; memset(end , NULLB , sizeof(char) *EWORD+1) ; printf("a,b,c ?:") ; fgets(input , ECOUNT+1 , stdin) ; input_len = strlen(input) ; if(input_len <ECOUNT) { a_len = strlen(a) ; b_len = strlen(b) ; c_len = strlen(c) ; sscanf(input , "%[^,], %[^,], %s" , a , b , c) ; if(a[0] != NULLB && b[0] != NULLB && c[0] != NULLB) { if(word_judge(a) == NORMAL && word_judge(b) == NORMAL && word_judge(c) == NORMAL) { if(a_len > LIMIT || b_len > LIMIT || c_len > LIMIT) { disp_error(a_len , b_len , c_len) ; } else { number_a = strtol(a , NULL , 10) ; number_b = strtol(b , NULL , 10) ; number_c = strtol(c , NULL , 10) ; max = number_a ; printf("最大値:") ; if(number_b > number_a) { max = number_b ; if(number_c > number_b) { max = number_c ; } } else { if(number_c > number_a) { max = number_c ; } } printf("%d\n" , max) ; break ; } } else { printf("文字が混ざっています。 \n") ; } } else { printf("正しく、入力をしてください。\n") ; } } else { if(input[ECOUNT-1] == LF) { } else { /* バッファのクリアを行う */ while(getchar() != LF); } printf("入力数が多いです。\n") ; } } while(1) { printf("終了しますか? y/n:" ); fgets(end , EWORD+1 , stdin ) ; end_len = strlen(end) ; if(end_len < 3) { if(end[0] != 'y' && end[0] != 'n') { printf("y or nを入力して下さい。\n") ; } else { break ; } } else { if(end[EWORD-1] == LF) { } else { while(getchar() != LF) ; } printf("入力が間違っています。y or nを入力しなおしてください。\n") ; } } } return 0 ; } int word_judge(char array[]) { int array_len ; int i ; int sub_number ; int r_value ; sub_number = 0 ; r_value = NORMAL ; array_len = strlen(array) ; for(i=0 ; i<array_len ; i++) { sub_number = isdigit(array[i]) ; if(sub_number != 0) { r_value = NORMAL ; } else { r_value = ABNORMAL ; break ; } } return r_value ; } void disp_error(int x_len, int y_len , int z_len) { int fc ; fc = 0 ; if(x_len > LIMIT) { fc += 1 ; } if(y_len > LIMIT) { fc += 10 ; } if(z_len > LIMIT) { fc += 100 ; } switch(fc) { case 11 : printf("aとbの桁が多いです。 \n") ; break ; case 110 : printf("bとcの桁が多いです。 \n") ; break ; case 101 : printf("aとcの桁が多いです。 \n") ; break ; case 1 : printf("aの桁が多いです。 \n") ; break ; case 10 : printf("bの桁が多いです。 \n") ; break ; case 100 : printf("cの桁が多いです。 \n") ; break ; } }

  • セグメンテーション違反

    環境はLinux・C言語です。 #include<stdio.h> #include<string.h> struct book{ char author[256]; char title[256]; char publisher[256]; int year; }; int main(void); int main(void) { FILE *fp1,*fp2; struct book data[256]={0},dummy={0}; char author[256]; char title[256]; char publisher[256]; int year; int i=0,j=0; fp1=fopen("biblio.txt","r"); while(fscanf(fp1,"%s,%s,%s,%d\n",&author[0],&title[0],&publisher[0],&year)!=EOF){ strcpy(&data[i].author[0],author); strcpy(&data[i].title[0],title); strcpy(&data[i].publisher[0],publisher); data[i].year=year; i++; } j=i; fclose(fp1); while(1){ for(i=0;i<256;i++){ if(data[i].year > data[i+1].year){ dummy=data[i]; data[i]=data[i+1]; data[i+1]=dummy; break; } } if(i==256) break; } fp2=fopen("biblio2.txt","w"); for(i=0;i<j;i++){ fwrite(&data[i],sizeof(struct book),1,fp2); } fclose(fp2); return(0); } 以上のソースで、セグメンテーションエラーが出ます。 問題は while(fscanf(fp1,"%s,%s,%s,%d\n",&author[0],&title[0],&publisher[0],&year)!=EOF){ の部分だとは思うのですが、どう改善すればいいのかわかりません。 どなたかわかる方お願い致します。 ちなみに、biblio.txtの内容は B.W.Kernighan & D.M.Ritchie,The C Programming Language,Prentice Hall,1988 H.M.Deitel & P.J.Deitel,C How to Program,Prentice Hall,2001 J.R.Hanly & E.B.Koffman,Problem Solving and Program Design in C,Addison-Wesley,2002 D.M.Etter,Introduction to C,Prentice Hall,1999 H.H.Tan & T.B.D'Orazio,C Programming for Engineering and Computer Science,McGraw-Hill,2000 です。

  • セグメンテーション違反

    OSはリナックスでC言語です。 #include<stdio.h> #include<stdlib.h> typedef struct{ int id; char *name; }user; int main(void) { user *users; int i,j; users=(user *)malloc(sizeof(user)*100); for(j=0;j<5;j++) scanf("%d",&(users+j)->id); scanf("%s",(users+j)->name); free(users); printf("input your id;"); scanf("%d",&i); printf("NO%d %s\n",(users+i)->id,(users+i)->name); return 0; } 上記のプログラムソースでセグメンテーション違反と出てしまいます。 原因はなんなのでしょうか。 教えていただければ光栄です。