【问题标题】:Proper way of using strtok();正确使用 strtok();
【发布时间】:2016-03-28 12:48:18
【问题描述】:

我正在编写一个程序,它根据从我的简单文件中加载的数字创建向量 [x,y,z],这些数字仅由空格分隔。我在使用 Strtok() 方法创建新对象时遇到问题。这是代码。

#include "FileStaff.h"
vector<Vector>& FileStaff::readFile(string tekst)
{
    vector<Vector> main;
    string buffor;
    char *text;
    ifstream infile(tekst, ios::in);
    //Checking if file exists
    if (!infile.good()) {
        cout << "cannot open the file!";
        return main;
    }
    while (!infile.eof())
    {
        text = paraseStringToChar(tekst);
        pushingToVector(main, text);
    }
    infile.close();
    return main;
}

创建 wektor 并将它们推入 Vector 的方法。

void FileStaff::pushingToVector(vector<Vector>& main, char * tekst)
{
    Vector *wektor = new Vector[1000000];
    char korektor[] = " ";
    float helpTab[3];
    int wordCount=0;
    char * container = strtok(tekst, korektor);
    //counting numbers in our array
    while (container != NULL)
    {
        container = strtok(NULL, " ");
        wordCount++;
    }
    for (int i = 0; i <wordCount;i++ )
    {
        //Creating vectots [x,y,z]
        container = strtok(tekst, korektor);
        helpTab[i % 3] = atof(container);
        container = strtok(NULL, korektor);
        if (i % 3 == 0) {
            Vector wektor(helpTab[0], helpTab[1], helpTab[2]);
            main.push_back(wektor);
        }
    }
}

如果有人能帮助我,我会很感激的。

【问题讨论】:

  • 既然有可以解析字符串的std::stringstd::stringstreamstd::getline,为什么还要使用C 函数?
  • 最好的办法就是not to use strtok()
  • @πάνταῥεῖ 我已经使用strtok() 很多年了。排除使用string 数据类型,为什么不使用strtok()?它似乎一直对我很有效。我很想知道您为什么建议避免使用它。
  • 如果你使用的是 C 而不是 C++,你应该改变你的问题的标签:你会得到相关的答案。
  • @Logicrat 我的链接中提到的缺乏重新进入是这些原因之一。

标签: c string object vector strtok


【解决方案1】:

根据您的问题:

我正在编写一个从数字创建向量 [x,y,z] 的程序 从我的简单文件中加载,数字仅由 空间。

你正在用 C++ 编程(不是 C,正如标签所声称的那样)所以我很抱歉,但我不明白你为什么不做这样的事情(完全避免 strtok):

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

struct Vector {
    double x,y,z;

    // ... vector operations stuff...

    // input operator
    friend std::istream &operator>>( std::istream &is, Vector &v ) {        
        return is >> v.x >> v.y >> v.z;
    }
    // output operator
    friend std::ostream &operator<<( std::ostream &os, Vector &v ) {
        return os << v.x << ' ' << v.y << ' ' << v.z;
    }   
};

std::vector<Vector> readFile( const std::string &fname)
{
    std::vector<Vector> main;
    std::string buf;
    Vector vtemp;

    std::ifstream infile{fname, std::ios::in};

    if (!infile.good()) {
        std::cout << "cannot open the file!";
        return main;
    }
    while ( infile >> vtemp ) {
        main.push_back(vtemp);
    }

    return main;
}

int main() {
    std::vector<Vector> data = readFile("input.txt");
    std::cout << "Vectors read: " << data.size() << '\n';
    for ( Vector & i : data ) {
        std::cout << i << '\n';
    }
    return 0;
}

【讨论】:

  • 我在 while 循环中遇到了“>>”的问题。没有运算符“>>”与这些操作数匹配。一切都包括在内
  • @LucasPG 您是在尝试编译我的代码,还是只是在您的代码中调整 readFile() 函数?因为你必须像我一样为你的 Vector 类重载 operator>>。
  • 我复制了你的整个结构,操作符仍然不起作用。你能用“朋友”向我解释创建运算符吗?
  • @LucasPG 小步骤。复制、编译并运行我发布的整个程序,然后创建一个名为 input.txt 的带有空格分隔数字的小文本文件,看看它是否有效,或者您的编译器(这是?)是否抱怨它。
  • @LucasPG 我使用了friend关键字,因为我希望该函数访问类的成员而不是它的一部分。这是在 C++ 中定义流运算符的常用方法。
