user535450
user535450

Reputation:

strcmp segmentation fault

Here is a problem from spoj. nothing related to algorithms, but just c

Sample Input

2

a aa bb cc def ghi

a a a a a bb bb bb bb c c

Sample Output

3

5

it counts the longest sequence of same words http://www.spoj.pl/problems/WORDCNT/ The word is less than 20 characters But when i run it, it's giving segmentation fault. I debugged it using eclipse. Here's where it crashes

if (strcmp(previous, current) == 0)
                currentLength++;

with the following message

No source available for "strcmp() at 0x2d0100" What's the problem?

#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;
}

Upvotes: 2

Views: 3067

Answers (8)

Anil Arya
Anil Arya

Reputation: 3110

Try this one...

#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;
    }

Upvotes: 0

Loki Astari
Loki Astari

Reputation: 264471

The problem is probably here:

    while (p != NULL) {
        p = strtok(NULL, " '\t''\r'");
        strcpy(current, p);

While p may not be NULL when the loop is entered.
It may be NULL when strcpy is used on it.

A more correct form of the loop would be:

    while ((p != NULL) && ((p = strtok(NULL, " \t\r")) != NULL))
    {
        strcpy(current, p);

Note. Tokenizing a stream in C++ is a lot easier.

std::string  token;
std::cin >> token;  // Reads 1 white space seoporated word

If you want to tokenize a line

// 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
}

Upvotes: 9

Vikram.exe
Vikram.exe

Reputation: 4585

The strtok man page says:

 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. 

And in your code,

while (p != NULL) {
            p = strtok(NULL, " '\t''\r'");
            strcpy(current, p);

you are not checking for NULL (for p) once the whole string has been parsed. After that you are trying to copy p (which is NULL now) in current and so getting the crash.

Upvotes: 2

Kunya
Kunya

Reputation: 26

If you insist on using C strings, I'd suggest using strncmp instead of strcmp. That way, in case you are ending up with a non-null terminated string (which is what I suspect is the case), you can restrict your compare to the max length of the string (in this case 21).

Upvotes: 0

bcsanches
bcsanches

Reputation: 2372

Forgot to check for NULL on strtok, it will return NULL when done and you cannot use that NULL on strcpy, strcmp, etc.

Note that you do a strcpy right after the strtok, you should check for null before doing that using p as a source.

Upvotes: 2

Puppy
Puppy

Reputation: 146940

You probably undersized current and previous. You should really use std::string for this kind of thing- that's what it's for.

Upvotes: 1

Zan Lynx
Zan Lynx

Reputation: 54325

You are doing nothing to check your string lengths before copying them into buffers of size 21. I bet that you are somehow overwriting the end of the buffer.

Upvotes: 0

OrangeDog
OrangeDog

Reputation: 38777

You will find that one of previous or current does not point to a null-terminated string at that point, so strcmp doesn't know when to stop.

Use proper C++ strings and string functions instead, rather than mixing C and C++. The Boost libraries can provide a much safer tokeniser than strtok.

Upvotes: 1

Related Questions