繁体   English   中英

strcmp分段错误

[英]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),因此得到了崩溃。

你会发现previouscurrent中的一个在该点没有指向以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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM