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

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

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

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

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

解決済

4回答

962閲覧

出力結果が@+iみたいな感じにでてしまう

L4zy

総合スコア18

C

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

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

0グッド

0クリップ

投稿2020/04/29 01:23

空白ごとに分割して出力したいのですが、
なぜか、"@+i"みたいな意味不明なものが表示されてしまいます。
どこが悪さしているのでしょうか?

C

1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4 5void spacePart(char str[], char **num); 6// ハッシュ探索を行う関数 引数:なし 戻り値:0 7int main() 8{ 9 char str[1000]; 10 char *num[100]; 11 puts("100個以内の数値を入力してください。"); 12 gets(str); 13 // 文字列を空白ごと分ける 14 spacePart(str, num); 15 return 0; 16} 17 18// 文字列を空白ごとに分けて配列に格納する関数 引数:入力値、配列 戻り値:なし 19void spacePart(char str[], char **num) 20{ 21 // メモリ確保 22 num[0] = (char *)malloc(strlen(str) + 1); 23 // 空白区切りに文字列を分割 24 strcpy(num[0], strtok(str, " ")); 25 26 for(int i = 0; num[i] != NULL; i++) 27 { num[i] = (char *)malloc(strlen(str) + 1); 28 printf("%s\n", num[i]); 29 strcpy(num[i], strtok(NULL, " ")); 30 } 31} 32

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

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

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

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

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

L4zy

2020/04/29 08:27

見てませんでしたてへぺろ
guest

回答4

0

すこーしいぢってみた。

C

1#define _CRT_SECURE_NO_WARNINGS 2#include <stdio.h> 3#include <string.h> 4#include <stdlib.h> 5 6char* spacePart(const char* str, char** num); 7 8int main() { 9 char* num[100]; 10 char* buffer = spacePart("1 2 3 4 5 6 7 8 9 10", num); 11 12 // 結果の確認 13 int i = 0; 14 while ( num[i] != NULL ) { 15 printf("[%s] ", num[i]); 16 ++i; 17 } 18 puts(""); 19 20 // 後始末 21 free(buffer); 22 return 0; 23} 24 25// 文字列を空白ごとに分けて配列に格納する  26// 引数:入力値、配列 27// 戻り値:確保された領域(使い終わったらfreeすべし) 28char* spacePart(const char* str, char** num) { 29 // メモリ確保 30 char* token; 31 int i; 32 char* buffer = (char*)malloc(strlen(str) + 1); 33 strcpy(buffer, str); 34 35 i = 0; 36 for ( token = strtok(buffer, " "); token != NULL; token = strtok(NULL," ") ) { 37 num[i++] = token; 38 } 39 num[i] = NULL; // 終わりのシルシ 40 return buffer; 41}

投稿2020/04/29 03:26

episteme

総合スコア16614

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

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

0

ベストアンサー

C

1#include <stdio.h> // puts, fgets 2#include <string.h> // strtok, strdup 3#include <stdlib.h> // free 4 5int spacePart(char str[], char **num, int n); 6 7int main(void) 8{ 9 char str[1000]; 10 char *num[100]; 11 puts("100個以内の数値を入力してください。"); 12 if (fgets(str, sizeof str, stdin) == NULL) return 1; 13 int n = spacePart(str, num, 100); 14 for (int i = 0; i < n; i++) puts(num[i]); 15 for (int i = 0; i < n; i++) free(num[i]); 16 return 0; 17} 18 19int spacePart(char str[], char **num, int n) 20{ 21 char *p = strtok(str, " \n"); 22 for (int i = 0; i < n; i++) { 23 if (p == NULL) return i; 24 num[i] = strdup(p); // strdupの内部で malloc と strcpy 25 if (num[i] == NULL) { puts("out of memory"); return -1; } 26 p = strtok(NULL, " \n"); 27 } 28 return n; 29}

gets よりも fgets をお勧めします。
なお、strdup は非標準関数ですが、多くの処理系には入っています。
このコードについてのコメントをお待ちしております。

投稿2020/04/29 02:36

kazuma-s

総合スコア8224

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

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

0

自分がなぜそのコードを書いたのか、目的を意識してみましょう。

  1. strtokで文字列を分割したい

1-1. strtokは元の文字列を変更してしまう
1-1-A. 事前に複製しよう
1-1-1. そのために、元の文字列の長さ+1文字分の領域を確保して、strcpyでコピーしよう

C

1char* dup = (char*)malloc(strlen(str) + 1); 2strcpy(dup, str); 3strtok(dup, " ");
  1. strtokで各文字列を取り出してコピーをとろう

2-1. そのように書こう

C

1int i = 0; 2for(char* next = dup; next != NULL; i++){ 3 num[i] = (char *)malloc(strlen(next) + 1); 4 strcpy(num[i], next); 5 // printfを書くならここ 6 next = strtok(NULL, " "); 7} 8num[i] = NULL;
  1. 使い終わった領域は解放しよう

C

1free(dup);

みたいな感じで。

投稿2020/04/29 02:06

majiponi

総合スコア1720

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

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

L4zy

2020/04/29 02:21

// 文字列を空白ごとに分けて配列に格納する関数 引数:入力値、配列 戻り値:なし void spacePart(char str[], char **num) { // メモリ確保 *num = (char *)malloc(strlen(str) + 1); // 空白区切りに文字列を分割 strcpy(num[0], strtok(str, " ")); for(int i = 1; ; i++) { num[i] = strtok(NULL, " "); if(num[i] == NULL) break; } free(num); } このように変更してみたのですが、どうでしょうか?
jimbe

2020/04/29 03:41

> どこが悪さしているのでしょうか > どうでしょうか ご自分で確認する術をお考えになった方が良いのではないでしょうか.
L4zy

2020/04/29 08:30

影分身の術覚えます!
guest

0

for(int i = 0; num[i] != NULL; i++)

num[i]は初期化されていません

投稿2020/04/29 01:30

y_waiwai

総合スコア87784

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

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

L4zy

2020/04/29 01:46

配列の初期化はどのように書けば良いのでしょうか?
pepperleaf

2020/04/29 01:53

ついでに、 i = 0 の時の最初の malloc()で得られた領域は、ポインタが上書きされるため、メモリーリーク。 ... さきほど、こちら気づかず、別のに回答しましたが、一連の質問ですね。
kazuma-s

2020/04/29 04:10

配列の初期化は、char *num[100] = { 0 }; でできます。 これだと 100個のポインタがすべて NULL で初期化されます。 すると spacePart の中の for文で num[i] が NULL でなければループを回るとなっているので、ループを回りません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問