Laden...
Avatar #avatar-2617.png
Benutzerbeschreibung

Forenbeiträge von zommi Ingesamt 1.361 Beiträge

12.10.2015 - 14:10 Uhr

Ich kann Git eigentlich nur empfehlen. (wobei Mercurial auch gut funktioniert)

Beides kann man gratis, auch in Teams, für private Projekte auf Bitbucket hosten.

Als hilfreiches GUI-Tool hat sich bei mir SourceTree bewährt.

Wie bereits beschrieben, ist Git ein sehr mächtiges System, aber man muss ja nicht alles nutzen 😉 Für manche Mini-Projekte nutze ich auch keinerlei Branches und arbeite nur allein daran.

Dennoch ist es hilfreicht, nicht einen Stand zippen zu müssen um ihn zu archivieren. Auch kann ich jederzeit von überall wo ich Interesse daran hab, kurz in meinen Repos browsen. Ich muss nicht über Sicherungskopien nachdenken. Ich kann in den Commit-Messages bestimmte wichtige Dinge für mich selbst hinterlegen. Auch hilfreich ist, dass klar ist, welche Dinge wichtig in einem Projekt sind (die sind nämlich im Versionsverwaltungssystem verfügbar) und was nur Test/Example/QuickHack/Temp-Files sind, die man auch einfacher und ohne Angst entfernen lassen kann.

So oder so, klare Empfehlung: Git. Falls es kompliziert aussieht, sieh es als Weiterbildung 😉
Hilfreich: Git Book

Beste Grüße
Thomas

22.09.2015 - 11:49 Uhr

Hi Yedigun,

das Problem ist, dass der Regex wirklich überall matcht. Hier ein Beispiel für Fall (c):


Group[0] = "\\10.249.161.2\E" // (.*)
Group[1] = "" // (?!duNicht)
Group[2] = "rwin\x.54.5\duNicht\Franz\ghi.zip" // (.*)\.zip*$

Übrigens akzeptierst du auch die Endungen .zi, .zip, .zipp, zippp, zippp (wahrscheinlich nicht gewollt 😉 ).

Du musst es andersherum aufziehen. Erstelle einen Regex, der matcht, wenn es ein ungültiger Pfad ist!

Im übrigen kannst du auch ohne Regex vorankommen:


string[] directories = mypath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
bool valid = ! Array.Exists(directories, dir => dir == "duNicht");

beste Grüße
zommi

15.09.2015 - 23:19 Uhr

Um weitere Neuankömmlinge zusätzlich off-topic zu verwirren: Nonzero-Based Arrays sind auch in .NET spezifiziert und in C# erlaubt. Sie sind nur nicht CLS-konform, da nicht alle .NET Sprachen mit ihnen umgehen können. Zudem bietet C# selbst keine eigene Syntax dafür, aber über Array.CreateInstance ist so einiges möglich 😉

beste Grüße
zommi

24.06.2015 - 20:53 Uhr

Das kannst du mit Regex Groups and Captures lösen.
Schau dir mal das zweite Beispiel zu Group.Captures an.

Ein möglicher Regex wäre beispielsweise:

(?<value>\w+)(?:§~(?<value>\w+))*

Und dann beispielsweise auf Wert an dritter Stelle (Index 2):

myregex.Match(...).Groups["value"].Captures[2].Value

beste Grüße
zommi

23.06.2015 - 21:23 Uhr

Hey Quaneu,

da long = System.Int64 ist und System.Int64.MaxValue = 9,223,372,036,854,775,807 ist, kannst du Dateien mit über 8 Millionen Terabyte ansprechen.

Vielleicht hast du C#'s long mit C++'s long verwechselt, welcher auf den meisten Plattformen ein int32_t ist.

Beste Grüße
zommi

23.06.2015 - 12:53 Uhr

Eigentlich sollte so etwas einwandfrei funktionieren.

Allerdings matchen .NET Regexe direkt Unicode Codepoints und ignorieren alternative Darstellungen. Das Problem ist beispielsweise, dass sich das deutsche Ä als zwei Varianten kodieren lässt:
*Ä (U+00C4) (Latin capital letter A with diaeresis) *A (U+0041,U+0308 ) (Latin capital letter A + Combining Diaresis)

Die sehen zwar gleich aus, aber ein Regex mit dem einen findet den anderen nicht - und umgekehrt.

Die Thematik wird bei Unicode Normalization gut beschrieben und String.Normalize(...) hilft dir dabei.

beste Grüße
zommi

//PS: Interessanterweise ignoriert das Forum hier nach dem posten das zusammengesetze Unicodezeichen und zeigt nur noch ein "A" an. 🤔

23.06.2015 - 12:23 Uhr

Hey,

Nibble clearen und mit neuem Wert verodern:


var clearmask = ~(0xF << nibblePos);
value = (value && clearmask) || (nibble << nibblePos);

beste Grüße
zommi

09.06.2015 - 17:26 Uhr

CreateFile "ist" kein Sector-Copy sondern ein File-Copy; jedenfalls in dem Sinne, was ich unter einem Sector verstehe.

Die WinAPI möchte aber den Begriff "File" allgemeiner verstanden wissen, bisweilen so allgemein, dass er meines Erachtens auch "Sector" in deinem Sinne umfassen sollte.

Zitat von: msdn (CreateFile)
CreateFile was originally developed specifically for file interaction but has since been expanded and enhanced to include most other types of I/O devices and mechanisms available to Windows developers. [...] However, some uses of file may be referring more generally to an I/O object that supports file-like mechanisms. This liberal use of the term file is particularly prevalent in constant names and parameter names because of the previously mentioned historical reasons.

Gibt es denn eine andere API für sector-access in deinem Sinne?

beste Grüße
zommi

09.06.2015 - 11:16 Uhr

Hey nali,

du musst unterscheiden zwischen "E:&quot; und "\.\E:".
Das eine ist das Root-Verzeichnis auf der Partition E:, das andere ist die physische Diskpartition E: selbst.

Generell wenn du ein Verzeichnis mit CreateFile öffnen möchtest, musst du FILE_FLAG_BACKUP_SEMANTICS setzen, wofür du zusätzlich noch ein zwei Privilegien (SE_BACKUP_NAME + SE_RESTORE_NAME) benötigst.

Aber eigentlich willst du das ja garnicht, also kommentier dein "\.&quot;-Präfix wieder ein, und beachte die Hinweise zu CreateFile:

