How to determine the length of a string (without using strlen()) - c

size_t stringlength(const char *s)
Using this function, how could find the length of a string? I am not referring to using strlen(), but creating it. Any help is greatly appreciated.

Cycle/iterate through the string, keeping a count. When you hit \0, you have reached the end of your string.
The basic concepts involved are a loop, a conditional (to test for the end of string), maintaining a counter and accessing elements in a sequence of characters.
Note: There are more idiomatic/clever solution. However OP is clearly new to C and programming (no offense intended, we all started out as newbies), so to inflict pointer arithmetic on them as one of solutions did or write perhaps overly terse/compact solutions is less about OP's needs and more about a demonstration of the posters' programming skills :) Intentionally providing suggestions for a simple-to-understand solution earned me at least one downvote (yes, this for "imaginary code" that I didn't even provide. I didn't want to ready-serve a code solution, but let OP figure it out with some guidance).
Main Point: I think answers should always be adjusted to the level the questioner.

size_t stringlength(const char *s) {
size_t count = 0;
while (*(s++) != '\0') count++;
return count;
}
The confusing part could be the expression *(s++), here you're moving the pointer to point the next character in the buffer using the ++ operator, then you're using the dereferencing operator * to get the content at the pointer position. Another more legible approach would be:
size_t stringlength(const char *s) {
size_t count = 0;
while (s[count] != '\0') count++;
return count;
}
Another couple of reference versions (but less legible) are:
size_t stringlength(const char *s) {
size_t count = 0;
while (*s++) count++;
return count;
}
size_t stringlength(const char *s) {
const char* c = s;
for (; *c; c++);
return c - s;
}
Although the code stated here is just a reference to give you ideas of how to implement the algorithm described in the above answer, there exists more efficient ways of doing the same requirement (check the glibc implementation for example, that checks 4 bytes at a time)

This might not be a relevant code, But I think it worth to know.
Since it saves time...
int a[] = {1,2,3,4,5,6};
unsigned int i,j;
i = &a; //returns first address of the array say 100
j = &a+1; //returns last address of the array say 124
int size = (j-i)/sizeof(int); // (j-i) would be 24 and (24/4) would be 6
//assuming integer is of 4 bytes
printf("Size of int array a is :%d\n",size);
And for strings ::
char a[] = "Hello";
unsigned int i,j;
j = &a+1; //returns last address of the array say 106
i = &a; //returns first address of the array say 100
printf("size of string a is : %d\n",(j-i)-1); // (j-i) would be 6
If you are confused how come &a+1 returns the last address of the array, check this link.

Assuming s is a non-null pointer, the following function traverses s from its beginning until the terminating zero is found. For each character passed s++; count is incremented count++;.
size_t stringlength(const char *s) {
size_t count = 0;
while (*s) {
s++;
count++;
}
return count;
}

Related

The following C code outputs a segmentation fault error which I can hardly understand why

