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

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

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

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

Q&A

解決済

3回答

709閲覧

【C】配列を一つ左にずらしたいがバスエラーになってしまう

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

0クリップ

投稿2022/02/18 01:34

編集2022/02/18 05:48

該当コード(一部抜粋)

関数に渡された文字列に空白やマイナス、プラス記号があった場合左にずらしてこれらの記号を消したいのですがバスエラーがでてしまいうまく動作しません。どこが原因なのでしょうか?

※2連続で記号が来た場合jを初期化しないとダメですがそこは一回保留で1つだけ記号がある場合を考えてます

c

1 char str[] = "-1234" //example 2 i = 0; 3 j = 0; 4 while (str[i] == '-' || str[i] == '+' || str[i] == ' ') // check minus plus sings 5 { 6 while (digit > 1) //digitはstrの桁数 7 { 8 str[j] = str[j + 1]; 9 j++; 10 digit--; 11 } //2連続で記号が来た場合jを初期化しないとダメですがそこは一回保留で1つだけ記号がある場合を考えてます 12 i++; 13 }

dititを求める関数

c

1int ft_len(char *base) //to check base 2{ 3 int len; 4 5 len = 0; 6 while (base[len] != '\0') 7 len++; 8 return (len); 9}

該当コード全て

c

1#include <stdio.h> 2int base_check(char *base) 3{ 4 int i; 5 int j; 6 7 i = 0; 8 j = i + 1; 9 while (base[i] == '\0') 10 { 11 if (base[i] == '+' || base[i] == '-') 12 return (0); 13 while (base[j] != '\0') 14 { 15 if (base[i] == base[j]) 16 return (0); 17 j++; 18 } 19 i++; 20 } 21 return (1); 22} 23 24int ft_atoi_base(char *str, char *base) 25{ 26 int num[256]; 27 int base_s; 28 int sum; 29 int minus; 30 int i; 31 int j; 32 33 i = 0; 34 j = 0; 35 minus = 1; 36 if (!(base_check(base))) 37 return (0); 38 while (str[j] == '-' || str[j] == '+' || str[j] == ' ') 39 { 40 if (str[j] == '-') 41 minus *= -1; 42 j++; 43 } 44 while ((str[i++] = str[j++]) != '\0'); 45 printf("%s ", str); 46 47 return (0); 48} 49 50int main(void) 51{ 52 int num; 53 num = ft_atoi_base("-1234", "0123456789"); // A798BF(16) → 10983615(10) 54 printf("%d", num); 55 return 0; 56} 57

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

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

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

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

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

itagagaki

2022/02/18 01:41

digitが初期化されてないようですね。 あとstrの終端'\0'以降にアクセスしないようなコードにしないといけないような気もします。
maisumakun

2022/02/18 01:42

「digitはstrの桁数」を割り出すコードはどのように書いていますか?
退会済みユーザー

退会済みユーザー

2022/02/18 01:50

digit = ft_len(str)で値は入っている状態です
退会済みユーザー

退会済みユーザー

2022/02/18 01:50

コード追加しました
退会済みユーザー

退会済みユーザー

2022/02/18 01:56

wsl2上のubuntuでgcc 9.3.0でビルドした限りでは、少なくともご提示のコードで落ちることはありませんでした。 エラーを起こしてしまうのはどういった環境で動作させていますでしょうか。
退会済みユーザー

退会済みユーザー

2022/02/18 01:58

あ、すみません、自分が知らないだけかもしれませんが、ft_lenってなんでしょう
退会済みユーザー

退会済みユーザー

2022/02/18 01:59

MacOS Unix環境です
退会済みユーザー

退会済みユーザー

2022/02/18 02:12

自分は今Mac触れる環境にないのでこれ以上はお役に立てなさそうです。ごめんなさい。 ちなみに終端文字の処理が気になる所ではありますが、落ちないです。 (動作させると12344が出力されます)
ozwk

2022/02/18 02:25 編集

ご自身でこの質問のコードを実行して問題が再現しますか? 再現できたら再現に使ったコードを貼ってください。 現状ではコピペで実行できるようになっていないので色々付け加えないとならず、 回答者側で問題を再現させるのが難しくなっています。
guest

回答3

0

ベストアンサー

