[英]strcmp segmentation fault
这是一个来自spoj的问题。 与算法无关,但只是c
样本输入
2
a a bb cc def ghi
aaaaa bb bb bb bb cc
样本输出
3
五
它计算相同单词的最长序列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;
}
问题可能出在这里:
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
}
忘了在strtok上检查NULL,完成后它将返回NULL,你不能在strcpy,strcmp等上使用那个NULL。
请注意,您在strtok之后立即执行strcpy,在使用p作为源之前,应该检查null。
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),因此得到了崩溃。
你会发现previous
或current
中的一个在该点没有指向以null结尾的字符串,因此strcmp不知道何时停止。
使用适当的C ++字符串和字符串函数,而不是混合使用C和C ++。 Boost库可以提供比strtok
更安全的tokeniser。
您可能会将当前和之前的内容缩小。 你应该真的使用std :: string来做这种事情 - 这就是它的用途。
在将它们复制到大小为21的缓冲区之前,你没有做任何事情来检查你的字符串长度。我打赌你以某种方式覆盖了缓冲区的末尾。
如果你坚持使用C字符串,我建议使用strncmp而不是strcmp。 这样,如果您最终得到一个非空终止字符串(我怀疑是这种情况),您可以将比较限制为字符串的最大长度(在本例中为21)。
试试这个......
#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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.