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

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

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

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

Q&A

3回答

720閲覧

C言語で区切り文字で区切って単語を一個ずつbucketに入れる

YDjff

総合スコア1

C

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

0グッド

0クリップ

投稿2020/11/11 07:39

C言語でcallocを使いテキストファイルから読み込んだ奴をbuffer に入れてそれを区切り文字で区切ってbucket
の中に入れたいです。例えば buffer の中身が aaa bbbb cccc, dddd; とかであればそれを下のコードに書いてあるspliterで区切ってその区切りもじをbucketの中にどんどん入れたいです。 この場合bucket の中が4個になるはずで。
ですが今のところ正しく読み込めていなくSegmentfaultがでます。多分ですがこのtokenize_stringのbucket++が問題だと思うのですが。。

コード #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #define EXAMPLE_ERROR_CODE 1 #define FILE_NOT_FOUND -1 #define unableallocate 3 #define True 1 #define False 0 int tokenize_string(char* buffer, size_t size, word_t* bucket){ size_t len = 0; int count = 0; char* p = NULL; char* spliter = " .,;()\n"; p = strtok(buffer, spliter); while(p!= NULL){ len = strlen(p); if(len != 0){ strcpy(bucket->word, p); bucket->len = len; bucket++; count++; }  p = strtok(NULL,spliter); } return count; } //----------------------------------------------------------- size_t readfile(char* filepath, char *buffer){ size_t buff_size; FILE* fp = fopen(filepath, "rb"); if (fp == NULL){ return (size_t)FILE_NOT_FOUND; } fseek(fp, 0, SEEK_END); long pos = ftell(fp); fseek(fp,0,SEEK_SET); buff_size = (size_t)pos; fread(buffer,sizeof(char), buff_size,fp); fclose(fp); return buff_size; } int main(int argc, char *argv[]) { int infile = False; int is_sort = False; char* filename = NULL; size_t size = 0; int count = 0; char *buffer ; word_t *bucket; typedef struct word_t { int len; char* word; } word_t; int i = 0; if (argc <3){ printf("program: missing '--infile <filename> [--sort] [--print-words]'\n"); return EXAMPLE_ERROR_CODE; } for (i = 1; i < argc; i++){ if(strcmp(argv[i], "--infile") == 0){ infile = True; } else if(strcmp(argv[i], "--infile") == 0){ is_sort = True; } else{ if (infile == True && filename ==NULL){ filename = argv[i]; } } } if(infile == False){ printf("No infile error. Exit the program."); return EXAMPLE_ERROR_CODE; } if (filename == NULL){ printf("No filename error. Exit the program"); return EXAMPLE_ERROR_CODE; } // ------------------------------------------------------------ buffer = (char *) calloc(10000, sizeof(char)); if (buffer == NULL){ printf(" can not get memory\n"); return unableallocate; } size = readfile(filename,buffer) ; printf("%s", buffer); size = size -1; printf("%zu",size); // delete later //-------------------------------------------------------------- // tokernize --------------------------------------------------- bucket = (word_t *) calloc(1500, sizeof(word_t)); bucket-> len = 0; bucket-> word = (char*)calloc(1500,sizeof(char)); count = tokenize_string(buffer, size, bucket); printf("%d",count); // delete later free(buffer); free(bucket->word); free(bucket); return 0; } // end main

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

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

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

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

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

guest

回答3

0

文字列はすべて buffer に入ります。
bucket の word はその文字列へのポインタです。

C

1#include <stdio.h> // printf, fopen, fclose, fread 2#include <stdlib.h> // calloc, free 3#include <string.h> // strlen, strtok 4 5typedef struct word_t { 6 int len; 7 char* word; 8} word_t; 9 10int tokenize_string(char *buffer, size_t size, word_t *bucket) 11{ 12 int count = 0; 13 char *p = NULL; 14 const char *spliter = " .,;()\n"; 15 p = strtok(buffer, spliter); 16 while (p != NULL) { 17 bucket->word = p; 18 bucket->len = strlen(p); 19 bucket++; 20 count++; 21 p = strtok(NULL, spliter); 22 } 23 return count; 24} 25 26int readfile(const char *name, char *buffer, int size) 27{ 28 FILE *fp = fopen(name, "r"); 29 if (fp == NULL) { perror(name); return 0; } 30 size = fread(buffer, 1, size, fp); 31 fclose(fp); 32 return size; 33} 34 35int main(void) 36{ 37 char *buffer = (char *)calloc(10000, sizeof(char)); 38 word_t *bucket = (word_t *)calloc(1500, sizeof(word_t)); 39 if (buffer == NULL || bucket == NULL) { 40 printf(" can not get memory\n"); 41 return 0; 42 } 43 const char *filename = "data.txt"; 44 int size = readfile(filename, buffer, 9999); 45 buffer[size] = '\0'; 46 47 int count = tokenize_string(buffer, size, bucket); 48 49 printf("%d\n", count); 50 for (int i = 0; i < count; i++) 51 puts(bucket[i].word); 52 53 free(buffer); 54 free(bucket); 55}

tokenize_string で buffer のサイズは不要ですが、
bucket のサイズはあったほうがいいでしょう。

投稿2020/11/11 09:40

kazuma-s

総合スコア8224

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

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

0

bucketの一番先頭のwordだけ、callocしてメモリを割り当ててます。
2番目以降のwordのメモリが割り当てられていません。

これだと、先頭のwordだけ。

c

1 bucket-> len = 0; 2 bucket-> word = (char*)calloc(1500,sizeof(char));

tokenize_string関数の中で、 strcpy(bucket->word, p)する前にメモリを割り当てる必要があります。

c

1while(p!= NULL){ 2 3 len = strlen(p); 4 5 if(len != 0){ 6 7     // ★★コピーする前にメモリ割り当てが必要 8 strcpy(bucket->word, p); 9 bucket->len = len; 10 bucket++; 11 count++; 12 } 13  p = strtok(NULL,spliter); 14 }

投稿2020/11/11 07:53

akiruno-oneone

総合スコア815

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

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

YDjff

2020/11/11 07:56

返信ありがとうございます。 一応メイン関数内で bucket-> wordをcalloc で用意したのですがそれではないですか?
akiruno-oneone

2020/11/11 08:45

それだと、一番最初の1個だけです。 2個目以降のwordも割り当てる必要があります。
guest

0

まず、

size = readfile(filename,buffer) ;

ファイルを全部一括で読み込むコードになってますが、それは意図したコードなんでしょうか
たかだか約10Kbyteを超えるファイルを読み込むと破綻します

投稿2020/11/11 07:46

編集2020/11/11 07:47
y_waiwai

総合スコア88042

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

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

YDjff

2020/11/11 07:50

返信ありがとうございます 一応あまり考えずに作ったのですが。。
y_waiwai

2020/11/11 07:55 編集

なら、バッファサイズも一緒に渡すようにして、そのサイズまでのデータを読み込むように、この関数を修正しましょう
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問