gpt4 book ai didi

c++ - strtok 读长

转载 作者:行者123 更新时间:2023-11-27 23:21:54 28 4
gpt4 key购买 nike

这是一个文本文件的内容:

SQUARE 2
SQUARE
RECTANGLE 4 5

我想弄清楚为什么我的 strtok() 循环不会结束第二个“SQUARE”而只是使长度 = 0。也不完全理解 strtok 背后的概念,我不会不介意关于 strtok 的讲座。这是代码:

#include <cstring>
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
using std::ios;

#include<iomanip>
using std::setprecision;

#include <fstream>
using std::ifstream;

const int MAX_CHARS_PER_LINE = 512;
const int MAX_TOKENS_PER_LINE = 20;
const char* const DELIMITER = " ";

int main()
{
// create a file-reading object
ifstream fin;
fin.open("geo.txt"); // open a file
if (!fin.good())
return 1; // exit if file not found

//PI
float pi = 3.14159265359;

//DIMENSIONS
float length, width, height, radius;

//AREAS, PERIMETERS, VOLUMES
float areaSquare, periSquare;
float areaRectangle, periRectangle;
float areaCube, volCube;
float areaPrism, volPrism;
float areaCircle, periCircle;
float areaCylinder, volCylinder;

// read each line of the file
while (!fin.eof())
{
// read an entire line into memory
char buf[MAX_CHARS_PER_LINE];
fin.getline(buf, MAX_CHARS_PER_LINE);
// parse the line into blank-delimited tokens
int n = 0; // a for-loop index

// array to store memory addresses of the tokens in buf
const char* token[MAX_TOKENS_PER_LINE] = {0}; // initialize to 0

// parse the line
token[0] = strtok(buf, DELIMITER); // first token
if (token[0]) // zero if line is blank
{
for (n = 1; n < MAX_TOKENS_PER_LINE; n++)
{
token[n] = strtok(0, DELIMITER); // subsequent tokens
if (!token[n] || token[n]==0) break;
}
}

if(strcmp("SQUARE", token[0]) == 0) //1
{
length = atof(token[1])?atof(token[1]):0;
areaSquare = length * length;
periSquare = 4 * length;

cout.setf(ios::fixed|ios::showpoint);
cout << setprecision(2);
cout << token[0] << ' ' << "length="<< token[1] << ' ';
cout << "Area=" << areaSquare << ' ';
cout << "Perimeter=" << periSquare << '\n';
cout.unsetf(ios::fixed|ios::showpoint);
cout << setprecision(6);
}

else if(strcmp("RECTANGLE", token[0]) == 0) //2
{
length = atof(token[1])?atof(token[1]):0;
width = atof(token[2])?atof(token[2]):0;

areaRectangle = length * width;
periRectangle = 2 * length + 2 * width;

cout.setf(ios::fixed|ios::showpoint);
cout << setprecision(2);
cout << token[0] << ' ' << "length="<< token[1] << ' ';
cout << "width=" << token[2] << ' ' ;
cout << "Area=" << areaRectangle << ' ';
cout << "Perimeter=" << periRectangle << '\n';
cout.unsetf(ios::fixed|ios::showpoint);
cout << setprecision(6);
}
else
{
cout << "End of program. Press ENTER to exit.";
cin.ignore(1000,10);
break;
}
}
}

最佳答案

你的段错误是这样造成的:

length = atof(token[1])?atof(token[1]):0;

您错误地假设 token[1] 已被标记化。如果您查看第二个“SQUARE”,您会发现该行已将 token[1] 设置为 NULL。然后,您将 NULL 传递给 atof(),这是可以理解的错误。

您还错误地使用了 strtok()。 strcpy()从它的结果来看是没有道理的,因为strtok()本身就是一个破坏性的操作。

所以这是关于 strtok 的讲座。

首先,它是邪恶的,但它非常方便,所以有时你还是会用到它。分词器编写起来可能会很痛苦。

strtok 背后的想法是创建一个简单的分词器。分词器写起来很麻烦,如果你不介意让你的电脑很容易被它炸毁的话,它的界面实际上相当不错。例如,您可以使用非常少量的代码来解析命令行参数。

但是,strtok 会破坏您使用它的字符串。它将用 0 替换它找到的标记,自动以 null 终止返回值。这意味着您可以直接使用返回的字符串而无需复制它。像这样的字符串:

here are spaces0

变成了

here0are0spaces0

其中 0 分隔字符串字符 (0) 的结尾。这是就地完成的,您会得到指向此处、区域和空格的指针。

strtok 使用静态变量 - 这意味着它保留调用之间的状态信息。在第一次调用时,您向它传递一个指向您要标记化的字符串的指针;从那时起,您向它传递一个 NULL 指针,表示您希望它从之前停止的地方继续。它返回下一个标记,在找到字符串结尾时返回 NULL。

strtok 循环非常容易编写。此代码将为您正确标记字符串。下面的示例代码很丑,怪我累。

char *input_string;        // Just so we have it
const int MAX_TOKENS = 10; // Arbitrary number
char *tokens[MAX_TOKENS]; // This will do all the storage we need.
tokens[0] = strtok(input_string, " -=\""); // Setup call.
int number_of_tokens = 1; // We've already filled tokens[0], so we have 1 token. We want to start filling from 1.

do {
if (tokens[number_of_tokens] = strtok(NULL," -=\"")) number_of_tokens++;
else break;
} while(number_of_tokens < MAX_TOKENS);

循环中的第一行是 C 程序员的常见做法,但不利于可读性。这是它的作用:

a) 它将 tokens[number_of_tokens] 设置为 strtok 的返回值。b) 如果那是 NULL,它终止循环(第二行)。 附录:有一个在线测试。您可以执行 if (a = 1),它将返回 true 并将 a 设置为 1。您可以执行 if (a = 0),它将返回 false,同时将 a 设置为 0。此行利用了这一事实,如果 strtok( ) 返回 NULL,嗯,这是错误的。c) 如果它不为 NULL,则 tokens[number_of_tokens] 现在包含一个指向在字符串中找到的下一个标记的指针。d) 由于找到了 token , token 的数量 (number_of_tokens) 增加。5) 它重用了记录有多少标记的变量作为它保存的指针数组的索引。6) 无限循环,直到要么满足strtok返回NULL的条件,要么满足while()条件(本例中有10个以上的token)。

如果给它这个字符串:

这里有一些=words0

应该是

*tokens[0]="here"
*tokens[1]="are"
*tokens[2]="some"
*tokens[3]="words"
*tokens[4] = NULL
number_of_tokens = 4

如您所见,无需复制任何内容,因为该字符串已在内存中被替换:

这里0are0some0words0

其中 0 分隔字符串字符 (0) 的结尾。

我希望这能回答您的问题。

关于c++ - strtok 读长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12223918/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com