String-Länge
-
Moin,
ich soll eine Funktion erstellen, die die Länge eines Strangs im Puffer s - einem Array von
char
der Längebuf_len
- zurückliefert. Der Prototyp seiint string_len(const char s[], int buf_len)
.Kann mir zunächst bitte einmal einer erklären wieso ich in der Funktion 2 Variablen habe? Also ich verstehe nicht wieso ich
const char s[]
undint buf_len
benötige.
Eigentlich brauche ich doch nur den eingegebenen String als Variable in der Funktion um dann damit weiterzuarbeiten.Wie habe ich die Aufgabe zu verstehen?
-
Und wie stellst du die Stringlänge fest?
-
Durch suchen nach '\0'?!
-
Und was passiert wenn keine '\0' drin ist?
-
Dann ist es kein String. Die Bibliotheksfunktion strlen, und die WinAPI-Funktion lstrlen, die die gleiche Aufgabe erfüllen, kommen auch mit einem Zeiger auf char aus.
-
Es kann aber ein Ergebnis von strncpy sein.
-
Iterativ würde das ganze so aussehen
#include <stdio.h> #include <string.h> int main(void) { char string[] = "Das ist ein Teststring"; size_t laenge; laenge = strlen(string); printf("Der String \"%s\" hat %d Zeichen\n",string, laenge); return 0; }
Wie könnte ich das zu meiner gewünschten Funktion umbasteln?
-
Da ist nichts iterativ. Du nutzt nur die Standardfunktion strlen.
Und gerade die sollst du ja neu schreiben.
-
DirkB schrieb:
Es kann aber ein Ergebnis von strncpy sein.
Klar. Aber da muss doch dann der Programmierer drauf achten, dass sein String ein '\0' bekommt - meine Meinung.
-
R231SL schrieb:
Wie könnte ich das zu meiner gewünschten Funktion umbasteln?
So:
#include <stdio.h> #include <string.h> #define BUFLEN 10 int string_len(const char s[], int buf_len) { int i; for (i=0; i<buf_len; ++i) { if (s[i] == '\0') return i; } return -1; /* Fehler */ } int main( void ) { char string[BUFLEN] = "Das ist ein Teststring"; size_t strlen_laenge; int string_len_laenge; strlen_laenge = strlen(string); printf("Der String \"%s\" hat %d Zeichen\n",string, strlen_laenge); string_len_laenge = string_len (string,BUFLEN); if (string_len_laenge < 0) { puts("Der String ist gar kein String"); } else { printf("Der String \"%s\" hat %d Zeichen\n",string, string_len_laenge); } return 0; }
Ich denke, damit ist auch Deine Frage nach buf_len beantwortet.
viele grüße
ralph
-
rkhb schrieb:
#define BUFLEN 10 char string[BUFLEN] = "Das ist ein Teststring";
Undefiniertes Verhalten.
rkhb schrieb:
size_t strlen_laenge; printf("Der String \"%s\" hat %d Zeichen\n",string, strlen_laenge);
Undefiniertes Verhalten.
-
Wutz schrieb:
...
Undefiniertes Verhalten.
...
Undefiniertes Verhalten.Aha. Und? Außerdem stimmt es nicht:
- "An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array." (ISO/IEC 8999:TC3, S.126 Rn 14).
Das heißt: Das Array wird angelegt und sukzessive soweit gefüllt, wie Platz ist. Deswegen geben GCC und MSVC auch "nur" eine Warnung heraus.
- %s: "If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type." (aaO. S. 279)
%d: "The int argument is converted to signed decimal in the style [−]dddd." (aaO. S. 277). Nun gut, dem C99-Standard zuliebe hätte ich %zd schreiben müssen, aber das hätte der MSVC im C-Modus nicht geschluckt.
viele grüße
ralph
-
Du kannst nicht beides haben. Entweder schneidet deine Zuweisung nicht das Nullzeichen ab oder alle deine Operationen darauf sind undefiniert. Das erstere ist dir tatsächlich vom C-Standard so garantiert, das bedeutet der Rest des Programms ist voller undefinierten Verhaltens.
-
char szString[] = "Das ist ein String";
So deklariert hat der String genau die Länge der angegeben Zeichen
plus noch einen Null-Terminierer.Man muss sich also nicht darum bemühen, die Länge des Strings bei
der Deklaration zu wissen und hat keine Probleme damit, dass der
String länger als die Array Größe ist.
-
SeppJ schrieb:
Du kannst nicht beides haben. Entweder schneidet deine Zuweisung nicht das Nullzeichen ab oder alle deine Operationen darauf sind undefiniert. Das erstere ist dir tatsächlich vom C-Standard so garantiert, das bedeutet der Rest des Programms ist voller undefinierten Verhaltens.
Warum sollte ich beides haben wollen? Ich wollte dem OP nur schnell vor Augen führen, wann ein Bound-Checking nützen kann, denn danach hatte er gefragt. Die Logik Deiner Ausführungen erschließt sich mir nicht. Wenn etwas vom C-Standard garantiert ist, dann bedeutet das doch, dass dieser Teil definiert ist, und der Rest des Programms muss deswegen nicht voller undefinierten Verhaltens sein.
Dass
printf
bei%s
einen "pointer to the initial element of an array of character type" erwartet, heißt doch eindeutig, dass es sich bei dem Array nicht um einen richtigen C-String handeln muss, bzw. dass auf C-String geprüft wird. Es wird Speicher gelesen und ausgegeben - bis zur ersten Null, und die kann weit hinter den Grenzen des Arrays liegen. Das Verhalten ist zwar unerwünscht, aber nicht undefiniert.viele grüße
ralph
-
@chara
Es ist hier aber beabsichtigt, dass da kein Platz für eine Terminierung ist.
-
int string_len(const char s[], int buf_len) { if ((!s) || (!buf_len)) return -1; int i; for (i = 0; i < buf_len; i++) { if (s[i] == '\0') return i; } return -1; }
So würde ich es machen.
Ist eine Terminierung innerhalb des Strings vorhanden, dann wird die Anzahl der Zeichen bis dahin zurückgegeben. Ist keine Vorhanden, dann wird -1 zurückgegeben, weil irgendwann die als Argument übergebene Grenze erreicht wurde. Außerdem werden noch die beiden Funktionsargumente überprüft (Null-Zeiger und 0-Größe).
So wäre doch die Aufgabenstellung des Threaderstellers gelöst oder nicht?!
-
chara schrieb:
Außerdem werden noch die beiden Funktionsargumente überprüft (Null-Zeiger und 0-Größe).
Die 0-Größe bei buf_len wird auch in der for-Schleife abgefangen.
Und bis auf den NULL-Zeifer-Test ist es doch identisch mit der Version von rkhb.(Ich hätte beim NULL-Zeiger -2 zurück gegeben)
-
chara schrieb:
So würde ich es machen.
Und ich so
int string_len( const char * buf, int buf_len ) { int i; for( i = 0; *buf && buf_len; buf_len--, i++, buf++ ); return buf_len ? i : -1; }
-
rkhb schrieb:
Dass
printf
bei%s
einen "pointer to the initial element of an array of character type" erwartet, heißt doch eindeutig, dass es sich bei dem Array nicht um einen richtigen C-String handeln muss, bzw. dass auf C-String geprüft wird. Es wird Speicher gelesen und ausgegeben - bis zur ersten Null, und die kann weit hinter den Grenzen des Arrays liegen. Das Verhalten ist zwar unerwünscht, aber nicht undefiniert.Doch, das ist undefiniert ohne Ende, auf wer weiß was für Speicher zuzugreifen.