I've written a program that will check if a given string has all characters unique or not. I usually write in Python, but I'm learning C++ and I wanted to write the program using it. I get an error when I translate Python into C++: Thread 1: EXC_BAD_ACCESS (code=257, address=0x100000001)
I am using Xcode. When I run this program, I get the above error:
#include <iostream>
using namespace std;
int isUnique(string str) {
int arr[] = {};
for (int i = 0; i < str.length(); ++i) {
arr[i] = 0;
}
for (int j = 0; j < str.length(); ++j) {
arr[j] += 1;
}
for (int k = 0; k < sizeof(arr)/sizeof(arr[0]); ++k) {
if (arr[k] > 1) {
return false;
}
}
return true;
}
int main() {
string str;
cout << "Enter a string: ";
getline(cin, str);
cout << isUnique(str) << endl;
}
Here is the original code I wrote in Python:
def is_unique(string):
chars = []
for i in range(len(string)):
chars.append(0)
chars[string.find(string[i])] += 1 # I am using find and not just i because I want the first occurrence of the substring in the string to update it to 2 if it happens twice, 3 if it is thrice, etc.
for k in chars:
if k > 1: # Note that I'm checking for > 1
return False
return True
# Driver code
if __name__ == "__main__":
print(is_unique("abcd"))
When run, this outputs True, which means that the string has unique characters only. Change print(is_unique("abcd") to something else with a word without only unique characters, such as print(is_unique("hello") to get False.
When I translated this into C++, the Xcode terminal shows '(lldb)', and the Xcode editor opens up a file 0_mh_execute_header and its contents are as follows:
dsa`_mh_execute_header:
0x100000000 <+0>: .long 0xfeedfacf ; unknown opcode
0x100000004 <+4>: .long 0x0100000c ; unknown opcode
0x100000008 <+8>: udf #0x0
0x10000000c <+12>: udf #0x2
0x100000010 <+16>: udf #0x12
0x100000014 <+20>: udf #0x638
0x100000018 <+24>: .long 0x00218085 ; unknown opcode
0x10000001c <+28>: udf #0x0
0x100000020 <+32>: udf #0x19
0x100000024 <+36>: udf #0x48
0x100000028 <+40>: .long 0x41505f5f ; unknown opcode
0x10000002c <+44>: saddwt z7.h, z10.h, z26.b
0x100000030 <+48>: udf #0x4f52
0x100000034 <+52>: udf #0x0
0x100000038 <+56>: udf #0x0
0x10000003c <+60>: udf #0x0
0x100000040 <+64>: udf #0x0
0x100000044 <+68>: udf #0x1
0x100000048 <+72>: udf #0x0
0x10000004c <+76>: udf #0x0
0x100000050 <+80>: udf #0x0
0x100000054 <+84>: udf #0x0
...
NOTE: ... in the above means that it continues on. Stack Overflow allows only 30000 characters in the body, but this will exceed 950000
On line 1, Xcode shows an error: Thread 1: EXC_BAD_ACCESS (code=257, address=0x100000001) on the right side of the file (like it usually does when there are compiler issues).
Do you know how to solve this?
The problem is here:
int arr[] = {};
The array you're creating has length 0 which you can verify using
cout << "sizeof(arr): " << sizeof(arr) << endl;
The error occurs when you try to access values beyond the size of the array here:
arr[i] = 0;
What you need to do is specify a size of the array, for example int arr[128]; which creates an array that can hold 128 ints, which covers the range of 7-bit-ASCII. Or use a vector, which you can change the size of.
I will also point out that the logic as it is doesn't work, what you might want to do is
int isUnique(string str) {
// Create an array that holds 128 ints and initialize it to 0
int arr[128] = {0};
// First loop no longer needed
for (int i = 0; i < str.length(); ++i) {
// Increment count for cell that corresponds to the character
char c = str[i];
arr[c] += 1;
}
// Note that you can reuse variable name when previous one
// has fallen out of scope
for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i) {
if (arr[i] > 1) {
return false;
}
}
return true;
}
I suggest you read more on the C++ memory model.
The problem lies here:
int arr[] = {};
Arrays in C and C++ are not dynamic. What you have created there is an array with 0 elements, and that's what it forevermore will be. So, when you do:
arr[i] = 0;
you are writing off the end of the array into random memory. If you want the array to be the same length as the string, you would need:
int arr[str.size()];
Or, use a vector:
std::vector arr(str.size());
Related
in python language i can easily do this and output is whole list:
import random
list = [random.randrange(150) for i in range(10)]
print(list)
Can i do this thing in C# language without for cycle like this? Because output seperates my list's elements.
List<int> list = new List<int> ();
Random rnd = new Random();
for (int i = 0; i < 10; i++){
list.Add(rnd.Next (150));
}
for(int i = 0; i < list.Count; i++){
Console.WriteLine(list[i]);
}
Well, we can do it in one line if you want as well. This code is also thread-safe but requires .NET 6.0 or higher due to the use of Random.Shared.
Console.WriteLine(string.Join(",", Enumerable.Range(0, 10).Select(_ => Random.Shared.Next(150))));
This generates an IEnumerable<int> with random integers from 0 to 149 and then writes them to the Console separated by commas.
As far as I know, there is not a method generating a list of random integers in .NET, but why won't you write your own? For example:
public static class MyEnumerable
{
public static IEnumerable<int> RandomEnumerable(int maxValue, int count, Random random = default)
{
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count));
}
if (maxValue < 0)
{
throw new ArgumentOutOfRangeException(nameof(maxValue));
}
random ??= Random.Shared;
for (int i = 0; i < count; i++)
{
yield return random.Next(maxValue);
}
}
}
Now you can do your task in two lines like in phyton:
var randomList = MyEnumerable.RandomEnumerable(150, 10).ToList();
Console.WriteLine($"[{string.Join(", ", randomList)}]");
The Leetcode question is: Given a string s, find the length of the longest substring without repeating characters.
https://leetcode.com/problems/longest-substring-without-repeating-characters/
I coded in both C++ and Python to see whether there is a huge performance gap, and found the result to be:
Here are the c++ and python implementations of the same logic:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int max_count=0;
int k=1;
int i=0;
int j=0;
bool visited[256];
memset(visited,false,256);
int n=s.size();
while(k<=n && i<n && j<n){
/*for(int l=i;l<=j;l++) cout << s[l];
cout << endl;*/
if(visited[int(s[j])]){
memset(visited,false,256);
k=1;
i++;
j=i+k-1;
}else{
if (max_count<k) max_count=k;
visited[int(s[j])]=true;
k++;
j++;
}
}
return max_count;
}
};
and
class Solution:
def lengthOfLongestSubstring(self, a: str) -> int:
#apply sliding window for k=0,1,2,..,n until repetition is found for a substring
k=1 #wndow length
i=0 #starting indx of substring
j=0 #ending indx of substring
init_visited=[False]*256
visited=init_visited[:]
max_count=0
n=len(a)
while k<=n and j<n and i<n:
#print(k,i,j)
#print(a[i:j+1])
if visited[ord(a[j])]:
visited = init_visited[:]
i+=1
k=1
j=i+k-1
else:
visited[ord(a[j])]=True
max_count=max(max_count,k)
k+=1
j+=1
return max_count
What could have I improved in the Python code to make it faster?
Python will never be as fast as C++ but you can optimize this function using a dictionary:
def longestsub(S):
distinct = set()
result = 0
start = 0
for i,c in enumerate(S):
if c in distinct:
result = max(result,i-start)
distinct.difference_update(S[start:i])
start = i
distinct.add(c)
result = max(result,len(S)-start)
return result
output:
testData = ["abcabcbb","bbbbb","pwwkew",""]
for s in testData:
print(f"'{s}' : ",longestsub(s))
'abcabcbb' : 3
'bbbbb' : 1
'pwwkew' : 3
'' : 0
performance:
longestsub("abcabcbb"*10000) # 80,000 characters --> 3 in 30 ms
I just want to create a simple C++ struct that has an int index and an int grayValue .The function is given the vector with the gray values. When I try to compile it I get a segmentation fault, does anyone know why? (didn't sort the vector) Thank you.
vector<gray> createStruct( vector<int> grayValues)
{
vector <gray> grayStruct;
for (int i = 0; i<grayValues.size();i++)
{
grayStruct[i].originalIndex= i;
grayStruct[i].grayValue= grayValues[i];
}
return grayStruct;
}
int main() {
vector <int> grayVals={411,21,78,23};
vector <gray> grayStruct=createStruct(grayVals);
// sort(grayStruct);
for (int i = 0; i < grayStruct.size(); i++)
{cout << grayStruct[i].originalIndex<<' '<<grayStruct[i].grayValue;
cout<<endl;
}
return 0;
}
It is because you are using elements of grayStruct, which actually doesn't exist, in the function createStruct.
You have to create elements before use or use push_back() to create elements.
Create elements via the constructor:
vector<gray> createStruct( vector<int> grayValues)
{
vector <gray> grayStruct(grayValues.size()); // add number of elements to create
for (int i = 0; i<grayValues.size();i++)
{
grayStruct[i].originalIndex= i;
grayStruct[i].grayValue= grayValues[i];
}
return grayStruct;
}
Create elements via resize():
vector<gray> createStruct( vector<int> grayValues)
{
vector <gray> grayStruct;
grayStruct.resize(grayValues.size()); // create elements
for (int i = 0; i<grayValues.size();i++)
{
grayStruct[i].originalIndex= i;
grayStruct[i].grayValue= grayValues[i];
}
return grayStruct;
}
Add elements one-by-one via push_back():
vector<gray> createStruct( vector<int> grayValues)
{
vector <gray> grayStruct;
for (int i = 0; i<grayValues.size();i++)
{
gray value;
value.originalIndex= i;
value.grayValue= grayValues[i];
grayStruct.push_back(value); // add an element
}
return grayStruct;
}
I want to make a custom sorting method in C++ and import it in Python. I am not an expert in C++, here are implementation of "sort_counting"
#include <iostream>
#include <time.h>
using namespace std;
const int MAX = 30;
class cSort
{
public:
void sort( int* arr, int len )
{
int mi, mx, z = 0; findMinMax( arr, len, mi, mx );
int nlen = ( mx - mi ) + 1; int* temp = new int[nlen];
memset( temp, 0, nlen * sizeof( int ) );
for( int i = 0; i < len; i++ ) temp[arr[i] - mi]++;
for( int i = mi; i <= mx; i++ )
{
while( temp[i - mi] )
{
arr[z++] = i;
temp[i - mi]--;
}
}
delete [] temp;
}
private:
void findMinMax( int* arr, int len, int& mi, int& mx )
{
mi = INT_MAX; mx = 0;
for( int i = 0; i < len; i++ )
{
if( arr[i] > mx ) mx = arr[i];
if( arr[i] < mi ) mi = arr[i];
}
}
};
int main( int* arr )
{
cSort s;
s.sort( arr, 100 );
return *arr;
}
and then using it in python
from ctypes import cdll
lib = cdll.LoadLibrary('sort_counting.so')
result = lib.main([3,4,7,5,10,1])
compilation goes nice
How to rewrite a C++ method to receive an array and then return a sorted array?
The error is quite clear: ctypes doesn't know how to convert a python list into a int * to be passed to your function. In fact a python integer is not a simple int and a list is not just an array.
There are limitations on what ctypes can do. Converting a generic python list to an array of ints is not something that can be done automatically.
This is explained here:
None, integers, bytes objects and (unicode) strings are the only
native Python objects that can directly be used as parameters in these
function calls. None is passed as a C NULL pointer, bytes objects and
strings are passed as pointer to the memory block that contains their
data (char * or wchar_t *). Python integers are passed as the
platforms default C int type, their value is masked to fit into the C
type.
If you want to pass an integer array you should read about arrays. Instead of creating a list you have to create an array of ints using the ctypes data types and pass that in instead.
Note that you must do the conversion from python. It doesn't matter what C++ code you write. The alternative way is to use the Python C/API instead of ctypes to only write C code.
A simple example would be:
from ctypes import *
lib = cdll.LoadLibrary('sort_counting.so')
data = [3,4,7,5,10,1]
arr_type = c_int * len(data)
array = arr_type(*data)
result = lib.main(array)
data_sorted = list(result)
So my python program is
from ctypes import *
import ctypes
number = [0,1,2]
testlib = cdll.LoadLibrary("./a.out")
testlib.init.argtypes = [ctypes.c_int]
testlib.init.restype = ctypes.c_double
#create an array of size 3
testlib.init(3)
#Loop to fill the array
#use AccessArray to preform an action on the array
And the C part is
#include <stdio.h>
double init(int size){
double points[size];
return points[0];
}
double fillarray(double value, double location){
// i need to access
}
double AccessArray(double value, double location){
// i need to acess the array that is filled in the previous function
}
So what I need to do is to pass an array from the python part to the C function somehow move that array in C to the another function where I will access it in order to process it.
I'm stuck though because I cant figure out a way to move the array in the C part.
can someone show me how to do this?
You should try something like this (in your C code):
#include <stdio.h>
double points[1000];//change 1000 for the maximum size for you
int sz = 0;
double init(int size){
//verify size <= maximum size for the array
for(int i=0;i<size;i++) {
points[i] = 1;//change 1 for the init value for you
}
sz = size;
return points[0];
}
double fillarray(double value, double location){
//first verify 0 < location < sz
points[(int)location] = value;
}
double AccessArray(double value, double location){
//first verify 0 < location < sz
return points[(int)location];
}
This is a very simple solution but if you need to allocate an array with just any size you shoul study the use of malloc
Maybe something like this?
$ cat Makefile
go: a.out
./c-double
a.out: c.c
gcc -fpic -shared c.c -o a.out
zareason-dstromberg:~/src/outside-questions/c-double x86_64-pc-linux-gnu 27062 - above cmd done 2013 Fri Dec 27 11:03 AM
$ cat c.c
#include <stdio.h>
#include <malloc.h>
double *init(int size) {
double *points;
points = malloc(size * sizeof(double));
return points;
}
double fill_array(double *points, int size) {
int i;
for (i=0; i < size; i++) {
points[i] = (double) i;
}
}
double access_array(double *points, int size) {
// i need to access the array that is filled in the previous function
int i;
for (i=0; i < size; i++) {
printf("%d: %f\n", i, points[i]);
}
}
zareason-dstromberg:~/src/outside-questions/c-double x86_64-pc-linux-gnu 27062 - above cmd done 2013 Fri Dec 27 11:03 AM
$ cat c-double
#!/usr/local/cpython-3.3/bin/python
import ctypes
testlib = ctypes.cdll.LoadLibrary("./a.out")
testlib.init.argtypes = [ctypes.c_int]
testlib.init.restype = ctypes.c_void_p
#create an array of size 3
size = 3
double_array = testlib.init(size)
#Loop to fill the array
testlib.fill_array(double_array, size)
#use AccessArray to preform an action on the array
testlib.access_array(double_array, size)