#include <stdio.h>
void append(char* s, char n);
void splitstr(char* string);
int main()
{
splitstr("COMPUTE 1-1");
printf("\n");
splitstr("COMPUTE 1+1");
printf("\n");
splitstr("COMPUTE 1*1");
return 0;
}
void append(char* s, char ch) {
while(*s != '\0'){
s = s + 1;
}
*s = ch;
s = s + 1;
*s = '\0';
}
void splitstr(char* string){
int count = 1;
char* expression = "";
while(*string != '\0'){
if(count > 8){
append(expression, *string);
string = string + 1;
count = count + 1;
}else{
string = string + 1;
count = count + 1;
}
}
printf("%s",expression);
}
Example Input and Output:
Input: COMPUTE 1+1
Output: 1+1
Input: COMPUTE 2-6
Output: 2-6
Originally, this code does not include stdio.h (I am doing this for testing on an online C compiler) because I am building an OS from scratch so I need to write all the functions by myself. I think the problem might be in the append function but I cannot find it.
instead of
char* expression = "";
do
char[MAX_expression_length+1] expression;
or use realloc in the append function
I think this line is the culprit:
append(expression, *string);
Notice how expression is declared:
char* expression = "";
In other words, expression consists of one byte, a single \0. Right away, we can see that append() won't work like you want it to--the while loop will never run, because *s is already \0.
But beyond that, the segfault likely happens at the bottom of append(). After the while loop, you unconditionally increment s and then write to the location it now points to. The problem is that this is a location that has never been allocated (since s is a reference to splitstr()'s expression, which is a single byte long). Furthermore, because expression is declared as a string constant, depending on your platform it may be placed in an area of memory marked read-only. Consequently, this is an attempt to write into memory that may not actually belong to the process and may also not be writable, raising the fault.
expression points to a string literal, and trying to modify a string literal leads to undefined behavior.
You need to define expression as an array of char large enough to store your final result:
char expression[strlen(string)+1]; // VLA
Since your result isn’t going to be any longer than the source string, this should be sufficient (provided your implementation supports VLAs).

Simple question on dynamically allocating memory to a char pointer

I am studying for a Data Structures and Algorithms exam. One of the sample questions related to dynamic memory allocation requires you to create a function that passes a string, which takes it at copies it to a user defined char pointer. The question provides the struct body to start off.
I did something like this:
typedef struct smart_string {
char *word;
int length;
} smart_string;
smart_string* create_smart_string(char *str)
{
smart_string *s = (smart_string*)malloc(sizeof(smart_string));
s->length = strlen(str);
s->word = malloc(s->length);
strcpy(s->word, str);
return s;
}
But the answer was this
typedef struct smart_string {
char *word;
int length;
} smart_string;
smart_string *create_smart_string(char *str)
{
smart_string *s = malloc(sizeof(smart_string));
s->length = strlen(str);
s->word = malloc(sizeof(char) * (s->length + 1));
strcpy(s->word, str);
return s;
}
I went on code:blocks and tested them both to see any major differences. As far as I'm aware, their outputs were the same.
I did my code the way it is because I figured if we were to allocate a specific block of memory to s->word, then it should be the same number of bytes as s ->length, because that's the string we want to copy.
However the correct answer below multiplies sizeof(char) (which is just 1 byte), with s->length + 1. Why the need to add 1 to s->length? What's the importance of multiplying s->length by sizeof(char)? What mistakes did I make in my answer that I should look out for?
sizeof(char) == 1 by definition, so that doesn't matter.
You should not cast the result of malloc: Do I cast the result of malloc?
And your only real difference is that strlen returns the length of the string, not including the terminating NUL ('\0') character, so you need to add + 1 to the size of the buffer as in the solution.
If you copy there the string, the terminating character won't be copied (or worse, it will be copied on some other memory), and therefore, any function that deals with strings (unless you use special safety functions such as strscpy) will run through the buffer and past it since they won't find the end. At that point it is undefined behaviour and everything can happen, even working as expected, but can't rely on that.
The reason it is working as expected is because probably the memory just next to the buffer will be 0 and therefore it is being interpreted as the terminating character.
Your answer is incorrect because it doesn't account for the terminating '\0'-character. In C strings are terminated by 0. That's how their length can be determined. A typical implementation of strlen() would look like
size_t strlen(char const *str)
{
for (char const *p = str; *p; ++p); // as long as p doesn't point to 0 increment p
return p - str; // the length of the string is determined by the distance of
} // the '\0'-character to the beginning of the string.
But both "solutions" are fubar, though. Why would one allocate a structure consisting of an int and a pointer on the free-store ("heap")!? smart_string::length being an int is the other wtf.
#include <stddef.h> // size_t
typedef struct smart_string_tag { // *)
char *word;
size_t length;
} smart_string_t;
#include <assert.h> // assert()
#include <string.h> // strlen(), strcpy()
#include <stdlib.h> // malloc()
smart_string_t create_smart_string(char const *str)
{
assert(str); // make sure str isn't NULL
smart_string_t new_smart_string;
new_smart_string.length = strlen(str);
new_smart_string.word = calloc(new_smart_string.length + 1, sizeof *new_smart_string.word);
if(!new_smart_string.word) {
new_smart_string.length = 0;
return new_smart_string;
}
strcpy(new_smart_string.word, str);
return new_smart_string;
}
*) Understanding C Namespaces

Getting length of string by typecasting it to int pointer in c

