# Ein char in long int umwandeln



## lalalala (15. November 2010)

Hallöchen, 
kann mir jemand helfen habe eine Aufgabe die ich nicht lösen kann und überhaupt nicht weiß wie ich anfangen soll .

Hier ist sie....

Viele Programme erwarten die Eingaben der Benutzer als String. Es ist dann die Aufgabe
des Programms diese Eingabe zu überprüfen.
Schreiben Sie eine Funktion, die einen String, der eine ganze Zahl darstellt (C-Datentyp:
long int) in den entsprechenden Wert umwandelt. Die Deklaration dieser Funktion ist also:
long int str_to_long(char in[]);
Dabei soll diese Funktion den Parameter in (den String) auf Fehler überprüfen. Es ist auch
zu berücksichtigen, dass der String zu viele Ziffern enthält und auf dem Rechner gar nicht als
long int darstellbar ist.
Das Resultat der Funktion (der Return-Wert) soll sind:
• der entsprechende Wert des Strings, wenn der String fehlerfrei ist.
• der Wert der größten oder kleinsten long int-Zahl, wenn der String fehlerhaft
ist. Die kleinste Zahl wird verwendet, wenn der String am Anfang das Zeichen
'-' besitzt, sonst wird die größte Zahl verwendet.
Schreiben Sie Ihre Funktion so, dass sie unabhängig von einem spezifischen Rechner ist!
Probieren Sie die Funktion in einem kleinen Hauptprogramm, insbesondere wie sie auf Fehler
reagiert.


----------



## sheel (15. November 2010)

Willkommen bei tutorials.de 



lalalala hat gesagt.:


> Schreiben Sie Ihre Funktion so, dass sie unabhängig von einem spezifischen Rechner ist!


 
Na das ist ja lustig.
Unabhängig von Variablengröße, signed/unsigned und dem Zeichensatz(?).
@all: Gibts eigentlich einen Zeichensatz, der die Ziffern nich hintereinander von 0 bis 9 hat?

Ich würde einem Anfänger zuerst einmal die Aufgabe ohne diesen einen Satz geben und dann eventuell mit.
Nur verständlich, dass du jetzt verwirrt bist 

Also, generell musst du:
-Eine Variable haben, 0 reinschreiben
-Den String Zeichen für Zeichen durchgehen, bei jedem Zeichen die Variable mal 10 + die aktuelle Ziffer im String nehmen
-Wenn die Variable einen Überlauf hat, Fehler zurückgeben
-Wenn ein Zeichen drin ist, das keine Ziffer ist, auch einen Fehler zurückgeben

Einen Überlauf/zu großen Wert in der Variable erkennst du in dem Fall (du vergrößerst sie ja nur immer mit Multiplikation un Plus), dass nach so einer Rechnung auf einmal ein kleinerer Wert als vorher drin ist.
Ist in C generell so, wenn man über den Größten Wert hinauskommt wird beim kleinsten weitergemacht.

Noch zu beachtenist, dass die Ziffern im String in irgendeinem Zeichensatz (zB Ascii) abgespeichert sind, bei dem die Ziffern in wirklichkeit andere Zahlenwerte haben
Wenn man zB 0 ab Bildschirm sieht, wird das in Wirklichkeit als 48 abgespeichert, 1->49...
Welche Werte die Ziffern wirklich haben, hängt aber auch vom Zeichensatz und somit vom Computer ab.

edit: Compiler spinnt herum, kann dir zurzeit leider kein (getestetes) Beispiel posten
Ich veruchs aber weiter

Gruß


----------



## Trulleberg (15. November 2010)

Die Formulierung der Aufgabenstellung lässt darauf schließen, dass der Aufgabensteller Wert auf Plattformunabhängigkeit legt, d.h. du sollst maximal portabel sein. Dies ist nur mit strikt konformen ANSI C89 möglich. Für den genannten Fall gibt es meines Wissens ausschließlich die Standardbibliotheks-Funktion strtol. Eine Lösung könnte sein:


```
#include <limits.h>
#include <stdlib.h>

long str_to_long(const char *in)
{
  long l;
  char *e;
  l=strtol(in,&e,10);
  return *e?LONG_MAX:l;
}
```

