Calculating length of a string in C - c

int strlength(const char *myStr){
//variable used for str length counter
int strlength = 0;
//loop through string until end is reached. Each iteration adds one to the string length
while (myStr[strlength] != '\0'){
putchar(myStr[strlength]);
strlength++;
}
return strlength;
}
Why will this not work as intended? I just want to find the length of a string.

From a comment on another answer:
I am using fgets to read in a string. and i have checked to make sure that the string that was typed was stored correclty
In that case, there is a trailing newline stored, so your function computes
strlength("hello\n")
The code is correct, you just didn't pass it the input you believed to pass.

More reliable version:
size_t strlength(const char * myStr)
{
return strlen(myStr);
}

You can try this also:-
int string_length(char *s)
{
int c = 0;
while(*(s+c))
c++;
return c;
}

No need to worry about fgets() and removing the trailing \n.
while (myStr[strlength] != '\0'){
putchar(myStr[strlength]);
strlength++; //When mysStr[strlength] == \0, this line would have already incremented by 1
}
Quick fix:
return (strlength-1);//This will return correct value.
A more better approach:
int strlen(const char *s)
{
char *str=s;
while(*str)
{
str++;
}
return (s-str);
}

Related

How to return empty string from a function in C?

How should I return an empty string from a function? I tried using lcp[i] = ' ' but it creates an error. Then I used lcp[i] = 0 and it returned an empty string. However, I do not know if it's right.
Also, is it necessary to use free(lcp) in the caller function? Since I could not free and return at the same time.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 50
char *find_LCP(char str1[], char str2[]);
char *find_LCP(char str1[], char str2[]){
char * lcp = malloc(MAX_LEN * sizeof(char));
int a = strlen(str1);
int b = strlen(str2);
int min = a < b ? a : b;
for(int i = 0; i < min; i++){
if(str1[i] == str2[i])
lcp[i] = str1[i];
else
lcp[i] = 0;
}
return lcp;
}
int main()
{
char str1[MAX_LEN], str2[MAX_LEN];
char * lcp;
printf("Enter first word > ");
scanf("%s", str1);
printf("Enter second word > ");
scanf("%s", str2);
lcp = find_LCP(str1, str2);
printf("\nLongest common prefix: '%s'\n", lcp);
free(lcp);
return 0;
}
An "empty" string is just a string with the first byte zero, so you can write:
s[0] = 0;
However, it is not clear what you are trying to do. The LCP of "foo" and "fob" is "fo", not the empty string.
You can also return as soon as you find the first non-matching character, no need to go until the end.
Further, you can simply pass the output string as a parameter and have lcp be an array. That way you avoid both malloc and free:
char lcp[MAX_LEN];
...
find_LCP(lcp, str1, str2);
If you want to empty a string without using a for loop then you can do
lcp[0] = 0
but for emptying a string it was right the way you did using a for loop.
There are plenty other ways of emptying the string word by word using for loop:
lcp[i] = '\0';
and it's the right way to make string empty as letter by letter you trying to do using for loop
But if you are not using some loops and simply empty a string then you can do this.
memset(buffer,0,strlen(buffer));
but this will only work for zeroing up to the first NULL character.
If the string is a static array, you can use:
memset(buffer,0,sizeof(buffer));
Your program has a bug: If you supply two identical strings, lcp[i] = 0; never executes which means that your function will return a string which is not NUL-terminated. This will cause undefined behvaior when you use that string in your printf in main.
The fix for this is easy, NUL-terminate the string after the loop:
int i;
for (i = 0; i < min; i++){
if(str1[i] == str2[i])
lcp[i] = str1[i];
else
break;
}
lcp[i] = 0;
As for the answer to the question, an empty string is one which has the NUL-terminator right at the start. We've already handled that as we've NUL-terminated the string outside the loop.
Also, is it necessary to use free(lcp) in the caller function?
In this case, it is not required as the allocated memory will get freed when the program exits, but I'd recommend keeping it because it is good practice.
As the comments say, you can use calloc instead of malloc which fills the allocated memory with zeros so you don't have to worry about NUL-terminating.
In the spirit of code golf. No need to calculate string lengths. Pick any string and iterate through it until the current character either null or differs from the corresponding character in the other string. Store the index, then copy appropriate number of bytes.
char *getlcp(const char *s1, const char *s2) {
int i = 0;
while (s1[i] == s2[i] && s1[i] != '\0') ++i;
char *lcp = calloc((i + 1), sizeof(*lcp));
memcpy(lcp, s1, i);
return lcp;
}
P.S. If you don't care about preserving one of input strings then you can simplify the code even further and just return the index (the position of the last character of the common prefix) from the function, then put '\0' at that index into one of the strings.

