0
bool isSubsequence(char* s, char* t) {

    int len = 0;
    bool res = false;
    int k = 0; 
    len = strlen(t);
    char str[len+1];
    uint64_t z;
    
    for (uint64_t i = 0; i < pow(2, len); i++)
    {
        k = 0;
        for (uint64_t j = 0; j < len; j++)
        {
            z = i & (1 << j);
            printf("z value %u",z);
            if (z != 0)
            {
                str[k++] = t[j];
            }
        }
        str[k] = '\0';
        if(strcmp(s,str)==0)
        {
            res= true;
            break;
        }
        printf("%s %d\n",str,i);
        str[0] = '\0';
    }
    
    return res;
}

Why do I get the error

runtime error: left shift of 1 by 31 places cannot be represented in type 'int' [solution.c]

for the line z = i & (1 << j);

I also tried z= i & (uint64_t(1) <<j) or other options like uint32_t replacing uint64_t also tried only using int for variables z, i and j. It is the leetcode problem, to find subsequence.

note : i have used pow to check all the subsequence of the string. using bit manipulation. yes we can solve the problem using string comparison that is more easier, I just wanted to know here, if the bits get larger than 31, than how to handle it, and what we do to eliminate the error i am getting.

Thank You so much everyone for taking time and answering my question.

7
  • in z = i & (1 << j); the 1 is an int. Commented May 20 at 15:29
  • 2
    (uint64_t(1) <<j) - this is a bad syntax. If you did (uint64_t)1 <<j it could work. Alternatively 1ull << j. Commented May 20 at 15:30
  • 2
    Sidenote: Don't use pow for integer powers. For integer powers of 2, you could just bitshift instead: 1ull << len. Commented May 20 at 15:31
  • 1
    %u and %d are also the wrong conversion specifiers for uint64_t. Use %" PRIu64 from inttypes.h. Commented May 20 at 16:02
  • 1
    Welcome to Stack Overflow! Please edit your code to reduce it to a minimal reproducible example of your problem. Your current code includes much that is peripheral to your problem - a minimal sample normally looks similar to a good unit test: only performing one task, with input values specified for reproducibility. It's also incomplete, missing at least one include an a main() function. Commented May 20 at 17:13

3 Answers 3

5

You are correct that this left shift is an overflow when applied to the 1 literal. In C, literals are int, by default. However, your syntax uint64_t(1) is the wrong syntax for a cast in C.

Instead, if the type uint64_t exists, you can cast to it in the expression (uint64_t)1. C also defines1 the UINT64_C macro (in all caps) which allows you to create an unsigned constant of width at least 64, which will always work. In this case it is best to do UINT64_C(1)

For example, (UINT64_C(1) << j) and ((uint64_t)1 << j) should both work.


1 Thanks to @john-bollinger and this stackoverflow answer for pointing this out.

Sign up to request clarification or add additional context in comments.

13 Comments

Using 1ull might not create a uint64_t. You actually want UINT64_C(1) (which probably expands to 1ull). /// That said, 1ull is guaranteed to be at least 64 bits, so it would work fine here.
@ikegami In the OP case any 32-bit unsigned or wider would work.
No, (uint64_t)1 is not a particularly better option. For example, it will be rejected by systems that don't provide uint64_t (which is optional, after all), whereas UINT64_C(1) should always produce an acceptable constant. Not that in practice you're likely to encounter a system that doesn't support uint64_t. Likewise UINT32_C(1), since the OP doesn't actually need the constant's type to be wider than 32 bits as long the type is unsigned.
These are required in C.
Those are (both) mandatory, @TedLyngmo. And they are also the types that UINT32_C() and UINT64_C() actually produce.
|
2

Your code is too complicated and the used algorithm is entirely unclear. To solve the problem there is no any need to use the function pow that deals with floating point numbers and the left shift operator. And creating a variable length array within the function makes it even more unsafe.

In my opinion your code just does not make sense relative to the decribed problem.

It is usually the case that any complicated code contains a bug.

All what you need is the standard C string function strchr.

I would write the function the following way.

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

bool isSubsequence( const char *s, const char *t ) 
{
    bool subsequence = true;
    
    while ( *s && ( subsequence = ( ( t = strchr( t, *s ) ) != NULL ) ) )
    {
        ++t;
        ++s;
    }
    
    return subsequence;
}

int main(void) 
{
    puts( isSubsequence( "abc", "ahbgdc" ) ? "true" : "false" );
    puts( isSubsequence( "axc", "ahbgdc" ) ? "true" : "false" );
}

The program output is

true
false

It is assumed that an empty string is always a substring of any other string.

Comments

0

The code is definitely too complicated and only works for short strings.

If the string has 31 characters, shifting 1 left by 31 positions shifts the bit into the sign bit, which has undefined behavior, if the shift count is 32 or larger (equal or larger than the width of the int type), the behavior is undefined too. You could use 1ULL << j but this would only work up to 63 characters, not enough for a reliable implementation.

There is a much simpler algorithm to check if s is a subsequence of t: all characters from s must be present in t in the same order.

Let's analyse this:

  • the empty string is a subsequence of any string.
  • if the first character of s is not present in t, not a subsequence.
  • if it is, s can be a subsequence if the remainder of s is a subsequence of the remainder of t.

This can be implemented recursively:

#include <stdbool.h>
#include <string.h>

bool isSubsequence(const char *s, const char *t) 
{
    if (!*s)
        return true;
    t = strchr(t, *s);
    if (!t)
        return false;
    return isSubsequence(s + 1, t + 1);
}

You can pack this as a single expression, but less readable for no performance gain:

bool isSubsequence(const char *s, const char *t) 
{
    return *s ? (t = strchr(t, *s)) ? isSubsequence(s + 1, t + 1) : false : true;
}

Here is simple alternative as a loop:

#include <stdbool.h>
#include <string.h>

bool isSubsequence(const char *s, const char *t) 
{
    while (*s) {               // while there are more bytes in the pattern
        t = strchr(t, *s++);   // scan the string for the first occurrence
        if (!t)                // not found: not a subsequence, return failure
            return false;
        t++;                   // skip the byte found and continue
    }
    return true;               // all bytes found in sequence: return success
}

Here is a shorter but slightly less efficient iterative version:

#include <stdbool.h>
#include <string.h>

bool isSubsequence(const char *s, const char *t) 
{
    while ((t = strchr(t, *s++)) != NULL) {
        if (!*t++)
            return true;
    }
    return false;
}

Finally an iterative self contained implementation:

#include <stdbool.h>

bool isSubsequence(const char *s, const char *t) 
{
    char cs, ct;
    while ((cs = *s++) != '\0') {
        while ((ct = *t++) != cs) {
            if (ct == '\0')
                return false;
        }
    }
    return true;
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.