【解决方案2】:

这是你要找的吗?

#ifndef _STRING_H
#include <string>
#endif
#ifndef _FSTREAM_H
#include <fstream>
#endif
#ifndef _STREAMBUF_H
#include <streambuf>
#endif
#ifndef _VECTOR_H
#include <vector>
#endif

using namespace std;

void writeToFile(string path, string data) {
    ofstream ofs(path,ios::app);
    ofs << data;
    ofs.close();
}
string readFromFile(string path) {
    ifstream ifs(path);
    std::string ret((std::istreambuf_iterator<char>(ifs)),
        std::istreambuf_iterator<char>());
    return ret;
}

enum XYZ { X = 0, Y = 1, Z = 2 };

struct Vector {
    float x, y, z;
    Vector(float _x=0, float _y=0, float _z=0) {
        x = _x;
        y = _y;
        z = _z;
    }
    float& operator[](size_t index) {
        if (index == XYZ::X) return x;
        if (index == XYZ::Y) return y;
        if (index == XYZ::Z) return z;
        throw new exception;
    }
};



#define min(a, b) (((a) < (b)) ? (a) : (b))

bool isCharNumeric(char c) {
    const char* numbers = "0123456789";
    for (size_t index = 0; index < strlen(numbers); index++)
        if (c == numbers[index]) return true; return false;
}

vector<Vector> parseFloatVectors(string str_in) {
    str_in += "  "; //safe, no out of bounds
    vector<Vector> results = {};
    char currentChar;
    char skipChar = ' ';
    bool found_period = false;
    size_t count_len = 0;
    Vector vector_buffer(0,0,0);
    XYZ current_axis = (XYZ)0;
    for (size_t index = 0; index < str_in.length(); index++) {
        currentChar = str_in[index];
        if (currentChar == skipChar || currentChar == '\n' || currentChar == '\t')
            continue;

        else if (isCharNumeric(currentChar)) {
            string word = ""; //word buffer
            size_t word_len = min(min(str_in.find_first_of(' ', index + 1) - (index), str_in.find_first_of('\n', index + 1) - (index)), str_in.find_first_of('\t', index + 1) - (index)); //whatever char comes first; newline, tab or space
                                                                                                                                                              //append chars of following word checking if it is still valid number char
            if (word_len > 0) {
                size_t count_word_len = 0;
                for (count_word_len = 0; count_word_len < word_len; count_word_len++)
                    if (isCharNumeric(str_in[index + count_word_len])) {
                        word += str_in[index + count_word_len];
                    }
                    else if (str_in[index + count_word_len] == '.' && isCharNumeric(str_in[index + count_word_len + 1])) {
                        //Floating-point numbers
                        word += '.';
                        found_period = true;
                        continue;
                    }
                    else {
                        word = "";
                        continue;
                    }

                    vector_buffer[current_axis] = stof(word);


                    if (current_axis == XYZ::Z) {
                        current_axis = XYZ::X;
                        results.push_back(vector_buffer);
                    }
                    else {
                        current_axis = (XYZ)(current_axis + 1);
                    }


                    index += count_word_len;
                    word = "";
                    continue;
            }

        }
    }
    return results;
}

示例用法: 字符串 input_floats = readFromFile("myVectors.txt"); 矢量vectors = parseNumbers(input_floats);

for each(Vector v in vectors) {
     printf("X = %f\n", v.x);
     printf("Y = %f\n", v.y);
     printf("Z = %f\n\n", v.z);
}

它只会解析完整的向量(一次 3 个浮点数)。换句话说,您最终只会得到一组完整向量。

【讨论】:

  • 不完全是。我正在寻找,如何创建多个对象:Vector(float x,float y,float z);用 strtook 将它们推入我的 Vector.
  • 我会删除我完全误读的答案。我的错。我想我知道你想要什么。
  • 查看新答案。当然,你可以使用自己的方法将文本文件读入字符串。
猜你喜欢
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 2021-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多