Format "%s" expects and agument of type char* etc, I just want to print the alphabet

Why can't I print the alphabet using this code?
void ft_putchar(char c)
{
write(1, &c, 1);
}
int print_alf(char *str)
{
int i;
i = 0;
while (str[i])
{
if (i >= 'A' && i <= 'Z')
ft_putchar(str[i]);
else
ft_putchar('\n');
i++;
}
return (str);
}
int main ()
{
char a[26];
printf("%s", print_alf(a));
return (0);
}
I get this warning
format ' %s ' expects type 'char*' but argument 2 has type 'int'
How do I print the alphabet using a string, and write function?
Your entire print_alf function looks suspicious.
You are returning str which is of type char *. Therefore the return type of print_alf should to be char * instead of int.
Your while (str[i]) loop makes no sense at all since you are passing uninitialized memory to it. So your code will very likely corrupt the memory since the while loop will continue to run until a '\0' is found within the memory which does not need to be the case within the boundaries of the passed memory (a).
You are not adding a zero termination character ('\0') at the end of the string. This will result in printf("%s", print_alf(a)); printing as many characters beginning at the address of a until a '\0' is found within the memory.
Here is a suggestion how to fix all that problems:
char *print_alf(char *str, size_t len)
{
char letter;
if ((str) && (len >= 27)) // is str a valid pointer and length is big enough?
{
for (letter = 'A'; letter <= 'Z'; letter++) // iterate all characters of the alphabet
{
*str = letter;
str++;
}
*str = '\0'; // add zero termination!!!
}
else
{
str = NULL; // indicate an error!
}
return (str);
}
int main()
{
char a[26 + 1]; // ensure '\0' fits into buffer!
printf("%s", print_alf(a, sizeof(a)));
return (0);
}
Make up your mind whether print_alf should return a string which you then print with printf or whether print_alf should be a void function that does the printing, which you should then just call without printf. At the moment, your code tries to be a mixture of both.
The easiest way is to just print the alphabet:
void print_alf(void)
{
int c;
for (c = 'A'; c <= 'Z'; c++) putchar(c);
}
Call this function like so:
print_alf(); // print whole alphabet to terminal
A more complicated variant is to fill a string with the alphabet and then print that string. That's what you tried to achieve, I think. In that case, you must pass a sufficiently big buffer to the function and return it. Note that if you want to use the string functions and features of the standard lib (of which printf("%s", ...) is one) you must null-terminate your string.
char *fill_alf(chat *str)
{
int i;
for (i = 0; i < 26; i++) str[] = 'A' + i;
str[26] = '\0';
return str;
}
It is okay to return the buffer that was passed into the function, but beware of cases where you return local character buffers, which will lead to undefined behaviour.
You can call it as you intended in your original code, but note that you must make your buffer at least 27 characters big to hold the 26 letters and the null terminator:
char a[27];
printf("%s\n", fill_alf(a));
Alternatively, you could do the filling and printing in twp separate steps:
char a[27];
fill_alf(a); // ignore return value, because it's 'a'
printf("%s\n", a); // print filled buffer
If you just want to print the alphabet, the print_alf variant is much simpler and straightforward. If you want to operate further on the alphabet, eg do a shuffle, consider using fill_alf.
Your print_alf(char *str) function actually returns an integer which causes the error (it is defined to return int). When you specify %s to printf it expects characters, not numbers.
You can fix this by changing the return type of your function to char and if everything else works in your code you'll be good to go.

