• ベストアンサー

ポインタのポインタの使い方

文字列の途中からの部分を表示させる場合もあって、途中からの 位置というのをcahr**型の配列に記憶させることにしました。 ポインタとnewがよく分からないから、それに近いサンプルを 作って実験しているところです。 #include <iostream.h> main() {  char selected[][6] = {"full", "nomal", "short"};  char *buf;  char **p;  buf = new char[500];  strcpy(buf, ",東京都,千代田区,九段南");  p = new char*[3];  for(unsigned int i=0, j=0; i<strlen(buf); i++)  {   if(buf[i] == ',')p[j++] = &buf[i+1];  }  for(int i=0; i<3; i++)  {   cout << selected[i] << "-" << p[i] << endl;  }  delete [] buf;  delete [] p; } 結果は full-東京都,千代田区,九段南 nomal-千代田区,九段南 short-九段南 で、問題なさそうに見えるけど心配だから質問しました。 このソースに問題はないですか? 得に、 char **p; と p = new char*[3]; と p[j++] = &buf[i+1]; と delete [] buf; が心配です。

質問者が選んだベストアンサー

  • ベストアンサー
  • s2t
  • ベストアンサー率79% (47/59)
回答No.3

配列で処理する場合と、ポインタで処理する場合では後者の方がパフォーマンスが良いです。 ただ、最近のコンパイラは賢いので、配列でもポインタでもあまり差はないと言われています。 ポインタに関する理解が曖昧な場合、バグを組み込みやすいので配列を用いた方が無難です。 実験でGCCでコンパイルして10万回実行するのにかかった時間を計測し、それを5回行いその平均値を求めると 配列で処理した場合、58秒 ポインタで処理した場合、44秒 という結果になりました。 ご参考までに。

A__
質問者

お礼

ありがとうございます。ポインタでの処理の方が速いとは知りませんでした。 実験もありがとうございます。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

  • s2t
  • ベストアンサー率79% (47/59)
回答No.2

特に問題はないと思います。 敢えて突っ込ませて頂きますと、 for(unsigned int i=0, j=0; i<strlen(buf); i++) がforの条件を評価する際に毎回strlen()が実行されるので無駄かと思います。 以下はコードの読みやすさを考えるとダメかもしれませんが、パフォーマンスを重視する場合のサンプルです。 int main(int argc, char *argv[]) { const char *sec[3] = {"full", "normal", "short"}; char *buf = new char[500]; char **p = new char*[3]; strcpy(buf, "東京都,新宿区,西新宿"); int n = strlen(buf); *p = buf; for(unsigned int i = 0, j = 1; i < n; i++) { if(*(buf+i) == ',') *(p+(j++)) = (buf+i+1); } for(int i = 0; i < 3; i++) { cout << *(sec+i) << " - " << *(p+i) << endl; } delete[] p; delete[] buf; return 0; } yatokesaさんへの回答になりますが、 newで割り当てたメモリはdeleteで,new[]で割り当てたメモリはdelete[]で解放することになっています。 どちらでも解放できるかもしれませんが、これに従わなかった場合の動作は未定義です。

A__
質問者

補足

ありがとうございます。パフォーマンス重視の方がいいです。 for()でstrlen()が毎回実行されるのは気がつきませんでした。 s2tさんが書いてくれたソースは、ポインタの配列表現が 別の表現で書いてあります。 (char *)型の文字列の場合、例えば左辺値なら、  buf[i] よりも *(buf+i)、 例えば右辺値なら、  &buf[i] よりも buf+i、 の方がいい。速いというこですか?

全文を見る
すると、全ての回答が全文表示されます。
  • yatokesa
  • ベストアンサー率40% (201/496)
回答No.1

問題ないですよ。きれいにできてると思います。 #実を言えば、delete [] buf; の []の意味がよくわかってなかったりしますが...^^;)。 仕様的に「東京都」の前のカンマが気になりますが....。 #プログラムを作りやすくするために先頭にカンマを入れないといけないと言うのであれば、と言うことです。

A__
質問者

お礼

