这是一个来自spoj的问题。与算法无关,但只是c
示例输入
2
a aa bb cc def ghi
a a a a a bb bb bb bb c c
示例输出
3
5
它计算相同单词的最长序列 http://www.spoj.pl/problems/WORDCNT/ 这个词不到20个字符 但是当我运行它时,它会给出分段错误。我使用eclipse调试它。这是它崩溃的地方
if (strcmp(previous, current) == 0)
currentLength++;
带有以下消息
没有可用于“strcmp()0x2d0100”的源代码“ 有什么问题?
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
int main(int argc, const char *argv[])
{
int t;
cin >> t;
while (t--) {
char line[20000], previous[21], current[21], *p;
int currentLength = 1, maxLength = 1;
if (cin.peek() == '\n') cin.get();
cin.getline(line, 20000);
p = strtok(line, " '\t''\r'");
strcpy(previous, p);
while (p != NULL) {
p = strtok(NULL, " '\t''\r'");
strcpy(current, p);
if (strcmp(previous, current) == 0)
currentLength++;
else
currentLength = 1;
if (currentLength > maxLength)
maxLength = currentLength;
}
cout << maxLength << endl;
}
return 0;
}
答案 0 :(得分:9)
问题可能在这里:
while (p != NULL) {
p = strtok(NULL, " '\t''\r'");
strcpy(current, p);
输入循环时p可能不为NULL 在使用strcpy时它可能为NULL。
更正确的循环形式是:
while ((p != NULL) && ((p = strtok(NULL, " \t\r")) != NULL))
{
strcpy(current, p);
请注意。使用C ++对流进行标记更加容易。
std::string token;
std::cin >> token; // Reads 1 white space seoporated word
如果你想标记一行
// Step 1: read a single line in a safe way.
std::string line;
std::getline(std::cin, line);
// Turn that line into a stream.
std::stringstream linestream(line);
// Get 1 word at a time from the stream.
std::string token;
while(linestream >> token)
{
// Do STUFF
}
答案 1 :(得分:2)
忘了在strtok上检查NULL,完成后它将返回NULL,你不能在strcpy,strcmp等上使用那个NULL。
请注意,您在strtok之后立即执行strcpy,在使用p作为源之前,应检查null。
答案 2 :(得分:2)
strtok
手册页说:
Each call to strtok() returns a pointer to a null-terminated string containing the next
token. This string does not include the delimiting character. If no more tokens are found,
strtok() returns NULL.
在你的代码中,
while (p != NULL) {
p = strtok(NULL, " '\t''\r'");
strcpy(current, p);
一旦整个字符串被解析,你就不会检查NULL(对于p)。之后,您正试图在current
中复制p(现在为NULL),从而导致崩溃。
答案 3 :(得分:1)
你会发现previous
或current
中的一个在该点没有指向以空字符结尾的字符串,因此strcmp不知道何时停止。
使用适当的C ++字符串和字符串函数,而不是混合使用C和C ++。 Boost库可以提供比strtok
更安全的tokeniser。
答案 4 :(得分:1)
您可能会将当前和之前的内容缩小。你应该真的使用std :: string来做这件事 - 这就是它的用途。
答案 5 :(得分:0)
在将字符串长度复制到大小为21的缓冲区之前,你没有做任何事情来检查你的字符串长度。我打赌你以某种方式覆盖了缓冲区的末尾。
答案 6 :(得分:0)
如果你坚持使用C字符串,我建议使用strncmp而不是strcmp。这样,如果您最终得到一个非空终止字符串(我怀疑是这种情况),您可以将比较限制为字符串的最大长度(在本例中为21)。
答案 7 :(得分:0)
试试这个...
#include <cstdio>
#include <cstring>
#define T(x) strtok(x, " \n\r\t")
char line[44444];
int main( )
{
int t; scanf("%d\n", &t);
while(t--)
{
fgets(line, 44444, stdin);
int cnt = 1, len, maxcnt = 0, plen = -1;
for(char *p = T(line); p != NULL; p = T(NULL))
{
len = strlen(p);
if(len == plen) ++cnt;
else cnt = 1;
if(cnt > maxcnt)
maxcnt = cnt;
plen = len;
}
printf("%d\n", maxcnt);
}
return 0;
}