The dwCreationDisposition parameter must have the OPEN_EXISTINGflag.
When opening a volume or floppy disk, the dwShareMode parameter must have the FILE_SHARE_WRITEflag.

Beachte zusätzlich, dass eventuell ein Stream.Seek nur mit festen Sektoren-Größen funktioniert.

Das CharSet sollte egal sein, solange du nicht ExactSpelling bewusst auf die falsche Version von CreateFileA/W setzt. Es wird automatisch die richtige Methode aufgerufen.
Und nach meinen Tests (Win7) unterstützten CreateFileA und CreateFileW beide UNC-Pfade, auch wenn die Ansi-Variante noch immer auf MAX_PATH begrenzt ist.

PS: CreateFile ist nicht für Sector-Copy geeignet, falls das Dein eigentliches Ziel ist.

@Abt, hattest du damit Probleme?

beste Grüße
zommi

02.06.2015 - 15:05 Uhr

Hi Bloggeroli,

Meiner Meinung nach ist bei dir (wie bei vielerlei Verschlüsselungstechniken) das Hauptproblem der Schlüsselaustausch.

Wenn du öffentliche Schlüssel austauschen möchtest, brauchst du eine Public-Key-Infrastruktur, oder kurz: irgendeine Trusted Party.

Ich sehe bei deinem Konzept für einen Chatteilnehmer niemanden, der trusted wäre.
Weder das Gegenüber kenne ich vorher, noch bietet dein Server eine authentifizierte Kommunikation. Du nutzt überall nur selbst-signierte Zertifikate, mit all offenen Problemen für beliebige Man-in-the-Middle Angriffe.

Das kannst du nur verhindern, indem du bestehende PKIs nutzt, sei es SSL-CAs oder Alternativen.

Aber so kann ich einfach jeglichen Verkehr vom Client zu deinem Chatserver über mich leiten, MITM spielen und jegliche Verschlüsselung untergraben.

beste Grüße
zommi

08.05.2015 - 14:49 Uhr

Mit der einfachste Weg aus HTML Seiten gezielt etwas rauszufummeln ist sicherlich über CSS-Selektoren. XPATH kann manchmal etwas klobig sein.
Zudem ist nicht jedes HTML hunderprozentig ein wohlgeformtes XML, was die Verwendung von XML-Technologien manchmal schwierig macht.
Ein Tipp: CsQuery.

beste Grüße
zommi

05.05.2015 - 14:47 Uhr

Hi UZI,

FZelle hat Recht, du verwendest ein unterschiedliches Encoding in beiden Snippets.

Da bei Python dem Aufruf von "bytearray()" kein Encoding mitgegeben wurde, muss hier das 1-Byte Encoding zum Zuge kommen.

Bei .NET kommt durch Verwendung von ToCharArray und dem BlockCopy aber ein 2-Byte encoding zustande.

Du musst also explizit über die Encoding-Funktionen sicherstellen, dass du auch 1 Byte pro Character nutzt, beispielsweise mit dem ASCII-Encoding:

    
static byte[] GetBytes(string str)
{
    return Encoding.ASCII.GetBytes(str);
}

Dann kommt auch exakt das selbe heraus.
beste Grüße
zommi

21.04.2015 - 13:34 Uhr

Bei bearbeiten würde aber eine etwaige Signatur ungültig werden.
Insofern kann man sich davor schützen.

Darauf vertrauende Programmteile müssten aber auch die Signatur überprüfen, Strong Names wäre das Stichwort.

beste Grüße
zommi

02.04.2015 - 23:10 Uhr

Hi TheBraniac,

freut mich, dass du eine Lösung hast implementieren können.

Dennoch mein Tipp: Schau dir nochmal die Google or-tools an.

Damit wird dein Code viel viel viel viel eleganter 😉

Denn der C#-Wrapper spricht nicht nur unterschiedliche Solver-Backends an (darunter GLPK), sondern bietet gleichzeitig auch eine schöne "Natural API".

Hier mal der Link zu deren Beispiel-Code: csintegerprogramming.cs.

beste Grüße
zommi

31.03.2015 - 13:15 Uhr

Hey,
ich habe mal ein echtes, funktionsfähiges Beispiel formuliert.
Ich habe 25 Studenten, 5 Kurse und Erst- sowie Zweitwünsche mit Strafpunkten (1, 10, 100).

Die Datei course.lp beschreibt das Problem nach oben erklärter Weise im LP-Format.

Hat man nun beispielsweise GLPK installiert, kann man wie folgt das Problem lösen lassen:

[pre]glpsol --lp course.lp -o course.sol[/pre]

Heraus kommt dann die course.sol, in der man die Belegung der Variablen, also die Zuweisung der Studenten zu den Kursen, ablesen kann. Beispielsweise sieht man, dass es keine Lösung gibt, die alle Studenten zufrieden stellt, zwei bekommen nur ihren Zweitwunsch.

Um zu zeigen, dass man auch programmatisch mit den Solvern sprechen kann, habe ich noch ein Programm geschreiben, was selbes Problem löst. Da ich das noch nie mit C# versucht habe, anbei nur ein Python-Programm, welches das PuLP-Framework als Frontend zu den Solvern nutzt: course.py.

Bestenfalls sollte sich etwas Vergleichbares mit C# genauso umsetzen lassen.
beste Grüße
zommi

31.03.2015 - 11:44 Uhr

Hallo Braniac,

der Zweig der Mathmatik/Informatik diesbezüglich heißt "Kombinatorische Optimierung".
Dafür modelliert man sein Problem oftmals mittels Ganzzahlig Linearer Programmierung (Integer Linear Programming).

Im Grunde stellst du dein Problem einfach durch ein paar Ungleichungen dar und eine Zielfunktion - alles linear.

Vorteil ist, dass es zum Lösen dieser Probleme schon extrem weit entwickelte Verfahren gibt!
Wie jaensen erwähnt hat, ist ein bekannter Solver der optaplanner. Andere sind IBM's ILOG CPLEX, Gurobi's Optimizer oder Open source Varianten wie das GNU Linear Programming Kit, lp_solve, coin-or CBC, Google's or-tools, ...

Die kommerziellen Tools kosten zumeist einige Tausend Euros, sind dafür aber noch flotter, Aber dir reicht sicherlich eine freie Variante. Es gibt auch noch die Microsoft Solver Foundation, habe aber gelesen, dass es wohl nicht mehr weiterentwickelt wird. Aber auch lp_solve hat C#-Wrapper und Google's or-tools bringen auch C# Schnittstellen zu GLPK und CBC mit.