ありがとうございます。問題なくて安心しました。 s2tさんが回答してくれたけど、東京都の前のコンマのことで p[0]は&buf[0]だと分かっているから、そこは改良した方が いいですねー。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ポインタについて

    途中までのソースコード typedef struct node{ char moji[128]; --------(1) }NODE; int main(int argc, char *argv[]){ FILE *fp; char buf[128]; NODE p[128]; char *tp; int i = 0; int j,k; int res; NODE temp; fp = fopen(argv[1],"r"); while(fscanf(fp,"%s",&buf) == 1){ tp = strtok(buf," ,.-"); strcpy(p[i].moji,tp); ---------(2) i++; while(tp != NULL){ tp = strtok(NULL," ,.-"); if(tp != NULL){ strcpy(p[i].moji, tp); --------(2) i++; } } } for(j = 0;j < i; j++) puts(p[j].moji); return 0; } file.txt これ以下の文字を読み込む -------------- The Java programming language is a general-purpose, concurrent, class-based, object-oriented language. It is designed to be simple enough that many programmers can achieve fluency in the language. 例えばこんなソースコードがあって、(1)をポインタにして、(2)のstrcpyを使わずにポインタだけで表現するとしたらどのようになるんですか?

  • ポインタ

    #include<stdio.h> int main() { char *p; p="ポインタ"; printf(p); return 0; } なぜ p="ポインタ"; とできるのですか? 普通は  int *i, j; i=&j; *i=100; こんな感じでやるのでは?

  • char (*data)[10] のようなポインタの使い方教えてください

    char (*data)[10]; のようのポインタの使い方がよくわからないので, 詳しい方いたら,教えてください. void main (){ char (*data)[10]; data = ????;//newを使ってメモリを確保したい for (int i = 0; i < ????; i++){ for (int j = 0; j < 10; j++){ data[i][j] = 何かデータ; } } //最終的にはこんな風に使いたいと思っています. } このような感じで new を使ってメモリの領域を確保したいのですが, どうもうまくいきません. data = new char[3]; data = new char*[3]; など,いろいろ試したのですが,だめでした. 使用しているOSはwindowsXPでvisual studio 2005を使ってプログラムをコンパイルしています. わかる方いたら,よろしくお願いします.

  • javaのbyte配列へintなどを埋め込む方法

    javaのbyte配列へintなどを埋め込む方法 java初心者です。データ編集がわからなくて悩んでいます。 下記のコードは"棒読みちゃん"といソフトへのTCPパケットを作成するコードです。 char buf[15]; *((short*)&buf[0]) = 0x0001; *((short*)&buf[2]) = speed; *((short*)&buf[4]) = tone; *((short*)&buf[6]) = volume; *((short*)&buf[8]) = voice; *((char* )&buf[10]) = 2; *((long* )&buf[11]) = len; 同じことをJAVAでしたいのですがわかりません。 (バイト型配列へint,long型を簡単に埋め込む方法がわかりません) よろしくお願いします。 よかったら、こちらもお願いします memcpy(&buf[15],message,strlen(messege)); TCPパケットのようなデータ処理が頻繁にある場合、 このようなコードは、どうしたらいいでしょうか? *((unsigned char* )&buf[15]) = message; CとJAVAになってますが、このような処理を簡単に書けないでしょうか?

    • ベストアンサー
    • Java
  • デストラクタについて

    #include <iostream> #include <string> using namespace std; #define NUM 2 //登録人数 class Person{ char *name; int *age; char *hobby; public: Person() { name = new char; age = new int; hobby= new char; } void Set(char *n,int a,char *h) { name=n; *age=a; hobby=h; } char *Get_name(void) { return name; } int Get_age(void) { return *age; } char *Get_hobby(void) { return hobby; } ~Person() { cout<<name<<"のデストラクタ\n"; delete [] name; delete age; delete [] hobby; } }; int main(void) { Person *p; int i; p=new Person[NUM]; p[0].Set("永嶋",21,"映画鑑賞"); p[1].Set("平林",54,"車"); for(i=0;i<NUM;i++){ cout<<"\n名前:"<<p[i].Get_name(); cout<<"\n年齢:"<<p[i].Get_age(); cout<<"\n趣味:"<<p[i].Get_hobby()<<"\n"; } delete [] p; return 0; } というプログラムを作成したのですが デストラクタの3つのdeleteがおかしいようなのですが どのような部分が問題となっているのでしょうか? 回答・アドバイス宜しくお願いいたします。

  • ポインタ

    String String Mid(int start, int length) const { char *p="HelloWorld"; char s[100]; p+=start; for(int i=0;i<length;i++) { *s++=*p+;; } return s3; で++には左辺値が必要ですとでます。 stringクラスのMid関数を実装しているのですが start分ポインタを進めてlength取り出す関数なんですが ここまでは組んだのですが、うまくいきません。 どうすればうまくいきますか?

  • 配列の配列をmemcpyやmemcmpしたいです

    【環境】WindowsXP(SP2)、VisualStudio2005++(MFC) タイトルの通りなんですが、配列の配列を比較したりコピーしたいのですが、以下に質問を3つ記載させていただきますので、どなたかご教授お願いいたしますm(__)m 1.宣言と初期化について char **buf; buf = new char*[3200]; for(int i=0; i < 3200; i++) { buf[i] = new char[4]; } これで、buf[1]、buf[2]、buf[3]、buf[4]に、それぞれ3200のchar型の配列が宣言された事になりますでしょうか? ※buf[4][3200] なのか buf[3200][4]なのかよく分からないです。 2.上記の方法で定義した2つの配列(bufとtmp)の比較 for(int i =0; i < 4; i++) { memcmp (buf[i], tmp[i], sizeof(tmp[i])); } これで比較出来ますでしょうか? 3.上記の方法で定義した2つの配列(bufとtmp)のコピー for(int i =0; i < 4; i++) { memcpy_s(buf[i], sizeof(buf[i]), tmp[i], 3200 * sizeof(char)); } これではバッファオーバーランエラーが発生してしまうのですが、どこがおかしいでしょうか? 以上3点、初心者の質問なので意味が分からないような箇所があるとは思いますが、どうかご教授お願いいたしますm(__)m  

  • ファイル読み込みを配列に入れる方法

    ファイルから数字を読み込んで 並び替えて出力するプログラムを作成しているのですが ファイルから一度に配列に取り込んで、その配列で並び変えたいのですが取り込みができないのです、int型の配列に一度に取り込むのは可能なのでしょうか? import java.io.*; class Sort { public static void main(String[] args) { String path = args[0]; File file = new File(path); FileReader fr = null; int[] buf = new int[(int)file.length()]; try { fr = new FileReader(file); fr.read(buf); for (int i=0; i<buf.length-1;i++) { int mini=buf[i]; int miniIndex = i; for(int j = i+1; j<buf.length;j++){ if(buf[j] < mini){ mini = buf[j]; miniIndex = j; } } buf[miniIndex] = buf[i]; buf[i] = mini; } for(int i =0; i<buf.length;i++) { System.out.print( buf[i]+","); } } catch (IOException e) { System.out.println("ファイル入力エラー"); } } } と作ってみたのですが‥ ご教授お願いいたします。

    • ベストアンサー
    • Java
  • プログラミングのポインタの所の課題で、途中までやったのですが・・・

    プログラミングのポインタの所の課題で、途中までやったのですが・・・ どうしてもとけません。どなたか解けるかた、ご指導お願いします。。。 課題は以下の通りです。 1.文字配列の先頭文字でソートを行って出力するプログラムを完成させよ。ただし、my_sort_stringsはポインタ配列とその要素数を引数として、登録されている文字配列を昇順に並べ替える関数である。 #include<stdio.h> #include<string.h> void print_strings(char **p, int n); void swap_strings(char **p, int i, int j); int min_index(); void my_sort_strings(); int main() { char*p[100]; char Orange[] = "orange"; char Apple[] = "apple"; char Peach[] = "peach"; char Grape[] = "grape"; char Melon[] = "melon"; int i; p[0] = Orange; p[1] = Apple; p[2] = Peach; p[3] = Grape; p[4] = Melon; print_strings(p, 5); my_sort_strings(); print_strings(p, 5); return 0; } void print_strings(char **s, int n) { int i; printf("-----------begin: print_string ----------\n"); printf("print_string: s's value: %08x\n", s); for(i = 0; i < n; i++) { printf("(s[%d])'s value: %08x\n", i, s[i]); printf("(s[%d])'s address: %08x\n", i, &s[i]); } for(i = 0; i < n; i++) printf("%d: %s\n, i, s[i]"); printf("-----------end: print_strings-----------\n"); } void swap_strings(char **p, int i, int j) { char *tmp; tmp = p[i]; p[i] = p[j]; p[j] = tmp; } int min_index(char **a, int n) { } void my_sort_strings( ) { } 2.課題1を元に文字配列の2文字目以降の順序まで考慮した辞書式順序でソートを行うプログラムを作成せよ。関数名はlexicographic_sortとする。

  • java

    Base64にエンコードしたものをデコードするプログラムです。(汎用性が低いのは仕様です)コンパイルは通ったのですが、実行したら以下のエラーが出てきました。 C:\Users\Owner\Documents\javadev>java Base64Decode2 hello.dat hello2.txt java.lang.ArrayIndexOutOfBoundsException: 97 at Base64Decode2.decode(Base64Decode2.java:51) at Base64Decode2.main(Base64Decode2.java:23) 指定の行を見ても原因がよく分かりません。とても初歩的な質問なのかもしれませんが、お願いします。 以下がプログラムコードです import java.io.*; public class Base64Decode2 { public static void main(String[] args) { // 変換テーブル char[] table = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; InputStream in = null; // 入力データ OutputStream out = null; // 出力先 try { in = new FileInputStream(args[0]); out = new FileOutputStream(args[1]); char[] cs; while ((cs=read4(in)) != null) { int[] buf = decode(cs, table);//ここが問題? for (int i=0; i<buf.length; i++) { System.out.print(buf[i]+", "); } System.out.println(); int[] buf2 = convert6to8(buf); write3(out, buf2); } } catch (Exception e) { e.printStackTrace(); // 例外の情報を表示する } finally { // in, out を閉じる try { in.close(); out.close(); } catch (Exception e) { } } } /** * 8ビットの2進数の列を復号化する. * @param cs * @param table 符号テーブル * @return */ public static int[] decode(char[] cs, char[] table) { int[] buf = new int[cs.length]; for (int i=0; i<buf.length; i++) { buf[i] = table[cs[i]];//ここが問題? } return buf; } public static int[] convert6to8(int[] buf) { String b; int[] buf2; if (buf.length == 2) { b = toBinary(buf[0], 6); buf2 = new int[1]; buf2[0] = fromBinary(b.substring(0, 8)); } else if (buf.length == 3) { b = toBinary(buf[0], 6) + toBinary(buf[1], 6); buf2 = new int[2]; buf2[0] = fromBinary(b.substring(0, 8)); buf2[1] = fromBinary(b.substring(8, 16)); } else { b = toBinary(buf[0], 6) + toBinary(buf[1], 6) + toBinary(buf[2], 6); buf2 = new int[3]; buf2[0] = fromBinary(b.substring(0, 8)); buf2[1] = fromBinary(b.substring(8, 16)); buf2[2] = fromBinary(b.substring(16, 24)); } return buf2; } /** * バイト列 bt の数を順に出力する. * @param bt 数の配列。長さは 3以下. 各数は8ビットの整数 */ public static void write3(OutputStream out, int[] bt) throws IOException { for (int i=0; i<3; i++) { if (i<bt.length) { out.write(bt[i]); } } } /** * in から文字を最大4つ読み出す. * @param in 入力ストリーム * @return 文字の配列。配列長は最大4. 入力終了したときには null を返す. */ public static char[] read4(InputStream in) throws IOException { char[] bs; int n0=in.read(); int n1=in.read(); int n2=in.read(); int n3=in.read(); if (n0 < 0) { // 読み込み終了 bs = null; } else if (n2 < 0 || (char) n2=='=') { bs = new char[2]; bs[0] = (char) n0; bs[1] = (char) n1; } else if (n3 < 0 || (char) n3=='=') { bs = new char[3]; bs[0] = (char) n0; bs[1] = (char) n1; bs[2] = (char) n2; } else { bs = new char[4]; bs[0] = (char) n0; bs[1] = (char) n1; bs[2] = (char) n2; bs[3] = (char) n3; } return bs; } /** * 数を読み取って、nビットの2進数を表す文字列に変換する * @param bt 1バイトの数 * @param n 2進数のビット数 * @return 2進数を表す文字列 */ public static String toBinary(int bt, int n) { String s = Integer.toBinaryString(bt); for (int i=s.length(); i<n; i++) { s = "0" + s; } return s; } /** * 2進数を表す文字列を数に変換する * @param b 2進数を表す文字列 * @return b が表す数 */ public static int fromBinary(String b) { return Integer.parseInt(b, 2); } }

    • ベストアンサー
    • Java