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

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

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

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

解決済

3回答

3913閲覧

ポインタ渡しと文字列比較

token_regain

総合スコア25

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

0クリップ

投稿2015/07/16 02:13

編集2015/07/16 02:18

C言語初心者です。

文字列rawcがリストlistの中に入っていない(登録されていない)とき、
その文字列をリストの登録されている最後に格納する関数regを作成しました。
既に登録されている文字列を上書きする事を防ぐため、
int*型cntをリストに登録された最終番号として関数に渡し、
新しく文字列が登録されたときにはインクリメントするようにしました。
(用いたいプログラムの都合上list[0]には格納しないようにスキップ)
しかしポインタを渡す過程でかプログラムがフリーズしてしまいます。
ポインタ渡しを調べても解決ができませんでした。
どなたかご教授頂きたいです。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void reg(char rawc[50], char list[300][50], int *cnt);

int main(void){
int i;
int cnt;
char raw[300][50], rawc[50];
char list[300][50];
cnt=(int
)malloc(sizeof(int));

for(i=0;i<300;i++){
strcpy(list[i],"nothing");
}
strcpy(rawc,"test");
*cnt=0;
reg(rawc,list,cnt);
}
void reg(char rawc[50], char list[300][50], int *cnt){
int i;
int flag=0;
if(*cnt!=0){
for(i=0;i<*cnt;i++){
puts("a");
if(strcmp(rawc,list[i])==0){
flag=1-flag;
break;
}
}
}
if(flag==0){
*cnt++;
strcpy(list[*cnt],rawc);
}
}

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

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

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

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

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

guest

回答3

0

フリーズする原因は、*cnt++; の部分ですね。
(*cnt)++; とすれば、フリーズしなくなります。

前者だと、ポインタのアドレスを進めてしまうので、
list[*cnt]でフリーズ。

(*cnt)++; とすれば、ポインタの指し示す値を+1してくれます。

それから、
この場合、cntは、ポインタ変数で宣言する必要ありませんね。
int cnt;で宣言し、mallocは必要ありません。

cnt=0;
reg(rawc,list,&cnt); としてください。

さらに、reg関数内の処理は、
目的の処理にはなってないんで、フリーズ回避できたら、
勉強のためもう一度見直してみてください。

投稿2015/07/16 03:02

ta-kun

総合スコア59

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

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

token_regain

2015/07/16 03:16

回答ありがとうございます。 int*でなくてよいのですね。 ポインタに限らずあくまでその変数のアドレスを関数に渡してあげれば、 間接的に変数を書き換えることが出来るという理解で正しいでしょうか。 puts()はどこでフリーズするかデバッグしていたもので消し損ねました、 勘違いを生みましたらすみません。 テスト用に省略したデータですので実際に動かしたいデータを掲示いたします。
guest

0

ベストアンサー

*cnt++;

この結果はポインタ変数cntに対して+されますので、参照先の値を+したい場合は

(*cnt)++;

とします

投稿2015/07/16 02:47

takito

総合スコア3111

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

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

token_regain

2015/07/16 02:54

解決しました。 ありがとうございます。 これではポインタを進めることになってしまうのですね。
guest

0

void reg(char rawc[50], char list[300][50], int *cnt){

ここはシングルポインタとダブルポインタで受け取る形がよいのではないかと思います。
こんな感じ。

void reg(char *rawc, char **list, int *cnt){

テスト中のプログラムのためだと思いますが、

*cnt=0;
reg(rawc,list,cnt);

.
.
.

void reg(char rawc[50], char list[300][50], int *cnt){
int i;
int flag=0;
if(*cnt!=0){

だとif文の判定は常に偽になるのではないかと思います。

投稿2015/07/16 02:42

HachiyaKouya

総合スコア85

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

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

token_regain

2015/07/16 02:51

回答ありがとうございます。 テスト中のプログラムですので、本来試したい形を追加で記入しておきます。 配列についてはダブルポインタを使いこなせないためこのような形になっています。 もし複数の文字列(文字列の長さは50文字以内、文字列数は100以内とします)を ダブルポインタ**cで管理したいのならば、 int i; c=(char**)malloc(sizeof(char*)*100); for(i=0;i<100;i++) *c=(char*)malloc(sizeof(char)*50); } という形で動的にメモリ確保すればよいのでしょうか。 動的なメモリが確保の必要な場合が理解できていないのですが、 ポインタを使用するときは必ず動的メモリ確保をすべきなのでしょうか。 よろしくお願いいたします。
HachiyaKouya

2015/07/16 05:00

ダブルポインタのメモリ動的確保はそれで良いと思います。 配列の変数名に添え字をつけなければ配列の先頭アドレス(ポインタ変数と同じ)になりますので、事前に配列で変数を宣言できると所は配列で宣言するのがソースもシンプルになりますしバグの元も減るので良いと思います。 それと、C言語の文字列は文字列本体の後にヌル文字("\0")が入りますので、50文字の文字列を配列に入れる場合は要素数は51必要になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問