Printing a string due to a new line

Is there any efficient (- in terms of performance) way for printing some arbitrary string, but only until the first new line character in it (excluding the new line character) ?
Example:
char *string = "Hello\nWorld\n";
printf(foo(string + 6));
Output:
World
If you are concerned about performance this might help (untested code):
void MyPrint(const char *str)
{
int len = strlen(str) + 1;
char *temp = alloca(len);
int i;
for (i = 0; i < len; i++)
{
char ch = str[i];
if (ch == '\n')
break;
temp[i] = ch;
}
temp[i] = 0;
puts(temp);
}
strlen is fast, alloca is fast, copying the string up to the first \n is fast, puts is faster than printf but is is most likely far slower than all three operations mentioned before together.
size_t writetodelim(char const *in, int delim)
{
char *end = strchr(in, delim);
if (!end)
return 0;
return fwrite(in, 1, end - in, stdout);
}
This can be generalized somewhat (pass the FILE* to the function), but it's already flexible enough to terminate the output on any chosen delimiter, including '\n'.
Warning: Do not use printf without format specifier to print a variable string (or from a variable pointer). Use puts instead or "%s", string.
C strings are terminated by '\0' (NUL), not by newline. So, the functions print until the NUL terminator.
You can, however, use your own loop with putchar. If that is any performance penalty is to be tested. Normally printf does much the same in the library and might be even slower, as it has to care for more additional constraints, so your own loop might very well be even faster.
for ( char *sp = string + 6 ; *sp != '\0'; sp++ ) {
if ( *sp == '\n' ) break; // newline will not be printed
putchar(*sp);
}
(Move the if-line to the end of the loop if you want newline to be printed.)
An alternative would be to limit the length of the string to print, but that would require finding the next newline before calling printf.
I don't know if it is fast enough, but there is a way to build a string containing the source string up to a new line character only involving one standard function.
char *string = "Hello\nWorld\nI love C"; // Example of your string
static char newstr [256]; // String large enough to contain the result string, fulled with \0s or NULL-terimated
sscanf(string + 6, "%s", newstr); // sscanf will ignore whitespaces
sprintf(newstr); // printing the string
I guess there is no more efficient way than simply looping over your string until you find the first \n in it. As Olaf mentioned it, a string in C ends with a terminating \0 so if you want to use printf to print the string you need to make sure it contains the terminating \0 or yu could use putchar to print the string character by character.
If you want to provide a function creating a string up to the first found new line you could do something like that:
#include <stdio.h>
#include <string.h>
#define MAX 256
void foo(const char* string, char *ret)
{
int len = (strlen(string) < MAX) ? (int) strlen(string) : MAX;
int i = 0;
for (i = 0; i < len - 1; i++)
{
if (string[i] == '\n') break;
ret[i] = string[i];
}
ret[i + 1] = '\0';
}
int main()
{
const char* string = "Hello\nWorld\n";
char ret[MAX];
foo(string, ret);
printf("%s\n", ret);
foo(string+6, ret);
printf("%s\n", ret);
}
This will print
Hello
World
Another fast way (if the new line character is truly unwanted)
Simply:
*strchr(string, '\n') = '\0';

Counting how many times a word is in a file

I'm trying to write a program that gets a string, and counts how many times that string is found in a specific file.
The file is currently: hello my name hello is oria
I like hello to program
And the word I'm counting is hello.
this is my code
int num_of_words(FILE* stream,char* str)
{
int count=0,i=0,length;
char c;
rewind(stream);
length=strlen(str);
do
{
c=fgetc(stream);
while(c==*(str+i))
{
c=fgetc(stream);
i++;
if(i==length)
{
count++;
i=0;
}
}
i=0;
}while(c!=EOF);
return count;
}
The idea is that there is a certain index called i, and it advances only if there is a match between letters. if i reached the length of the string, then it means we found all the letters in succession, and i raise count by one.
For some reason, it always returns zero.
I. while (!eof) is wrong.
II. Don't reinvent the wheel - there's the strstr() function in the C standard library which helps you find a substringĀ in another string.
I'd rather read the file into a buffer then use the following function. If the file is not too large, this should not be a problem.
int count(const char *haystack, const char *needle)
{
int n = 0;
const char *p = haystack;
size_t len = strlen(needle);
while (p = strstr(p, needle)) {
n++;
p += len;
}
return n;
}
char c; should probably be int c; to accommodate for the type of data that fgetc returns. Otherwise, when char is an unsigned type c can never equal EOF and your loop will never end.
Before your code increments i once, it reads two characters from the file. That seems problematic to me. I'd move the c=fgetc(stream); in the inner loop to the end of that loop, eg:
while(c==*(str+i))
{
i++;
if(i==length)
{
count++;
i=0;
break;
}
c=fgetc(stream);
}