考え方を変えれば、 ft_len 関数や"記号が複数の場合等を考える"必要はありません。
先頭から記号等をスキップして最初の数字の位置を求め、その位置から文字列の終端までを先頭に移動させます。

c

1#include <stdio.h> 2 3int main(void){ 4 char str[10] = "-1234"; //example 5 6 //最初の数字の位置 7 int j = 0; 8 while(str[j] == '-' || str[j] == '+' || str[j] == ' ') j++; 9 10 if(j > 0) { 11 //j の位置から ’\0’ までを先頭にコピー 12 for(int i=0; (str[i++]=str[j++]) != '\0'; ); 13 } 14 15 printf(str); 16}

投稿2022/02/18 03:35

編集2022/02/18 03:38
jimbe

総合スコア12648

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

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

退会済みユーザー

退会済みユーザー

2022/02/18 04:55

このやり方を採用してみたのですがやはりバスエラーでした違うところに原因があるみたいです
退会済みユーザー

退会済みユーザー

2022/02/18 05:02

違うファイルを作ってやったらなぜかできました。これはファイルが損傷してるとかそういう次元のお話なのでしょうか?
jimbe

2022/02/18 06:25 編集

> 違うファイルを作ってやったらなぜかできました。 二つのファイルの違いを出してくれるツールなどを使って違う箇所を探してみるというのはどうでしょう。 [diff(https://atmarkit.itmedia.co.jp/ait/spv/1704/13/news021.html) とか。
退会済みユーザー

退会済みユーザー

2022/02/18 05:45

やはり関数を書き足していくとbusエラーになります。
退会済みユーザー

退会済みユーザー

2022/02/18 05:48

該当コード全て載せたのでお願いします
退会済みユーザー

退会済みユーザー

2022/02/18 06:11

charの配列に一旦処理したい文字列をコピーし、その配列を渡せば通ります。 char arr[10]; strcpy(arr, "-1234"); num = ft_atoi_base(arr, "0123456789");
退会済みユーザー

退会済みユーザー

2022/02/18 06:11

文字列リテラルを書き換えようとして落ちてます。
退会済みユーザー

退会済みユーザー

2022/02/18 08:55

なるほどそういうことなのですね。ありがとうございます。
jimbe

2022/02/18 09:25 編集

char str[] = "-1234" で書き換え可能な領域に6バイトの値が保存されそのアドレスが str となるはずですが、 shuta_202141 さんの環境ではそうならないということになりそうです。 その可能性があるため、私のコードではサイズを指定しました。 STR30-C. 文字列リテラルを変更しない https://www.jpcert.or.jp/sc-rules/c-str30-c.html STR11-C. 文字列リテラルで初期化される文字配列のサイズを指定しない https://www.jpcert.or.jp/sc-rules/c-str11-c.html
guest

0

一応自分が確認に使ったコードを貼っておきます。

c

1#include <stdio.h> 2 3int ft_len(char *base) //to check base 4{ 5 int len; 6 7 len = 0; 8 while (base[len] != '\0') 9 len++; 10 return (len); 11} 12 13int main() { 14 char str[] = "-1234"; //example 15 int i = 0; 16 int j = 0; 17 int digit = ft_len(str); 18 while (str[i] == '-' || str[i] == '+' || str[i] == ' ') // check minus plus sings 19 { 20 while (digit > 1) //digitはstrの桁数 21 { 22 str[j] = str[j + 1]; 23 j++; 24 digit--; 25 } //2連続で記号が来た場合jを初期化しないとダメですがそこは一回保留で1つだけ記号がある場合を考えてます 26 i++; 27 } 28 printf("%s\n", str); 29 return 0; 30}

これを以下のコマンドでコンパイルしています。

sh

1> gcc -o test test.c

実行すると「12344」が出力されます。

※補足1:文字列長の算出は標準でstrlenという関数が用意されているので、特別な事情がないのであればそちらを使うのをお勧めします。

※補足2:今回の質問からは外れますが、このコードだと「先頭に記号が書かれている文字列」以外は最初のwhile文の条件ではじかれてしまうので、エラーが解消されても望んでいる挙動にはならないのではないかと思います。

投稿2022/02/18 03:04

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

文字列終端で処理を打ち切る処理が入ってませんね
そのため、配列の範囲を超えてアクセスしてしまってるんでしょう

投稿2022/02/18 02:41

編集2022/02/18 02:41
y_waiwai

総合スコア87774

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問