Python read character - python

I would like to know how can I read the charaters into a buffer in Python?
In C code, I can easy decralare the buffer character like char buffer[256];:
void read_char(int x, char buffer[], int *flag_stop) {
int i, length;
char character;
i = 0;
bzero(buffer, 256);
do {
if ((length = read(x, &character, 1)) <= 0)
{
*flag_stop = 1;
break;
}
buffer[i] = character;
i++;
}
while(c != 0x0A);
}
But I don't know how to do in Python so the code is something like this:
def read_char(x,buffer,**flag_stop):
i = 0
buffer = np.array([], dtype='S64')
while True:
if os.read(x, character, 1) <= 0:
**flag_stop == 1
break
buffer[i] = str(character)
i=i+1
if(character != 0x0A):
break
I have tried with numpy.chararray but I did not work. Any idea for this problem? thank you very much!

Your main problem is that you want in Python write code exactly like in C.
Python would need something like this
def read_char(x):
flag_stop = False # or 0
i = 0
buffer = np.array([], dtype='S64')
while True:
character = os.read(x, 1)
if not character: # if len(character) < 0
flag_stop = True # or 1
break
buffer[i] = character
i += 1
if character != 0x0A:
break
return buffer, flag_stop
# ---
buffer, flag_stop = read_char(file_handler)
I don't like str() in your code - you may get single byte which is part of mulit-bytes code (like utf-8) and converting to str() can only mess it.

Related

Negative number causes VarInt's encoding function to crash

I try to implement the function below in Python but as soon as I enter a negative number the function crashes. Does anyone understand why?
public static void writeVarInt(int value) {
do {
byte temp = (byte)(value & 0b01111111);
value >>>= 7;
if (value != 0) {
temp |= 0b10000000;
}
writeByte(temp);
} while (value != 0);
}
Here my function :
def write_varint(array, data):
first_pass = True
while data != 0 or first_pass:
first_pass = False
temp = (data & 0b01111111)
data >>= 7
if data != 0:
temp |= 0b10000000
print(temp)
write_byte(array, temp)
def write_byte(array, data):
write_bytes(array, struct.pack('>b', data))
def write_bytes(array, source_bytes):
for byte in source_bytes:
array.append(byte)
if data != 0:
temp |= 0b10000000
When data value is -1 this conditional does not get called and therefore temp ends up out of range of the needed [-128, 127], and wounds up crashing when struct.pack() function gets called (which requires a number within that range).

printing out or returning strings between brackets

I'm trying to write a function in similar manner as started, so that I will get what it's doing. I'm assuming this can be done with one line of code, with some fancy functions, but for the sake of practice and understanding I'm trying to come up with similar solution.
The task is the following: the function takes a text once it encounters enclosed square brackets [ word ] It should print out or return all words which are between square brackets. For example, if the text string would be "[a]n example[ string]", you are expected to print out "a string".
def string():
text = "some random text [and I need this bit of txt] but I don't know how to continue [to get this bit as well]"
for i in text:
for j in range(len(text)):
if text[j] == '[':
new = text.find(']')
return(text[j+1:new])
print(string())
Try this:
def extract(text, skip_chars=("\n", )):
output = ""
flag = False
for c in text:
if c == "]":
flag = False
if flag and not c in skip_chars:
output += c
if c == "[":
flag = True
return output
print(extract("""[a]n example[
stri
ng]"""))
# -> "a string"
def string():
result = []
text = "some random text [and I need this bit of txt] but I don't know how to continue [to get this bit as well]"
for i in text:
if i == '[':
new = text.find(']')
result.append(text[text.index(i) + 1:new])
return " ".join(result)
print(string())
def parse(source):
i = source.index("[") # throw an exception
result = ""
while i < len(source):
if s[i] == "[":
i += 1
while i < len(source):
temp = ""
if source[i] == "]":
result += temp
break;
temp += source[i]
i += 1
i += 1
return result

C++ equivalent of python's expandtabs() function?