Going mad with string pointers, please help.
Here is my question:
static int ByteOrder(
char **charPtrPtr,
long length,
char *destPtr)
{
char *endPtr = destPtr + length;
while (destPtr < endPtr)
{
*destPtr++ = *((*charPtrPtr)++);
}
return 0;
}
int LenGet( char **charPtrPtr,
long *lengthPtr)
{
if (ByteOrder(charPtrPtr,
sizeof(long),
(char *)lengthPtr) != 0)
{
return 1;
}
printf("charPtrPtr: %s, lenPtr: %ld\n", *charPtrPtr, *lengthPtr);
return 0;
}
int main()
{
char *charPtr = "ffffff";
long length = 0;
LenGet(&charPtr, &length);
printf("charPtr: %s, len: %ld\n", charPtr, length);
}
Output:
charPtrPtr: ff, lenPtr: 1717986918
charPtr: ff, len: 1717986918
In the above sections of code, what is the function ByteOrder does?
I tried searching the answer for it, could not get it directly. I assume it copies all the stirngs from charPtrPtr to destPtr. And in the function LenGet, the lengthPtr returns the length of the string. Trying to understand this logic. Spent enough time in searching for it and now posting it here. If any links available for the same that helps me understanding this logic, please help me by posting it here or explaining it. Thanks, Denise.
In the above sections of code, what is the function ByteOrder does?
The function does two things:
1) It copies length characters from a source string to a destination string
2) It advances the pointer to the source string by length
It can be shown like this:
So the idea of the function is pretty simple. Copy N bytes and advance the pointer N positions - probably to indicate the next bytes to be processed.
The function could be rewritten to something like:
static int ByteOrder(
char **charPtrPtr,
long length,
char *destPtr)
{
memcpy(destPtr, *charPtrPtr, length); // Copy characters
*charPtrPtr += length; // Advance source pointer
return 0; // Don't know why the function returns a fixed value
}
The rest of the code is horrible and probably violates strict aliasing.
Anyway:
The code copied the first 4 bytes of the source string into the integer variable length (and advanced the source string pointer by 4).
Notice that length = 1717986918 = 0x66666666 and 0x66=102 which is the character 'f'.

Find the size of a string pointed by a pointer