strlen inconsistent with zero length string

I'm creating a DataStage parallel routine, which is a C or C++ function that is called from within IBM (formerly Ascential) DataStage. It is failing if one of the strings passed in is zero length. If I put this at the very first line of the function:
return strlen(str);
then it returns 0 for the calls that pass in empty values into str. If I put this at the first line, however...
if (strlen(str)==0) {return 0;}
then it does not return and goes into an infinite loop
I'm baffled - it works fine in a test harness, but not in DataStage.
Maybe there is something odd about the way DataStage passes empty strings to C routines?
int pxStrFirstCharList(char *str, char *chars )
{
if (strlen(str)==0) {return 0;}
if (strlen(chars)==0) {return 0;}
int i = 0;
//Start search
while (str[i]) //for the complete input string
{
if (strchr(chars, str[i]))
{
return i+1;
}
++i;
}
return 0;
}
There is a builtin function for what you are doing, it's called strcspn. This function takes two strings, and searches the first one for the first occurance of any of the characters of the second string.
I suggest using that than RYO...
http://www.cplusplus.com/reference/clibrary/cstring/strcspn/
How about this?
int pxStrFirstCharList(char *str, char *chars )
{
if (str && chars && (0 != strlen(str)) && (0 != strlen(chars)))
{
int i = 0;
//Start search
while (str[i]) //for the complete input string
{
if (strchr(chars, str[i]))
{
return i+1;
}
++i;
}
}
return 0;
}
Also, I don't quite get the point of the while loop ... (and no, I don't mean that this could be written as for). What I mean is that on one hand you are doing a search (strstr) that itself will be implemented as a loop and still you have some outer loop. Could it be that you actually wanted to have chars in its place, i.e.:
int pxStrFirstCharList(char *str, char *chars )
{
if (str && chars && (0 != strlen(str)) && (0 != strlen(chars)))
{
int i = 0;
//Start search
while (chars[i]) //for the complete input string
{
if (strchr(str, chars[i]))
{
return i+1;
}
++i;
}
}
return 0;
}
...? That is, look for each of the characters within chars inside the string denoted by str ...
If NULL is not explicitly part of the game, at least during development phase, it's always a good idea to add a precondition check on pointers received by a function:
int pxStrFirstCharList(char *str, char *chars )
{
if (!str)
return -1;
if (!chars)
return -2;
....
(The negative values -1 and -2 than tell the caller that something went wrong)
Or doing it in a more relaxed way, silently accepting NULL pointer strings as ""-string:
int pxStrFirstCharList(char *str, char *chars )
{
if (!str)
return 0;
if (!chars)
return 0;
...
If you are the only one using this API you could #ifndef BUILD_RELEASE these checks away for a release build if anything is tested stable.
I guess it is the strlen's issue when the length of the string is 0. For example,
char s1[0];
char *s2="a";
printf("%d %s\n", sizeof(s1), s1);//0 #
printf("%d %s\n", strlen(s1), s1);//3 #
printf("%d %s\n", sizeof(s2), s2);//8 a
printf("%d %s\n", strlen(s2), s2);// 1 a
You will get a weird answer for using strlen and you can check its source code in detail(https://code.woboq.org/userspace/glibc/string/strlen.c.html). In nutshell, you can use sizeof instead of strlen for char string or avoid 0 length case by using strlen.

Resources