I need to implement the C++ equivalent of the expandtabs() function. Can someone help me with converting this code to C++?
def expandtabs(string, n):
result = ""
pos = 0
for char in string:
if char == "\t":
# instead of the tab character, append the
# number of spaces to the next tab stop
char = " " * (n - pos % n)
pos = 0
elif char == "\n":
pos = 0
else:
pos += 1
result += char
return result
This is what I have:
std::string ExpandTabs(const std::string &str, int tabsize =4){
std::string ReturnString = str;
std::string result = " ";
int pos = 0;
for(std::string::size_type i = 0; i < ReturnString.size(); ++i) {
if (ReturnString[i] == '\t'){
int spaces = tabsize - pos % tabsize ;
ReturnString.append(" ", spaces);
pos = 0;
}
else{
pos+=1;
}
}
return ReturnString;
You need to build up the string character by character. Currently you assign str to ReturnString at the start of the function and then append whatever spaces you decide are necessary to the end of the string, instead of in place of the tabs.
There are no doubt more idiomatic ways to achieve the same result, but a like for like conversion of the python might look like.
#include <iostream>
#include <string>
std::string expand_tabs(const std::string &str, int tabsize=4)
{
std::string result = "";
int pos = 0;
for(char c: str)
{
if(c == '\t')
{
// append the spaces here.
result.append(tabsize - pos % tabsize, ' ');
pos = 0;
} else
{
result += c;
pos = (c == '\n') ? 0: pos + 1;
}
}
return result;
}
int main()
{
std::cout << expand_tabs("i\tam\ta\tstring\twith\ttabs") << '\n';
std::cout << expand_tabs("1\t2\t3\t4", 2) << '\n';
}
It basically steps through the input forwarding on any non tab characters to the result string, otherwise it adds the correct number of spaces to the result.
Output:
i am a string with tabs
1 2 3 4
A straight translation of the python code is problematic, since char cannot be both a string and a single character, but apart from that it's straightforward:
std::string expandtabs(std::string const&str, std::string::size_type tabsize=8)
{
std::string result;
std::string::size_type pos = 0
result.reserve(str.size()); // avoid re-allocations in case there are no tabs
for(c : str)
switch(c) {
default:
result += c;
++pos;
break;
case '\n':
result += c;
pos = 0;
break;
case '\t':
result.append(tabsize - pos % tabsize,' ');
pos = 0;
}
return result
}

Python - Ported AS2 function doesn't work

This game uses this encryption to stop people from being able to connect bots easily the function used by the game is:
function djinndecrypt(string, key) {
var crypt = "";
var part = "";
var parts = 0;
var keyGen = key.length;
for(var i = 0; i < string.length; i++) {
var char = string.charAt(i);
var chrNum = string.charCodeAt(i);
var keyChr = key.charAt(parts % key.length);
var keyNum = key.charCodeAt(parts % key.length);
part += char;
if((i+1) % 3 == 0 && i > 0) {
crypt += String.fromCharCode((coreHash.indexOf(part)+2) - keyNum - keyGen);
part = "";
parts++;
}
}
return crypt;
I have attempted to port this to python my code is:
coreHash = "4Qiqc3mpjw2jFLJBaV9ANsWoYDR8ktvZIMeJTfOd1lyH5P7XKxhU6rCbzuE10nS5Ks7rPj1YvnDlbX4m2jI0NkyOL3hHU6FRVduJJoCwfWiABzqSaETMet1pZ89xQc81ieHA0F5EuNnWCwJvMJLQhV3UxPYRB76pbfIy2dcoaT14XkqlZsSzj9KDtrmjO9fjdMPERB12TYzDJrNxc3QajKU0kbvu4F56yHAXWO7tlwni8mZqCSosLVIehJ1pzT1kEsSXAl1O45CdLnRwQeM06ZqxJfJayBN8FWj2prYjuKIhiHU7VbomDPvct935yULcOHNJZsa31DeSlmnPBxJkYbTdAFRotIizv2VpXuf9w0KqQ8Ehjr4MW7Cj164Y1ukWxp9EjOwDPF8rsX5vlZN7QJqfteCATKncUoLVaM16Shy";
def djinndecrypt(string, key):
crypt = ""
part = ""
parts = 0;
keyGen = len(key)
for i in xrange(len(string)):
char = string[i]
chrNum = ord(char)
keyChr = key[parts % len(key)]
keyNum = ord(keyChr)
part += char
if((i + 1) % 3 == 0 and i > 0):
crypt += chr((coreHash.find(part) + 2) - keyNum - keyGen)
part = ""
parts += 1
print crypt
djinndecrypt("zQDHzljoHM6RhuhuhWzQDA5dgOAzQDlbAqkgOA57mM", "69338277581336797325449966279465")
The code ends up raising an exception:
ValueError: chr() arg not in range(256)
chr() only accepts up to 255 as described by the error. You can get more distance using unichr() but that returns Unicode characters instead of ACSII like chr().
However, given that this is supposed to result in an English string, the problem appears to be in the coreHash, as results above 122 [ chr(122) is 'z' ] will be out of alphabetical range.

Idiomatic way to port C bitfiddling to Python

How would you port the following C code in a Pythonic way (especially the bit fiddling part in Get2, Get3, ...)
switch(mem[pos-1])
{
...
case 0x10: pos+=Get2(&mem[pos+0x02])+0x04; break;
case 0x11: pos+=Get3(&mem[pos+0x0F])+0x12; break;
case 0x16: pos+=Get4(&mem[pos+0x00])+0x04; break;
...
case 0x20: pos+=0x02; break;
}
...
//////////////////////////////////////////////////////////
// Conversion routines to fetch bytes in Big Endian order
//////////////////////////////////////////////////////////
unsigned int Get2(unsigned char *pointer)
{
return (pointer[0] | (pointer[1]<<8));
}
unsigned int Get3(unsigned char *pointer)
{
return (pointer[0] | (pointer[1]<<8) | (pointer[2]<<16));
}
unsigned int Get4(unsigned char *pointer)
{
return (pointer[0] | (pointer[1]<<8) | (pointer[2]<<16) | (pointer[3]<<24));
}
This is what I've got so far:
x = struct.unpack('B', mem[pos-1])[0]
if x == 0x10:
# pos += ???
continue
if x == 0x11:
# pos += ???
continue
if x == 0x16:
# pos += ???
continue
if x == 0x20:
pos += 0x02
continue
If you're just getting one unsigned byte, just do
x = ord(mem[pos - 1])
on Python 2 or
x = mem[pos - 1]
on Python 3.
Instead of select / case, You want a dictionary.
positions = {0x10: do_10, 0x11: do_12, 0x16: do_16}
Where do_10 etc. are functions:
def do_10(pos):
# This actually would need an endianness character
return struct.unpack('H', mem[pos + 0x02])[0] + 0x04
You use it like this:
pos += positions[mem[pos - 1]](pos)
If you want to define the functions right in the dictionary, you can:
positions = {
# This actually would need an endianness character
0x10: (lambda pos: struct.unpack('H', mem[pos + 0x02])[0] + 0x04)
# ...
}
This is a guess, but based on your code, I think this is what you're looking for:
x = struct.unpack('B', mem[pos-1])[0]
if x == 0x10:
pos += 0x04 + struct.unpack('>h' mem[pos+0x04])
elif x == 0x11:
pos += 0x12 + (0x00FFFFFF & struct.unpack('>i' mem[pos+0x0F]))
elif x == 0x16:
pos += 0x04 + struct.unpack('>i' mem[pos])
elif x == 0x20:
pos += 0x02
Your four bit-fiddlers could almost transliterated in python
def bigstr_to_int2(str) :
return (ord(str[0])<<8) | ord(str[1])
Seems to work, but is perhaps not "idiomatic". Ideally, you should try to use the struct.unpack to do the whole thing in bulk, but I can't tell you how to do that, because I don't understand the main function up the top.

Categories