#include <stdio.h>
int main ()
{
char *ptr = "stackoverflow"
}
Is there any way to find the length of stackoverflow pointed by ptr, as sizeof ptr always gives 4
Use strlen to find the length of (number of characters in) a string
const char *ptr = "stackoverflow";
size_t length = strlen(ptr);
Another minor point, note that ptr is a string literal (a pointer to const memory which cannot be modified). Its better practice to declare it as const to show this.
sizeof() returns the size required by the type. Since the type you pass to sizeof in this case is a pointer, it will return size of the pointer.
If you need the size of the data pointed by a pointer you will have to remember it by storing it explicitly.
sizeof() works at compile time. so, sizeof(ptr) will return 4 or 8 bytes typically. Instead use strlen.
The strlen() function provided by string.h gives you how many "real characters" the string pointed by the argument contains. However, this length does not include the terminating null character '\0'; you have to consider it if you need the length to allocate memory.
That 4 bytes is the size of a pointer to char on your platform.
#include<stdio.h>
main()
{
int mystrlen(char *);
char str[100];
char *p;
p=str;
printf("Enter the string..?\n");
scanf("%s",p);
int x=mystrlen(p);
printf("Length of string is=%d\n",x);
}
int mystrlen(char *p)
{
int c=0;
while(*p!='\0')
{
c++;
*p++;
}
return(c);
}
simple code to understand
You are looking for the strlen() function.
You can try using:
char *ptr = "stackoverflow"
size_t len = strlen(ptr);
if ptr length is an argument of a function it's reasonable to use pointers as a strings. we can get string length by following code:
char *ptr = "stackoverflow";
length=strlen((const char *)ptr);
And for more explanation, if string is an input string by user with variable length, we can use following code:
unsigned char *ptr;
ptr=(unsigned char *)calloc(50, sizeof(unsigned char));
scanf("%s",ptr );
length=strlen((const char *)ptr);
Purely using pointers you can use pointer arithmetic:
int strLen(char *s)
{
int *p = s;
while(*p !=’\0’)
{
p++; /* increase the address until the end */
}
Return p – s; /* Subtract the two addresses, end - start */
}
Even though this is a generic C question, it gets pretty high hits when looking this question up for C++. Not only was I in C/C++ territory, I also had to be mindful of Microsoft's Security Development Lifecycle (SDL) Banned Function Calls for a specific project which made strlen a no-go due to,
For critical applications, such as those accepting anonymous Internet connections, strlen must also be replaced...
Anyway, this answer is basically just a twist on the answers from the others but with approved Microsoft C++ alternative function calls and considerations for wide-character handling in respect to C99's updated limit of 65,535 bytes.
#include <iostream>
#include <Windows.h>
int wmain()
{
// 1 byte per char, 65535 byte limit per C99 updated standard
// https://stackoverflow.com/a/5351964/3543437
const size_t ASCII_ARRAY_SAFE_SIZE_LIMIT = 65535;
// Theoretical UTF-8 upper byte limit of 6; can typically use 16383 for 4 bytes per char instead:
// https://stijndewitt.com/2014/08/09/max-bytes-in-a-utf-8-char/
const size_t UNICODE_ARRAY_SAFE_SIZE_LIMIT = 10922;
char ascii_array[] = "ACSCII stuff like ABCD1234.";
wchar_t unicode_array[] = L"Unicode stuff like → ∞ ∑ Σὲ γνωρίζω τὴν ደሀ ᚦᚫᛏ.";
char * ascii_array_ptr = &ascii_array[0];
wchar_t * unicode_array_ptr = &unicode_array[0];
std::cout << "The string length of the char array is: " << strnlen_s(ascii_array_ptr, ASCII_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
std::wcout << L"The string length of the wchar_t array is: " << wcsnlen_s(unicode_array_ptr, UNICODE_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
return 0;
}
Output:
The string length of the char array is: 27
The string length of the wchar_t array is: 47
strlen() gives you the exact length of the string [excluding '\0']
sizeof() gives you the size of the data type used.
// stackoverflow = 13 Characters
const char* ptr = "stackoverflow";
strlen(ptr); // 13 bytes - exact size (NOT includes '\0')
sizeof(ptr); // 4 bytes - Size of integer pointer used by the platform
sizeof(*ptr); // 1 byte - Size of char data type
strlen("stackoverflow"); // 13 bytes - exact size
sizeof("stackoverflow"); // 14 bytes - includes '\0'
#include<stdio.h>
int main() {
char *pt = "String of pointer";
int i = 0;
while (*pt != '\0') {
i++;
pt++;
}
printf("Length of String : %d", i);
return 0;
}
We can also use strlen() function or sizeof() operator which is builtin in C.
We can also take help of pointer arithmetic as above example.

please help making strstr()

I have made strstr() function but the program does not give any output,just a blank screen.Please have a look at the code.
#include<stdio.h>
#include<conio.h>
const char* mystrstr(const char *str1, const char *str2);
int main()
{
const char *str1="chal bhai nikal";
const char *str2="nikal",*result;
result=mystrstr(str1,str2);
printf("found at %d location",(int*)*result);
getch();
return 0;
}
const char * mystrstr(const char *s1, const char *s2)
{
int i,j,k,len2,count=0;
char *p;
for(len2=0;*s2!='\0';len2++);//len2 becomes the length of s2
for(i=0,count=0;*s1!='\0';i++)
{
if(*(s1+i)==*s2)
{
for(j=i,k=0;*s2!='\0';j++,k++)
{
if(*(s1+j)==*(s2+i))
count++;
if(count==len2)
{
p=(char*)malloc(sizeof(char*));
*p='i';
return p;
}
}
}
}
return NULL;
}
The line with this comment:
//len2 becomes the length of s2
is broken. You repeatedly check the first character of s2. Instead of *s2, try s2[len2].
Edit: as others have said, there are apparently a lot more things wrong with this implementation. If you want the naive, brute-force strstr algorithm, here's a concise and fast version of it:
char *naive_strstr(const char *h, const char *n)
{
size_t i;
for (i=0; n[i] && h[i]; i++)
for (; n[i] != h[i]; h++) i=0;
return n[i] ? 0 : (char *)h;
}
It looks like this is an exercise you're doing to learn more about algorithms and C strings and pointers, so I won't solve those issues for you, but here are some starting points:
You have an infinite loop when calculating len2 (your loop condition is *s2 but you're never changing s2)
You have a similar issue with the second for loop, although I you have an early return so it might not be infinite, but I doubt the condition is correct
Given you want to behave like strstr(), you should return a pointer to the first string, not a new pointer you allocate. There is no reason for you to allocate during a function like strstr.
In main() if you want to calculate the position of the found string, you want to print result-str1 unless result is NULL). (int*)*result makes no sense - result should be a pointer to the string (or NULL)
You also need to change this line:
if(*(s1+j)==*(s2+i))
to this:
if(*(s1+j)==*(s2+k))
As already mentioned, the return value is a bit odd. You are returning a char* but kind of trying to put an integer value in it. The result doesn't make sense logically. You should either return a pointer to the location where it is found (no malloc needed) or return the integer position (i). But returning the integer position is not the "typical" strstr implementation.

Resources