hageking
@hageking

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

csvでcharの文字列サイズを気にせず代入したい。

Q&A

Closed

解決したいこと

c++でcsvを読み込むプログラムを作りました。
csvの文字列サイズが大きくなっても、strに文字列サイズに気にせず、代入できるようにしたいです。
解決方法を教えてください。

参考サイト

ソースコード

main.cpp
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    FILE *fp; // FILE型構造体
    char fname[] = "test.csv";
    char str[1];

    fp = fopen(fname, "r"); // ファイルを開く。失敗するとNULLを返す。
    if (fp == NULL)
    {
        printf("%s file not open!\n", fname);
        return -1;
    }

    while (fscanf(fp, "%s\n", str) != EOF)
    {
        printf("%s\n", str);
    }

    fclose(fp); // ファイルを閉じる

    return 0;
}
output
zsh: segmentation fault  ./a.out
test.csv
test
testtesttesttest
testtesttesttesttest
0

2Answer

std::string使えば良いんじゃないですか

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    std::string fname("test.csv");
    std::ifstream ifs;
    std::string str;

    ifs.open(fname);
    if (!ifs) {
        std::cerr << fname << " file not open!" << std::endl;
        return 1;
    }

    while (getline(ifs, str)) {
        std::cout << str << std::endl;
    }

    ifs.close();

    return 0;
}

2Like

Comments

  1. @hageking

    Questioner

    ありがとうございます。
    出来ました。

C言語の話なのか、C++の話なのかで全然違いますね…

C言語ならば、realloc()を使ってバッファの継ぎ足ししながら、1文字ずつ読み出す感じですかね。まあ、メンドクサイです。また、エラーハンドリング不十分なので、realoc()がNULL returnしたらダメになります。

とりあえずこういう方法もできますよ、ぐらいの参考情報で。

/**
 * gcc main.c -o a.out
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    FILE *fp; // FILE型構造体
    char fname[] = "test.csv";
    size_t str_capable = 4;
    size_t str_pos     = 0;
    char *str = (char*) malloc( sizeof(char) * str_capable );

    fp = fopen(fname, "r"); // ファイルを開く。失敗するとNULLを返す。
    if (fp == NULL)
    {
        printf("%s file not open!\n", fname);
        return -1;
    }

    // 現在位置を先頭に
    str_pos = 0;
    while ( !feof(fp) )
    {
        // 次の文字が読み出せるだけのバッファがあるか?
        if ( str_pos >= str_capable )
        {
            // バッファサイズを25%ましする
            str_capable = (int) ( double ) str_capable * 1.25 ;
            str = (char*)realloc(str, sizeof(char) * str_capable );
        }

        // 1文字だけ読み出す
        int c = fgetc(fp);

        if ( (c == '\n' ) || ( c == ' ' ) || ( c == EOF ) )
        {
            if ( str_pos == 0 ) { continue ; }
            // 改行やスペースだったら、文字列を表示
            str[str_pos] = '\0';
            printf("str = %s, len(str) = %ld, str_capable = %ld \n",
                str, strlen(str), str_capable );
            str_pos = 0; // バッファ先頭に戻る
        }else
        {
            // バッファに保持する
            str[str_pos] = c;
            str_pos ++;
        }
    }

    fclose(fp); // ファイルを閉じる

    free(str);
    return 0;
}

2Like

Comments

  1. @hageking

    Questioner

    説明不足ですいません。
    書いて頂いたコードを使いこなす自信がないので、stringを使うことにしました。
    ありがとうございました。
  2. (テストコードを書いておきながらで申し訳ございませんが)C++でstringを使う方が間違いも少なく、汎用性も高いと思われます。

Your answer might help someone💌