Die Aufgabenstellung ist aber ungenau, falls nämlich der String genau LONG_MIN oder LONG_MAX bedeutet, kann durch den Aufruf der Funktion dieser Wert nicht von einem übergebenen String mit einem Über/Unterlauf von <long int> unterschieden werden.


----------



## sheel (15. November 2010)

Trulleberg hat gesagt.:


> Die Aufgabenstellung ist aber ungenau, falls nämlich der String genau LONG_MIN oder LONG_MAX bedeutet, kann durch den Aufruf der Funktion dieser Wert nicht von einem übergebenen String mit einem Über/Unterlauf von <long int> unterschieden werden.



Naja, so lautet aber die Aufgabe.
Bei Schulaufgaben ist es oft sowieso überflüssig, sich über den Sinn Gedanken zu machen.

Und bei einer Schulufgabe (die es ja wahrscheinlich ist) sollte man normalerweise keine Standardfunktion hernehmen, die einem fast alles abnehmen, sondern das Ganze selber implementieren.

Jedenfalls hier einmal der Code

```
#include<limits.h>

long int str_to_long(char in[])
{
    long int erg=0;
    if((*in)=='-')return LONG_MIN;
    while((*in)!='\0')
    {
        if( (*in)<'0'|| (*in)>'9' ) return LONG_MAX;
        if(erg>( erg*10-'0'+(*in) )) return LONG_MAX;
        erg=erg*10-'0'+(*in);
        in++;
    }
    return erg;
}
```


----------



## Trulleberg (15. November 2010)

Standard schreibt man übrigens Standard und nicht Standart.


----------



## sheel (15. November 2010)

Habs ausgebessert, zusammen mit dem ganzen Satz (der mir sowieso nicht gefallen hat).

Und die Überlaufprüfung ist das Zweite if im while.

Gruß


----------



## lalalala (16. November 2010)

danke schön.....aber wie soll ich dann weiter machen


----------



## Matthias Reitinger (16. November 2010)

sheel hat gesagt.:


> ```
> if((*in)=='-')return LONG_MIN;
> ```


Ich denke die Aufgabenstellung ist eher so gemeint, dass LONG_MIN nur im Fehlerfall zurückgegeben werden soll, sofern das erste Zeichen ein Minus ist. Sonst könnte man ja keine negativen Zahlen eingeben.

Grüße,
Matthias


----------



## sheel (16. November 2010)

Weitermachen? Gar nicht, denn die Funktion läuft so wie ich sie gepostet habe.
Oder doch, die Aufgabenstellung verlangt ja noch ein main, in dem die Funktion getestet wird

Wie du das "Testen" genau machst, bleibt dann wohl dir überlassen.

Du könntest zB immer einen String von der Tastatur einlesen, durch die Funktion schicken, am Ende das Ergebnis am Bildschirm ausgeben und dann das Ganze wieder von vorne.

zB so:

```
#include<stdio.h>

int main()
{
    char c[1024];
    while(1)
    {
        gets(c);
        printf("%d\n", str_to_long(c) );
    }
}
```

@Matthias Reitinger: Ist natürlich auch eine Möglichkeit.
Und weils grad so lustig ist, gibts die Variante auch gleich...


----------



## sheel (16. November 2010)

Hier die andere Variante (falls das mit dem Minus anders gemeint war):

```
#include<limits.h>

long int str_to_long(char in[])
{
    long int erg=0, test;
    bool negativ=0;
    if((*in)=='-')
    {
        negativ=true;
        in++;
    }
    while((*in)!='\0')
    {
        if( (*in)<'0'|| (*in)>'9' ) return ((negativ)?LONG_MIN:LONG_MAX);
        test=erg*10-'0'+(*in);
        if(erg>test) return ((negativ)?LONG_MIN:LONG_MAX);
        erg=test;
        in++;
    }
    return ((negativ)?(-erg):erg);
}
```

edit: 1300


----------



## brunlorenz (16. November 2010)

Mal etwas, was die Funktionalität bereitstellt (aber für eine Schulaufgabe nicht tauglich ist):

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