Kommen wir nun mal zum Inhaltlichen, anhand eines Beispiels mit 4 Kursen, 20 Leuten, Erst- und Zweitwünschen.

Wir definieren hierfür 80 (20*4) binäre Variablen bA,Xdie jeweils mit 0/1 dafür stehen, ob nun Person A dem Kurs X zugewiesen wurde.
Wenn also "Klaus" dem Kurs "Optimierung" zugewiesen würde, wäre

[TT]b[SUB][Klaus],[Optimierung][/SUB]=1
b[SUB][Klaus],[Grundlagen] [/SUB]=0
b[SUB][Klaus],[Algorithmen][/SUB]=0
...[/TT]

Aber zurück zur Problem-Modellierung. Alle Randbedingungen müssen wir nun als lineare (Un-)Gleichungen beschreiben.
1.Jede Person wird genau einem Kurs (Optimierung, Grundlagen, Algorithmen, C#) zugewiesen:

[TT]b[SUB][Klaus],[Optimierung][/SUB] + b[SUB][Klaus],[Grundlagen][/SUB] + b[SUB][Klaus],[Algorithmen][/SUB] + b[SUB][Klaus],[C#][/SUB] = 1

b[SUB][Alice],[Optimierung][/SUB] + b[SUB][Alice],[Grundlagen][/SUB] + b[SUB][Alice],[Algorithmen][/SUB] + b[SUB][Alice],[C#][/SUB] = 1

...[/TT]

1.Die Kurse haben Kapazitäten (mindestens 3, maximal 9)

[TT]b[SUB][Klaus],[Optimierung][/SUB] + b[SUB][Alice],[Optimierung][/SUB] + b[SUB][Bernd],[Optimierung][/SUB] + ...  > 2
b[SUB][Klaus],[Optimierung][/SUB] + b[SUB][Alice],[Optimierung][/SUB] + b[SUB][Bernd],[Optimierung][/SUB] + ... < 10

b[SUB][Klaus],[Grundlagen][/SUB] + b[SUB][Alice],[Grundlagen][/SUB] + b[SUB][Bernd],[Grundlagen][/SUB] + ... > 2
b[SUB][Klaus],[Grundlagen][/SUB] + b[SUB][Alice],[Grundlagen][/SUB] + b[SUB][Bernd],[Grundlagen][/SUB] + ... < 10

...[/TT]

Und als Zielfunktion definieren wir eine lineare Größe, die es zu minimieren gilt. Und zwar so, dass es umso kleiner wird, je öfter der Erstwunsch oder Zweitwunsch zugewiesen wird. Wir vergeben also "Strafpunkte". Für einen erfüllten Erstwunsch gibt es einen Strafpunkt, für einen erfüllten Zweitwunsch gibt es 10 Strafpunkte und wenn etwas anderes zugewiesen werden muss, gibt es 100 Strafpunkte.

Im Beispiel hat Klaus als Erst- und Zweitwunsch (Optimierung, Grundlagen), Alice hat (C#, Optimierung), Bernd hat (Algorithmen, Grundlagen).

Das ergibt nun folgende Zielfunktion, die alle 80 Variablen umfasst:

[TT]
Minimize: 

001 * b[SUB][Klaus],[Optimierung][/SUB] + 010 * b[SUB][Klaus],[Grundlagen][/SUB] + 100 * b[SUB][Klaus],[Algorithmen][/SUB] + 100 * b[SUB][Klaus],[C#][/SUB] + 
010 * b[SUB][Alice],[Optimierung][/SUB] + 100 * b[SUB][Alice],[Grundlagen][/SUB] + 100 * b[SUB][Alice],[Algorithmen][/SUB] + 001 * b[SUB][Alice],[C#][/SUB] + 
100 * b[SUB][Bernd],[Optimierung][/SUB] + 010 * b[SUB][Bernd],[Grundlagen][/SUB] + 001 * b[SUB][Bernd],[Algorithmen][/SUB] + 100 * b[SUB][Bernd],[C#][/SUB] + 
...[/TT]

Insgesamt hast du also 80 Variablen, eine Zielfunktion und 28 (Un-)Gleichungen. Das steckst du in einen Solver und heraus kommt eine Belegung deiner Variablen, bei der das Ziel möglichst minimal ist.
Natürlich kannst du noch weitere Bedingungen einbauen, die Strafpunkte anders bemessen, Dritt- und Viertwünschen einführen, etc... Das Modell ist wunderbar erweiterbar.
Das Prinzip konnte ich aber hoffentlich rüberbringen.

Das schöne an ILP (Integer Linear Programming), wenn man einmal das Grundlegende Konzept verstanden hat, kann man irrsinnig viele Optimierungs-Probleme mit geringem Aufwand so darstellen und vor allem Lösen lassen!

Als Schnittstelle zu den Solvern bietet sich an:*Das Problem als Datei generieren in einem der Formate LP, AMPL, ... und den Solver als Unterprozess starten. *Das Problem über einen Wrapper direkt an den Solver als Komponente übergeben.

Vielleicht sieht das jetzt kompliziert aus, aber glaub mir, es ist eigentlich total einfach 😃

beste Grüße
zommi

03.03.2015 - 09:21 Uhr

^                       Zeilenanfang  

(.*ToLower\(\).*)       Irgendwas wo "ToLower()" drin vorkommt

(==|!=)                 == oder !=

\WTables                Whitespace + "Tables"

(.(?!ToLower\(\)))*     Irgendein Zeichen, das nicht direkt von "ToLower()" gefolgt wird - beliebig oft
                        (aka Irgendwas wo "ToLower()" nicht drin vorkommt)

$                       Zeilenende

beste Grüße
zommi

02.03.2015 - 17:39 Uhr

Dann kombiniere doch das .* mit dem !ToLower\(\):

^(.*ToLower\(\).*)(==|!=)\WTables(.(?!ToLower\(\)))*$

Wobei ab irgendwann ein einfaches String.Split bei == bzw. != mit anschließendem Contains(...) für "ToLower()" und "Tables" auf beiden Seiten sicherlich lesbarer ist.

beste Grüße
zommi

02.03.2015 - 15:18 Uhr

Hi Rabenschwinge,

wie wäre es mit einem Matching aufs Zeilenende mit Negative Lookbehind?

^(.*ToLower\(\).*)(==|!=)(.*Tables.*)(?<!ToLower\(\))$

zusammen mit RegexOptions.Multiline.

beste Grüße
zommi

19.02.2015 - 15:22 Uhr
[pre]findstr /spin /c:"foobar" *.csv[/pre]

beste Grüße
zommi

09.02.2015 - 17:52 Uhr

Hi Maniac,

dein Datenformat sieht doch halbwegs strukturiert aus.
Ich glaube, dass es besser wäre, es direkt zu parsen. Hier im Forum findest du auch einige Beiträge zu Parsern.

Das Format selbst kenne ich nicht, aber vielleicht gibt es sogar schon etwas fertiges?!

Was mir neben einem eigenen Parser oder mühsamen Regexes noch einfallen würde, wäre ein generischer Konverter, der das Format in beispielsweise JSON umwandelnt und es dann parsed. Da sich die Formate etwas ähneln, kann man mit einfachen Ersetzungen ans Ziel kommen.

Da ich momentan kein C# zur Hand habe, skizziere ich das mal kurz mit einem Python Programm.

import re
import json

text = open("stuff.txt").read()

# convert to uppercase
text = text.upper()

# wrap entire blocks into parenthesis
# wrap doc in paranthesis
text = "(" + text + ")"
# put in empty, separating lines )(
text = re.sub(r"$[\t ]*^", ")(", text, flags=re.MULTILINE)

# replace = with :
text = re.sub(r"\s*=", ":", text)

# enquote identifiers
text = re.sub(r"([\w\-_\.]+)", '"\\1"', text)

# replace close-open )( by comma
text = re.sub(r"\)\s*\(", ", ", text)

# replace ( by {
text = re.sub(r"\(", "{", text)

# replace ) by }
text = re.sub(r"\)", "}", text)

data = json.loads(text)

for interface, settings in data.items():
    address = settings['DESCRIPTION']['ADDRESS_LIST']['ADDRESS']
    host, port = address['HOST'], address['PORT']
    print "{0} ({1}:{2})".format(interface, host, port)

Beste Grüße
zommi

08.02.2015 - 08:56 Uhr

Hey Biggie,

hier bietet sich die Inversionszahl an. Die Anzahl der Inversionen zwischen deiner Ziel-Folge und deiner Test-Folge.

Das Ergebnis kannst du freilich auf 0-1 normieren.

Zur Berechnung werden meist abgewandelte Sortier-Verfahren verwendet.

beste Grüße
zommi

10.01.2015 - 22:52 Uhr

Let's try

static int RomToInt(char[] x) {
  int last=0, result=0;
  for (int i=x.Length-1; i>=0; i--) {
    if (!"IVXLCDM".Contains(x[i].ToString()))
      throw new System.ArgumentException();
    int current = (int)((x[i]\*(x[i]\*(x[i]\*(x[i]\*(x[i]\*(134149L*x[i]-61251763)+11624806957)-1173838830541)+66515437336342)-2005476756276328)+25136183219933184)/5896800);
    last = System.Math.Abs(-result + (result += current*(current<last?-1:+1)));
  }
  return result;
}

//Edit: hier noch eine etwas weniger obfuskierte Variante:

static int RomToInt(char[] x) {
  int last=0, result=0;
  for (int i=x.Length-1; i>=0; i--) {
    char c = x[i];
    if (!"IVXLCDM".Contains(c.ToString()))
      throw new System.ArgumentException();
    int current = (c=='M'?1000:c=='D'?500:c=='C'?100:c=='L'?50:c=='X'?10:c=='V'?5:1);
    result += current * (current<last ? -1 : +1);
    last = current;
  }
  return result;
}

beste Grüße
zommi

03.01.2015 - 00:50 Uhr

Hi Tweak,

also willst du in gerichteten Graphen nach Zyklen suchen? Dann mach das doch 😃 Geht im Grunde so ähnlich wie die topologische Sortierung, die du ja bereits erwähnt hast.

Oder wonach suchst du?

beste Grüße
zommi

10.12.2014 - 11:43 Uhr

Unter neueren Windows (meines Wissens > XP 64bit) gehts auch über die Shell:

echo "Hallo Welt" | clip

Sollte sich sehr leicht in AutoIt einbinden lassen.

beste Grüße
zommi

01.12.2014 - 17:21 Uhr

Hi Slaughter,

Anscheinend hast du in deinem Code schon die Möglichkeit unterschiedliche Versionen dieser Library gleichzeitig zu nutzen.

Machst du das über extern alias?

Wenn ja, dann sollte dein einziges Problem am Ende nur noch sein, dass die Bibliotheken vom Dateinamen her gleich heißen ("wasAuchImmer.dll"), du aber hiervon zwei Versionen mitliefern willst.
Du kann abhängig von der Version über die app.config auf verschiedene Pfade verweisen: Multiple Assemblies with the Same Name

<?xml version="1.0"?>
<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="wasAuchImmer" /> 
            <codeBase version="1.0.0.0" href="lib/v1/wasAuchImmer.dll"/>
            <codeBase version="2.0.0.0" href="lib/v2/wasAuchImmer.dll"/>
        </dependentAssembly>
      </assemblyBinding>   
   </runtime>
</configuration>

beste Grüße
zommi

01.12.2014 - 14:34 Uhr

In wie fern wäre in dem simplem Fall minimalcode notwendig?

Um zu verstehen, was passiert. Wie du selbst siehst, passiert etwas unerwartetes. So simpel ist es also nicht.

Daher wäre ein minimales, vollständiges, kompilierbares Beispiel super hilfreich.

Ich habe versucht, selbst eins zu erstellen, schaffe es aber nicht dein Problem zu reproduzieren:

using System;
using System.Collections.Generic;

namespace Rextester {

class Tree
{
    private Node _tree;

    public Tree(Node tree)
    {
        this._tree = tree;
    }

    public void PrintNextIndex()
    {
        var nextIndex = this.GetNextIndex(this._tree) + 1;
        Console.WriteLine(nextIndex);
    }

    private int GetNextIndex(Node node, Int32 iCurrentMax = -1)
    {
         int iIndex = iCurrentMax >= 0 ? iCurrentMax : 0;

         if (node.Index > iIndex)
             iIndex = node.Index;

         if (node.Nodes.Count > 0)
         {
             foreach (Node child in node.Nodes)
             {
                  iIndex = this.GetNextIndex(child, iIndex);
             }
         }

         return iIndex;
    }

}

class Node
{
    public int Index {get; set;}
    public List<Node> Nodes {get; set;}
}

public class Program
{
    static Node N(int index, params Node[] nodes)
    {
        return new Node{Index=index, Nodes=new List<Node>(nodes)};
    }

    public static void Main(System.String[] args)
    {
        var tree = new Tree(N(1,
                                N(2,
                                    N(3),
                                    N(4),
                                    N(6),
                                    N(9)),
                                N(5,
                                    N(8)),
                                N(7)));
        tree.PrintNextIndex();
    }
}

}

Kannst du das Problem in einem solch minimalen Snippet reproduzierbar machen?

Zudem verwürfelst du oft "GetNextIndex" mit "GetMaxIndex" in deinen Beschreibungen. Rufen sich diese beiden Methoden eventuell gegenseitig rekursiv auf? Das würde irgendwie erklären, warum ein +1 in der einen auch ein +1 in der anderen entspricht - jedoch nicht das unterschiedliche Klammerverhalten.

beste Grüße
zommi

28.11.2014 - 15:02 Uhr

Hey,

Für das Umdrehen gibt es Array.Reverse. Es gibt sogar eine Variante, wo man inline nur einen Teil eines Array umdrehen kann. Das wäre für dich perfekt. Für strings direkt gibt es keine solche Hilfsmethoden. Daher am besten zu Beginn einmal in ein Char-Array umwandeln, alles umdrehen in den Blöcken und am Ende wieder zu einem String umwandeln:

string text = "123456";
int chunkSize = 2;        

char[] chars = text.ToCharArray();
for (int i=0; i<chars.Length; i+=chunkSize)
{
    Array.Reverse(chars, i, Math.Min(chunkSize, chars.Length - i));
}
string result = new String(chars);

System.Console.WriteLine(result);

beste Grüße
zommi

28.11.2014 - 10:41 Uhr

Hey,

nunja, in dem SO-Thread werden mehrere Lösungen skizziert.
*Datum des letzten Schreibzugriffs auf die Datei *Zurückrechnen aus den automatisch zugewiesenen Build/Revision-Nummern der Assmembly *Den Zeitstempel des Linkers aus dem Header des Executables auslesen

Wobei die erste Variante nicht immer funktioniert.
(Datei übers Netzwerk, kopieren, aus (Zip)Archiven entpacken, etc...)

Die zweite fühlt sich wie ein Hack an.

Lediglich die dritte scheint mir ein robustes ermitteln des Link-Zeitpunkts (und damit der Compilation) zu ermöglichen.

beste Grüße
zommi

27.11.2014 - 00:24 Uhr

Hey,

Raspberry Pi ist super. 35€ für das Gerät. 10-20€ für die SD Karte, 10€ für ein Gehäuse, dazu ein WLAN-Mini-Stick für 5-10€ oder ein Surfstick und du bist im Netz.

Für schlechte Tonqualität findest du externe USB-Soundkarten für 5-10€ auf Amazon und dazu noch ein mieses Mikro für weitere 5-10€ und du kannst schonmal loswerkeln.

Wenn das dann alles funktioniert, holst du dir ne gescheihte externe Soundkarte, nen Vorverstärker und n gutes Mikro, oder vielleicht auch direkt ein USB-Mikrophone mit integrierten AD-Wandler. (Nur so als Beispiel: AT2020 USB)

Mono auf dem Raspberry zum laufen zu bekommen ist nicht ganz trivial.
Echte Unterstützung der Mono-Runtime für die spezielle ARM-Hardware gibts erst seit Mono 3.2.irgendwas und momentan ist 3.10.0 aktuell. Allerdings haben die gängigen RapsberryPi-Distros nicht die passende Version im Paket-Repo. Daher heißt es höchst wahrscheinlich: Mono-Quellen auschecken und selber kompilieren.

Du kannst aber auch auf Python aufbauen. Könnte sogar noch einfacher sein, fluppt auf dem Raspberry und hat auch gute Libs zur Audio Recording, Processing und natürlich alles andere auch.

beste Grüße
zommi

//Edit:
Oder du schnappst dir n altes rumliegenden Android Smartphone (oder ersteigerst eins), kaufst dir so ein externes Mikrophon wie iRig Mic, und schreibst ne App für Android, entweder nativ oder mit Xamarin in C#.
Wie gut da die Audo Bindings sind, keine Ahnung.
Aber du hast natürlich alle Möglichkeiten der Konnektivität (und Akku und Kamera und Display und und und) gleich eingebaut

26.11.2014 - 23:36 Uhr

Hey Marwyc,

schau mal hier auf Stackoverflow:
Displaying the build date.

Das Build-Datum versteckt sich im Header deines Executables.

beste Grüße
zommi

26.11.2014 - 22:25 Uhr

Hey,

Lookarounds nützen allerdings nichts, wenn sich mehrere Teile, die im Ergebnis enthalten sein sollen, mit Teilen abwechseln, die nicht enthalten sein sollen.

🤔 Also wenn ich dich richtig verstehe, nutzt du lieber die Methode Match und iterierst nachfolgend über die CaptureCollection einer Group.

Nunja, ich habe es lieber, wenn mein Regex bereits genau das zurückliefert, woran ich interessiert bin, und nicht in einer Group gekapselt ist.
Zudem kann ich dann von außen Steuern, wie oft ich Matchen möchte... vielleicht reicht ja drei mal. Oder ich will alle, dafür gibt es ja die Methode Matches und iteriere direkt über die MatchCollection.

Bei mir klappt mein RegEx jedenfalls einwandfrei - bei euch nicht?
Test @ regexstorm

@Nokinger,
Das "Singleline machen" kannst du so einfach nicht tun, weil dann jedes "." auch auf newline matched. Insbesondere auch das im Lookbehind.
Er versteht also den gesamten ersten Block als "Überschrift"

[pre]
         (matcht auch mehrere Zeilen vom Mitte Zeile 5 bis Ende Zeile 15)
              vv
(?s)(?<=ABC\s:.*[-]{50})(:question:.*?)*?(?=[-]{50})
[/pre]

Damit genau dieses ".*" eben nicht mehrere Zeilen umspannt habe ich die Zeilenumbrüche explizit eingebaut und singleline deaktiviert.

beste Grüße
zommi

26.11.2014 - 19:07 Uhr

Hey,

wenn du Header und Footer erkennen willst, aber es nicht in endgültigen Match auftauchen soll, dann bieten sich dafür positive Lookaheads/Lookbehinds an.

[pre](?<=ABC\s:.*\n[-]{50}\n)(?:.*\n)*?(?=[-]{50})[/pre]

Oder mit überall funktionierenden Line-Endings:

[pre](?<=ABC\s:.*(\n|\r|\r\n)[-]{50}(\n|\r|\r\n))(?:.*(\n|\r|\r\n)?)*?(?=[-]{50})[/pre]

beste Grüße
zommi

25.11.2014 - 13:35 Uhr

Ich weiß, dass in vielen AGBs viel drin steht, wenn der Tag lang ist. Und wenn alles wirksam wäre, was in AGBs stünde, bräuchte niemand die salvatorische Klausel 😉

Und wie "unklar" so etwas ist, zeigte beispielsweise die Rechtsdebatte um ebay-Sniper-Programme. Auch ist fraglich, wie Suchmaschinen-Crawling zu bewerten ist, oder Preisvergleichsportale.

Dass ein üblicher Browser legal und AGB-konform ist, ist sicher unzweifelhaft.
Dass wie Abt es sagt, das Abgreifen von Daten oft über AGBs untersagt wird, ebenfalls.
Ob solch ein Verbot im konkreten Fall wirksam ist, hängt wie allzu oft vom konkreten Fall und seiner Ausgestaltung ab.

Bezüglich: "Aber was ist schon Diebstahl von etwas das man nicht anfassen kann?"
Genau genommen eben kein Diebstahl, da es sich ja gerade nicht um eine "fremde bewegliche Sache" handelt 😉

Natürlich tangiert man hier Datenschutz, Urheberrecht, AGBRecht. Doch nur weil eine Thematik juristisch komplex ist, ist sie nicht pauschal "verboten".
Natürlich ist der Ratschlag "oftmals / meistens verboten" bzw. "lass es lieber" gut gemeint, aber nicht immer der beste. Ein beherztes "hängt davon ab..." ist da oftmals ehrlicher.

beste Grüße
zommi

25.11.2014 - 13:02 Uhr

Hi baer999,

Das was du vorhast, nennt sich Browser 😉 (Und im übrigen ist ein Browser legal 😉 )

Problem ist, wenn du eine Webseite möglichst so abfragen willst, wie sie auch im Browser XY läuft, dann brauchst du die Engine des Browsers XY - nicht mehr und nicht weniger.

Erstens in eine Browser Engine schon ein riesen Ding. Und Zweitens sind viel zu viele Seiten auf die handvoll Browser-Engines die es gibt optimiert. Wenn du da nun mit einer eigenen Engine ankommst, interessiet die niemanden und bei dir wird das Ergebnis ein anderes sein als in Blink, Trident, Gecko oder WebKit.

Und die "Daten" einer modernen Homepage hängen dann noch von Cookies, Policies, Browser-Spezifika, usw ab. Und nur HTTP(s) reicht in Zeiten von WebSockets auch nicht.

Wenn du glaubst, mit System.Net.Http.HttpClient und nem HTML-Parser wäre es getan ... leider falsch.

Schau mal bei Google/Stackoverflow/Forum, wie man WebEngines einbindet und anspricht. Es gibt glaube ich sogar einen .NET-Wrapper für WebKit. Aber wie aktuelle die sind... keine Ahnung.

beste Grüße
zommi

16.11.2014 - 19:03 Uhr

Hi Network_127,

früher hätte man einen Zone-Transfer auf den zugehörigen Nameservern initiieren können. Mittlerweile ist diese Funktion aber nahezu überall deaktiviert.

Ohne diese Option bleibt nur das zufällige Durch-Probieren - was in absehbarer Zeit nicht zu erhofften Ergebnissen führen wird oder aber ein Crawler, in der Hoffnung dass alle Seiten irgendwie verlinkt sind und auf jede verwiesen wird.

Natürlich musst du einen Crawler nicht selber bauen, sondern kannst zuvor gecrawltes Nutzen. Dazu gehört eben die Bing-API oder Dienste wie Hackertarget oder LogonTube. Auch beim Projekt Sonar kannst du Gigabyte große DNS-Snapshots runterladen.

Du musst aber wissen, dass Crawler natürlich immer veraltet sind und wohl nicht vollständig. Insbesondere in Zeiten wie "Darknet".

Übrigens würde selbst ein (nicht durchführbarer) Zonentransfer dir nicht 100% helfen. Denn viele Hoster nutzen Wildcard-Einträge und verweisen auf die selben IPs. Erst der Webserver selbst wird dann über Name Based Virtual Hosts die Auflösung vollenden.
Beispielsweise gibt es ja zigmillionen Tumblr-Blogs. Einem kurzen Test nach, sind dort nur zwei Wildcard-Einträge für alle Subdomains:

[pre];; ANSWER SECTION:
ich.glaube.nicht.dass.diese.domain.wirklich.existiert.w345if8wfsh856kiw.tumblr.com. 30 IN A 66.6.42.21
ich.glaube.nicht.dass.diese.domain.wirklich.existiert.w345if8wfsh856kiw.tumblr.com. 30 IN A 66.6.41.21[/pre]

Also hast du recht: eine völlig fehlerfreie Möglichkeit gibt es nicht.

beste Grüße
zommi

10.11.2014 - 00:48 Uhr

Hi scarpall,

du liest nur knapp die Hälfte aller Zeilen ein (541520 * 2 sind so gut wie 1083038), was daran liegt, dass du sowohl im Schleifenkopf als auch im Schleifenrumpf eine Zeil "wegliest". Pro Schleifendurchlauf liest du also zwei Zeilen ein und verarbeitest insbesondere aber nur jede zweite, also insgesamt nur halb so viele.

Generell empfehlenswerter sind die Methoden File.ReadLines bzw. File.ReadAllLines.

Beste Grüße,
zommi

05.11.2014 - 13:59 Uhr

Aber zu beachten ist auch, dass ver- und entschlüsseln natürlich immer länger dauert und deshalb embedded-Chipsätze oftmals nur geringere Schlüssellängen erlauben.

Key Size & Speed?:
Ein 16K RSA Key benötigt zum Signieren auf nem Celeron 500 ca. eine halbe Minute.
Niemand möchte so lange auf den Aufbau einer gesicherten HTTPS-Verbindung warten 😉

Hier sind noch andere Tabellen:

The Table from the Lenstra/Verheul research

How big should my asymmetric key be?

beste Grüße
zommi

05.11.2014 - 13:47 Uhr

512 Bit effektive Schlüsselstärke sollten eigentlich genug für jeden sein. [640 kB sollten eigentlich genug für jeden sein.] 😉

Rechnen wir mal aus, wie lange ein Cluster aus Einer Million CPUs brauchen würde, von denen jeder mit 5GHz getaktet ist und durch clevere Konstruktion 1000 Instruktionen gleichzeitig ausführen kann, "mindestens" braucht:

73 Bits (1024 Bit RSA):

2^73/ 5Ghz / (1000) / (1 million) = 31.4824432 minutes 

512 Bits (~16384 Bit RSA, oder 1024Bit ECDSA * ):

2^512/ 5Ghz / (1000) / (1 million) = 8.4975374 * 10^127 years 

Solange sich die Rechnerarchitektur nicht grundlegend ändert (Quantencomputer), brauch auch niemand effektiv mehr als 512 Bits.

  • Wobei der NIST Standard FIPS-186-4 nur Elliptische Kurven für bis zu 512 Bits vorschlägt, man müsste sich also erstmal ein passende Kurve für ECDSA mit 1024 Bits "bauen". Dessen "Güte" wäre dann aber noch nicht von einer breiten Masse akzeptiert...

beste Grüße
zommi

05.11.2014 - 13:36 Uhr

hey dr4g0n76,

ich zitiere hier auch noch einen anderen Wikipedia-Eintrag:

Zitat von: Wikipedia (Schlüssellänge und Sicherheitsniveau)
Bei asymmetrischen Verfahren („Public-Key-Methoden“) ist das Sicherheitsniveau nicht gleich der Schlüssellänge. Zum einen gibt die Schlüssellänge nicht direkt die Anzahl der möglichen Schlüssel an, da ein Schlüssel ein mathematisches Objekt beschreibt. Bei dem RSA-Kryptosystem gibt es beispielsweise für eine Schlüssellänge von 1024 Bit nicht 2^{1024} Schlüssel, da nicht jede 1024-Bit-Zahl ein RSA-Modulus, also das Produkt zweier Primzahlen, ist. Weiterhin gibt es bekannte Verfahren, die schneller sind als das Ausprobieren aller Schlüssel. Zur Bestimmung des äquivalenten Sicherheitsniveaus müssen diese Verfahren herangezogen werden. Zum Brechen einer RSA-Verschlüsselung mit einem 1024-Bit-Schlüssel braucht ein solcher Algorithmus ca. 2^{73} „elementare Operationen“, das äquivalente Sicherheitsniveau ist also 73 Bit.

Und der Berechnungsaufwand mit RSA steigt sehr stark an. So stark, dass übliche Tools nicht einmal beliebig lange Keys generieren:> Fehlermeldung:

key bits exceeds maximum 16384

Ich kenne zwar nicht das genaue Verhältnis, aber wenn 1024Bit RSA gerade mal 73Bit real entsprechen, dann entspricht ein 16384Bit RSA-Schlüssel wohl "lediglich" 1168 realen Bits.

Bei den anderen Verfahren gibt es ähnliche "Abschwächungen":

Zitat von: Wikipedia (Elliptic curve cryptography: Key Sizes)
For example, for 128-bit security one needs a curve [...][with] 2^{256} [bits]. This can be contrasted with finite-field cryptography (e.g., DSA) which requires 3072-bit public keys and 256-bit private keys, and integer factorization cryptography (e.g., RSA) which requires a 3072-bit value of n, where the private key should be just as large. However the public key may be smaller to accommodate efficient encryption, especially when processing power is limited.

Setzt man auf diese Zahlen den Dreisatz an, ergibt ein 16384Bit RSA Schlüssel sogar nur 682 Bits.
Wahrscheinlich ist die Beziehung also nicht-linear, und vielleicht sogar nur 512Bits?
Also wäre es sogar irgendwie irgendwo korrekt zu behaupten:

Es gibt [unter einem Linux wie Ubuntu] keine [RSA-basierte] Verschlüsselung mit mehr als 512 Bit [echter Schlüsselstärke]. [Sofern man nicht seine SSL-LIB mit einem Patch neu kompiliert und sich so längere Schlüssel generieren kann.]

beste Grüße
zommi

16.10.2014 - 08:54 Uhr

Nach OESIS:

a(n) is the largest k such that n can be written as sum of k consecutive positive integers.

lässt sich auch jede Zweierpotenz als Summe von einer Abfolge von Zahlen (genau einer Zahl) darstellen. Ist also kein Problem.
Prinzipiell hängt diese Darstellbarkeit von den ungeraden Teilern von N ab, die es natürlich bei Zweierpotenzen (neben der 1) nicht gibt.

Die Beschreibung zu A109814 gibt auch gleich noch eine Berechnungsvorschrift, die ich mal nach Python übersetzt habe:

max(min(d, 2*N/d) for d in xrange(1, N+1, 2) if (N%d == 0))

Man braucht natürlich nur bis zur Wurzel zu testen, da ein Teiler ja nicht größer sein kann.

beste Grüße
zommi

15.10.2014 - 11:47 Uhr

Hey SilverX,

dein eingangs erdachtes Schema scheint mir hier am zielführendsten:

Betrachte ein Intervall von Zahlen (n, n+1, n+2, ..., m) und "verschiebe" es:*Wenn die Summe dieses Intervalls kleiner ist als dein Ziel "Z", dann füge hinten (m+1) an. *Wenn die Summe dieses Intervalls größer ist als dein Ziel "Z", dann entferne vorn (n). *Wenn die Summe dieses Intervalls exakt gleich deinem Ziel "Z" ist, dann merke dir (m-n) als Länge des Intervalls und füge hinten (m+1) an.

Anfangen tust du mit dem leeren Intervall und n=m=0.
Sobald du bei m=Z angelangt bist, kannst du aufhören.
Und immer wenn die Summe gerade Z entspricht, guckst du, ob dies die bisher längste Abfolge ist und speicherst diese Länge.

Glücklicherweise brauchst du das Intervall selbst überhaupt nicht zu speichern.
Denn erstens ist es implizit durch deine momentanen Zahlen n und m gegeben und es genügt darüber hinaus, wenn du lediglich die Summe des Intervalls mitführst.
Die Summe kannst du direkt updaten, indem du m+1 addierst oder n abziehst.

Das ganze kannst du in einer einzigen Schleife implementieren, benötigst nur Addition, Subtraktion und 4 Variablen:
n (Intervallbeginn), m (Intervallende), s (Summe des Intervalls von n bis m) und x (das bisherige Maximum der Längen derjenigen Intervalle, deren Summe s gerade gleich Z ist)

beste Grüße
zommi

14.10.2014 - 13:45 Uhr

Hi Sebastian,

kannst du noch ein paar Dinge erklären?

  • Worüber soll denn iteriert/enumeriert werden? Über ein Zahlen-Intervall, über eine List<T>, über einen gekapselten anderen IEnumerator?

  • Was genau meinst du mit der positiven Ergebnissmenge? Und wie kann ein Enumerator mehrfache Sachen zurückliefern?

beste Grüße
zommi

07.10.2014 - 14:45 Uhr

Also ich habe das mal bei mir getestet, und interessanterweise geht es ohne Verrenkungen:

Meine Settings:

  • Windows 7 x64
  • MinGW x64 mit gcc 4.8.1
  • Visual Studio 2012

Mit korrekt gessetzten Pfaden kompiliere ich dann meine oben bereits gezeigten Demo-Dateien - die DLL als 32bit mit mingw und das .NET executable für x86. So klappt alles. Auch ein __cdecl ist kein compiler error.

g++ -m32 -shared -o library.dll library.cpp
csc /platform:x86 main.cs
main.exe

Und auch ohne explizites statisches binden der C/C++ libraries. (Das macht MinGW glaub ich automatisch)

Funktioniert das bei dir auch?

beste Grüße
zommi

07.10.2014 - 13:37 Uhr

Hey,

damit hätte ich eig. begonnen aus der C++ Datei hab ich wie folgt eine .dll erstellt und zwar unter Settings-> ToolSettings->Miscellaneous-> Linker flags: (-static-libgcc -static-libstdc++)

Und libgcc sowie libstdc++ sind eben die GNU-Implementierungen, und eben nicht die msvcrt von Microsoft, welche aber innerhalb .NET verwendet wird. Und daran könnte es eventuell liegen.

cdecl nimmt er mir auf C++ Seite nicht an

Fehlermeldung beim Kompilieren?

Eigentlich müsste es auch über Mono klappen: mit MinGW das Mono-Projekt kompilieren und dann mit diesem Mono deine C#-Anwendung kompilieren. Diese sollte dann auch die MinGW DLL p/invoken können.
Aber versuch es erstmal mit einer nativen microsoft wrapper-DLL.

beste Grüße
zommi

07.10.2014 - 12:52 Uhr

Hi kise1990,

aus einer Nachricht von dir habe ich jetzt entnommen, dass du deine native DLL mit MinGW/gcc kompilierst.

Rein theoretisch könnte das natürlich auch funktionieren, das Verwenden einer MinGW/gcc-DLL aus .NET via DLL/Interop.
Aber bisher habe ich das noch nicht in freier Wildbahn erlebt. Ich habe hier starke Bedenken, dass das einfach so funktioniert.

Möglicherweise könntest du mit dem nativen Visual Studio Compiler (cl.exe) eine native Wrapper-DLL schreiben, die deine gcc-Bibliothek statisch linked.
(schon das ist nicht-trivial: MSVC and MinGW DLLs)
Dann verhält sie sich nach außen zumindest wie eine originäre Windows-DLL, mit echter Microsoft C/C++-Runtime und dazu konformen malloc/new sowie Exception Handling.

Dort duplizierst du dann alle relevanten Funktionen, exportierst sie erneut, kompilierst diese mit cl.exe und nutzt nur diese DLL dann aus C# heraus.

Und bitte bitte bitte, nutze cdecl.
StdCall ist ursprünglich eine Microsoft-Geschichte. Und auch wenn gcc das prinzipiell auch unterstützt, nimm einen Standard, der in beiden Welten (gcc + cl) beheimatet ist: cdecl.

beste Grüße
zommi

06.10.2014 - 15:28 Uhr

Also wenn beim DependencyWalker nichts angezeigt wird, dann wird auch nichts exportiert.

Gibt es zufälligerweise eine Suchfunktion bei Despendency Walker habe jetzt KERNEL32.DLL , MSVCRT.DLL durchgesehen jedoch ohne Erfolg.

Du brauchst auch lediglich die Top-Level-DLL EOLINK.DLL im Baum links anzuschauen
Der Baum zeigt dir lediglich diejenigen Bibliotheken an, die wiederum intern von der EOLINK.DLL verwendet werden. Das interessiert dich aber nicht.

Dieser Baum ist beispielsweise dann interessant um zu gucken, welche Abhängigkeiten zu Dritt-DLLs noch bestehen, da es oft den Fehler gibt, dass ein Programm wegen fehlender DLLs crashed. Du kennst sicherlich Fehlermeldungen wie "Programm ... konnte nicht gestartet werden da xyz.dll nicht gefunden wurde."

Wähle links deine DLL. Und rechts in der Mitte siehst zu die Exporte.
Siehst du nichts, wird nichts exportiert und du hast die falsche DLL.
Du kannst auch rein über die Kommandozeile arbeiten - ohne dependency walker.

[pre]dumpbin /EXPORTS library.dll[/pre]

(Das Tool gehört zu Visual Studio, musst also eine Visual Studio Konsole starten, oder eben die vcvarsall.bat vorher ausführen, siehe vorheriger Post)

Hier nochmal das generelle Vorgehen zum exportieren von Funktionen für eine DLL mit allen drei Varianten, wobei du sicherlich beim __declspec(dllexport) bleiben kannst:
/EXPORT (Exports a Function)

beste Grüße
zommi

06.10.2014 - 15:19 Uhr

Hey,

also hier nochmal ein Test-Snippet:

#include <iostream>
#include <string>
using namespace std;

extern "C" __declspec(dllexport) int __cdecl stringme() {
    string message = "Hello from C++";
    cout << message << endl;
    return 42;
}
using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("library.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern int stringme(); 

    static void Main()
    {
        int result = stringme();
        Console.WriteLine("Got return value: {0}", result);
    }
}

Das ganze kompiliert und ausgeführt mit den 32bit tools unter meinem 64bit Windows funktioniert einwandfrei

"%VS110COMNTOOLS%\..\..\VC\vcvarsall.bat"
cl /LD library.cpp
csc /platform:x86 main.cs
main.exe

Und exportiert wird auch der pure Name "stringme".
Interessanterweise, wenn ich bei C++ auf __stdcall umstelle, dann wird bei mir "_stringme@0" exportiert.
Wenn ich nun auf C# Seite auch auf StdCall umstelle, dann findet er sie sogar... also das .NET Framework sucht sogar nach gemangelten Namen, clever clever.
Aber eben nur, wenn man auch auf stdcall umstellt.

Auf jeden fall MUSST du sicherstellen, dass beides stdcall oder beides cdecl ist. Sonst crashed es mit hoher Wahrscheinlichkeit, sobald echte Argumente oder was anderes als int zurückgegeben wird.