- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是一个文本文件的内容:
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/
我有一个如下所示的数据框: import pandas as pd d = {'decil': ['1. decil','1. decil','2. decil','2. decil','3. dec
我有一些数据想要添加到我的应用中...大约 650 个类别(包括名称 + ID 号),每个类别平均有 85 个项目(每个都有一个名称/ID 号)。 iPhone会支持这么大的plist吗?我想首先在
我目前正在使用 Python 从头开始实现决策树算法。我在实现树的分支时遇到了麻烦。在当前的实现中,我没有使用深度参数。 发生的情况是,要么分支结束得太快(如果我使用标志来防止无限递归),要么如果
我在 Stack 上发现了这个问题 - Measuring the distance between two coordinates in PHP 这个答案在很多方面似乎对我来说都是完美的,但我遇到了
我目前正在清理一个具有 2 个索引和 2.5 亿个事件行以及大约同样多(或更多)的死行的表。我从我的客户端计算机(笔记本电脑)向我的服务器发出命令 VACCUM FULL ANALYZE。在过去的 3
这一切都有点模糊,因为该计划是相当深入的,但坚持我,因为我会尽量解释它。我编写了一个程序,它接受一个.csv文件,并将其转换为MySQL数据库的INSERT INTO语句。例如: ID Numbe
我有一个地址示例:0x003533,它是一个字符串,但要使用它,我需要它是一个 LONG,但我不知道该怎么做:有人有解决方案吗? s 字符串:“0x003533”到长 0x003533 ?? 最佳答案
请保持友善 - 这是我的第一个问题。 =P 基本上作为一个暑期项目,我一直在研究 wikipedia page 上的数据结构列表。并尝试实现它们。上学期我参加了 C++ 类(class),发现它非常有
简单的问题。想知道长 IN 子句是否是一种代码味道?我真的不知道如何证明它。除了我认为的那样,我不知道为什么它会闻起来。 select name, code, capital, pop
我正在尝试基于 C# 中的种子生成一个数字。唯一的问题是种子太大而不能成为 int32。有什么方法可以像种子一样使用 long 吗? 是的,种子必须很长。 最佳答案 这是我移植的 Java.Util.
我一直想知道这个问题有一段时间了。在 CouchDB 中,我们有一些相当的日志 ID……例如: “000ab56cb24aef9b817ac98d55695c6a” 现在,如果我们正在搜索此项目并浏览
列的虚拟列 c和一个给定的值 x等于 1如果 c==x和 0 其他。通常,通过为列创建虚拟对象 c , 一排除一个值 x选择,因为最后一个虚拟列不添加任何信息 w.r.t.已经存在的虚拟列。 这是我如
使用 tarantool,为什么我要记录这些奇怪的消息: 2016-03-24 16:19:58.987 [5803] main/493623/http/XXX.XXX.XXX.XXX:57295 t
我显然是 GitHub 的新手,想确保在开始之前我做的事情是正确的。 我想创建一个新的存储库,它使用来自 2 个现有项目的复刻/克隆。现有项目不是我的。 假设我想使用的 repo 被称为来自开发人员“
我的应用程序名称长度为 17 个字符。当安装在设备上时,它看起来像应用程序...名称。有没有办法在多行上显示应用程序名称?请帮忙。 最佳答案 不,你不能。我认为 iPad 支持 15 个字符来完整显示
我必须编写一个程序来读取文件中的所有单词,并确定每个单词使用了多少次。我的任务是使用多线程来加快运行时间,但是单线程程序的运行速度比多线程程序快。我曾尝试研究此问题的解决方案,但很多解释只会让我更加困
假设我在给定的范围内有一个位置pos,这样: 0 = newRange*newRange : "Case not supported yet"; // Never happens in my code
我试图在 Java 中将 unix 时间四舍五入到该月的第一天,但没有成功。示例: 1314057600 (Tue, 23 Aug 2011 00:00:00 GMT) 至 1312156800
我们的项目有在 CVS 中从现有分支创建新分支的历史。几年后,这导致了每次发布时更改的文件上的这种情况: 新版本:1.145.4.11.2.20.2.6.2.20.2.1.2.11.2.3.2.4.4
我有以下数据框: DAYS7 <- c('Monday','Tuesday','Wednesday','Thursday','Friday', 'Saturday', 'Sunday') DAYS
我是一名优秀的程序员,十分优秀!