long int str_to_long(char in[])
{
long int zahl=0;
if(sscanf(in,"%ld",&zahl)==0) return -1; // oder den Fehlercode
else return zahl;
}
```
Das dürfte laufen
Falls es aber eine Aufgabe ist, bei der ihr selbst den Code verfassen müsst:

```
long int str_to_long(char in[])
{
long int zahl=0;
int z;
bool minus=false;
for(z=0;z<strlen(in);z++)
{
if(in[0]=='-' && z==0) { minus=true; continue; }
if(isdigit(in[z])==0) return -1; // oder anderer Fehlercode
if((zahl+in[z]-'0')*pow(10,z)>LONG_MAX)) return -1;
zahl+=(in[z]-'0')*pow(10,z);
}
if(minus) zahl*=(-1);
return zahl;
}
```
Das noch für den Fall, dass es eine Schulaufgabe war.
Falls du noch eine Erklärung für die Schule brauchst:


> Jedes Zeichen des Strings durch eine for-Schleife laufen lassen.
> Dabei prüfen, ob es sich um eine Zahl handelt.
> Falls ja, dem Zeichen 48 abziehen, weil 48 im ASCII-Zeichensatz die 0 ist und das Ergebnis (also die Ziffer)
> mit der jeweiligen Zehnerpotenz multiplizieren, dass die Zahl an der richtigen Stelle landet.
> Falls ein Minuszeichen erkannt wurde, am Schluss noch die Zahl mit -1 multiplizieren.


Ich hoffe, das genügt dir
lorenzbrun


----------



## lalalala (16. November 2010)

hey danke supper, das einzigste was ich noch nicht verstehe ist die zahl die du bei char c [] eingegeben hast, also 1024.
Ich hab da auch andere Zahlen eingesetzt das ging mit den auch.....oder hat diese Zahl ne bestimmte bedeutung?


----------



## sheel (16. November 2010)

Du meinst jetzt mich, oder (nicht brunlorenz) ?

Um von der Tastatur was einzulesen, brauchts ja klarerweise eine Variable zum abspeichern, bevor ich dann str_to_long damit aufrufe

In C wird das im Normalfall als ein Char-Array, also einfach eine Menge einzelner Buchstaben hintereinander, gemacht.
Und das 1024 heißt hier, dass meine Variable c maximal 1024 Buchstaben speichern kann, nichts weiter.
Wenn du 400 reinschreibst, passen eben bis zu 400 Buchstaben rein, und 1024 ist mir einfach zufällig eingefallen .

Falls wer wirklich mehr als 1024 Buchstaben eingibt, hätte meine Variante vom main aber ein Problem.
Da gibts schönere/sicherere Lösungen, aber euer Lehrer gibt sicher keine tausendstellige Zahl ein (  ).

Falls du die Zahl änderst, solltest du sie nicht zu niedrig wählen; wie gesagt hätte meine Einfachvariante vom main ein Problem mit einer zu langen Eingabe.

Also nicht 4 oder so, dann ist beim 5 Buchstaben Mist (und man merkt es eventuell nicht beim ersten Mal)
Das Programm könnte auch huntertmal funktionieren und beim 101.Mal abstürzen...

Also entweder entsprechend absichern oder einfach eine große Zahl nehmen und sich auf tippfaule Anwender verlassen.

Auf str_to_long hat das übrigens keine Auswirkungen, die Schlampigkeit liegt allein beim main.

Gruß

PS an brunlorenz:

Die (in der Aufgabe geforderte) Überlaufkontrolle fehlt bei dir.

Und diese Zeile

```
zahl+=in[z]-48*pow(10,z);
```
hat einen witzigen Klammernmangel 

Und (sorry für das ganze Meckern), aber die Aufgabe schreibt Rechnerunabhängigkeit vor.
Also auch vom Zeichensatz unabhängig.
48 muss nicht '0' sein, '0' in den Code schreiben wäre besser.

Gruß


----------



## lalalala (17. November 2010)

ne meinte dich .......
achsoo ja verstehe, aha gut habe jetzt verstanden  dankeschön hast mir echt geholfen


----------



## brunlorenz (19. November 2010)

Ok, verbessere es im Code


----------

